linux/drivers/pci/search.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * PCI searching functions
   4 *
   5 * Copyright (C) 1993 -- 1997 Drew Eckhardt, Frederic Potter,
   6 *                                      David Mosberger-Tang
   7 * Copyright (C) 1997 -- 2000 Martin Mares <mj@ucw.cz>
   8 * Copyright (C) 2003 -- 2004 Greg Kroah-Hartman <greg@kroah.com>
   9 */
  10
  11#include <linux/pci.h>
  12#include <linux/slab.h>
  13#include <linux/module.h>
  14#include <linux/interrupt.h>
  15#include "pci.h"
  16
  17DECLARE_RWSEM(pci_bus_sem);
  18
  19/*
  20 * pci_for_each_dma_alias - Iterate over DMA aliases for a device
  21 * @pdev: starting downstream device
  22 * @fn: function to call for each alias
  23 * @data: opaque data to pass to @fn
  24 *
  25 * Starting @pdev, walk up the bus calling @fn for each possible alias
  26 * of @pdev at the root bus.
  27 */
  28int pci_for_each_dma_alias(struct pci_dev *pdev,
  29                           int (*fn)(struct pci_dev *pdev,
  30                                     u16 alias, void *data), void *data)
  31{
  32        struct pci_bus *bus;
  33        int ret;
  34
  35        /*
  36         * The device may have an explicit alias requester ID for DMA where the
  37         * requester is on another PCI bus.
  38         */
  39        pdev = pci_real_dma_dev(pdev);
  40
  41        ret = fn(pdev, pci_dev_id(pdev), data);
  42        if (ret)
  43                return ret;
  44
  45        /*
  46         * If the device is broken and uses an alias requester ID for
  47         * DMA, iterate over that too.
  48         */
  49        if (unlikely(pdev->dma_alias_mask)) {
  50                unsigned int devfn;
  51
  52                for_each_set_bit(devfn, pdev->dma_alias_mask, MAX_NR_DEVFNS) {
  53                        ret = fn(pdev, PCI_DEVID(pdev->bus->number, devfn),
  54                                 data);
  55                        if (ret)
  56                                return ret;
  57                }
  58        }
  59
  60        for (bus = pdev->bus; !pci_is_root_bus(bus); bus = bus->parent) {
  61                struct pci_dev *tmp;
  62
  63                /* Skip virtual buses */
  64                if (!bus->self)
  65                        continue;
  66
  67                tmp = bus->self;
  68
  69                /* stop at bridge where translation unit is associated */
  70                if (tmp->dev_flags & PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT)
  71                        return ret;
  72
  73                /*
  74                 * PCIe-to-PCI/X bridges alias transactions from downstream
  75                 * devices using the subordinate bus number (PCI Express to
  76                 * PCI/PCI-X Bridge Spec, rev 1.0, sec 2.3).  For all cases
  77                 * where the upstream bus is PCI/X we alias to the bridge
  78                 * (there are various conditions in the previous reference
  79                 * where the bridge may take ownership of transactions, even
  80                 * when the secondary interface is PCI-X).
  81                 */
  82                if (pci_is_pcie(tmp)) {
  83                        switch (pci_pcie_type(tmp)) {
  84                        case PCI_EXP_TYPE_ROOT_PORT:
  85                        case PCI_EXP_TYPE_UPSTREAM:
  86                        case PCI_EXP_TYPE_DOWNSTREAM:
  87                                continue;
  88                        case PCI_EXP_TYPE_PCI_BRIDGE:
  89                                ret = fn(tmp,
  90                                         PCI_DEVID(tmp->subordinate->number,
  91                                                   PCI_DEVFN(0, 0)), data);
  92                                if (ret)
  93                                        return ret;
  94                                continue;
  95                        case PCI_EXP_TYPE_PCIE_BRIDGE:
  96                                ret = fn(tmp, pci_dev_id(tmp), data);
  97                                if (ret)
  98                                        return ret;
  99                                continue;
 100                        }
 101                } else {
 102                        if (tmp->dev_flags & PCI_DEV_FLAG_PCIE_BRIDGE_ALIAS)
 103                                ret = fn(tmp,
 104                                         PCI_DEVID(tmp->subordinate->number,
 105                                                   PCI_DEVFN(0, 0)), data);
 106                        else
 107                                ret = fn(tmp, pci_dev_id(tmp), data);
 108                        if (ret)
 109                                return ret;
 110                }
 111        }
 112
 113        return ret;
 114}
 115
 116static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
 117{
 118        struct pci_bus *child;
 119        struct pci_bus *tmp;
 120
 121        if (bus->number == busnr)
 122                return bus;
 123
 124        list_for_each_entry(tmp, &bus->children, node) {
 125                child = pci_do_find_bus(tmp, busnr);
 126                if (child)
 127                        return child;
 128        }
 129        return NULL;
 130}
 131
 132/**
 133 * pci_find_bus - locate PCI bus from a given domain and bus number
 134 * @domain: number of PCI domain to search
 135 * @busnr: number of desired PCI bus
 136 *
 137 * Given a PCI bus number and domain number, the desired PCI bus is located
 138 * in the global list of PCI buses.  If the bus is found, a pointer to its
 139 * data structure is returned.  If no bus is found, %NULL is returned.
 140 */
 141struct pci_bus *pci_find_bus(int domain, int busnr)
 142{
 143        struct pci_bus *bus = NULL;
 144        struct pci_bus *tmp_bus;
 145
 146        while ((bus = pci_find_next_bus(bus)) != NULL)  {
 147                if (pci_domain_nr(bus) != domain)
 148                        continue;
 149                tmp_bus = pci_do_find_bus(bus, busnr);
 150                if (tmp_bus)
 151                        return tmp_bus;
 152        }
 153        return NULL;
 154}
 155EXPORT_SYMBOL(pci_find_bus);
 156
 157/**
 158 * pci_find_next_bus - begin or continue searching for a PCI bus
 159 * @from: Previous PCI bus found, or %NULL for new search.
 160 *
 161 * Iterates through the list of known PCI buses.  A new search is
 162 * initiated by passing %NULL as the @from argument.  Otherwise if
 163 * @from is not %NULL, searches continue from next device on the
 164 * global list.
 165 */
 166struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
 167{
 168        struct list_head *n;
 169        struct pci_bus *b = NULL;
 170
 171        down_read(&pci_bus_sem);
 172        n = from ? from->node.next : pci_root_buses.next;
 173        if (n != &pci_root_buses)
 174                b = list_entry(n, struct pci_bus, node);
 175        up_read(&pci_bus_sem);
 176        return b;
 177}
 178EXPORT_SYMBOL(pci_find_next_bus);
 179
 180/**
 181 * pci_get_slot - locate PCI device for a given PCI slot
 182 * @bus: PCI bus on which desired PCI device resides
 183 * @devfn: encodes number of PCI slot in which the desired PCI
 184 * device resides and the logical device number within that slot
 185 * in case of multi-function devices.
 186 *
 187 * Given a PCI bus and slot/function number, the desired PCI device
 188 * is located in the list of PCI devices.
 189 * If the device is found, its reference count is increased and this
 190 * function returns a pointer to its data structure.  The caller must
 191 * decrement the reference count by calling pci_dev_put().
 192 * If no device is found, %NULL is returned.
 193 */
 194struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn)
 195{
 196        struct pci_dev *dev;
 197
 198        down_read(&pci_bus_sem);
 199
 200        list_for_each_entry(dev, &bus->devices, bus_list) {
 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}
 211EXPORT_SYMBOL(pci_get_slot);
 212
 213/**
 214 * pci_get_domain_bus_and_slot - locate PCI device for a given PCI domain (segment), bus, and slot
 215 * @domain: PCI domain/segment on which the PCI device resides.
 216 * @bus: PCI bus on which desired PCI device resides
 217 * @devfn: encodes number of PCI slot in which the desired PCI device
 218 * resides and the logical device number within that slot in case of
 219 * multi-function devices.
 220 *
 221 * Given a PCI domain, bus, and slot/function number, the desired PCI
 222 * device is located in the list of PCI devices. If the device is
 223 * found, its reference count is increased and this function returns a
 224 * pointer to its data structure.  The caller must decrement the
 225 * reference count by calling pci_dev_put().  If no device is found,
 226 * %NULL is returned.
 227 */
 228struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus,
 229                                            unsigned int devfn)
 230{
 231        struct pci_dev *dev = NULL;
 232
 233        for_each_pci_dev(dev) {
 234                if (pci_domain_nr(dev->bus) == domain &&
 235                    (dev->bus->number == bus && dev->devfn == devfn))
 236                        return dev;
 237        }
 238        return NULL;
 239}
 240EXPORT_SYMBOL(pci_get_domain_bus_and_slot);
 241
 242static int match_pci_dev_by_id(struct device *dev, const void *data)
 243{
 244        struct pci_dev *pdev = to_pci_dev(dev);
 245        const struct pci_device_id *id = data;
 246
 247        if (pci_match_one_device(id, pdev))
 248                return 1;
 249        return 0;
 250}
 251
 252/*
 253 * pci_get_dev_by_id - begin or continue searching for a PCI device by id
 254 * @id: pointer to struct pci_device_id to match for the device
 255 * @from: Previous PCI device found in search, or %NULL for new search.
 256 *
 257 * Iterates through the list of known PCI devices.  If a PCI device is found
 258 * with a matching id a pointer to its device structure is returned, and the
 259 * reference count to the device is incremented.  Otherwise, %NULL is returned.
 260 * A new search is initiated by passing %NULL as the @from argument.  Otherwise
 261 * if @from is not %NULL, searches continue from next device on the global
 262 * list.  The reference count for @from is always decremented if it is not
 263 * %NULL.
 264 *
 265 * This is an internal function for use by the other search functions in
 266 * this file.
 267 */
 268static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
 269                                         struct pci_dev *from)
 270{
 271        struct device *dev;
 272        struct device *dev_start = NULL;
 273        struct pci_dev *pdev = NULL;
 274
 275        if (from)
 276                dev_start = &from->dev;
 277        dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
 278                              match_pci_dev_by_id);
 279        if (dev)
 280                pdev = to_pci_dev(dev);
 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_device_id id = {
 306                .vendor = vendor,
 307                .device = device,
 308                .subvendor = ss_vendor,
 309                .subdevice = ss_device,
 310        };
 311
 312        return pci_get_dev_by_id(&id, from);
 313}
 314EXPORT_SYMBOL(pci_get_subsys);
 315
 316/**
 317 * pci_get_device - begin or continue searching for a PCI device by vendor/device id
 318 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
 319 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
 320 * @from: Previous PCI device found in search, or %NULL for new search.
 321 *
 322 * Iterates through the list of known PCI devices.  If a PCI device is
 323 * found with a matching @vendor and @device, the reference count to the
 324 * device is incremented and a pointer to its device structure is returned.
 325 * Otherwise, %NULL is returned.  A new search is initiated by passing %NULL
 326 * as the @from argument.  Otherwise if @from is not %NULL, searches continue
 327 * from next device on the global list.  The reference count for @from is
 328 * always decremented if it is not %NULL.
 329 */
 330struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
 331                               struct pci_dev *from)
 332{
 333        return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
 334}
 335EXPORT_SYMBOL(pci_get_device);
 336
 337/**
 338 * pci_get_class - begin or continue searching for a PCI device by class
 339 * @class: search for a PCI device with this class designation
 340 * @from: Previous PCI device found in search, or %NULL for new search.
 341 *
 342 * Iterates through the list of known PCI devices.  If a PCI device is
 343 * found with a matching @class, the reference count to the device is
 344 * incremented and a pointer to its device structure is returned.
 345 * Otherwise, %NULL is returned.
 346 * A new search is initiated by passing %NULL as the @from argument.
 347 * Otherwise if @from is not %NULL, searches continue from next device
 348 * on the global list.  The reference count for @from is always decremented
 349 * if it is not %NULL.
 350 */
 351struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
 352{
 353        struct pci_device_id id = {
 354                .vendor = PCI_ANY_ID,
 355                .device = PCI_ANY_ID,
 356                .subvendor = PCI_ANY_ID,
 357                .subdevice = PCI_ANY_ID,
 358                .class_mask = PCI_ANY_ID,
 359                .class = class,
 360        };
 361
 362        return pci_get_dev_by_id(&id, from);
 363}
 364EXPORT_SYMBOL(pci_get_class);
 365
 366/**
 367 * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not.
 368 * @ids: A pointer to a null terminated list of struct pci_device_id structures
 369 * that describe the type of PCI device the caller is trying to find.
 370 *
 371 * Obvious fact: You do not have a reference to any device that might be found
 372 * by this function, so if that device is removed from the system right after
 373 * this function is finished, the value will be stale.  Use this function to
 374 * find devices that are usually built into a system, or for a general hint as
 375 * to if another device happens to be present at this specific moment in time.
 376 */
 377int pci_dev_present(const struct pci_device_id *ids)
 378{
 379        struct pci_dev *found = NULL;
 380
 381        while (ids->vendor || ids->subvendor || ids->class_mask) {
 382                found = pci_get_dev_by_id(ids, NULL);
 383                if (found) {
 384                        pci_dev_put(found);
 385                        return 1;
 386                }
 387                ids++;
 388        }
 389
 390        return 0;
 391}
 392EXPORT_SYMBOL(pci_dev_present);
 393