X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fpci%2Fsearch.c;h=6dae871432588e29f93b86e7a2565856cc36ab99;hb=50d9c84ee522ce6f61cd6a7dfce1b82a260edd3c;hp=1aabe3dbc7c3c6cf4495b7eeebe9a2be5cbfd1be;hpb=448432c4b8e2e3189177d6dbd16b8a8d83c5c11c;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 1aabe3d..6dae871 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -26,14 +26,14 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev) { struct pci_dev *tmp = NULL; - if (pdev->is_pcie) + if (pci_is_pcie(pdev)) return NULL; while (1) { - if (!pdev->bus->self) + if (pci_is_root_bus(pdev->bus)) break; pdev = pdev->bus->self; /* a p2p bridge */ - if (!pdev->is_pcie) { + if (!pci_is_pcie(pdev)) { tmp = pdev; continue; } @@ -113,34 +113,6 @@ pci_find_next_bus(const struct pci_bus *from) return b; } -#ifdef CONFIG_PCI_LEGACY - -/** - * pci_find_slot - locate PCI device from a given PCI slot - * @bus: number of PCI bus on which desired PCI device resides - * @devfn: encodes number of PCI slot in which the desired PCI - * device resides and the logical device number within that slot - * in case of multi-function devices. - * - * Given a PCI bus and slot/function number, the desired PCI device - * is located in system global list of PCI devices. If the device - * is found, a pointer to its data structure is returned. If no - * device is found, %NULL is returned. - */ -struct pci_dev * -pci_find_slot(unsigned int bus, unsigned int devfn) -{ - struct pci_dev *dev = NULL; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (dev->bus->number == bus && dev->devfn == devfn) - return dev; - } - return NULL; -} - -#endif /* CONFIG_PCI_LEGACY */ - /** * pci_get_slot - locate PCI device for a given PCI slot * @bus: PCI bus on which desired PCI device resides @@ -177,113 +149,78 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) } /** - * pci_get_bus_and_slot - locate PCI device from a given PCI bus & slot - * @bus: number of PCI bus on which desired PCI device resides - * @devfn: encodes number of PCI slot in which the desired PCI - * device resides and the logical device number within that slot - * in case of multi-function devices. - * - * Note: the bus/slot search is limited to PCI domain (segment) 0. + * pci_get_domain_bus_and_slot - locate PCI device for a given PCI domain (segment), bus, and slot + * @domain: PCI domain/segment on which the PCI device resides. + * @bus: PCI bus on which desired PCI device resides + * @devfn: encodes number of PCI slot in which the desired PCI device + * resides and the logical device number within that slot in case of + * multi-function devices. * - * Given a PCI bus and slot/function number, the desired PCI device - * is located in system global list of PCI devices. If the device - * is found, a pointer to its data structure is returned. If no - * device is found, %NULL is returned. The returned device has its - * reference count bumped by one. + * Given a PCI domain, bus, and slot/function number, the desired PCI + * device is located in the list of PCI devices. If the device is + * found, its reference count is increased and this function returns a + * pointer to its data structure. The caller must decrement the + * reference count by calling pci_dev_put(). If no device is found, + * %NULL is returned. */ - -struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn) +struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus, + unsigned int devfn) { struct pci_dev *dev = NULL; while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (pci_domain_nr(dev->bus) == 0 && - (dev->bus->number == bus && dev->devfn == devfn)) + if (pci_domain_nr(dev->bus) == domain && + (dev->bus->number == bus && dev->devfn == devfn)) return dev; } return NULL; } +EXPORT_SYMBOL(pci_get_domain_bus_and_slot); -#ifdef CONFIG_PCI_LEGACY -/** - * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id - * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids - * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids - * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids - * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids - * @from: Previous PCI device found in search, or %NULL for new search. - * - * Iterates through the list of known PCI devices. If a PCI device is - * found with a matching @vendor, @device, @ss_vendor and @ss_device, a - * pointer to its device structure is returned. Otherwise, %NULL is returned. - * A new search is initiated by passing %NULL as the @from argument. - * Otherwise if @from is not %NULL, searches continue from next device - * on the global list. - * - * NOTE: Do not use this function any more; use pci_get_subsys() instead, as - * the PCI device returned by this function can disappear at any moment in - * time. - */ -static struct pci_dev * pci_find_subsys(unsigned int vendor, - unsigned int device, - unsigned int ss_vendor, - unsigned int ss_device, - const struct pci_dev *from) +static int match_pci_dev_by_id(struct device *dev, void *data) { - struct list_head *n; - struct pci_dev *dev; + struct pci_dev *pdev = to_pci_dev(dev); + struct pci_device_id *id = data; - WARN_ON(in_interrupt()); - - /* - * 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; - down_read(&pci_bus_sem); - n = from ? from->global_list.next : pci_devices.next; - - while (n && (n != &pci_devices)) { - dev = pci_dev_g(n); - if ((vendor == PCI_ANY_ID || dev->vendor == vendor) && - (device == PCI_ANY_ID || dev->device == device) && - (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) && - (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device)) - goto exit; - n = n->next; - } - dev = NULL; -exit: - up_read(&pci_bus_sem); - return dev; + if (pci_match_one_device(id, pdev)) + return 1; + return 0; } -/** - * pci_find_device - begin or continue searching for a PCI device by vendor/device id - * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids - * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids +/* + * pci_get_dev_by_id - begin or continue searching for a PCI device by id + * @id: pointer to struct pci_device_id to match for the device * @from: Previous PCI device found in search, or %NULL for new search. * * Iterates through the list of known PCI devices. If a PCI device is found - * with a matching @vendor and @device, a pointer to its device structure is - * returned. Otherwise, %NULL is returned. - * A new search is initiated by passing %NULL as the @from argument. - * Otherwise if @from is not %NULL, searches continue from next device - * on the global list. - * - * NOTE: Do not use this function any more; use pci_get_device() instead, as - * the PCI device returned by this function can disappear at any moment in - * time. + * with a matching id a pointer to its device structure is returned, and the + * reference count to the device is incremented. Otherwise, %NULL is returned. + * A new search is initiated by passing %NULL as the @from argument. Otherwise + * if @from is not %NULL, searches continue from next device on the global + * list. The reference count for @from is always decremented if it is not + * %NULL. + * + * This is an internal function for use by the other search functions in + * this file. */ -struct pci_dev * -pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from) +static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, + struct pci_dev *from) { - return pci_find_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); + struct device *dev; + struct device *dev_start = NULL; + struct pci_dev *pdev = NULL; + + WARN_ON(in_interrupt()); + if (from) + dev_start = &from->dev; + dev = bus_find_device(&pci_bus_type, dev_start, (void *)id, + match_pci_dev_by_id); + if (dev) + pdev = to_pci_dev(dev); + if (from) + pci_dev_put(from); + return pdev; } -#endif /* CONFIG_PCI_LEGACY */ /** * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id @@ -301,42 +238,34 @@ pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev * * searches continue from next device on the global list. * The reference count for @from is always decremented if it is not %NULL. */ -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 *pci_get_subsys(unsigned int vendor, unsigned int device, + unsigned int ss_vendor, unsigned int ss_device, + struct pci_dev *from) { - struct list_head *n; - struct pci_dev *dev; - - WARN_ON(in_interrupt()); + struct pci_dev *pdev; + struct pci_device_id *id; /* - * pci_get_subsys() can potentially be called by drivers 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. + * 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; - down_read(&pci_bus_sem); - n = from ? from->global_list.next : pci_devices.next; - - while (n && (n != &pci_devices)) { - dev = pci_dev_g(n); - if ((vendor == PCI_ANY_ID || dev->vendor == vendor) && - (device == PCI_ANY_ID || dev->device == device) && - (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) && - (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device)) - goto exit; - n = n->next; - } - dev = NULL; -exit: - dev = pci_dev_get(dev); - up_read(&pci_bus_sem); - pci_dev_put(from); - return dev; + + 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; } /** @@ -360,46 +289,6 @@ pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from) } /** - * pci_get_device_reverse - begin or continue searching for a PCI device by vendor/device id - * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids - * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids - * @from: Previous PCI device found in search, or %NULL for new search. - * - * Iterates through the list of known PCI devices in the reverse order of - * pci_get_device. - * If a PCI device is found with a matching @vendor and @device, the reference - * count to the device is incremented and a pointer to its device structure - * is returned Otherwise, %NULL is returned. A new search is initiated by - * passing %NULL as the @from argument. Otherwise if @from is not %NULL, - * searches continue from next device on the global list. The reference - * count for @from is always decremented if it is not %NULL. - */ -struct pci_dev * -pci_get_device_reverse(unsigned int vendor, unsigned int device, struct pci_dev *from) -{ - struct list_head *n; - struct pci_dev *dev; - - WARN_ON(in_interrupt()); - down_read(&pci_bus_sem); - n = from ? from->global_list.prev : pci_devices.prev; - - while (n && (n != &pci_devices)) { - dev = pci_dev_g(n); - if ((vendor == PCI_ANY_ID || dev->vendor == vendor) && - (device == PCI_ANY_ID || dev->device == device)) - goto exit; - n = n->prev; - } - dev = NULL; -exit: - dev = pci_dev_get(dev); - up_read(&pci_bus_sem); - pci_dev_put(from); - return dev; -} - -/** * pci_get_class - begin or continue searching for a PCI device by class * @class: search for a PCI device with this class designation * @from: Previous PCI device found in search, or %NULL for new search. @@ -415,24 +304,18 @@ exit: */ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) { - struct list_head *n; struct pci_dev *dev; + struct pci_device_id *id; - WARN_ON(in_interrupt()); - down_read(&pci_bus_sem); - n = from ? from->global_list.next : pci_devices.next; + 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; - while (n && (n != &pci_devices)) { - dev = pci_dev_g(n); - if (dev->class == class) - goto exit; - n = n->next; - } - dev = NULL; -exit: - dev = pci_dev_get(dev); - up_read(&pci_bus_sem); - pci_dev_put(from); + dev = pci_get_dev_by_id(id, from); + kfree(id); return dev; } @@ -449,38 +332,27 @@ exit: */ int pci_dev_present(const struct pci_device_id *ids) { - struct pci_dev *dev; - const struct pci_device_id *found = NULL; + struct pci_dev *found = NULL; WARN_ON(in_interrupt()); - down_read(&pci_bus_sem); while (ids->vendor || ids->subvendor || ids->class_mask) { - list_for_each_entry(dev, &pci_devices, global_list) { - if ((found = pci_match_one_device(ids, dev)) != NULL) - goto exit; - } + found = pci_get_dev_by_id(ids, NULL); + if (found) + goto exit; ids++; } exit: - up_read(&pci_bus_sem); if (found) return 1; return 0; } EXPORT_SYMBOL(pci_dev_present); -#ifdef CONFIG_PCI_LEGACY -EXPORT_SYMBOL(pci_find_device); -EXPORT_SYMBOL(pci_find_slot); -#endif /* CONFIG_PCI_LEGACY */ - /* For boot time work */ EXPORT_SYMBOL(pci_find_bus); EXPORT_SYMBOL(pci_find_next_bus); /* For everyone */ EXPORT_SYMBOL(pci_get_device); -EXPORT_SYMBOL(pci_get_device_reverse); EXPORT_SYMBOL(pci_get_subsys); EXPORT_SYMBOL(pci_get_slot); -EXPORT_SYMBOL(pci_get_bus_and_slot); EXPORT_SYMBOL(pci_get_class);