diff --git a/0001-drmgr-pci-Enable-in-kernel-functionality-to-update-d.patch b/0001-drmgr-pci-Enable-in-kernel-functionality-to-update-d.patch new file mode 100644 index 0000000..3146091 --- /dev/null +++ b/0001-drmgr-pci-Enable-in-kernel-functionality-to-update-d.patch @@ -0,0 +1,99 @@ +From a6a7d375d38823a08d358b50866a95f6f326907e Mon Sep 17 00:00:00 2001 +From: Haren Myneni +Date: Tue, 13 Aug 2024 14:40:23 -0700 +Subject: [PATCH 1/4] drmgr/pci: Enable in-kernel functionality to update + device tree + +drmgr updates the device tree by writing to /proc/ppc64/ofdt. Also +invokes configure_connector RTAS call to retrieve new device nodes +for IO ADD. But this functionality need /dev/mem access which is +restricted under system lockdown. + +The kernel updates provided a sysfs file (/sys/kernel/dlpar) that +will allow drmgr command invoke the following interfaces to update +the device tree. + +dt add index ---> To add new device nodes to the device +tree which is used for IO ADD. + +dt remove index ---> To remove device nodes for IO +REMOVE + +This patch checks the kernel interface for the availability of +device tree update feature and adds do_dt_kernel_dlpar() to invoke +the above kernel interfaces. + +Signed-off-by: Haren Myneni +--- + src/drmgr/common.c | 6 ++++++ + src/drmgr/common_pci.c | 29 +++++++++++++++++++++++++++++ + src/drmgr/dr.h | 1 + + 3 files changed, 36 insertions(+) + +diff --git a/src/drmgr/common.c b/src/drmgr/common.c +index bfec0b9bb966..70f4dfda92a5 100644 +--- a/src/drmgr/common.c ++++ b/src/drmgr/common.c +@@ -1504,6 +1504,12 @@ int kernel_dlpar_exists(void) + if (strstr(buf, "cpu")) + return 1; + break; ++ case DRC_TYPE_PCI: ++ case DRC_TYPE_PHB: ++ case DRC_TYPE_SLOT: ++ if (strstr(buf, "dt")) ++ return 1; ++ break; + default: + return 0; + } +diff --git a/src/drmgr/common_pci.c b/src/drmgr/common_pci.c +index 1ef4ec9653b0..374129cf33e0 100644 +--- a/src/drmgr/common_pci.c ++++ b/src/drmgr/common_pci.c +@@ -1619,3 +1619,32 @@ int disable_hp_children(char *drc_name) + } + return 0; + } ++ ++/* ++ * kernel interface to update device tree nodes. ++ * dlpar dt [add|remove] index <#drc index> ++ */ ++int do_dt_kernel_dlpar(uint32_t index, int action) ++{ ++ char cmdbuf[256]; ++ int offset; ++ ++ offset = sprintf(cmdbuf, "%s ", "dt"); ++ ++ switch (action) { ++ case ADD: ++ offset += sprintf(cmdbuf + offset, "add "); ++ break; ++ case REMOVE: ++ offset += sprintf(cmdbuf + offset, "remove "); ++ break; ++ default: ++ /* Should not happen */ ++ say(ERROR, "Invalid action type specified\n"); ++ return -EINVAL; ++ } ++ ++ offset += sprintf(cmdbuf + offset, "index 0x%x", index); ++ ++ return do_kernel_dlpar(cmdbuf, offset); ++} +diff --git a/src/drmgr/dr.h b/src/drmgr/dr.h +index 60c31c44b7e3..72ede55547a3 100644 +--- a/src/drmgr/dr.h ++++ b/src/drmgr/dr.h +@@ -188,4 +188,5 @@ static inline int do_kernel_dlpar(const char *cmd, int len) + { + return do_kernel_dlpar_common(cmd, len, 0); + } ++int do_dt_kernel_dlpar(uint32_t, int); + #endif +-- +2.46.0 + diff --git a/0002-drmgr-SLOT-Add-kernel-interface-support-for-device-t.patch b/0002-drmgr-SLOT-Add-kernel-interface-support-for-device-t.patch new file mode 100644 index 0000000..51fb709 --- /dev/null +++ b/0002-drmgr-SLOT-Add-kernel-interface-support-for-device-t.patch @@ -0,0 +1,72 @@ +From e2388681df4aec97ab9a3f883baf37f51a710a00 Mon Sep 17 00:00:00 2001 +From: Haren Myneni +Date: Tue, 13 Aug 2024 14:40:26 -0700 +Subject: [PATCH 2/4] drmgr/SLOT: Add kernel interface support for device tree + update + +Use the following kernel interfaces for SLOT device type to update +the device tree if this feature is enabled in the kernel. + +dt add index --> for IO add +dt remove index --> for IO remove + +Signed-off-by: Haren Myneni +--- + src/drmgr/drslot_chrp_slot.c | 25 +++++++++++++++++-------- + 1 file changed, 17 insertions(+), 8 deletions(-) + +diff --git a/src/drmgr/drslot_chrp_slot.c b/src/drmgr/drslot_chrp_slot.c +index 0966c256aa01..180b10857add 100644 +--- a/src/drmgr/drslot_chrp_slot.c ++++ b/src/drmgr/drslot_chrp_slot.c +@@ -71,7 +71,10 @@ release_slot(struct dr_node *slot) + if (rc) + return rc; + +- rc = remove_device_tree_nodes(slot->ofdt_path); ++ if (kernel_dlpar_exists()) ++ rc = do_dt_kernel_dlpar(slot->drc_index, REMOVE); ++ else ++ rc = remove_device_tree_nodes(slot->ofdt_path); + if (rc) { + acquire_drc(slot->drc_index); + return rc; +@@ -160,7 +163,6 @@ static int + acquire_slot(char *drc_name, struct dr_node **slot) + { + struct dr_connector drc; +- struct of_node *of_nodes; + char path[DR_PATH_MAX]; + int rc; + +@@ -180,14 +182,21 @@ acquire_slot(char *drc_name, struct dr_node **slot) + if (rc) + return rc; + +- of_nodes = configure_connector(drc.index); +- if (of_nodes == NULL) { +- release_drc(drc.index, PCI_DLPAR_DEV); +- return -1; ++ if (kernel_dlpar_exists()) { ++ rc = do_dt_kernel_dlpar(drc.index, ADD); ++ } else { ++ struct of_node *of_nodes; ++ ++ of_nodes = configure_connector(drc.index); ++ if (of_nodes == NULL) { ++ release_drc(drc.index, PCI_DLPAR_DEV); ++ return -1; ++ } ++ ++ rc = add_device_tree_nodes(path, of_nodes); ++ free_of_node(of_nodes); + } + +- rc = add_device_tree_nodes(path, of_nodes); +- free_of_node(of_nodes); + if (rc) { + say(ERROR, "add_device_tree_nodes failed at %s\n", path); + release_drc(drc.index, PCI_DLPAR_DEV); +-- +2.46.0 + diff --git a/0003-drmgr-pci-Add-kernel-interface-support-for-device-tr.patch b/0003-drmgr-pci-Add-kernel-interface-support-for-device-tr.patch new file mode 100644 index 0000000..f8d5451 --- /dev/null +++ b/0003-drmgr-pci-Add-kernel-interface-support-for-device-tr.patch @@ -0,0 +1,79 @@ +From 7038756642711fa53143906b3b3f29900eb4a4ea Mon Sep 17 00:00:00 2001 +From: Haren Myneni +Date: Tue, 13 Aug 2024 14:40:25 -0700 +Subject: [PATCH 3/4] drmgr/pci: Add kernel interface support for device tree + update + +Use the following kernel interfaces for PCI device type to update +the device tree if this feature is enabled in the kernel. + +dt add index --> for IO add +dt remove index --> for IO remove + +Signed-off-by: Haren Myneni +--- + src/drmgr/drslot_chrp_pci.c | 32 ++++++++++++++++++++++---------- + 1 file changed, 22 insertions(+), 10 deletions(-) + +diff --git a/src/drmgr/drslot_chrp_pci.c b/src/drmgr/drslot_chrp_pci.c +index 3b48de30be66..56f8bb397e67 100644 +--- a/src/drmgr/drslot_chrp_pci.c ++++ b/src/drmgr/drslot_chrp_pci.c +@@ -366,7 +366,6 @@ static int add_work(struct dr_node *node) + int pow_state; /* Tells us if power was turned on when */ + int iso_state; /* Tells us isolation state after */ + int rc; +- struct of_node *new_nodes;/* nodes returned from configure_connector */ + + /* if we're continuing, set LED_ON and see if a card is really there. */ + if (process_led(node, LED_ON)) +@@ -425,16 +424,26 @@ static int add_work(struct dr_node *node) + * the return status requires a message, print it out + * and exit, otherwise, add the nodes to the OF tree. + */ +- new_nodes = configure_connector(node->drc_index); +- if (new_nodes == NULL) { +- rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE); +- set_power(node->drc_power, POWER_OFF); +- return -1; ++ if (kernel_dlpar_exists()) { ++ rc = do_dt_kernel_dlpar(node->drc_index, ADD); ++ } else { ++ struct of_node *new_nodes; /* nodes returned from */ ++ /* configure_connector */ ++ ++ new_nodes = configure_connector(node->drc_index); ++ if (new_nodes == NULL) { ++ rtas_set_indicator(ISOLATION_STATE, node->drc_index, ++ ISOLATE); ++ set_power(node->drc_power, POWER_OFF); ++ return -1; ++ } ++ ++ say(DEBUG, "Adding %s to %s\n", new_nodes->name, ++ node->ofdt_path); ++ rc = add_device_tree_nodes(node->ofdt_path, new_nodes); ++ free_of_node(new_nodes); + } + +- say(DEBUG, "Adding %s to %s\n", new_nodes->name, node->ofdt_path); +- rc = add_device_tree_nodes(node->ofdt_path, new_nodes); +- free_of_node(new_nodes); + if (rc) { + say(DEBUG, "add_device_tree_nodes failed at %s\n", + node->ofdt_path); +@@ -692,7 +701,10 @@ static struct dr_node *remove_work(struct dr_node *all_nodes) + * the device tree. + */ + for (child = node->children; child; child = child->next) { +- rc = remove_device_tree_nodes(child->ofdt_path); ++ if (kernel_dlpar_exists()) ++ rc = do_dt_kernel_dlpar(child->drc_index, REMOVE); ++ else ++ rc = remove_device_tree_nodes(child->ofdt_path); + if (rc) { + say(ERROR, "%s", sw_error); + rtas_set_indicator(ISOLATION_STATE, node->drc_index, +-- +2.46.0 + diff --git a/0004-drmgr-phb-Add-kernel-interface-support-for-device-tr.patch b/0004-drmgr-phb-Add-kernel-interface-support-for-device-tr.patch new file mode 100644 index 0000000..cd4a4e5 --- /dev/null +++ b/0004-drmgr-phb-Add-kernel-interface-support-for-device-tr.patch @@ -0,0 +1,142 @@ +From b8ab373035984dd8aba29f1a0c03dcef6546f004 Mon Sep 17 00:00:00 2001 +From: Haren Myneni +Date: Tue, 13 Aug 2024 14:40:24 -0700 +Subject: [PATCH 4/4] drmgr/phb: Add kernel interface support for device tree + update + +Use the following kernel interfaces for PHB device type to update +the device tree if this feature is enabled in the kernel. + +dt add index --> for IO add +dt remove index --> for IO remove + +Signed-off-by: Haren Myneni +--- + src/drmgr/common_pci.c | 29 +++++++++++++++++++++------- + src/drmgr/drslot_chrp_phb.c | 38 ++++++++++++++++++++----------------- + 2 files changed, 43 insertions(+), 24 deletions(-) + +diff --git a/src/drmgr/common_pci.c b/src/drmgr/common_pci.c +index 374129cf33e0..540864574569 100644 +--- a/src/drmgr/common_pci.c ++++ b/src/drmgr/common_pci.c +@@ -1390,7 +1390,6 @@ print_node_list(struct dr_node *first_node) + static int + acquire_hp_resource(struct dr_connector *drc, char *of_path) + { +- struct of_node *new_nodes; + int state; + int rc; + +@@ -1429,12 +1428,21 @@ acquire_hp_resource(struct dr_connector *drc, char *of_path) + } + + if (state == PRESENT) { +- new_nodes = configure_connector(drc->index); +- if (new_nodes == NULL) +- return -1; ++ /* ++ * Use kernel DLPAR interface if it is enabled ++ */ ++ if (kernel_dlpar_exists()) { ++ rc = do_dt_kernel_dlpar(drc->index, ADD); ++ } else { ++ struct of_node *new_nodes; ++ ++ new_nodes = configure_connector(drc->index); ++ if (new_nodes == NULL) ++ return -1; + +- rc = add_device_tree_nodes(of_path, new_nodes); +- free_of_node(new_nodes); ++ rc = add_device_tree_nodes(of_path, new_nodes); ++ free_of_node(new_nodes); ++ } + if (rc) { + say(ERROR, "add nodes failed for 0x%x\n", drc->index); + return rc; +@@ -1490,7 +1498,14 @@ release_hp_resource(struct dr_node *node) + { + int rc; + +- rc = remove_device_tree_nodes(node->ofdt_path); ++ /* ++ * Use kernel DLPAR interface if it is enabled ++ */ ++ if (kernel_dlpar_exists()) ++ rc = do_dt_kernel_dlpar(node->drc_index, REMOVE); ++ else ++ rc = remove_device_tree_nodes(node->ofdt_path); ++ + if (rc) { + say(ERROR, "failed to remove kernel nodes for index 0x%x\n", + node->drc_index); +diff --git a/src/drmgr/drslot_chrp_phb.c b/src/drmgr/drslot_chrp_phb.c +index f59baa4f9e27..ffa17d8f6b7d 100644 +--- a/src/drmgr/drslot_chrp_phb.c ++++ b/src/drmgr/drslot_chrp_phb.c +@@ -108,17 +108,16 @@ release_phb(struct dr_node *phb) + { + int rc; + +- rc = remove_device_tree_nodes(phb->ofdt_path); +- if (rc) +- return rc; +- +- if (phb->phb_ic_ofdt_path[0] != '\0') { +- rc = remove_device_tree_nodes(phb->phb_ic_ofdt_path); +- if (rc) +- return rc; ++ if (kernel_dlpar_exists()) ++ rc = do_dt_kernel_dlpar(phb->drc_index, REMOVE); ++ else { ++ rc = remove_device_tree_nodes(phb->ofdt_path); ++ if (!rc && (phb->phb_ic_ofdt_path[0] != '\0')) ++ rc = remove_device_tree_nodes(phb->phb_ic_ofdt_path); + } + +- rc = release_drc(phb->drc_index, PHB_DEV); ++ if (!rc) ++ rc = release_drc(phb->drc_index, PHB_DEV); + + return rc; + } +@@ -371,7 +370,6 @@ phb_remove_error: + static int acquire_phb(char *drc_name, struct dr_node **phb) + { + struct dr_connector drc; +- struct of_node *of_nodes; + char path[DR_PATH_MAX]; + int rc; + +@@ -386,14 +384,20 @@ static int acquire_phb(char *drc_name, struct dr_node **phb) + if (rc) + return rc; + +- of_nodes = configure_connector(drc.index); +- if (of_nodes == NULL) { +- release_drc(drc.index, PHB_DEV); +- return -1; +- } ++ if (kernel_dlpar_exists()) { ++ rc = do_dt_kernel_dlpar(drc.index, ADD); ++ } else { ++ struct of_node *of_nodes; + +- rc = add_device_tree_nodes(path, of_nodes); +- free_of_node(of_nodes); ++ of_nodes = configure_connector(drc.index); ++ if (of_nodes == NULL) { ++ release_drc(drc.index, PHB_DEV); ++ return -1; ++ } ++ ++ rc = add_device_tree_nodes(path, of_nodes); ++ free_of_node(of_nodes); ++ } + if (rc) { + say(ERROR, "add_device_tree_nodes failed at %s\n", path); + release_drc(drc.index, PHB_DEV); +-- +2.46.0 + diff --git a/powerpc-utils.changes b/powerpc-utils.changes index adb390e..ebb3c4e 100644 --- a/powerpc-utils.changes +++ b/powerpc-utils.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Fri Sep 20 06:15:46 UTC 2024 - Michal Suchanek + +- dlpar: move key portions of I/O hotplug into kernel (jsc#PED-10566, jsc#PED-9919). + * 0001-drmgr-pci-Enable-in-kernel-functionality-to-update-d.patch + * 0002-drmgr-SLOT-Add-kernel-interface-support-for-device-t.patch + * 0003-drmgr-pci-Add-kernel-interface-support-for-device-tr.patch + * 0004-drmgr-phb-Add-kernel-interface-support-for-device-tr.patch + ------------------------------------------------------------------- Wed Jul 31 10:02:13 UTC 2024 - Michal Suchanek diff --git a/powerpc-utils.spec b/powerpc-utils.spec index 672e053..ce324d4 100644 --- a/powerpc-utils.spec +++ b/powerpc-utils.spec @@ -37,6 +37,10 @@ Patch9: ppc64_cpu-Clean-up-sysfs-smt-control-error-handling.patch Patch10: 0002-lparstat-Fix-Idle-and-busy-PURR-SPURR.patch Patch11: 0003-lparstat-app-Use-pic-value-at-boot-for-accurate-boot.patch Patch12: 0004-lparstat-Use-CLOCK_BOOTTIME-for-get_time-interface-a.patch +Patch13: 0001-drmgr-pci-Enable-in-kernel-functionality-to-update-d.patch +Patch14: 0002-drmgr-SLOT-Add-kernel-interface-support-for-device-t.patch +Patch15: 0003-drmgr-pci-Add-kernel-interface-support-for-device-tr.patch +Patch16: 0004-drmgr-phb-Add-kernel-interface-support-for-device-tr.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: libnuma-devel