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        WARN_ON(in_interrupt());
 172        down_read(&pci_bus_sem);
 173        n = from ? from->node.next : pci_root_buses.next;
 174        if (n != &pci_root_buses)
 175                b = list_entry(n, struct pci_bus, node);
 176        up_read(&pci_bus_sem);
 177        return b;
 178}
 179EXPORT_SYMBOL(pci_find_next_bus);
 180
 181/**
 182 * pci_get_slot - locate PCI device for a given PCI slot
 183 * @bus: PCI bus on which desired PCI device resides
 184 * @devfn: encodes number of PCI slot in which the desired PCI
 185 * device resides and the logical device number within that slot
 186 * in case of multi-function devices.
 187 *
 188 * Given a PCI bus and slot/function number, the desired PCI device
 189 * is located in the list of PCI devices.
 190 * If the device is found, its reference count is increased and this
 191 * function returns a pointer to its data structure.  The caller must
 192 * decrement the reference count by calling pci_dev_put().
 193 * If no device is found, %NULL is returned.
 194 */
 195struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn)
 196{
 197        struct pci_dev *dev;
 198
 199        WARN_ON(in_interrupt());
 200        down_read(&pci_bus_sem);
 201
 202        list_for_each_entry(dev, &bus->devices, bus_list) {
 203                if (dev->devfn == devfn)
 204                        goto out;
 205        }
 206
 207        dev = NULL;
 208 out:
 209        pci_dev_get(dev);
 210        up_read(&pci_bus_sem);
 211        return dev;
 212}
 213EXPORT_SYMBOL(pci_get_slot);
 214
 215/**
 216 * pci_get_domain_bus_and_slot - locate PCI device for a given PCI domain (segment), bus, and slot
 217 * @domain: PCI domain/segment on which the PCI device resides.
 218 * @bus: PCI bus on which desired PCI device resides
 219 * @devfn: encodes number of PCI slot in which the desired PCI device
 220 * resides and the logical device number within that slot in case of
 221 * multi-function devices.
 222 *
 223 * Given a PCI domain, bus, and slot/function number, the desired PCI
 224 * device is located in the list of PCI devices. If the device is
 225 * found, its reference count is increased and this function returns a
 226 * pointer to its data structure.  The caller must decrement the
 227 * reference count by calling pci_dev_put().  If no device is found,
 228 * %NULL is returned.
 229 */
 230struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus,
 231                                            unsigned int devfn)
 232{
 233        struct pci_dev *dev = NULL;
 234
 235        for_each_pci_dev(dev) {
 236                if (pci_domain_nr(dev->bus) == domain &&
 237                    (dev->bus->number == bus && dev->devfn == devfn))
 238                        return dev;
 239        }
 240        return NULL;
 241}
 242EXPORT_SYMBOL(pci_get_domain_bus_and_slot);
 243
 244static int match_pci_dev_by_id(struct device *dev, const void *data)
 245{
 246        struct pci_dev *pdev = to_pci_dev(dev);
 247        const struct pci_device_id *id = data;
 248
 249        if (pci_match_one_device(id, pdev))
 250                return 1;
 251        return 0;
 252}
 253
 254/*
 255 * pci_get_dev_by_id - begin or continue searching for a PCI device by id
 256 * @id: pointer to struct pci_device_id to match for the device
 257 * @from: Previous PCI device found in search, or %NULL for new search.
 258 *
 259 * Iterates through the list of known PCI devices.  If a PCI device is found
 260 * with a matching id a pointer to its device structure is returned, and the
 261 * reference count to the device is incremented.  Otherwise, %NULL is returned.
 262 * A new search is initiated by passing %NULL as the @from argument.  Otherwise
 263 * if @from is not %NULL, searches continue from next device on the global
 264 * list.  The reference count for @from is always decremented if it is not
 265 * %NULL.
 266 *
 267 * This is an internal function for use by the other search functions in
 268 * this file.
 269 */
 270static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
 271                                         struct pci_dev *from)
 272{
 273        struct device *dev;
 274        struct device *dev_start = NULL;
 275        struct pci_dev *pdev = NULL;
 276
 277        WARN_ON(in_interrupt());
 278        if (from)
 279                dev_start = &from->dev;
 280        dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
 281                              match_pci_dev_by_id);
 282        if (dev)
 283                pdev = to_pci_dev(dev);
 284        pci_dev_put(from);
 285        return pdev;
 286}
 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 *pci_get_subsys(unsigned int vendor, unsigned int device,
 305                               unsigned int ss_vendor, unsigned int ss_device,
 306                               struct pci_dev *from)
 307{
 308        struct pci_device_id id = {
 309                .vendor = vendor,
 310                .device = device,
 311                .subvendor = ss_vendor,
 312                .subdevice = ss_device,
 313        };
 314
 315        return pci_get_dev_by_id(&id, from);
 316}
 317EXPORT_SYMBOL(pci_get_subsys);
 318
 319/**
 320 * pci_get_device - begin or continue searching for a PCI device by vendor/device id
 321 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
 322 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
 323 * @from: Previous PCI device found in search, or %NULL for new search.
 324 *
 325 * Iterates through the list of known PCI devices.  If a PCI device is
 326 * found with a matching @vendor and @device, the reference count to the
 327 * device is incremented and a pointer to its device structure is returned.
 328 * Otherwise, %NULL is returned.  A new search is initiated by passing %NULL
 329 * as the @from argument.  Otherwise if @from is not %NULL, searches continue
 330 * from next device on the global list.  The reference count for @from is
 331 * always decremented if it is not %NULL.
 332 */
 333struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
 334                               struct pci_dev *from)
 335{
 336        return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
 337}
 338EXPORT_SYMBOL(pci_get_device);
 339
 340/**
 341 * pci_get_class - begin or continue searching for a PCI device by class
 342 * @class: search for a PCI device with this class designation
 343 * @from: Previous PCI device found in search, or %NULL for new search.
 344 *
 345 * Iterates through the list of known PCI devices.  If a PCI device is
 346 * found with a matching @class, the reference count to the device is
 347 * incremented and a pointer to its device structure is returned.
 348 * Otherwise, %NULL is returned.
 349 * A new search is initiated by passing %NULL as the @from argument.
 350 * Otherwise if @from is not %NULL, searches continue from next device
 351 * on the global list.  The reference count for @from is always decremented
 352 * if it is not %NULL.
 353 */
 354struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
 355{
 356        struct pci_device_id id = {
 357                .vendor = PCI_ANY_ID,
 358                .device = PCI_ANY_ID,
 359                .subvendor = PCI_ANY_ID,
 360                .subdevice = PCI_ANY_ID,
 361                .class_mask = PCI_ANY_ID,
 362                .class = class,
 363        };
 364
 365        return pci_get_dev_by_id(&id, from);
 366}
 367EXPORT_SYMBOL(pci_get_class);
 368
 369/**
 370 * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not.
 371 * @ids: A pointer to a null terminated list of struct pci_device_id structures
 372 * that describe the type of PCI device the caller is trying to find.
 373 *
 374 * Obvious fact: You do not have a reference to any device that might be found
 375 * by this function, so if that device is removed from the system right after
 376 * this function is finished, the value will be stale.  Use this function to
 377 * find devices that are usually built into a system, or for a general hint as
 378 * to if another device happens to be present at this specific moment in time.
 379 */
 380int pci_dev_present(const struct pci_device_id *ids)
 381{
 382        struct pci_dev *found = NULL;
 383
 384        WARN_ON(in_interrupt());
 385        while (ids->vendor || ids->subvendor || ids->class_mask) {
 386                found = pci_get_dev_by_id(ids, NULL);
 387                if (found) {
 388                        pci_dev_put(found);
 389                        return 1;
 390                }
 391                ids++;
 392        }
 393
 394        return 0;
 395}
 396EXPORT_SYMBOL(pci_dev_present);
 397