mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-11 16:29:05 +00:00
PCI: Fix pci cardbus removal
During test busn_res allocation with cardbus, found pci card removal is not working anymore, and it turns out it is broken by: |commit 79cc9601c3e42b4f0650fe7e69132ebce7ab48f9 |Date: Tue Nov 22 21:06:53 2011 -0800 | | PCI: Only call pci_stop_bus_device() one time for child devices at remove The above changed the behavior of pci_remove_behind_bridge that yenta_cardbus depended on. So restore the old behavoir of pci_remove_behind_bridge (which requires stopping and removing of all devices) by: 1. rename pci_remove_behind_bridge to __pci_remove_behind_bridge, and let __pci_remove_bus_device() call it instead. 2. add pci_stop_behind_bridge that will stop devices behind a bridge 3. add back pci_remove_behind_bridge that will stop and remove devices under bridge. -v2: update commit description a little bit. Tested-by: Dominik Brodowski <linux@dominikbrodowski.net> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
parent
8161fe91d8
commit
3682a3946d
@ -77,6 +77,7 @@ void pci_remove_bus(struct pci_bus *pci_bus)
|
||||
}
|
||||
EXPORT_SYMBOL(pci_remove_bus);
|
||||
|
||||
static void __pci_remove_behind_bridge(struct pci_dev *dev);
|
||||
/**
|
||||
* pci_remove_bus_device - remove a PCI device and any children
|
||||
* @dev: the device to remove
|
||||
@ -94,7 +95,7 @@ static void __pci_remove_bus_device(struct pci_dev *dev)
|
||||
if (dev->subordinate) {
|
||||
struct pci_bus *b = dev->subordinate;
|
||||
|
||||
pci_remove_behind_bridge(dev);
|
||||
__pci_remove_behind_bridge(dev);
|
||||
pci_remove_bus(b);
|
||||
dev->subordinate = NULL;
|
||||
}
|
||||
@ -107,6 +108,24 @@ void pci_remove_bus_device(struct pci_dev *dev)
|
||||
__pci_remove_bus_device(dev);
|
||||
}
|
||||
|
||||
static void __pci_remove_behind_bridge(struct pci_dev *dev)
|
||||
{
|
||||
struct list_head *l, *n;
|
||||
|
||||
if (dev->subordinate)
|
||||
list_for_each_safe(l, n, &dev->subordinate->devices)
|
||||
__pci_remove_bus_device(pci_dev_b(l));
|
||||
}
|
||||
|
||||
static void pci_stop_behind_bridge(struct pci_dev *dev)
|
||||
{
|
||||
struct list_head *l, *n;
|
||||
|
||||
if (dev->subordinate)
|
||||
list_for_each_safe(l, n, &dev->subordinate->devices)
|
||||
pci_stop_bus_device(pci_dev_b(l));
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_remove_behind_bridge - remove all devices behind a PCI bridge
|
||||
* @dev: PCI bridge device
|
||||
@ -117,11 +136,8 @@ void pci_remove_bus_device(struct pci_dev *dev)
|
||||
*/
|
||||
void pci_remove_behind_bridge(struct pci_dev *dev)
|
||||
{
|
||||
struct list_head *l, *n;
|
||||
|
||||
if (dev->subordinate)
|
||||
list_for_each_safe(l, n, &dev->subordinate->devices)
|
||||
__pci_remove_bus_device(pci_dev_b(l));
|
||||
pci_stop_behind_bridge(dev);
|
||||
__pci_remove_behind_bridge(dev);
|
||||
}
|
||||
|
||||
static void pci_stop_bus_devices(struct pci_bus *bus)
|
||||
|
Loading…
x
Reference in New Issue
Block a user