linux/drivers/pci/search.c
<<
>>
Prefs
   1/*
   2 *      PCI searching functions.
   3 *
   4 *      Copyright (C) 1993 -- 1997 Drew Eckhardt, Frederic Potter,
   5 *                                      David Mosberger-Tang
   6 *      Copyright (C) 1997 -- 2000 Martin Mares <mj@ucw.cz>
   7 *      Copyright (C) 2003 -- 2004 Greg Kroah-Hartman <greg@kroah.com>
   8 */
   9
  10#include <linux/init.h>
  11#include <linux/pci.h>
  12#include <linux/module.h>
  13#include <linux/interrupt.h>
  14#include "pci.h"
  15
  16DECLARE_RWSEM(pci_bus_sem);
  17/*
  18 * find the upstream PCIE-to-PCI bridge of a PCI device
  19 * if the device is PCIE, return NULL
  20 * if the device isn't connected to a PCIE bridge (that is its parent is a
  21 * legacy PCI bridge and the bridge is directly connected to bus 0), return its
  22 * parent
  23 */
  24struct pci_dev *
  25pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
  26{
  27        struct pci_dev *tmp = NULL;
  28
  29        if (pdev->is_pcie)
  30                return NULL;
  31        while (1) {
  32                if (!pdev->bus->self)
  33                        break;
  34                pdev = pdev->bus->self;
  35                /* a p2p bridge */
  36                if (!pdev->is_pcie) {
  37                        tmp = pdev;
  38                        continue;
  39                }
  40                /* PCI device should connect to a PCIE bridge */
  41                if (pdev->pcie_type != PCI_EXP_TYPE_PCI_BRIDGE) {
  42                        /* Busted hardware? */
  43                        WARN_ON_ONCE(1);
  44                        return NULL;
  45                }
  46                return pdev;
  47        }
  48
  49        return tmp;
  50}
  51
  52static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
  53{
  54        struct pci_bus* child;
  55        struct list_head *tmp;
  56
  57        if(bus->number == busnr)
  58                return bus;
  59
  60        list_for_each(tmp, &bus->children) {
  61                child = pci_do_find_bus(pci_bus_b(tmp), busnr);
  62                if(child)
  63                        return child;
  64        }
  65        return NULL;
  66}
  67
  68/**
  69 * pci_find_bus - locate PCI bus from a given domain and bus number
  70 * @domain: number of PCI domain to search
  71 * @busnr: number of desired PCI bus
  72 *
  73 * Given a PCI bus number and domain number, the desired PCI bus is located
  74 * in the global list of PCI buses.  If the bus is found, a pointer to its
  75 * data structure is returned.  If no bus is found, %NULL is returned.
  76 */
  77struct pci_bus * pci_find_bus(int domain, int busnr)
  78{
  79        struct pci_bus *bus = NULL;
  80        struct pci_bus *tmp_bus;
  81
  82        while ((bus = pci_find_next_bus(bus)) != NULL)  {
  83                if (pci_domain_nr(bus) != domain)
  84                        continue;
  85                tmp_bus = pci_do_find_bus(bus, busnr);
  86                if (tmp_bus)
  87                        return tmp_bus;
  88        }
  89        return NULL;
  90}
  91
  92/**
  93 * pci_find_next_bus - begin or continue searching for a PCI bus
  94 * @from: Previous PCI bus found, or %NULL for new search.
  95 *
  96 * Iterates through the list of known PCI busses.  A new search is
  97 * initiated by passing %NULL as the @from argument.  Otherwise if
  98 * @from is not %NULL, searches continue from next device on the
  99 * global list.
 100 */
 101struct pci_bus * 
 102pci_find_next_bus(const struct pci_bus *from)
 103{
 104        struct list_head *n;
 105        struct pci_bus *b = NULL;
 106
 107        WARN_ON(in_interrupt());
 108        down_read(&pci_bus_sem);
 109        n = from ? from->node.next : pci_root_buses.next;
 110        if (n != &pci_root_buses)
 111                b = pci_bus_b(n);
 112        up_read(&pci_bus_sem);
 113        return b;
 114}
 115
 116#ifdef CONFIG_PCI_LEGACY
 117
 118/**
 119 * pci_find_slot - locate PCI device from a given PCI slot
 120 * @bus: number of PCI bus on which desired PCI device resides
 121 * @devfn: encodes number of PCI slot in which the desired PCI 
 122 * device resides and the logical device number within that slot 
 123 * in case of multi-function devices.
 124 *
 125 * Given a PCI bus and slot/function number, the desired PCI device 
 126 * is located in system global list of PCI devices.  If the device
 127 * is found, a pointer to its data structure is returned.  If no 
 128 * device is found, %NULL is returned.
 129 */
 130struct pci_dev *
 131pci_find_slot(unsigned int bus, unsigned int devfn)
 132{
 133        struct pci_dev *dev = NULL;
 134
 135        while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 136                if (dev->bus->number == bus && dev->devfn == devfn)
 137                        return dev;
 138        }
 139        return NULL;
 140}
 141
 142#endif /* CONFIG_PCI_LEGACY */
 143
 144/**
 145 * pci_get_slot - locate PCI device for a given PCI slot
 146 * @bus: PCI bus on which desired PCI device resides
 147 * @devfn: encodes number of PCI slot in which the desired PCI 
 148 * device resides and the logical device number within that slot 
 149 * in case of multi-function devices.
 150 *
 151 * Given a PCI bus and slot/function number, the desired PCI device 
 152 * is located in the list of PCI devices.
 153 * If the device is found, its reference count is increased and this
 154 * function returns a pointer to its data structure.  The caller must
 155 * decrement the reference count by calling pci_dev_put().
 156 * If no device is found, %NULL is returned.
 157 */
 158struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn)
 159{
 160        struct list_head *tmp;
 161        struct pci_dev *dev;
 162
 163        WARN_ON(in_interrupt());
 164        down_read(&pci_bus_sem);
 165
 166        list_for_each(tmp, &bus->devices) {
 167                dev = pci_dev_b(tmp);
 168                if (dev->devfn == devfn)
 169                        goto out;
 170        }
 171
 172        dev = NULL;
 173 out:
 174        pci_dev_get(dev);
 175        up_read(&pci_bus_sem);
 176        return dev;
 177}
 178
 179/**
 180 * pci_get_bus_and_slot - locate PCI device from a given PCI bus & slot
 181 * @bus: number of PCI bus on which desired PCI device resides
 182 * @devfn: encodes number of PCI slot in which the desired PCI
 183 * device resides and the logical device number within that slot
 184 * in case of multi-function devices.
 185 *
 186 * Note: the bus/slot search is limited to PCI domain (segment) 0.
 187 *
 188 * Given a PCI bus and slot/function number, the desired PCI device
 189 * is located in system global list of PCI devices.  If the device
 190 * is found, a pointer to its data structure is returned.  If no
 191 * device is found, %NULL is returned. The returned device has its
 192 * reference count bumped by one.
 193 */
 194
 195struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
 196{
 197        struct pci_dev *dev = NULL;
 198
 199        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 200                if (pci_domain_nr(dev->bus) == 0 &&
 201                   (dev->bus->number == bus && dev->devfn == devfn))
 202                        return dev;
 203        }
 204        return NULL;
 205}
 206
 207#ifdef CONFIG_PCI_LEGACY
 208/**
 209 * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
 210 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
 211 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
 212 * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
 213 * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
 214 * @from: Previous PCI device found in search, or %NULL for new search.
 215 *
 216 * Iterates through the list of known PCI devices.  If a PCI device is
 217 * found with a matching @vendor, @device, @ss_vendor and @ss_device, a
 218 * pointer to its device structure is returned.  Otherwise, %NULL is returned.
 219 * A new search is initiated by passing %NULL as the @from argument.
 220 * Otherwise if @from is not %NULL, searches continue from next device
 221 * on the global list.
 222 *
 223 * NOTE: Do not use this function any more; use pci_get_subsys() instead, as
 224 * the PCI device returned by this function can disappear at any moment in
 225 * time.
 226 */
 227static struct pci_dev * pci_find_subsys(unsigned int vendor,
 228                                        unsigned int device,
 229                                        unsigned int ss_vendor,
 230                                        unsigned int ss_device,
 231                                        const struct pci_dev *from)
 232{
 233        struct list_head *n;
 234        struct pci_dev *dev;
 235
 236        WARN_ON(in_interrupt());
 237
 238        /*
 239         * pci_find_subsys() can be called on the ide_setup() path, super-early
 240         * in boot.  But the down_read() will enable local interrupts, which
 241         * can cause some machines to crash.  So here we detect and flag that
 242         * situation and bail out early.
 243         */
 244        if (unlikely(no_pci_devices()))
 245                return NULL;
 246        down_read(&pci_bus_sem);
 247        n = from ? from->global_list.next : pci_devices.next;
 248
 249        while (n && (n != &pci_devices)) {
 250                dev = pci_dev_g(n);
 251                if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
 252                    (device == PCI_ANY_ID || dev->device == device) &&
 253                    (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
 254                    (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
 255                        goto exit;
 256                n = n->next;
 257        }
 258        dev = NULL;
 259exit:
 260        up_read(&pci_bus_sem);
 261        return dev;
 262}
 263
 264/**
 265 * pci_find_device - begin or continue searching for a PCI device by vendor/device id
 266 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
 267 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
 268 * @from: Previous PCI device found in search, or %NULL for new search.
 269 *
 270 * Iterates through the list of known PCI devices.  If a PCI device is found
 271 * with a matching @vendor and @device, a pointer to its device structure is
 272 * returned.  Otherwise, %NULL is returned.
 273 * A new search is initiated by passing %NULL as the @from argument.
 274 * Otherwise if @from is not %NULL, searches continue from next device
 275 * on the global list.
 276 * 
 277 * NOTE: Do not use this function any more; use pci_get_device() instead, as
 278 * the PCI device returned by this function can disappear at any moment in
 279 * time.
 280 */
 281struct pci_dev *
 282pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from)
 283{
 284        return pci_find_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
 285}
 286#endif /* CONFIG_PCI_LEGACY */
 287
 288/**
 289 * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
 290 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
 291 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
 292 * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
 293 * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
 294 * @from: Previous PCI device found in search, or %NULL for new search.
 295 *
 296 * Iterates through the list of known PCI devices.  If a PCI device is found
 297 * with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its
 298 * device structure is returned, and the reference count to the device is
 299 * incremented.  Otherwise, %NULL is returned.  A new search is initiated by
 300 * passing %NULL as the @from argument.  Otherwise if @from is not %NULL,
 301 * searches continue from next device on the global list.
 302 * The reference count for @from is always decremented if it is not %NULL.
 303 */
 304struct pci_dev * 
 305pci_get_subsys(unsigned int vendor, unsigned int device,
 306               unsigned int ss_vendor, unsigned int ss_device,
 307               struct pci_dev *from)
 308{
 309        struct list_head *n;
 310        struct pci_dev *dev;
 311
 312        WARN_ON(in_interrupt());
 313
 314        /*
 315         * pci_get_subsys() can potentially be called by drivers super-early
 316         * in boot.  But the down_read() will enable local interrupts, which
 317         * can cause some machines to crash.  So here we detect and flag that
 318         * situation and bail out early.
 319         */
 320        if (unlikely(no_pci_devices()))
 321                return NULL;
 322        down_read(&pci_bus_sem);
 323        n = from ? from->global_list.next : pci_devices.next;
 324
 325        while (n && (n != &pci_devices)) {
 326                dev = pci_dev_g(n);
 327                if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
 328                    (device == PCI_ANY_ID || dev->device == device) &&
 329                    (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
 330                    (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
 331                        goto exit;
 332                n = n->next;
 333        }
 334        dev = NULL;
 335exit:
 336        dev = pci_dev_get(dev);
 337        up_read(&pci_bus_sem);
 338        pci_dev_put(from);
 339        return dev;
 340}
 341
 342/**
 343 * pci_get_device - begin or continue searching for a PCI device by vendor/device id
 344 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
 345 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
 346 * @from: Previous PCI device found in search, or %NULL for new search.
 347 *
 348 * Iterates through the list of known PCI devices.  If a PCI device is
 349 * found with a matching @vendor and @device, the reference count to the
 350 * device is incremented and a pointer to its device structure is returned.
 351 * Otherwise, %NULL is returned.  A new search is initiated by passing %NULL
 352 * as the @from argument.  Otherwise if @from is not %NULL, searches continue
 353 * from next device on the global list.  The reference count for @from is
 354 * always decremented if it is not %NULL.
 355 */
 356struct pci_dev *
 357pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
 358{
 359        return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
 360}
 361
 362/**
 363 * pci_get_device_reverse - begin or continue searching for a PCI device by vendor/device id
 364 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
 365 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
 366 * @from: Previous PCI device found in search, or %NULL for new search.
 367 *
 368 * Iterates through the list of known PCI devices in the reverse order of
 369 * pci_get_device.
 370 * If a PCI device is found with a matching @vendor and @device, the reference
 371 * count to the  device is incremented and a pointer to its device structure
 372 * is returned Otherwise, %NULL is returned.  A new search is initiated by
 373 * passing %NULL as the @from argument.  Otherwise if @from is not %NULL,
 374 * searches continue from next device on the global list.  The reference
 375 * count for @from is always decremented if it is not %NULL.
 376 */
 377struct pci_dev *
 378pci_get_device_reverse(unsigned int vendor, unsigned int device, struct pci_dev *from)
 379{
 380        struct list_head *n;
 381        struct pci_dev *dev;
 382
 383        WARN_ON(in_interrupt());
 384        down_read(&pci_bus_sem);
 385        n = from ? from->global_list.prev : pci_devices.prev;
 386
 387        while (n && (n != &pci_devices)) {
 388                dev = pci_dev_g(n);
 389                if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
 390                    (device == PCI_ANY_ID || dev->device == device))
 391                        goto exit;
 392                n = n->prev;
 393        }
 394        dev = NULL;
 395exit:
 396        dev = pci_dev_get(dev);
 397        up_read(&pci_bus_sem);
 398        pci_dev_put(from);
 399        return dev;
 400}
 401
 402/**
 403 * pci_get_class - begin or continue searching for a PCI device by class
 404 * @class: search for a PCI device with this class designation
 405 * @from: Previous PCI device found in search, or %NULL for new search.
 406 *
 407 * Iterates through the list of known PCI devices.  If a PCI device is
 408 * found with a matching @class, the reference count to the device is
 409 * incremented and a pointer to its device structure is returned.
 410 * Otherwise, %NULL is returned.
 411 * A new search is initiated by passing %NULL as the @from argument.
 412 * Otherwise if @from is not %NULL, searches continue from next device
 413 * on the global list.  The reference count for @from is always decremented
 414 * if it is not %NULL.
 415 */
 416struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
 417{
 418        struct list_head *n;
 419        struct pci_dev *dev;
 420
 421        WARN_ON(in_interrupt());
 422        down_read(&pci_bus_sem);
 423        n = from ? from->global_list.next : pci_devices.next;
 424
 425        while (n && (n != &pci_devices)) {
 426                dev = pci_dev_g(n);
 427                if (dev->class == class)
 428                        goto exit;
 429                n = n->next;
 430        }
 431        dev = NULL;
 432exit:
 433        dev = pci_dev_get(dev);
 434        up_read(&pci_bus_sem);
 435        pci_dev_put(from);
 436        return dev;
 437}
 438
 439const struct pci_device_id *pci_find_present(const struct pci_device_id *ids)
 440{
 441        struct pci_dev *dev;
 442        const struct pci_device_id *found = NULL;
 443
 444        WARN_ON(in_interrupt());
 445        down_read(&pci_bus_sem);
 446        while (ids->vendor || ids->subvendor || ids->class_mask) {
 447                list_for_each_entry(dev, &pci_devices, global_list) {
 448                        if ((found = pci_match_one_device(ids, dev)) != NULL)
 449                                goto exit;
 450                }
 451                ids++;
 452        }
 453exit:
 454        up_read(&pci_bus_sem);
 455        return found;
 456}
 457
 458/**
 459 * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not.
 460 * @ids: A pointer to a null terminated list of struct pci_device_id structures
 461 * that describe the type of PCI device the caller is trying to find.
 462 *
 463 * Obvious fact: You do not have a reference to any device that might be found
 464 * by this function, so if that device is removed from the system right after
 465 * this function is finished, the value will be stale.  Use this function to
 466 * find devices that are usually built into a system, or for a general hint as
 467 * to if another device happens to be present at this specific moment in time.
 468 */
 469int pci_dev_present(const struct pci_device_id *ids)
 470{
 471        return pci_find_present(ids) == NULL ? 0 : 1;
 472}
 473
 474EXPORT_SYMBOL(pci_dev_present);
 475EXPORT_SYMBOL(pci_find_present);
 476
 477#ifdef CONFIG_PCI_LEGACY
 478EXPORT_SYMBOL(pci_find_device);
 479EXPORT_SYMBOL(pci_find_slot);
 480#endif /* CONFIG_PCI_LEGACY */
 481
 482/* For boot time work */
 483EXPORT_SYMBOL(pci_find_bus);
 484EXPORT_SYMBOL(pci_find_next_bus);
 485/* For everyone */
 486EXPORT_SYMBOL(pci_get_device);
 487EXPORT_SYMBOL(pci_get_device_reverse);
 488EXPORT_SYMBOL(pci_get_subsys);
 489EXPORT_SYMBOL(pci_get_slot);
 490EXPORT_SYMBOL(pci_get_bus_and_slot);
 491EXPORT_SYMBOL(pci_get_class);
 492