LCOV - code coverage report
Current view: top level - drivers/pci - search.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 60 118 50.8 %
Date: 2022-03-28 16:04:14 Functions: 9 12 75.0 %
Branches: 24 78 30.8 %

           Branch data     Line data    Source code
       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                 :            : 
      17                 :            : DECLARE_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                 :            :  */
      28                 :         91 : int 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                 :         91 :         struct pci_bus *bus;
      33                 :         91 :         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                 :         91 :         pdev = pci_real_dma_dev(pdev);
      40                 :            : 
      41                 :         91 :         ret = fn(pdev, pci_dev_id(pdev), data);
      42         [ +  - ]:         91 :         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         [ -  + ]:         91 :         if (unlikely(pdev->dma_alias_mask)) {
      50                 :          0 :                 unsigned int devfn;
      51                 :            : 
      52         [ #  # ]:          0 :                 for_each_set_bit(devfn, pdev->dma_alias_mask, MAX_NR_DEVFNS) {
      53                 :          0 :                         ret = fn(pdev, PCI_DEVID(pdev->bus->number, devfn),
      54                 :            :                                  data);
      55         [ #  # ]:          0 :                         if (ret)
      56                 :          0 :                                 return ret;
      57                 :            :                 }
      58                 :            :         }
      59                 :            : 
      60         [ -  + ]:         91 :         for (bus = pdev->bus; !pci_is_root_bus(bus); bus = bus->parent) {
      61                 :          0 :                 struct pci_dev *tmp;
      62                 :            : 
      63                 :            :                 /* Skip virtual buses */
      64         [ #  # ]:          0 :                 if (!bus->self)
      65                 :          0 :                         continue;
      66                 :            : 
      67                 :          0 :                 tmp = bus->self;
      68                 :            : 
      69                 :            :                 /* stop at bridge where translation unit is associated */
      70         [ #  # ]:          0 :                 if (tmp->dev_flags & PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT)
      71                 :          0 :                         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         [ #  # ]:          0 :                 if (pci_is_pcie(tmp)) {
      83   [ #  #  #  # ]:          0 :                         switch (pci_pcie_type(tmp)) {
      84                 :          0 :                         case PCI_EXP_TYPE_ROOT_PORT:
      85                 :            :                         case PCI_EXP_TYPE_UPSTREAM:
      86                 :            :                         case PCI_EXP_TYPE_DOWNSTREAM:
      87                 :          0 :                                 continue;
      88                 :          0 :                         case PCI_EXP_TYPE_PCI_BRIDGE:
      89                 :          0 :                                 ret = fn(tmp,
      90                 :          0 :                                          PCI_DEVID(tmp->subordinate->number,
      91                 :            :                                                    PCI_DEVFN(0, 0)), data);
      92         [ #  # ]:          0 :                                 if (ret)
      93                 :          0 :                                         return ret;
      94                 :          0 :                                 continue;
      95                 :          0 :                         case PCI_EXP_TYPE_PCIE_BRIDGE:
      96                 :          0 :                                 ret = fn(tmp, pci_dev_id(tmp), data);
      97         [ #  # ]:          0 :                                 if (ret)
      98                 :          0 :                                         return ret;
      99                 :          0 :                                 continue;
     100                 :            :                         }
     101                 :            :                 } else {
     102         [ #  # ]:          0 :                         if (tmp->dev_flags & PCI_DEV_FLAG_PCIE_BRIDGE_ALIAS)
     103                 :          0 :                                 ret = fn(tmp,
     104                 :          0 :                                          PCI_DEVID(tmp->subordinate->number,
     105                 :            :                                                    PCI_DEVFN(0, 0)), data);
     106                 :            :                         else
     107                 :          0 :                                 ret = fn(tmp, pci_dev_id(tmp), data);
     108         [ #  # ]:          0 :                         if (ret)
     109                 :          0 :                                 return ret;
     110                 :            :                 }
     111                 :            :         }
     112                 :            : 
     113                 :            :         return ret;
     114                 :            : }
     115                 :            : 
     116                 :          0 : static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
     117                 :            : {
     118                 :          0 :         struct pci_bus *child;
     119                 :          0 :         struct pci_bus *tmp;
     120                 :            : 
     121         [ #  # ]:          0 :         if (bus->number == busnr)
     122                 :            :                 return bus;
     123                 :            : 
     124         [ #  # ]:          0 :         list_for_each_entry(tmp, &bus->children, node) {
     125                 :          0 :                 child = pci_do_find_bus(tmp, busnr);
     126         [ #  # ]:          0 :                 if (child)
     127                 :          0 :                         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                 :            :  */
     141                 :         26 : struct pci_bus *pci_find_bus(int domain, int busnr)
     142                 :            : {
     143                 :         26 :         struct pci_bus *bus = NULL;
     144                 :         26 :         struct pci_bus *tmp_bus;
     145                 :            : 
     146         [ -  + ]:         26 :         while ((bus = pci_find_next_bus(bus)) != NULL)  {
     147         [ #  # ]:          0 :                 if (pci_domain_nr(bus) != domain)
     148                 :          0 :                         continue;
     149                 :          0 :                 tmp_bus = pci_do_find_bus(bus, busnr);
     150         [ #  # ]:          0 :                 if (tmp_bus)
     151                 :          0 :                         return tmp_bus;
     152                 :            :         }
     153                 :            :         return NULL;
     154                 :            : }
     155                 :            : EXPORT_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                 :            :  */
     166                 :         26 : struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
     167                 :            : {
     168                 :         26 :         struct list_head *n;
     169                 :         26 :         struct pci_bus *b = NULL;
     170                 :            : 
     171         [ -  + ]:         26 :         WARN_ON(in_interrupt());
     172                 :         26 :         down_read(&pci_bus_sem);
     173         [ -  + ]:         26 :         n = from ? from->node.next : pci_root_buses.next;
     174         [ -  + ]:         26 :         if (n != &pci_root_buses)
     175                 :          0 :                 b = list_entry(n, struct pci_bus, node);
     176                 :         26 :         up_read(&pci_bus_sem);
     177                 :         26 :         return b;
     178                 :            : }
     179                 :            : EXPORT_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                 :            :  */
     195                 :        507 : struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn)
     196                 :            : {
     197                 :        507 :         struct pci_dev *dev;
     198                 :            : 
     199         [ -  + ]:        507 :         WARN_ON(in_interrupt());
     200                 :        507 :         down_read(&pci_bus_sem);
     201                 :            : 
     202         [ +  + ]:       3484 :         list_for_each_entry(dev, &bus->devices, bus_list) {
     203         [ -  + ]:       2977 :                 if (dev->devfn == devfn)
     204                 :          0 :                         goto out;
     205                 :            :         }
     206                 :            : 
     207                 :            :         dev = NULL;
     208                 :        507 :  out:
     209                 :        507 :         pci_dev_get(dev);
     210                 :        507 :         up_read(&pci_bus_sem);
     211                 :        507 :         return dev;
     212                 :            : }
     213                 :            : EXPORT_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                 :            :  */
     230                 :          0 : struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus,
     231                 :            :                                             unsigned int devfn)
     232                 :            : {
     233                 :          0 :         struct pci_dev *dev = NULL;
     234                 :            : 
     235         [ #  # ]:          0 :         for_each_pci_dev(dev) {
     236         [ #  # ]:          0 :                 if (pci_domain_nr(dev->bus) == domain &&
     237   [ #  #  #  # ]:          0 :                     (dev->bus->number == bus && dev->devfn == devfn))
     238                 :          0 :                         return dev;
     239                 :            :         }
     240                 :            :         return NULL;
     241                 :            : }
     242                 :            : EXPORT_SYMBOL(pci_get_domain_bus_and_slot);
     243                 :            : 
     244                 :       5694 : static int match_pci_dev_by_id(struct device *dev, const void *data)
     245                 :            : {
     246                 :       5694 :         struct pci_dev *pdev = to_pci_dev(dev);
     247                 :       5694 :         const struct pci_device_id *id = data;
     248                 :            : 
     249         [ +  + ]:       5694 :         if (pci_match_one_device(id, pdev))
     250                 :        754 :                 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                 :            :  */
     270                 :       1560 : static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
     271                 :            :                                          struct pci_dev *from)
     272                 :            : {
     273                 :       1560 :         struct device *dev;
     274                 :       1560 :         struct device *dev_start = NULL;
     275                 :       1560 :         struct pci_dev *pdev = NULL;
     276                 :            : 
     277         [ -  + ]:       1560 :         WARN_ON(in_interrupt());
     278         [ +  + ]:       1560 :         if (from)
     279                 :        741 :                 dev_start = &from->dev;
     280                 :       1560 :         dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
     281                 :            :                               match_pci_dev_by_id);
     282         [ +  + ]:       1560 :         if (dev)
     283                 :        754 :                 pdev = to_pci_dev(dev);
     284                 :       1560 :         pci_dev_put(from);
     285                 :       1560 :         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                 :            :  */
     304                 :       1378 : struct 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                 :       1378 :         struct pci_device_id id = {
     309                 :            :                 .vendor = vendor,
     310                 :            :                 .device = device,
     311                 :            :                 .subvendor = ss_vendor,
     312                 :            :                 .subdevice = ss_device,
     313                 :            :         };
     314                 :            : 
     315                 :        143 :         return pci_get_dev_by_id(&id, from);
     316                 :            : }
     317                 :            : EXPORT_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                 :            :  */
     333                 :       1235 : struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
     334                 :            :                                struct pci_dev *from)
     335                 :            : {
     336                 :       1235 :         return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
     337                 :            : }
     338                 :            : EXPORT_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                 :            :  */
     354                 :          0 : struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
     355                 :            : {
     356                 :          0 :         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                 :          0 :         return pci_get_dev_by_id(&id, from);
     366                 :            : }
     367                 :            : EXPORT_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                 :            :  */
     380                 :         13 : int pci_dev_present(const struct pci_device_id *ids)
     381                 :            : {
     382                 :         13 :         struct pci_dev *found = NULL;
     383                 :            : 
     384         [ -  + ]:         13 :         WARN_ON(in_interrupt());
     385   [ +  +  -  +  :        195 :         while (ids->vendor || ids->subvendor || ids->class_mask) {
                   -  + ]
     386                 :        182 :                 found = pci_get_dev_by_id(ids, NULL);
     387         [ -  + ]:        182 :                 if (found) {
     388                 :          0 :                         pci_dev_put(found);
     389                 :          0 :                         return 1;
     390                 :            :                 }
     391                 :        182 :                 ids++;
     392                 :            :         }
     393                 :            : 
     394                 :            :         return 0;
     395                 :            : }
     396                 :            : EXPORT_SYMBOL(pci_dev_present);

Generated by: LCOV version 1.14