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