mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	Merge branch 'pci/bjorn-cleanup-remove' into next
* pci/bjorn-cleanup-remove: PCI: Remove unused pci_dev_b() sgi-agp: Use list_for_each_entry() for bus->devices traversal parisc/PCI: Use list_for_each_entry() for bus->devices traversal parisc/PCI: Enable PERR/SERR on all devices frv/PCI: Use list_for_each_entry() for bus->devices traversal PCI: Leave normal LIST_POISON in deleted list entries PCI: Rename local variables to conventional names PCI: Remove unused, commented-out, code PCI: Stop and remove devices in one pass PCI: Fold stop and remove helpers into their callers PCI: Use list_for_each_entry() for bus->devices traversal PCI: Remove pci_stop_and_remove_behind_bridge() PCI: Don't export stop_bus_device and remove_bus_device interfaces pcmcia: Use common pci_stop_and_remove_bus_device() PCI: acpiphp: Use common pci_stop_and_remove_bus_device() PCI: acpiphp: Stop disabling bridges on remove
This commit is contained in:
		
						commit
						7bf79d8a99
					
				
					 11 changed files with 47 additions and 263 deletions
				
			
		| 
						 | 
					@ -330,10 +330,8 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
 | 
				
			||||||
	pci_read_bridge_bases(bus);
 | 
						pci_read_bridge_bases(bus);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (bus->number == 0) {
 | 
						if (bus->number == 0) {
 | 
				
			||||||
		struct list_head *ln;
 | 
					 | 
				
			||||||
		struct pci_dev *dev;
 | 
							struct pci_dev *dev;
 | 
				
			||||||
		for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
 | 
							list_for_each_entry(dev, &bus->devices, bus_list) {
 | 
				
			||||||
			dev = pci_dev_b(ln);
 | 
					 | 
				
			||||||
			if (dev->devfn == 0) {
 | 
								if (dev->devfn == 0) {
 | 
				
			||||||
				dev->resource[0].start = 0;
 | 
									dev->resource[0].start = 0;
 | 
				
			||||||
				dev->resource[0].end = 0;
 | 
									dev->resource[0].end = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -289,12 +289,11 @@ static int __devinit agp_sgi_init(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	j = 0;
 | 
						j = 0;
 | 
				
			||||||
	list_for_each_entry(info, &tioca_list, ca_list) {
 | 
						list_for_each_entry(info, &tioca_list, ca_list) {
 | 
				
			||||||
		struct list_head *tmp;
 | 
					 | 
				
			||||||
		if (list_empty(info->ca_devices))
 | 
							if (list_empty(info->ca_devices))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		list_for_each(tmp, info->ca_devices) {
 | 
							list_for_each_entry(pdev, info->ca_devices, bus_list) {
 | 
				
			||||||
			u8 cap_ptr;
 | 
								u8 cap_ptr;
 | 
				
			||||||
			pdev = pci_dev_b(tmp);
 | 
					
 | 
				
			||||||
			if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
 | 
								if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
 | 
								cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,
 | 
						if (ccio_allocate_resource(dino_dev->hba.dev, res, _8MB,
 | 
				
			||||||
				F_EXTEND(0xf0000000UL) | _8MB,
 | 
									F_EXTEND(0xf0000000UL) | _8MB,
 | 
				
			||||||
				F_EXTEND(0xffffffffUL) &~ _8MB, _8MB) < 0) {
 | 
									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",
 | 
							printk(KERN_ERR "Dino: cannot attach bus %s\n",
 | 
				
			||||||
		       dev_name(bus->bridge));
 | 
							       dev_name(bus->bridge));
 | 
				
			||||||
		/* kill the bus, we can't do anything with it */
 | 
							/* kill the bus, we can't do anything with it */
 | 
				
			||||||
		list_for_each_safe(ln, tmp_ln, &bus->devices) {
 | 
							list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
 | 
				
			||||||
			struct pci_dev *dev = pci_dev_b(ln);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			list_del(&dev->bus_list);
 | 
								list_del(&dev->bus_list);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
| 
						 | 
					@ -549,7 +547,6 @@ dino_card_fixup(struct pci_dev *dev)
 | 
				
			||||||
static void __init
 | 
					static void __init
 | 
				
			||||||
dino_fixup_bus(struct pci_bus *bus)
 | 
					dino_fixup_bus(struct pci_bus *bus)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct list_head *ln;
 | 
					 | 
				
			||||||
        struct pci_dev *dev;
 | 
					        struct pci_dev *dev;
 | 
				
			||||||
        struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge));
 | 
					        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) {
 | 
						list_for_each_entry(dev, &bus->devices, bus_list) {
 | 
				
			||||||
		dev = pci_dev_b(ln);
 | 
					 | 
				
			||||||
		if (is_card_dino(&dino_dev->hba.dev->id))
 | 
							if (is_card_dino(&dino_dev->hba.dev->id))
 | 
				
			||||||
			dino_card_fixup(dev);
 | 
								dino_card_fixup(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -629,7 +629,7 @@ truncate_pat_collision(struct resource *root, struct resource *new)
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
lba_fixup_bus(struct pci_bus *bus)
 | 
					lba_fixup_bus(struct pci_bus *bus)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct list_head *ln;
 | 
						struct pci_dev *dev;
 | 
				
			||||||
#ifdef FBB_SUPPORT
 | 
					#ifdef FBB_SUPPORT
 | 
				
			||||||
	u16 status;
 | 
						u16 status;
 | 
				
			||||||
#endif
 | 
					#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;
 | 
							int i;
 | 
				
			||||||
		struct pci_dev *dev = pci_dev_b(ln);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		DBG("lba_fixup_bus() %s\n", pci_name(dev));
 | 
							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 */
 | 
						/* 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);
 | 
							(void) pci_read_config_word(dev, PCI_COMMAND, &status);
 | 
				
			||||||
		status |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR | fbb_enable;
 | 
							status |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR | fbb_enable;
 | 
				
			||||||
		(void) pci_write_config_word(dev, PCI_COMMAND, status);
 | 
							(void) pci_write_config_word(dev, PCI_COMMAND, status);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -869,17 +869,6 @@ static int __ref enable_device(struct acpiphp_slot *slot)
 | 
				
			||||||
	return retval;
 | 
						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 */
 | 
					/* return first device in slot, acquiring a reference on it */
 | 
				
			||||||
static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
 | 
					static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -931,12 +920,7 @@ static int disable_device(struct acpiphp_slot *slot)
 | 
				
			||||||
	 * here.
 | 
						 * here.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	while ((pdev = dev_in_slot(slot))) {
 | 
						while ((pdev = dev_in_slot(slot))) {
 | 
				
			||||||
		pci_stop_bus_device(pdev);
 | 
							pci_stop_and_remove_bus_device(pdev);
 | 
				
			||||||
		if (pdev->subordinate) {
 | 
					 | 
				
			||||||
			disable_bridges(pdev->subordinate);
 | 
					 | 
				
			||||||
			pci_disable_device(pdev);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		__pci_remove_bus_device(pdev);
 | 
					 | 
				
			||||||
		pci_dev_put(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
 | 
					 * acpiphp_enable_slot - power on slot
 | 
				
			||||||
 * @slot: ACPI PHP slot
 | 
					 * @slot: ACPI PHP slot
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -434,25 +434,6 @@ int pci_proc_detach_device(struct pci_dev *dev)
 | 
				
			||||||
	return 0;
 | 
						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)
 | 
					int pci_proc_detach_bus(struct pci_bus* bus)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct proc_dir_entry *de = bus->procdir;
 | 
						struct proc_dir_entry *de = bus->procdir;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,53 +32,30 @@ static void pci_stop_dev(struct pci_dev *dev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pci_destroy_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);
 | 
						down_write(&pci_bus_sem);
 | 
				
			||||||
	list_del(&dev->bus_list);
 | 
						list_del(&dev->bus_list);
 | 
				
			||||||
	dev->bus_list.next = dev->bus_list.prev = NULL;
 | 
					 | 
				
			||||||
	up_write(&pci_bus_sem);
 | 
						up_write(&pci_bus_sem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pci_free_resources(dev);
 | 
						pci_free_resources(dev);
 | 
				
			||||||
	pci_dev_put(dev);
 | 
						pci_dev_put(dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					void pci_remove_bus(struct pci_bus *bus)
 | 
				
			||||||
 * 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)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (pci_dev_driver(dev))
 | 
						pci_proc_detach_bus(bus);
 | 
				
			||||||
		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);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	down_write(&pci_bus_sem);
 | 
						down_write(&pci_bus_sem);
 | 
				
			||||||
	list_del(&pci_bus->node);
 | 
						list_del(&bus->node);
 | 
				
			||||||
	pci_bus_release_busn_res(pci_bus);
 | 
						pci_bus_release_busn_res(bus);
 | 
				
			||||||
	up_write(&pci_bus_sem);
 | 
						up_write(&pci_bus_sem);
 | 
				
			||||||
	if (!pci_bus->is_added)
 | 
						if (!bus->is_added)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pci_remove_legacy_files(pci_bus);
 | 
						pci_remove_legacy_files(bus);
 | 
				
			||||||
	device_unregister(&pci_bus->dev);
 | 
						device_unregister(&bus->dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(pci_remove_bus);
 | 
					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
 | 
					 * pci_stop_and_remove_bus_device - remove a PCI device and any children
 | 
				
			||||||
 * @dev: the device to remove
 | 
					 * @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
 | 
					 * device lists, remove the /proc entry, and notify userspace
 | 
				
			||||||
 * (/sbin/hotplug).
 | 
					 * (/sbin/hotplug).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void __pci_remove_bus_device(struct pci_dev *dev)
 | 
					void pci_stop_and_remove_bus_device(struct pci_dev *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (dev->subordinate) {
 | 
						struct pci_bus *bus = dev->subordinate;
 | 
				
			||||||
		struct pci_bus *b = dev->subordinate;
 | 
						struct pci_dev *child, *tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		__pci_remove_behind_bridge(dev);
 | 
						/*
 | 
				
			||||||
		pci_remove_bus(b);
 | 
						 * 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.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (bus) {
 | 
				
			||||||
 | 
							list_for_each_entry_safe_reverse(child, tmp,
 | 
				
			||||||
 | 
											 &bus->devices, bus_list)
 | 
				
			||||||
 | 
								pci_stop_and_remove_bus_device(child);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pci_remove_bus(bus);
 | 
				
			||||||
		dev->subordinate = NULL;
 | 
							dev->subordinate = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pci_stop_dev(dev);
 | 
				
			||||||
	pci_destroy_dev(dev);
 | 
						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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * 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.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	list_for_each_prev_safe(l, n, &bus->devices) {
 | 
					 | 
				
			||||||
		struct pci_dev *dev = pci_dev_b(l);
 | 
					 | 
				
			||||||
		pci_stop_bus_device(dev);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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_stop_dev(dev);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
 | 
					EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
 | 
				
			||||||
EXPORT_SYMBOL(pci_stop_and_remove_behind_bridge);
 | 
					 | 
				
			||||||
EXPORT_SYMBOL_GPL(pci_stop_bus_device);
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -167,44 +167,6 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
 | 
				
			||||||
	return rom;
 | 
						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
 | 
					 * pci_unmap_rom - unmap the ROM from kernel space
 | 
				
			||||||
 * @pdev: pointer to pci device struct
 | 
					 * @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);
 | 
							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
 | 
					 * pci_cleanup_rom - free the ROM copy created by pci_map_rom_copy
 | 
				
			||||||
 * @pdev: pointer to pci device struct
 | 
					 * @pdev: pointer to pci device struct
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -130,16 +130,14 @@ pci_find_next_bus(const struct pci_bus *from)
 | 
				
			||||||
 * decrement the reference count by calling pci_dev_put().
 | 
					 * decrement the reference count by calling pci_dev_put().
 | 
				
			||||||
 * If no device is found, %NULL is returned.
 | 
					 * 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;
 | 
						struct pci_dev *dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	WARN_ON(in_interrupt());
 | 
						WARN_ON(in_interrupt());
 | 
				
			||||||
	down_read(&pci_bus_sem);
 | 
						down_read(&pci_bus_sem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each(tmp, &bus->devices) {
 | 
						list_for_each_entry(dev, &bus->devices, bus_list) {
 | 
				
			||||||
		dev = pci_dev_b(tmp);
 | 
					 | 
				
			||||||
		if (dev->devfn == devfn)
 | 
							if (dev->devfn == devfn)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,8 +105,17 @@ int __ref cb_alloc(struct pcmcia_socket *s)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void cb_free(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)
 | 
						bridge = s->cb_dev;
 | 
				
			||||||
		pci_stop_and_remove_behind_bridge(bridge);
 | 
						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);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -369,7 +369,6 @@ static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern struct pci_dev *alloc_pci_dev(void);
 | 
					extern struct pci_dev *alloc_pci_dev(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list)
 | 
					 | 
				
			||||||
#define	to_pci_dev(n) container_of(n, struct pci_dev, dev)
 | 
					#define	to_pci_dev(n) container_of(n, struct pci_dev, dev)
 | 
				
			||||||
#define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
 | 
					#define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -734,9 +733,7 @@ u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp);
 | 
				
			||||||
extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
 | 
					extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
 | 
				
			||||||
extern void pci_dev_put(struct pci_dev *dev);
 | 
					extern void pci_dev_put(struct pci_dev *dev);
 | 
				
			||||||
extern void pci_remove_bus(struct pci_bus *b);
 | 
					extern void pci_remove_bus(struct pci_bus *b);
 | 
				
			||||||
extern void __pci_remove_bus_device(struct pci_dev *dev);
 | 
					 | 
				
			||||||
extern void pci_stop_and_remove_bus_device(struct pci_dev *dev);
 | 
					extern void pci_stop_and_remove_bus_device(struct pci_dev *dev);
 | 
				
			||||||
extern void pci_stop_bus_device(struct pci_dev *dev);
 | 
					 | 
				
			||||||
void pci_setup_cardbus(struct pci_bus *bus);
 | 
					void pci_setup_cardbus(struct pci_bus *bus);
 | 
				
			||||||
extern void pci_sort_breadthfirst(void);
 | 
					extern void pci_sort_breadthfirst(void);
 | 
				
			||||||
#define dev_is_pci(d) ((d)->bus == &pci_bus_type)
 | 
					#define dev_is_pci(d) ((d)->bus == &pci_bus_type)
 | 
				
			||||||
| 
						 | 
					@ -1047,7 +1044,6 @@ void pci_unregister_driver(struct pci_driver *dev);
 | 
				
			||||||
	module_driver(__pci_driver, pci_register_driver, \
 | 
						module_driver(__pci_driver, pci_register_driver, \
 | 
				
			||||||
		       pci_unregister_driver)
 | 
							       pci_unregister_driver)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pci_stop_and_remove_behind_bridge(struct pci_dev *dev);
 | 
					 | 
				
			||||||
struct pci_driver *pci_dev_driver(const struct pci_dev *dev);
 | 
					struct pci_driver *pci_dev_driver(const struct pci_dev *dev);
 | 
				
			||||||
int pci_add_dynid(struct pci_driver *drv,
 | 
					int pci_add_dynid(struct pci_driver *drv,
 | 
				
			||||||
		  unsigned int vendor, unsigned int device,
 | 
							  unsigned int vendor, unsigned int device,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue