From 3c0c6441883be7676b795939e268b90d6acab360 Mon Sep 17 00:00:00 2001 From: linas Date: Thu, 12 Jan 2006 14:36:25 -0600 Subject: [PATCH] PCI Hotplug: PCI panic on dlpar add (add pci slot to running partition) Removing and then adding a PCI slot to a running partition results in a kernel panic. The current code attempts to add iospace for an entire root bus, which is inappropriate, and silently fails. When a pci device tries to use the iospace, a page fault is taken, as the iospace had not been mapped, and of course the page fault cannot be resolved. This only occurs for PCI adapters using pio, which may be why it hadn't been seen earlier (this seems to have been broken for a while). This patch has survived testing of dozens of slot add and removes. Signed-off-by: Linas Vepstas Acked-by: John Rose Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/hotplug/rpadlpar_core.c') diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 7d93dbaf628..7f504b380f2 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -152,7 +152,7 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) pcibios_claim_one_bus(dev->bus); /* ioremap() for child bus, which may or may not succeed */ - (void) remap_bus_range(dev->bus); + remap_bus_range(dev->subordinate); /* Add new devices to global lists. Register in proc, sysfs. */ pci_bus_add_devices(phb->bus); -- cgit v1.2.3 From 01657868be1c21b2b8b0e683ea24bdcc2331d522 Mon Sep 17 00:00:00 2001 From: "linas@austin.ibm.com" Date: Thu, 12 Jan 2006 18:18:26 -0600 Subject: [PATCH] powerpc/PCI hotplug: remove rpaphp_find_bus() The function rpaphp_find_pci_bus() has been migrated to pcibios_find_pci_bus() in arch/powerpc/platforms/pseries/pci_dlpar.c This patch removes the old version. Signed-off-by: Linas Vepstas Acked-by: John Rose Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/pci/hotplug/rpadlpar_core.c') diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 7f504b380f2..bc17a13fc82 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -174,7 +174,7 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) { struct pci_dev *dev; - if (rpaphp_find_pci_bus(dn)) + if (pcibios_find_pci_bus(dn)) return -EINVAL; /* Add pci bus */ @@ -221,7 +221,7 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn) struct pci_dn *pdn; int rc = 0; - if (!rpaphp_find_pci_bus(dn)) + if (!pcibios_find_pci_bus(dn)) return -EINVAL; slot = find_slot(dn); @@ -366,7 +366,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) struct pci_bus *bus; struct slot *slot; - bus = rpaphp_find_pci_bus(dn); + bus = pcibios_find_pci_bus(dn); if (!bus) return -EINVAL; -- cgit v1.2.3 From eca845c71816669dace4bf1954d9ab276abb0002 Mon Sep 17 00:00:00 2001 From: "linas@austin.ibm.com" Date: Thu, 12 Jan 2006 18:20:26 -0600 Subject: [PATCH] powerpc/PCI hotplug: remove rpaphp_fixup_new_pci_devices() The function rpaphp_fixup_new_pci_devices() has been migrated to pcibios_fixup_new_pci_devices() in arch/powerpc/platforms/pseries/pci_dlpar.c This patch removes the old version. Signed-off-by: Linas Vepstas Acked-by: John Rose Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/hotplug/rpadlpar_core.c') diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index bc17a13fc82..6c148106518 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -146,7 +146,7 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) of_scan_pci_bridge(dn, dev); - rpaphp_init_new_devs(dev->subordinate); + pcibios_fixup_new_pci_devices(dev->subordinate,0); /* Claim new bus resources */ pcibios_claim_one_bus(dev->bus); -- cgit v1.2.3 From 8fe64399cccf8dddcc4e5eaff270a12064f6fe9f Mon Sep 17 00:00:00 2001 From: "linas@austin.ibm.com" Date: Thu, 12 Jan 2006 18:26:27 -0600 Subject: [PATCH] powerpc/PCI hotplug: de-convolute rpaphp_unconfig_pci_adap Remove general baroqueness. The function rpaphp_unconfig_pci_adapter() is really just three lines of code, once all the dbg printks are removed. And its called in only one place. So replace the call by the thre lines. Also, provide proper semaphore locking in the affected function disable_slot() Signed-off-by: Linas Vepstas Acked-by: John Rose Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/pci/hotplug/rpadlpar_core.c') diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 6c148106518..15e853e5e68 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -380,7 +380,11 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) return -EIO; } } else { - rpaphp_unconfig_pci_adapter(bus); + struct pci_dev *dev, *tmp; + list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { + eeh_remove_bus_device(dev); + pci_remove_bus_device(dev); + } } if (unmap_bus_range(bus)) { -- cgit v1.2.3 From f6afbad82c6b7bab0198442592b110341fb419ba Mon Sep 17 00:00:00 2001 From: "linas@austin.ibm.com" Date: Thu, 12 Jan 2006 18:31:01 -0600 Subject: [PATCH] powerpc/PCI hotplug: cleanup: add prefix Minor cleanup. Add the prefix rpaphp_* to several generic-sounding routines. Remove rpaphp_remove_slot(), which is a one-liner. Signed-off-by: Linas Vepstas Acked-by: John Rose Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/pci/hotplug/rpadlpar_core.c') diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 15e853e5e68..d3aa9df1acd 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -227,7 +227,7 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn) slot = find_slot(dn); if (slot) { /* Remove hotplug slot */ - if (rpaphp_remove_slot(slot)) { + if (rpaphp_deregister_slot(slot)) { printk(KERN_ERR "%s: unable to remove hotplug slot %s\n", __FUNCTION__, drc_name); @@ -373,7 +373,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) slot = find_slot(dn); if (slot) { /* Remove hotplug slot */ - if (rpaphp_remove_slot(slot)) { + if (rpaphp_deregister_slot(slot)) { printk(KERN_ERR "%s: unable to remove hotplug slot %s\n", __FUNCTION__, drc_name); -- cgit v1.2.3 From 8737d6a90cd8b085c2ea9cb4c7443c87f86c3429 Mon Sep 17 00:00:00 2001 From: "linas@austin.ibm.com" Date: Thu, 12 Jan 2006 18:35:23 -0600 Subject: [PATCH] powerpc/PCI hotplug: shuffle error checking to better location. Error checking is scattered through various layers of the dlpar code, leading to a somewhat opaque code structure. This patch consolidates error checking in one routine, simplifying the code a tad. There's also some whitespace cleanup here too. Signed-off-by: Linas Vepstas Acked-by: John Rose Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 44 ++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/pci/hotplug/rpadlpar_core.c') diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index d3aa9df1acd..3eefe2cec72 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -103,13 +103,13 @@ static struct slot *find_slot(struct device_node *dn) struct list_head *tmp, *n; struct slot *slot; - list_for_each_safe(tmp, n, &rpaphp_slot_head) { - slot = list_entry(tmp, struct slot, rpaphp_slot_list); - if (slot->dn == dn) - return slot; - } + list_for_each_safe(tmp, n, &rpaphp_slot_head) { + slot = list_entry(tmp, struct slot, rpaphp_slot_list); + if (slot->dn == dn) + return slot; + } - return NULL; + return NULL; } static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, @@ -126,9 +126,9 @@ static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, return NULL; } -static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) +static void dlpar_pci_add_bus(struct device_node *dn) { - struct pci_dn *pdn = dn->data; + struct pci_dn *pdn = PCI_DN(dn); struct pci_controller *phb = pdn->phb; struct pci_dev *dev = NULL; @@ -139,7 +139,7 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) if (!dev) { printk(KERN_ERR "%s: failed to create pci dev for %s\n", __FUNCTION__, dn->full_name); - return NULL; + return; } if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || @@ -156,35 +156,35 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) /* Add new devices to global lists. Register in proc, sysfs. */ pci_bus_add_devices(phb->bus); - - /* Confirm new bridge dev was created */ - dev = dlpar_find_new_dev(phb->bus, dn); - if (dev) { - if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { - printk(KERN_ERR "%s: unexpected header type %d\n", - __FUNCTION__, dev->hdr_type); - return NULL; - } - } - - return dev; } static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) { struct pci_dev *dev; + struct pci_controller *phb; if (pcibios_find_pci_bus(dn)) return -EINVAL; /* Add pci bus */ - dev = dlpar_pci_add_bus(dn); + dlpar_pci_add_bus(dn); + + /* Confirm new bridge dev was created */ + phb = PCI_DN(dn)->phb; + dev = dlpar_find_new_dev(phb->bus, dn); + if (!dev) { printk(KERN_ERR "%s: unable to add bus %s\n", __FUNCTION__, drc_name); return -EIO; } + if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { + printk(KERN_ERR "%s: unexpected header type %d, unable to add bus %s\n", + __FUNCTION__, dev->hdr_type, drc_name); + return -EIO; + } + /* Add hotplug slot */ if (rpaphp_add_slot(dn)) { printk(KERN_ERR "%s: unable to add hotplug slot %s\n", -- cgit v1.2.3