diff options
Diffstat (limited to 'drivers/pci/hotplug/pciehp_pci.c')
| -rw-r--r-- | drivers/pci/hotplug/pciehp_pci.c | 31 | 
1 files changed, 18 insertions, 13 deletions
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 0e0d0f7f63f..5f871f4c4af 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -39,27 +39,29 @@ int pciehp_configure_device(struct slot *p_slot)  	struct pci_dev *dev;  	struct pci_dev *bridge = p_slot->ctrl->pcie->port;  	struct pci_bus *parent = bridge->subordinate; -	int num; +	int num, ret = 0;  	struct controller *ctrl = p_slot->ctrl; +	pci_lock_rescan_remove(); +  	dev = pci_get_slot(parent, PCI_DEVFN(0, 0));  	if (dev) { -		ctrl_err(ctrl, "Device %s already exists " -			 "at %04x:%02x:00, cannot hot-add\n", pci_name(dev), -			 pci_domain_nr(parent), parent->number); +		ctrl_err(ctrl, "Device %s already exists at %04x:%02x:00, cannot hot-add\n", +			 pci_name(dev), pci_domain_nr(parent), parent->number);  		pci_dev_put(dev); -		return -EINVAL; +		ret = -EEXIST; +		goto out;  	}  	num = pci_scan_slot(parent, PCI_DEVFN(0, 0));  	if (num == 0) {  		ctrl_err(ctrl, "No new device found\n"); -		return -ENODEV; +		ret = -ENODEV; +		goto out;  	}  	list_for_each_entry(dev, &parent->devices, bus_list) -		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || -				(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) +		if (pci_is_bridge(dev))  			pci_hp_add_bridge(dev);  	pci_assign_unassigned_bridge_resources(bridge); @@ -73,12 +75,14 @@ int pciehp_configure_device(struct slot *p_slot)  	pci_bus_add_devices(parent); -	return 0; + out: +	pci_unlock_rescan_remove(); +	return ret;  }  int pciehp_unconfigure_device(struct slot *p_slot)  { -	int ret, rc = 0; +	int rc = 0;  	u8 bctl = 0;  	u8 presence = 0;  	struct pci_dev *dev, *temp; @@ -88,9 +92,9 @@ int pciehp_unconfigure_device(struct slot *p_slot)  	ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:00\n",  		 __func__, pci_domain_nr(parent), parent->number); -	ret = pciehp_get_adapter_status(p_slot, &presence); -	if (ret) -		presence = 0; +	pciehp_get_adapter_status(p_slot, &presence); + +	pci_lock_rescan_remove();  	/*  	 * Stopping an SR-IOV PF device removes all the associated VFs, @@ -126,5 +130,6 @@ int pciehp_unconfigure_device(struct slot *p_slot)  		pci_dev_put(dev);  	} +	pci_unlock_rescan_remove();  	return rc;  }  | 
