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->parent)
  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 * pci_find_slot - locate PCI device from a given PCI slot
 119 * @bus: number of PCI bus on which desired PCI device resides
 120 * @devfn: encodes number of PCI slot in which the desired PCI
 121 * device resides and the logical device number within that slot
 122 * in case of multi-function devices.
 123 *
 124 * Given a PCI bus and slot/function number, the desired PCI device
 125 * is located in system global list of PCI devices.  If the device
 126 * is found, a pointer to its data structure is returned.  If no
 127 * device is found, %NULL is returned.
 128 *
 129 * NOTE: Do not use this function any more; use pci_get_slot() instead, as
 130 * the PCI device returned by this function can disappear at any moment in
 131 * time.
 132 */
 133struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
 134{
 135        struct pci_dev *dev = NULL;
 136
 137        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 138                if (dev->bus->number == bus && dev->devfn == devfn) {
 139                        pci_dev_put(dev);
 140                        return dev;
 141                }
 142        }
 143        return NULL;
 144}
 145EXPORT_SYMBOL(pci_find_slot);
 146
 147/**
 148 * pci_find_device - begin or continue searching for a PCI device by vendor/device id
 149 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
 150 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
 151 * @from: Previous PCI device found in search, or %NULL for new search.
 152 *
 153 * Iterates through the list of known PCI devices.  If a PCI device is found
 154 * with a matching @vendor and @device, a pointer to its device structure is
 155 * returned.  Otherwise, %NULL is returned.
 156 * A new search is initiated by passing %NULL as the @from argument.
 157 * Otherwise if @from is not %NULL, searches continue from next device
 158 * on the global list.
 159 *
 160 * NOTE: Do not use this function any more; use pci_get_device() instead, as
 161 * the PCI device returned by this function can disappear at any moment in
 162 * time.
 163 */
 164struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
 165                                struct pci_dev *from)
 166{
 167        struct pci_dev *pdev;
 168
 169        pci_dev_get(from);
 170        pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
 171        pci_dev_put(pdev);
 172        return pdev;
 173}
 174EXPORT_SYMBOL(pci_find_device);
 175#endif /* CONFIG_PCI_LEGACY */
 176
 177/**
 178 * pci_get_slot - locate PCI device for a given PCI slot
 179 * @bus: PCI bus on which desired PCI device resides
 180 * @devfn: encodes number of PCI slot in which the desired PCI 
 181 * device resides and the logical device number within that slot 
 182 * in case of multi-function devices.
 183 *
 184 * Given a PCI bus and slot/function number, the desired PCI device 
 185 * is located in the list of PCI devices.
 186 * If the device is found, its reference count is increased and this
 187 * function returns a pointer to its data structure.  The caller must
 188 * decrement the reference count by calling pci_dev_put().
 189 * If no device is found, %NULL is returned.
 190 */
 191struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn)
 192{
 193        struct list_head *tmp;
 194        struct pci_dev *dev;
 195
 196        WARN_ON(in_interrupt());
 197        down_read(&pci_bus_sem);
 198
 199        list_for_each(tmp, &bus->devices) {
 200                dev = pci_dev_b(tmp);
 201                if (dev->devfn == devfn)
 202                        goto out;
 203        }
 204
 205        dev = NULL;
 206 out:
 207        pci_dev_get(dev);
 208        up_read(&pci_bus_sem);
 209        return dev;
 210}
 211
 212/**
 213 * pci_get_bus_and_slot - locate PCI device from a given PCI bus & slot
 214 * @bus: number of PCI bus on which desired PCI device resides
 215 * @devfn: encodes number of PCI slot in which the desired PCI
 216 * device resides and the logical device number within that slot
 217 * in case of multi-function devices.
 218 *
 219 * Note: the bus/slot search is limited to PCI domain (segment) 0.
 220 *
 221 * Given a PCI bus and slot/function number, the desired PCI device
 222 * is located in system global list of PCI devices.  If the device
 223 * is found, a pointer to its data structure is returned.  If no
 224 * device is found, %NULL is returned. The returned device has its
 225 * reference count bumped by one.
 226 */
 227
 228struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
 229{
 230        struct pci_dev *dev = NULL;
 231
 232        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 233                if (pci_domain_nr(dev->bus) == 0 &&
 234                   (dev->bus->number == bus && dev->devfn == devfn))
 235                        return dev;
 236        }
 237        return NULL;
 238}
 239
 240static int match_pci_dev_by_id(struct device *dev, void *data)
 241{
 242        struct pci_dev *pdev = to_pci_dev(dev);
 243        struct pci_device_id *id = data;
 244
 245        if (pci_match_one_device(id, pdev))
 246                return 1;
 247        return 0;
 248}
 249
 250/*
 251 * pci_get_dev_by_id - begin or continue searching for a PCI device by id
 252 * @id: pointer to struct pci_device_id to match for the device
 253 * @from: Previous PCI device found in search, or %NULL for new search.
 254 *
 255 * Iterates through the list of known PCI devices.  If a PCI device is found
 256 * with a matching id a pointer to its device structure is returned, and the
 257 * reference count to the device is incremented.  Otherwise, %NULL is returned.
 258 * A new search is initiated by passing %NULL as the @from argument.  Otherwise
 259 * if @from is not %NULL, searches continue from next device on the global
 260 * list.  The reference count for @from is always decremented if it is not
 261 * %NULL.
 262 *
 263 * This is an internal function for use by the other search functions in
 264 * this file.
 265 */
 266static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
 267                                         struct pci_dev *from)
 268{
 269        struct device *dev;
 270        struct device *dev_start = NULL;
 271        struct pci_dev *pdev = NULL;
 272
 273        WARN_ON(in_interrupt());
 274        if (from)
 275                dev_start = &from->dev;
 276        dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
 277                              match_pci_dev_by_id);
 278        if (dev)
 279                pdev = to_pci_dev(dev);
 280        if (from)
 281                pci_dev_put(from);
 282        return pdev;
 283}
 284
 285/**
 286 * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
 287 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
 288 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
 289 * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
 290 * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
 291 * @from: Previous PCI device found in search, or %NULL for new search.
 292 *
 293 * Iterates through the list of known PCI devices.  If a PCI device is found
 294 * with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its
 295 * device structure is returned, and the reference count to the device is
 296 * incremented.  Otherwise, %NULL is returned.  A new search is initiated by
 297 * passing %NULL as the @from argument.  Otherwise if @from is not %NULL,
 298 * searches continue from next device on the global list.
 299 * The reference count for @from is always decremented if it is not %NULL.
 300 */
 301struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
 302                               unsigned int ss_vendor, unsigned int ss_device,
 303                               struct pci_dev *from)
 304{
 305        struct pci_dev *pdev;
 306        struct pci_device_id *id;
 307
 308        /*
 309         * pci_find_subsys() can be called on the ide_setup() path,
 310         * super-early in boot.  But the down_read() will enable local
 311         * interrupts, which can cause some machines to crash.  So here we
 312         * detect and flag that situation and bail out early.
 313         */
 314        if (unlikely(no_pci_devices()))
 315                return NULL;
 316
 317        id = kzalloc(sizeof(*id), GFP_KERNEL);
 318        if (!id)
 319                return NULL;
 320        id->vendor = vendor;
 321        id->device = device;
 322        id->subvendor = ss_vendor;
 323        id->subdevice = ss_device;
 324
 325        pdev = pci_get_dev_by_id(id, from);
 326        kfree(id);
 327
 328        return pdev;
 329}
 330
 331/**
 332 * pci_get_device - begin or continue searching for a PCI device by vendor/device id
 333 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
 334 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
 335 * @from: Previous PCI device found in search, or %NULL for new search.
 336 *
 337 * Iterates through the list of known PCI devices.  If a PCI device is
 338 * found with a matching @vendor and @device, the reference count to the
 339 * device is incremented and a pointer to its device structure is returned.
 340 * Otherwise, %NULL is returned.  A new search is initiated by passing %NULL
 341 * as the @from argument.  Otherwise if @from is not %NULL, searches continue
 342 * from next device on the global list.  The reference count for @from is
 343 * always decremented if it is not %NULL.
 344 */
 345struct pci_dev *
 346pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
 347{
 348        return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
 349}
 350
 351/**
 352 * pci_get_class - begin or continue searching for a PCI device by class
 353 * @class: search for a PCI device with this class designation
 354 * @from: Previous PCI device found in search, or %NULL for new search.
 355 *
 356 * Iterates through the list of known PCI devices.  If a PCI device is
 357 * found with a matching @class, the reference count to the device is
 358 * incremented and a pointer to its device structure is returned.
 359 * Otherwise, %NULL is returned.
 360 * A new search is initiated by passing %NULL as the @from argument.
 361 * Otherwise if @from is not %NULL, searches continue from next device
 362 * on the global list.  The reference count for @from is always decremented
 363 * if it is not %NULL.
 364 */
 365struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
 366{
 367        struct pci_dev *dev;
 368        struct pci_device_id *id;
 369
 370        id = kzalloc(sizeof(*id), GFP_KERNEL);
 371        if (!id)
 372                return NULL;
 373        id->vendor = id->device = id->subvendor = id->subdevice = PCI_ANY_ID;
 374        id->class_mask = PCI_ANY_ID;
 375        id->class = class;
 376
 377        dev = pci_get_dev_by_id(id, from);
 378        kfree(id);
 379        return dev;
 380}
 381
 382/**
 383 * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not.
 384 * @ids: A pointer to a null terminated list of struct pci_device_id structures
 385 * that describe the type of PCI device the caller is trying to find.
 386 *
 387 * Obvious fact: You do not have a reference to any device that might be found
 388 * by this function, so if that device is removed from the system right after
 389 * this function is finished, the value will be stale.  Use this function to
 390 * find devices that are usually built into a system, or for a general hint as
 391 * to if another device happens to be present at this specific moment in time.
 392 */
 393int pci_dev_present(const struct pci_device_id *ids)
 394{
 395        struct pci_dev *found = NULL;
 396
 397        WARN_ON(in_interrupt());
 398        while (ids->vendor || ids->subvendor || ids->class_mask) {
 399                found = pci_get_dev_by_id(ids, NULL);
 400                if (found)
 401                        goto exit;
 402                ids++;
 403        }
 404exit:
 405        if (found)
 406                return 1;
 407        return 0;
 408}
 409EXPORT_SYMBOL(pci_dev_present);
 410
 411/* For boot time work */
 412EXPORT_SYMBOL(pci_find_bus);
 413EXPORT_SYMBOL(pci_find_next_bus);
 414/* For everyone */
 415EXPORT_SYMBOL(pci_get_device);
 416EXPORT_SYMBOL(pci_get_subsys);
 417EXPORT_SYMBOL(pci_get_slot);
 418EXPORT_SYMBOL(pci_get_bus_and_slot);
 419EXPORT_SYMBOL(pci_get_class);
 420