From f40a63b15c5639df93405b925a4dde740d9bfa23 Mon Sep 17 00:00:00 2001 From: Haren Myneni Date: Fri, 21 Jun 2024 15:45:58 -0700 Subject: [PATCH] drmgr/pci: Add multipath partner device support for hotplug replace If the PCI device has multipath partner device, its device node contains "ibm,multipath-partner-drc" property which gives the DRC index of the partner device. So for the replace operation, the following steps will be executed: - Find the device based on the partner DRC index of the requested device - Remove the requested device - Remove the partner path - Add the new device based on user input - Find the device based on the partner DRC index of the new device - Add the partner path of the new device Since both paths will be using the same slot, LED indicators and the slot identification will be done only for the primary device in both removal and add operations. Signed-off-by: Haren Myneni Signed-off-by: Tyrel Datwyler --- src/drmgr/drslot_chrp_pci.c | 99 ++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/src/drmgr/drslot_chrp_pci.c b/src/drmgr/drslot_chrp_pci.c index 2b8579b..ac078db 100644 --- a/src/drmgr/drslot_chrp_pci.c +++ b/src/drmgr/drslot_chrp_pci.c @@ -877,6 +877,44 @@ static int do_remove(struct dr_node *all_nodes) return 0; } +static int replace_add_work(struct dr_node *node, bool partner_device) +{ + + say(DEBUG, "repl_node:path=%s node:path=%s\n", + node->ofdt_path, node->children->ofdt_path); + + /* Prompt user to replace card and to press + * Enter to continue or x to exit. Exiting here + * means the original card has been removed. + */ + if (usr_prompt && !partner_device) { + if (process_led(node, LED_ACTION)) + return -1; + + printf("The visual indicator for the specified PCI slot <%s>\n" + "has been set to the action state. Replace the PCI\n" + "card in the identified slot and press Enter to " + "continue.\nEnter x to exit. Exiting now leaves the " + "PCI slot\nin the removed state.\n", + node->drc_name); + + if (!(getchar() == '\n')) { + process_led(node, LED_OFF); + return 0; + } + } + + if (add_work(node, partner_device)) + return -1; + + say(DEBUG, "CONFIGURING the card in node[name=%s, path=%s]\n", + node->drc_name, node->ofdt_path); + + set_hp_adapter_status(PHP_CONFIG_ADAPTER, node->drc_name); + + return 1; +} + /** * do_replace * @brief Allows the replacement of an adapter connected to a @@ -899,55 +937,43 @@ static int do_remove(struct dr_node *all_nodes) */ static int do_replace(struct dr_node *all_nodes) { - struct dr_node *repl_node; + struct dr_node *repl_node, *partner_node = NULL; int rc; repl_node = find_slot(usr_drc_name, 0, all_nodes, 0); if (repl_node == NULL) return -1; + partner_node = find_partner_node(repl_node, all_nodes); + if (partner_node) + printf("<%s> and <%s> are\nmultipath partner devices. " + "So <%s> will\nbe also replaced.\n", + repl_node->drc_name, partner_node->drc_name, + partner_node->drc_name); + /* Call the routine which does the work of getting the node info, * then removing it from the OF device tree. */ if (remove_work(repl_node, false)) return -1; + if (partner_node) { + if (remove_work(partner_node, true)) + return -1; + } + if (!repl_node->children) { say(ERROR, "Bad node struct.\n"); return -1; } - say(DEBUG, "repl_node:path=%s node:path=%s\n", - repl_node->ofdt_path, repl_node->children->ofdt_path); - - /* Prompt user to replace card and to press - * Enter to continue or x to exit. Exiting here - * means the original card has been removed. - */ - if (usr_prompt) { - if (process_led(repl_node, LED_ACTION)) - return -1; - - printf("The visual indicator for the specified PCI slot " - "has\nbeen set to the action state. Replace the PCI " - "card\nin the identified slot and press Enter to " - "continue.\nEnter x to exit. Exiting now leaves the " - "PCI slot\nin the removed state.\n"); - - if (!(getchar() == '\n')) { - process_led(repl_node, LED_OFF); - return 0; - } - } - - rc = add_work(repl_node, false); - if (rc) + rc = replace_add_work(repl_node, false); + if (rc <= 0) return rc; - say(DEBUG, "CONFIGURING the card in node[name=%s, path=%s]\n", - repl_node->drc_name, repl_node->ofdt_path); - - set_hp_adapter_status(PHP_CONFIG_ADAPTER, repl_node->drc_name); + rc = replace_add_work(partner_node, true); + if (rc <= 0) + return rc; if (repl_node->post_replace_processing) { int prompt_save = usr_prompt; @@ -961,11 +987,24 @@ static int do_replace(struct dr_node *all_nodes) if (remove_work(repl_node, false)) return -1; + partner_node = find_partner_node(repl_node, node); + if (partner_node) { + if (remove_work(partner_node, true)) + return -1; + } + rc = add_work(repl_node, false); if (!rc) set_hp_adapter_status(PHP_CONFIG_ADAPTER, repl_node->drc_name); + if (partner_node) { + rc = add_work(partner_node, true); + if (!rc) + set_hp_adapter_status(PHP_CONFIG_ADAPTER, + partner_node->drc_name); + } + usr_prompt = prompt_save; }