Skip to content

Commit 17a5117

Browse files
hmynenimpe
authored andcommitted
powerpc/pseries/dlpar: Remove device tree node for DLPAR IO remove
In the powerpc-pseries specific implementation, the IO hotplug event is handled in the user space (drmgr tool). But update the device tree and /dev/mem access to allocate buffers for some RTAS calls are restricted when the kernel lockdown feature is enabled. For the DLPAR IO REMOVE, the corresponding device tree nodes and properties have to be removed from the device tree after the device disable. The user space removes the device tree nodes by updating /proc/ppc64/ofdt which is not allowed under system lockdown is enabled. This restriction can be resolved by moving the complete IO hotplug handling in the kernel. But the pseries implementation need user interaction to power off and to remove device from the slot during hotplug event handling. To overcome the /proc/ppc64/ofdt restriction, this patch extends the /sys/kernel/dlpar interface and provides ‘dt remove index <drc_index>’ to the user space so that drmgr tool can remove the corresponding device tree nodes based on DRC index from the device tree. Signed-off-by: Scott Cheloha <cheloha@linux.ibm.com> Signed-off-by: Haren Myneni <haren@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://msgid.link/20240822025028.938332-2-haren@linux.ibm.com
1 parent b76e0d4 commit 17a5117

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

arch/powerpc/include/asm/rtas.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ inline uint16_t pseries_errorlog_length(struct pseries_errorlog *sect)
397397
#define PSERIES_HP_ELOG_RESOURCE_SLOT 3
398398
#define PSERIES_HP_ELOG_RESOURCE_PHB 4
399399
#define PSERIES_HP_ELOG_RESOURCE_PMEM 6
400+
#define PSERIES_HP_ELOG_RESOURCE_DT 7
400401

401402
#define PSERIES_HP_ELOG_ACTION_ADD 1
402403
#define PSERIES_HP_ELOG_ACTION_REMOVE 2

arch/powerpc/platforms/pseries/dlpar.c

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,87 @@ int dlpar_unisolate_drc(u32 drc_index)
327327
return 0;
328328
}
329329

330+
static int changeset_detach_node_recursive(struct of_changeset *ocs,
331+
struct device_node *node)
332+
{
333+
struct device_node *child;
334+
int rc;
335+
336+
for_each_child_of_node(node, child) {
337+
rc = changeset_detach_node_recursive(ocs, child);
338+
if (rc) {
339+
of_node_put(child);
340+
return rc;
341+
}
342+
}
343+
344+
return of_changeset_detach_node(ocs, node);
345+
}
346+
347+
static int dlpar_hp_dt_remove(u32 drc_index)
348+
{
349+
struct device_node *np;
350+
struct of_changeset ocs;
351+
u32 index;
352+
int rc = 0;
353+
354+
/*
355+
* Prune all nodes with a matching index.
356+
*/
357+
of_changeset_init(&ocs);
358+
359+
for_each_node_with_property(np, "ibm,my-drc-index") {
360+
rc = of_property_read_u32(np, "ibm,my-drc-index", &index);
361+
if (rc) {
362+
pr_err("%s: %pOF: of_property_read_u32 %s: %d\n",
363+
__func__, np, "ibm,my-drc-index", rc);
364+
of_node_put(np);
365+
goto out;
366+
}
367+
368+
if (index == drc_index) {
369+
rc = changeset_detach_node_recursive(&ocs, np);
370+
if (rc) {
371+
of_node_put(np);
372+
goto out;
373+
}
374+
}
375+
}
376+
377+
rc = of_changeset_apply(&ocs);
378+
379+
out:
380+
of_changeset_destroy(&ocs);
381+
return rc;
382+
}
383+
384+
static int dlpar_hp_dt(struct pseries_hp_errorlog *phpe)
385+
{
386+
u32 drc_index;
387+
int rc;
388+
389+
if (phpe->id_type != PSERIES_HP_ELOG_ID_DRC_INDEX)
390+
return -EINVAL;
391+
392+
drc_index = be32_to_cpu(phpe->_drc_u.drc_index);
393+
394+
lock_device_hotplug();
395+
396+
switch (phpe->action) {
397+
case PSERIES_HP_ELOG_ACTION_REMOVE:
398+
rc = dlpar_hp_dt_remove(drc_index);
399+
break;
400+
default:
401+
pr_err("Invalid action (%d) specified\n", phpe->action);
402+
rc = -EINVAL;
403+
break;
404+
}
405+
406+
unlock_device_hotplug();
407+
408+
return rc;
409+
}
410+
330411
int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog)
331412
{
332413
int rc;
@@ -341,6 +422,9 @@ int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog)
341422
case PSERIES_HP_ELOG_RESOURCE_PMEM:
342423
rc = dlpar_hp_pmem(hp_elog);
343424
break;
425+
case PSERIES_HP_ELOG_RESOURCE_DT:
426+
rc = dlpar_hp_dt(hp_elog);
427+
break;
344428

345429
default:
346430
pr_warn_ratelimited("Invalid resource (%d) specified\n",
@@ -393,6 +477,8 @@ static int dlpar_parse_resource(char **cmd, struct pseries_hp_errorlog *hp_elog)
393477
hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_MEM;
394478
} else if (sysfs_streq(arg, "cpu")) {
395479
hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_CPU;
480+
} else if (sysfs_streq(arg, "dt")) {
481+
hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_DT;
396482
} else {
397483
pr_err("Invalid resource specified.\n");
398484
return -EINVAL;
@@ -534,7 +620,7 @@ static ssize_t dlpar_store(const struct class *class, const struct class_attribu
534620
static ssize_t dlpar_show(const struct class *class, const struct class_attribute *attr,
535621
char *buf)
536622
{
537-
return sprintf(buf, "%s\n", "memory,cpu");
623+
return sprintf(buf, "%s\n", "memory,cpu,dt");
538624
}
539625

540626
static CLASS_ATTR_RW(dlpar);

0 commit comments

Comments
 (0)