diff options
Diffstat (limited to 'drivers/pci/hotplug/rpadlpar_core.c')
| -rw-r--r-- | drivers/pci/hotplug/rpadlpar_core.c | 30 | 
1 files changed, 19 insertions, 11 deletions
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 083034710fa..7660232ef46 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -18,6 +18,7 @@  #undef DEBUG  #include <linux/init.h> +#include <linux/module.h>  #include <linux/pci.h>  #include <linux/string.h>  #include <linux/vmalloc.h> @@ -156,9 +157,8 @@ static void dlpar_pci_add_bus(struct device_node *dn)  	}  	/* Scan below the new bridge */ -	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || -	    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) -		of_scan_pci_bridge(dn, dev); +	if (pci_is_bridge(dev)) +		of_scan_pci_bridge(dev);  	/* Map IO space for child bus, which may or may not succeed */  	pcibios_map_io_space(dev->subordinate); @@ -216,7 +216,7 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn)  	if (!pcibios_find_pci_bus(dn))  		return -EINVAL; -	/* If pci slot is hotplugable, use hotplug to remove it */ +	/* If pci slot is hotpluggable, use hotplug to remove it */  	slot = find_php_slot(dn);  	if (slot && rpaphp_deregister_slot(slot)) {  		printk(KERN_ERR "%s: unable to remove hotplug slot %s\n", @@ -353,10 +353,15 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)  {  	struct pci_bus *bus;  	struct slot *slot; +	int ret = 0; + +	pci_lock_rescan_remove();  	bus = pcibios_find_pci_bus(dn); -	if (!bus) -		return -EINVAL; +	if (!bus) { +		ret = -EINVAL; +		goto out; +	}  	pr_debug("PCI: Removing PCI slot below EADS bridge %s\n",  		 bus->self ? pci_name(bus->self) : "<!PHB!>"); @@ -370,7 +375,8 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)  			printk(KERN_ERR  				"%s: unable to remove hotplug slot %s\n",  				__func__, drc_name); -			return -EIO; +			ret = -EIO; +			goto out;  		}  	} @@ -381,16 +387,18 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)  	if (pcibios_unmap_io_space(bus)) {  		printk(KERN_ERR "%s: failed to unmap bus range\n",  			__func__); -		return -ERANGE; +		ret = -ERANGE; +		goto out;  	}  	/* Remove the EADS bridge device itself */  	BUG_ON(!bus->self);  	pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self)); -	eeh_remove_bus_device(bus->self); -	pci_remove_bus_device(bus->self); +	pci_stop_and_remove_bus_device(bus->self); -	return 0; + out: +	pci_unlock_rescan_remove(); +	return ret;  }  /**  | 
