Commit 29f3eb64634cf96903a3cdb56b1f9a80bebad17d

Authored by Alan Cox
Committed by Greg Kroah-Hartman
1 parent 11f242f04c

pci: Additional search functions

In order to finish converting to pci_get_* interfaces we need to add a couple
of bits of missing functionaility

pci_get_bus_and_slot() provides the equivalent to pci_find_slot()
(pci_get_slot is already taken as a name for something similar but not the
same)

pci_get_device_reverse() is the equivalent of pci_find_device_reverse but
refcounting

Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 2 changed files with 72 additions and 3 deletions Side-by-side Diff

drivers/pci/search.c
... ... @@ -140,6 +140,31 @@
140 140 }
141 141  
142 142 /**
  143 + * pci_get_bus_and_slot - locate PCI device from a given PCI slot
  144 + * @bus: number of PCI bus on which desired PCI device resides
  145 + * @devfn: encodes number of PCI slot in which the desired PCI
  146 + * device resides and the logical device number within that slot
  147 + * in case of multi-function devices.
  148 + *
  149 + * Given a PCI bus and slot/function number, the desired PCI device
  150 + * is located in system global list of PCI devices. If the device
  151 + * is found, a pointer to its data structure is returned. If no
  152 + * device is found, %NULL is returned. The returned device has its
  153 + * reference count bumped by one.
  154 + */
  155 +
  156 +struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
  157 +{
  158 + struct pci_dev *dev = NULL;
  159 +
  160 + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
  161 + if (dev->bus->number == bus && dev->devfn == devfn)
  162 + return dev;
  163 + }
  164 + return NULL;
  165 +}
  166 +
  167 +/**
143 168 * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
144 169 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
145 170 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
146 171  
... ... @@ -274,7 +299,46 @@
274 299 return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
275 300 }
276 301  
  302 +/**
  303 + * pci_get_device_reverse - begin or continue searching for a PCI device by vendor/device id
  304 + * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
  305 + * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
  306 + * @from: Previous PCI device found in search, or %NULL for new search.
  307 + *
  308 + * Iterates through the list of known PCI devices in the reverse order of
  309 + * pci_get_device.
  310 + * If a PCI device is found with a matching @vendor and @device, the reference
  311 + * count to the device is incremented and a pointer to its device structure
  312 + * is returned Otherwise, %NULL is returned. A new search is initiated by
  313 + * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
  314 + * searches continue from next device on the global list. The reference
  315 + * count for @from is always decremented if it is not %NULL.
  316 + */
  317 +struct pci_dev *
  318 +pci_get_device_reverse(unsigned int vendor, unsigned int device, struct pci_dev *from)
  319 +{
  320 + struct list_head *n;
  321 + struct pci_dev *dev;
277 322  
  323 + WARN_ON(in_interrupt());
  324 + down_read(&pci_bus_sem);
  325 + n = from ? from->global_list.prev : pci_devices.prev;
  326 +
  327 + while (n && (n != &pci_devices)) {
  328 + dev = pci_dev_g(n);
  329 + if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
  330 + (device == PCI_ANY_ID || dev->device == device))
  331 + goto exit;
  332 + n = n->prev;
  333 + }
  334 + dev = NULL;
  335 +exit:
  336 + dev = pci_dev_get(dev);
  337 + up_read(&pci_bus_sem);
  338 + pci_dev_put(from);
  339 + return dev;
  340 +}
  341 +
278 342 /**
279 343 * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id
280 344 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
281 345  
282 346  
283 347  
... ... @@ -382,13 +446,17 @@
382 446 }
383 447 EXPORT_SYMBOL(pci_dev_present);
384 448  
385   -EXPORT_SYMBOL(pci_find_bus);
386   -EXPORT_SYMBOL(pci_find_next_bus);
387 449 EXPORT_SYMBOL(pci_find_device);
388 450 EXPORT_SYMBOL(pci_find_device_reverse);
389 451 EXPORT_SYMBOL(pci_find_slot);
  452 +/* For boot time work */
  453 +EXPORT_SYMBOL(pci_find_bus);
  454 +EXPORT_SYMBOL(pci_find_next_bus);
  455 +/* For everyone */
390 456 EXPORT_SYMBOL(pci_get_device);
  457 +EXPORT_SYMBOL(pci_get_device_reverse);
391 458 EXPORT_SYMBOL(pci_get_subsys);
392 459 EXPORT_SYMBOL(pci_get_slot);
  460 +EXPORT_SYMBOL(pci_get_bus_and_slot);
393 461 EXPORT_SYMBOL(pci_get_class);
... ... @@ -452,13 +452,14 @@
452 452 int pci_find_capability (struct pci_dev *dev, int cap);
453 453 int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
454 454 int pci_find_ext_capability (struct pci_dev *dev, int cap);
455   -struct pci_bus * pci_find_next_bus(const struct pci_bus *from);
  455 +struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
456 456  
457 457 struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
458 458 struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device,
459 459 unsigned int ss_vendor, unsigned int ss_device,
460 460 struct pci_dev *from);
461 461 struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn);
  462 +struct pci_dev *pci_get_bus_and_slot (unsigned int bus, unsigned int devfn);
462 463 struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from);
463 464 int pci_dev_present(const struct pci_device_id *ids);
464 465