summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/agp/sgi-agp.c5
-rw-r--r--drivers/parisc/dino.c10
-rw-r--r--drivers/parisc/lba_pci.c7
-rw-r--r--drivers/pci/hotplug/Kconfig24
-rw-r--r--drivers/pci/hotplug/Makefile3
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c46
-rw-r--r--drivers/pci/hotplug/fakephp.c164
-rw-r--r--drivers/pci/hotplug/pciehp_core.c28
-rw-r--r--drivers/pci/pci.c40
-rw-r--r--drivers/pci/pcie/portdrv_core.c15
-rw-r--r--drivers/pci/proc.c19
-rw-r--r--drivers/pci/remove.c131
-rw-r--r--drivers/pci/rom.c59
-rw-r--r--drivers/pci/search.c61
-rw-r--r--drivers/pcmcia/cardbus.c15
15 files changed, 118 insertions, 509 deletions
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 19200037773..3a5af2f9b01 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -289,12 +289,11 @@ static int __devinit agp_sgi_init(void)
j = 0;
list_for_each_entry(info, &tioca_list, ca_list) {
- struct list_head *tmp;
if (list_empty(info->ca_devices))
continue;
- list_for_each(tmp, info->ca_devices) {
+ list_for_each_entry(pdev, info->ca_devices, bus_list) {
u8 cap_ptr;
- pdev = pci_dev_b(tmp);
+
if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
continue;
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index ffddc4f6426..fb6a1fe21b9 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -477,14 +477,12 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr)
if (ccio_allocate_resource(dino_dev->hba.dev, res, _8MB,
F_EXTEND(0xf0000000UL) | _8MB,
F_EXTEND(0xffffffffUL) &~ _8MB, _8MB) < 0) {
- struct list_head *ln, *tmp_ln;
+ struct pci_dev *dev, *tmp;
printk(KERN_ERR "Dino: cannot attach bus %s\n",
dev_name(bus->bridge));
/* kill the bus, we can't do anything with it */
- list_for_each_safe(ln, tmp_ln, &bus->devices) {
- struct pci_dev *dev = pci_dev_b(ln);
-
+ list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
list_del(&dev->bus_list);
}
@@ -549,7 +547,6 @@ dino_card_fixup(struct pci_dev *dev)
static void __init
dino_fixup_bus(struct pci_bus *bus)
{
- struct list_head *ln;
struct pci_dev *dev;
struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge));
@@ -596,8 +593,7 @@ dino_fixup_bus(struct pci_bus *bus)
}
- list_for_each(ln, &bus->devices) {
- dev = pci_dev_b(ln);
+ list_for_each_entry(dev, &bus->devices, bus_list) {
if (is_card_dino(&dino_dev->hba.dev->id))
dino_card_fixup(dev);
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 4f9cf2456f4..fdd63a6a62d 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -629,7 +629,7 @@ truncate_pat_collision(struct resource *root, struct resource *new)
static void
lba_fixup_bus(struct pci_bus *bus)
{
- struct list_head *ln;
+ struct pci_dev *dev;
#ifdef FBB_SUPPORT
u16 status;
#endif
@@ -710,9 +710,8 @@ lba_fixup_bus(struct pci_bus *bus)
}
- list_for_each(ln, &bus->devices) {
+ list_for_each_entry(dev, &bus->devices, bus_list) {
int i;
- struct pci_dev *dev = pci_dev_b(ln);
DBG("lba_fixup_bus() %s\n", pci_name(dev));
@@ -770,7 +769,7 @@ lba_fixup_bus(struct pci_bus *bus)
}
/* Lastly enable FBB/PERR/SERR on all devices too */
- list_for_each(ln, &bus->devices) {
+ list_for_each_entry(dev, &bus->devices, bus_list) {
(void) pci_read_config_word(dev, PCI_COMMAND, &status);
status |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR | fbb_enable;
(void) pci_write_config_word(dev, PCI_COMMAND, status);
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 66f29bc00be..b0e46dede1a 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -17,28 +17,6 @@ menuconfig HOTPLUG_PCI
if HOTPLUG_PCI
-config HOTPLUG_PCI_FAKE
- tristate "Fake PCI Hotplug driver"
- help
- Say Y here if you want to use the fake PCI hotplug driver. It can
- be used to simulate PCI hotplug events if even if your system is
- not PCI hotplug capable.
-
- This driver will "emulate" removing PCI devices from the system.
- If the "power" file is written to with "0" then the specified PCI
- device will be completely removed from the kernel.
-
- WARNING, this does NOT turn off the power to the PCI device.
- This is a "logical" removal, not a physical or electrical
- removal.
-
- Use this module at your own risk. You have been warned!
-
- To compile this driver as a module, choose M here: the
- module will be called fakephp.
-
- When in doubt, say N.
-
config HOTPLUG_PCI_COMPAQ
tristate "Compaq PCI Hotplug driver"
depends on X86 && PCI_BIOS
@@ -143,7 +121,7 @@ config HOTPLUG_PCI_SHPC
config HOTPLUG_PCI_RPA
tristate "RPA PCI Hotplug driver"
- depends on PPC_PSERIES && EEH && !HOTPLUG_PCI_FAKE
+ depends on PPC_PSERIES && EEH
help
Say Y here if you have a RPA system that supports PCI Hotplug.
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 6cd9f3c9887..c459cd4e39c 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -23,9 +23,6 @@ obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o
-# Link this last so it doesn't claim devices that have a real hotplug driver
-obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o
-
pci_hotplug-objs := pci_hotplug_core.o pcihp_slot.o
ifdef CONFIG_HOTPLUG_PCI_CPCI
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index ad6fd669549..7be4ca5e1f4 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -869,17 +869,6 @@ static int __ref enable_device(struct acpiphp_slot *slot)
return retval;
}
-static void disable_bridges(struct pci_bus *bus)
-{
- struct pci_dev *dev;
- list_for_each_entry(dev, &bus->devices, bus_list) {
- if (dev->subordinate) {
- disable_bridges(dev->subordinate);
- pci_disable_device(dev);
- }
- }
-}
-
/* return first device in slot, acquiring a reference on it */
static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
{
@@ -931,12 +920,7 @@ static int disable_device(struct acpiphp_slot *slot)
* here.
*/
while ((pdev = dev_in_slot(slot))) {
- pci_stop_bus_device(pdev);
- if (pdev->subordinate) {
- disable_bridges(pdev->subordinate);
- pci_disable_device(pdev);
- }
- __pci_remove_bus_device(pdev);
+ pci_stop_and_remove_bus_device(pdev);
pci_dev_put(pdev);
}
@@ -1477,34 +1461,6 @@ int __init acpiphp_get_num_slots(void)
}
-#if 0
-/**
- * acpiphp_for_each_slot - call function for each slot
- * @fn: callback function
- * @data: context to be passed to callback function
- */
-static int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
-{
- struct list_head *node;
- struct acpiphp_bridge *bridge;
- struct acpiphp_slot *slot;
- int retval = 0;
-
- list_for_each (node, &bridge_list) {
- bridge = (struct acpiphp_bridge *)node;
- for (slot = bridge->slots; slot; slot = slot->next) {
- retval = fn(slot, data);
- if (!retval)
- goto err_exit;
- }
- }
-
- err_exit:
- return retval;
-}
-#endif
-
-
/**
* acpiphp_enable_slot - power on slot
* @slot: ACPI PHP slot
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
deleted file mode 100644
index a019c9a712b..00000000000
--- a/drivers/pci/hotplug/fakephp.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/* Works like the fakephp driver used to, except a little better.
- *
- * - It's possible to remove devices with subordinate busses.
- * - New PCI devices that appear via any method, not just a fakephp triggered
- * rescan, will be noticed.
- * - Devices that are removed via any method, not just a fakephp triggered
- * removal, will also be noticed.
- *
- * Uses nothing from the pci-hotplug subsystem.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/list.h>
-#include <linux/kobject.h>
-#include <linux/sysfs.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-#include "../pci.h"
-
-struct legacy_slot {
- struct kobject kobj;
- struct pci_dev *dev;
- struct list_head list;
-};
-
-static LIST_HEAD(legacy_list);
-
-static ssize_t legacy_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct legacy_slot *slot = container_of(kobj, typeof(*slot), kobj);
- strcpy(buf, "1\n");
- return 2;
-}
-
-static void remove_callback(void *data)
-{
- pci_stop_and_remove_bus_device((struct pci_dev *)data);
-}
-
-static ssize_t legacy_store(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t len)
-{
- struct legacy_slot *slot = container_of(kobj, typeof(*slot), kobj);
- unsigned long val;
-
- if (strict_strtoul(buf, 0, &val) < 0)
- return -EINVAL;
-
- if (val)
- pci_rescan_bus(slot->dev->bus);
- else
- sysfs_schedule_callback(&slot->dev->dev.kobj, remove_callback,
- slot->dev, THIS_MODULE);
- return len;
-}
-
-static struct attribute *legacy_attrs[] = {
- &(struct attribute){ .name = "power", .mode = 0644 },
- NULL,
-};
-
-static void legacy_release(struct kobject *kobj)
-{
- struct legacy_slot *slot = container_of(kobj, typeof(*slot), kobj);
-
- pci_dev_put(slot->dev);
- kfree(slot);
-}
-
-static struct kobj_type legacy_ktype = {
- .sysfs_ops = &(const struct sysfs_ops){
- .store = legacy_store, .show = legacy_show
- },
- .release = &legacy_release,
- .default_attrs = legacy_attrs,
-};
-
-static int legacy_add_slot(struct pci_dev *pdev)
-{
- struct legacy_slot *slot = kzalloc(sizeof(*slot), GFP_KERNEL);
-
- if (!slot)
- return -ENOMEM;
-
- if (kobject_init_and_add(&slot->kobj, &legacy_ktype,
- &pci_slots_kset->kobj, "%s",
- dev_name(&pdev->dev))) {
- dev_warn(&pdev->dev, "Failed to created legacy fake slot\n");
- return -EINVAL;
- }
- slot->dev = pci_dev_get(pdev);
-
- list_add(&slot->list, &legacy_list);
-
- return 0;
-}
-
-static int legacy_notify(struct notifier_block *nb,
- unsigned long action, void *data)
-{
- struct pci_dev *pdev = to_pci_dev(data);
-
- if (action == BUS_NOTIFY_ADD_DEVICE) {
- legacy_add_slot(pdev);
- } else if (action == BUS_NOTIFY_DEL_DEVICE) {
- struct legacy_slot *slot;
-
- list_for_each_entry(slot, &legacy_list, list)
- if (slot->dev == pdev)
- goto found;
-
- dev_warn(&pdev->dev, "Missing legacy fake slot?");
- return -ENODEV;
-found:
- kobject_del(&slot->kobj);
- list_del(&slot->list);
- kobject_put(&slot->kobj);
- }
-
- return 0;
-}
-
-static struct notifier_block legacy_notifier = {
- .notifier_call = legacy_notify
-};
-
-static int __init init_legacy(void)
-{
- struct pci_dev *pdev = NULL;
-
- /* Add existing devices */
- for_each_pci_dev(pdev)
- legacy_add_slot(pdev);
-
- /* Be alerted of any new ones */
- bus_register_notifier(&pci_bus_type, &legacy_notifier);
- return 0;
-}
-module_init(init_legacy);
-
-static void __exit remove_legacy(void)
-{
- struct legacy_slot *slot, *tmp;
-
- bus_unregister_notifier(&pci_bus_type, &legacy_notifier);
-
- list_for_each_entry_safe(slot, tmp, &legacy_list, list) {
- list_del(&slot->list);
- kobject_del(&slot->kobj);
- kobject_put(&slot->kobj);
- }
-}
-module_exit(remove_legacy);
-
-
-MODULE_AUTHOR("Trent Piepho <xyzzy@speakeasy.org>");
-MODULE_DESCRIPTION("Legacy version of the fakephp interface");
-MODULE_LICENSE("GPL");
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 365c6b96c64..916bf4f53ab 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -300,24 +300,24 @@ static int pciehp_suspend (struct pcie_device *dev)
static int pciehp_resume (struct pcie_device *dev)
{
+ struct controller *ctrl;
+ struct slot *slot;
+ u8 status;
+
dev_info(&dev->device, "%s ENTRY\n", __func__);
- if (pciehp_force) {
- struct controller *ctrl = get_service_data(dev);
- struct slot *slot;
- u8 status;
+ ctrl = get_service_data(dev);
- /* reinitialize the chipset's event detection logic */
- pcie_enable_notification(ctrl);
+ /* reinitialize the chipset's event detection logic */
+ pcie_enable_notification(ctrl);
- slot = ctrl->slot;
+ slot = ctrl->slot;
- /* Check if slot is occupied */
- pciehp_get_adapter_status(slot, &status);
- if (status)
- pciehp_enable_slot(slot);
- else
- pciehp_disable_slot(slot);
- }
+ /* Check if slot is occupied */
+ pciehp_get_adapter_status(slot, &status);
+ if (status)
+ pciehp_enable_slot(slot);
+ else
+ pciehp_disable_slot(slot);
return 0;
}
#endif /* PM */
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index fac08f508d0..5ba60dd71fa 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -254,20 +254,17 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
}
/**
- * pci_find_ext_capability - Find an extended capability
+ * pci_find_next_ext_capability - Find an extended capability
* @dev: PCI device to query
+ * @start: address at which to start looking (0 to start at beginning of list)
* @cap: capability code
*
- * Returns the address of the requested extended capability structure
+ * Returns the address of the next matching extended capability structure
* within the device's PCI configuration space or 0 if the device does
- * not support it. Possible values for @cap:
- *
- * %PCI_EXT_CAP_ID_ERR Advanced Error Reporting
- * %PCI_EXT_CAP_ID_VC Virtual Channel
- * %PCI_EXT_CAP_ID_DSN Device Serial Number
- * %PCI_EXT_CAP_ID_PWR Power Budgeting
+ * not support it. Some capabilities can occur several times, e.g., the
+ * vendor-specific capability, and this provides a way to find them all.
*/
-int pci_find_ext_capability(struct pci_dev *dev, int cap)
+int pci_find_next_ext_capability(struct pci_dev *dev, int start, int cap)
{
u32 header;
int ttl;
@@ -279,6 +276,9 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
if (dev->cfg_size <= PCI_CFG_SPACE_SIZE)
return 0;
+ if (start)
+ pos = start;
+
if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL)
return 0;
@@ -290,7 +290,7 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
return 0;
while (ttl-- > 0) {
- if (PCI_EXT_CAP_ID(header) == cap)
+ if (PCI_EXT_CAP_ID(header) == cap && pos != start)
return pos;
pos = PCI_EXT_CAP_NEXT(header);
@@ -303,6 +303,26 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
return 0;
}
+EXPORT_SYMBOL_GPL(pci_find_next_ext_capability);
+
+/**
+ * pci_find_ext_capability - Find an extended capability
+ * @dev: PCI device to query
+ * @cap: capability code
+ *
+ * Returns the address of the requested extended capability structure
+ * within the device's PCI configuration space or 0 if the device does
+ * not support it. Possible values for @cap:
+ *
+ * %PCI_EXT_CAP_ID_ERR Advanced Error Reporting
+ * %PCI_EXT_CAP_ID_VC Virtual Channel
+ * %PCI_EXT_CAP_ID_DSN Device Serial Number
+ * %PCI_EXT_CAP_ID_PWR Power Budgeting
+ */
+int pci_find_ext_capability(struct pci_dev *dev, int cap)
+{
+ return pci_find_next_ext_capability(dev, 0, cap);
+}
EXPORT_SYMBOL_GPL(pci_find_ext_capability);
static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index aede99171e9..d03a7a39b2d 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -200,10 +200,13 @@ static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
{
int i, irq = -1;
- /* We have to use INTx if MSI cannot be used for PCIe PME or pciehp. */
+ /*
+ * If MSI cannot be used for PCIe PME or hotplug, we have to use
+ * INTx or other interrupts, e.g. system shared interrupt.
+ */
if (((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi()) ||
((mask & PCIE_PORT_SERVICE_HP) && pciehp_no_msi())) {
- if (dev->pin)
+ if (dev->irq)
irq = dev->irq;
goto no_msi;
}
@@ -212,8 +215,12 @@ static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
if (!pcie_port_enable_msix(dev, irqs, mask))
return 0;
- /* We're not going to use MSI-X, so try MSI and fall back to INTx */
- if (!pci_enable_msi(dev) || dev->pin)
+ /*
+ * We're not going to use MSI-X, so try MSI and fall back to INTx.
+ * If neither MSI/MSI-X nor INTx available, try other interrupt. On
+ * some platforms, root port doesn't support MSI/MSI-X/INTx in RC mode.
+ */
+ if (!pci_enable_msi(dev) || dev->irq)
irq = dev->irq;
no_msi:
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 27911b55c2a..eb907a8faf2 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -434,25 +434,6 @@ int pci_proc_detach_device(struct pci_dev *dev)
return 0;
}
-#if 0
-int pci_proc_attach_bus(struct pci_bus* bus)
-{
- struct proc_dir_entry *de = bus->procdir;
-
- if (!proc_initialized)
- return -EACCES;
-
- if (!de) {
- char name[16];
- sprintf(name, "%02x", bus->number);
- de = bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
- if (!de)
- return -ENOMEM;
- }
- return 0;
-}
-#endif /* 0 */
-
int pci_proc_detach_bus(struct pci_bus* bus)
{
struct proc_dir_entry *de = bus->procdir;
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 04a4861b474..4f9ca916289 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -32,53 +32,30 @@ static void pci_stop_dev(struct pci_dev *dev)
static void pci_destroy_dev(struct pci_dev *dev)
{
- /* Remove the device from the device lists, and prevent any further
- * list accesses from this device */
down_write(&pci_bus_sem);
list_del(&dev->bus_list);
- dev->bus_list.next = dev->bus_list.prev = NULL;
up_write(&pci_bus_sem);
pci_free_resources(dev);
pci_dev_put(dev);
}
-/**
- * pci_remove_device_safe - remove an unused hotplug device
- * @dev: the device to remove
- *
- * Delete the device structure from the device lists and
- * notify userspace (/sbin/hotplug), but only if the device
- * in question is not being used by a driver.
- * Returns 0 on success.
- */
-#if 0
-int pci_remove_device_safe(struct pci_dev *dev)
+void pci_remove_bus(struct pci_bus *bus)
{
- if (pci_dev_driver(dev))
- return -EBUSY;
- pci_destroy_dev(dev);
- return 0;
-}
-#endif /* 0 */
-
-void pci_remove_bus(struct pci_bus *pci_bus)
-{
- pci_proc_detach_bus(pci_bus);
+ pci_proc_detach_bus(bus);
down_write(&pci_bus_sem);
- list_del(&pci_bus->node);
- pci_bus_release_busn_res(pci_bus);
+ list_del(&bus->node);
+ pci_bus_release_busn_res(bus);
up_write(&pci_bus_sem);
- if (!pci_bus->is_added)
+ if (!bus->is_added)
return;
- pci_remove_legacy_files(pci_bus);
- device_unregister(&pci_bus->dev);
+ pci_remove_legacy_files(bus);
+ device_unregister(&bus->dev);
}
EXPORT_SYMBOL(pci_remove_bus);
-static void __pci_remove_behind_bridge(struct pci_dev *dev);
/**
* pci_stop_and_remove_bus_device - remove a PCI device and any children
* @dev: the device to remove
@@ -91,93 +68,27 @@ static void __pci_remove_behind_bridge(struct pci_dev *dev);
* device lists, remove the /proc entry, and notify userspace
* (/sbin/hotplug).
*/
-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_bus(b);
- dev->subordinate = NULL;
- }
-
- pci_destroy_dev(dev);
-}
-EXPORT_SYMBOL(__pci_remove_bus_device);
-
void pci_stop_and_remove_bus_device(struct pci_dev *dev)
{
- pci_stop_bus_device(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_stop_and_remove_behind_bridge - stop and remove all devices behind
- * a PCI bridge
- * @dev: PCI bridge device
- *
- * Remove all devices on the bus, except for the parent bridge.
- * This also removes any child buses, and any devices they may
- * contain in a depth-first manner.
- */
-void pci_stop_and_remove_behind_bridge(struct pci_dev *dev)
-{
- pci_stop_behind_bridge(dev);
- __pci_remove_behind_bridge(dev);
-}
-
-static void pci_stop_bus_devices(struct pci_bus *bus)
-{
- struct list_head *l, *n;
+ struct pci_bus *bus = dev->subordinate;
+ struct pci_dev *child, *tmp;
/*
- * VFs could be removed by pci_stop_and_remove_bus_device() in the
- * pci_stop_bus_devices() code path for PF.
- * aka, bus->devices get updated in the process.
- * but VFs are inserted after PFs when SRIOV is enabled for PF,
- * We can iterate the list backwards to get prev valid PF instead
- * of removed VF.
+ * Removing an SR-IOV PF device removes all the associated VFs,
+ * which will update the bus->devices list and confuse the
+ * iterator. Therefore, iterate in reverse so we remove the VFs
+ * first, then the PF.
*/
- list_for_each_prev_safe(l, n, &bus->devices) {
- struct pci_dev *dev = pci_dev_b(l);
- pci_stop_bus_device(dev);
- }
-}
+ if (bus) {
+ list_for_each_entry_safe_reverse(child, tmp,
+ &bus->devices, bus_list)
+ pci_stop_and_remove_bus_device(child);
-/**
- * pci_stop_bus_device - stop a PCI device and any children
- * @dev: the device to stop
- *
- * Stop a PCI device (detach the driver, remove from the global list
- * and so on). This also stop any subordinate buses and children in a
- * depth-first manner.
- */
-void pci_stop_bus_device(struct pci_dev *dev)
-{
- if (dev->subordinate)
- pci_stop_bus_devices(dev->subordinate);
+ pci_remove_bus(bus);
+ dev->subordinate = NULL;
+ }
pci_stop_dev(dev);
+ pci_destroy_dev(dev);
}
-
EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
-EXPORT_SYMBOL(pci_stop_and_remove_behind_bridge);
-EXPORT_SYMBOL_GPL(pci_stop_bus_device);
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index 48ebdb237f3..0b3037ab8b9 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -167,44 +167,6 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
return rom;
}
-#if 0
-/**
- * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy
- * @pdev: pointer to pci device struct
- * @size: pointer to receive size of pci window over ROM
- *
- * Return: kernel virtual pointer to image of ROM
- *
- * Map a PCI ROM into kernel space. If ROM is boot video ROM,
- * the shadow BIOS copy will be returned instead of the
- * actual ROM.
- */
-void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size)
-{
- struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
- void __iomem *rom;
-
- rom = pci_map_rom(pdev, size);
- if (!rom)
- return NULL;
-
- if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW |
- IORESOURCE_ROM_BIOS_COPY))
- return rom;
-
- res->start = (unsigned long)kmalloc(*size, GFP_KERNEL);
- if (!res->start)
- return rom;
-
- res->end = res->start + *size;
- memcpy_fromio((void*)(unsigned long)res->start, rom, *size);
- pci_unmap_rom(pdev, rom);
- res->flags |= IORESOURCE_ROM_COPY;
-
- return (void __iomem *)(unsigned long)res->start;
-}
-#endif /* 0 */
-
/**
* pci_unmap_rom - unmap the ROM from kernel space
* @pdev: pointer to pci device struct
@@ -226,27 +188,6 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
pci_disable_rom(pdev);
}
-#if 0
-/**
- * pci_remove_rom - disable the ROM and remove its sysfs attribute
- * @pdev: pointer to pci device struct
- *
- * Remove the rom file in sysfs and disable ROM decoding.
- */
-void pci_remove_rom(struct pci_dev *pdev)
-{
- struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
-
- if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
- sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
- if (!(res->flags & (IORESOURCE_ROM_ENABLE |
- IORESOURCE_ROM_SHADOW |
- IORESOURCE_ROM_BIOS_COPY |
- IORESOURCE_ROM_COPY)))
- pci_disable_rom(pdev);
-}
-#endif /* 0 */
-
/**
* pci_cleanup_rom - free the ROM copy created by pci_map_rom_copy
* @pdev: pointer to pci device struct
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 621b162ceb6..bf969ba58e5 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -130,16 +130,14 @@ pci_find_next_bus(const struct pci_bus *from)
* decrement the reference count by calling pci_dev_put().
* If no device is found, %NULL is returned.
*/
-struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn)
+struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn)
{
- struct list_head *tmp;
struct pci_dev *dev;
WARN_ON(in_interrupt());
down_read(&pci_bus_sem);
- list_for_each(tmp, &bus->devices) {
- dev = pci_dev_b(tmp);
+ list_for_each_entry(dev, &bus->devices, bus_list) {
if (dev->devfn == devfn)
goto out;
}
@@ -245,30 +243,14 @@ struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
unsigned int ss_vendor, unsigned int ss_device,
struct pci_dev *from)
{
- struct pci_dev *pdev;
- struct pci_device_id *id;
-
- /*
- * pci_find_subsys() can be called on the ide_setup() path,
- * super-early in boot. But the down_read() will enable local
- * interrupts, which can cause some machines to crash. So here we
- * detect and flag that situation and bail out early.
- */
- if (unlikely(no_pci_devices()))
- return NULL;
-
- id = kzalloc(sizeof(*id), GFP_KERNEL);
- if (!id)
- return NULL;
- id->vendor = vendor;
- id->device = device;
- id->subvendor = ss_vendor;
- id->subdevice = ss_device;
-
- pdev = pci_get_dev_by_id(id, from);
- kfree(id);
-
- return pdev;
+ struct pci_device_id id = {
+ .vendor = vendor,
+ .device = device,
+ .subvendor = ss_vendor,
+ .subdevice = ss_device,
+ };
+
+ return pci_get_dev_by_id(&id, from);
}
/**
@@ -307,19 +289,16 @@ pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
*/
struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
{
- struct pci_dev *dev;
- struct pci_device_id *id;
-
- id = kzalloc(sizeof(*id), GFP_KERNEL);
- if (!id)
- return NULL;
- id->vendor = id->device = id->subvendor = id->subdevice = PCI_ANY_ID;
- id->class_mask = PCI_ANY_ID;
- id->class = class;
-
- dev = pci_get_dev_by_id(id, from);
- kfree(id);
- return dev;
+ struct pci_device_id id = {
+ .vendor = PCI_ANY_ID,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class_mask = PCI_ANY_ID,
+ .class = class,
+ };
+
+ return pci_get_dev_by_id(&id, from);
}
/**
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index 24caeaf5052..9d3ac998fc1 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -105,8 +105,17 @@ int __ref cb_alloc(struct pcmcia_socket *s)
*/
void cb_free(struct pcmcia_socket *s)
{
- struct pci_dev *bridge = s->cb_dev;
+ struct pci_dev *bridge, *dev, *tmp;
+ struct pci_bus *bus;
- if (bridge)
- pci_stop_and_remove_behind_bridge(bridge);
+ bridge = s->cb_dev;
+ if (!bridge)
+ return;
+
+ bus = bridge->subordinate;
+ if (!bus)
+ return;
+
+ list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list)
+ pci_stop_and_remove_bus_device(dev);
}