LCOV - code coverage report
Current view: top level - drivers/pci/pcie - portdrv_core.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 8 223 3.6 %
Date: 2022-03-28 13:20:08 Functions: 1 23 4.3 %
Branches: 1 128 0.8 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * Purpose:     PCI Express Port Bus Driver's Core Functions
       4                 :            :  *
       5                 :            :  * Copyright (C) 2004 Intel
       6                 :            :  * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
       7                 :            :  */
       8                 :            : 
       9                 :            : #include <linux/module.h>
      10                 :            : #include <linux/pci.h>
      11                 :            : #include <linux/kernel.h>
      12                 :            : #include <linux/errno.h>
      13                 :            : #include <linux/pm.h>
      14                 :            : #include <linux/pm_runtime.h>
      15                 :            : #include <linux/string.h>
      16                 :            : #include <linux/slab.h>
      17                 :            : #include <linux/aer.h>
      18                 :            : 
      19                 :            : #include "../pci.h"
      20                 :            : #include "portdrv.h"
      21                 :            : 
      22                 :            : struct portdrv_service_data {
      23                 :            :         struct pcie_port_service_driver *drv;
      24                 :            :         struct device *dev;
      25                 :            :         u32 service;
      26                 :            : };
      27                 :            : 
      28                 :            : /**
      29                 :            :  * release_pcie_device - free PCI Express port service device structure
      30                 :            :  * @dev: Port service device to release
      31                 :            :  *
      32                 :            :  * Invoked automatically when device is being removed in response to
      33                 :            :  * device_unregister(dev).  Release all resources being claimed.
      34                 :            :  */
      35                 :          0 : static void release_pcie_device(struct device *dev)
      36                 :            : {
      37                 :          0 :         kfree(to_pcie_device(dev));
      38                 :          0 : }
      39                 :            : 
      40                 :            : /*
      41                 :            :  * Fill in *pme, *aer, *dpc with the relevant Interrupt Message Numbers if
      42                 :            :  * services are enabled in "mask".  Return the number of MSI/MSI-X vectors
      43                 :            :  * required to accommodate the largest Message Number.
      44                 :            :  */
      45                 :          0 : static int pcie_message_numbers(struct pci_dev *dev, int mask,
      46                 :            :                                 u32 *pme, u32 *aer, u32 *dpc)
      47                 :            : {
      48                 :          0 :         u32 nvec = 0, pos;
      49                 :          0 :         u16 reg16;
      50                 :            : 
      51                 :            :         /*
      52                 :            :          * The Interrupt Message Number indicates which vector is used, i.e.,
      53                 :            :          * the MSI-X table entry or the MSI offset between the base Message
      54                 :            :          * Data and the generated interrupt message.  See PCIe r3.1, sec
      55                 :            :          * 7.8.2, 7.10.10, 7.31.2.
      56                 :            :          */
      57                 :            : 
      58         [ #  # ]:          0 :         if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP |
      59                 :            :                     PCIE_PORT_SERVICE_BWNOTIF)) {
      60                 :          0 :                 pcie_capability_read_word(dev, PCI_EXP_FLAGS, &reg16);
      61                 :          0 :                 *pme = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
      62                 :          0 :                 nvec = *pme + 1;
      63                 :            :         }
      64                 :            : 
      65                 :            : #ifdef CONFIG_PCIEAER
      66         [ #  # ]:          0 :         if (mask & PCIE_PORT_SERVICE_AER) {
      67                 :          0 :                 u32 reg32;
      68                 :            : 
      69                 :          0 :                 pos = dev->aer_cap;
      70         [ #  # ]:          0 :                 if (pos) {
      71                 :          0 :                         pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS,
      72                 :            :                                               &reg32);
      73                 :          0 :                         *aer = (reg32 & PCI_ERR_ROOT_AER_IRQ) >> 27;
      74                 :          0 :                         nvec = max(nvec, *aer + 1);
      75                 :            :                 }
      76                 :            :         }
      77                 :            : #endif
      78                 :            : 
      79         [ #  # ]:          0 :         if (mask & PCIE_PORT_SERVICE_DPC) {
      80                 :          0 :                 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC);
      81         [ #  # ]:          0 :                 if (pos) {
      82                 :          0 :                         pci_read_config_word(dev, pos + PCI_EXP_DPC_CAP,
      83                 :            :                                              &reg16);
      84                 :          0 :                         *dpc = reg16 & PCI_EXP_DPC_IRQ;
      85                 :          0 :                         nvec = max(nvec, *dpc + 1);
      86                 :            :                 }
      87                 :            :         }
      88                 :            : 
      89                 :          0 :         return nvec;
      90                 :            : }
      91                 :            : 
      92                 :            : /**
      93                 :            :  * pcie_port_enable_irq_vec - try to set up MSI-X or MSI as interrupt mode
      94                 :            :  * for given port
      95                 :            :  * @dev: PCI Express port to handle
      96                 :            :  * @irqs: Array of interrupt vectors to populate
      97                 :            :  * @mask: Bitmask of port capabilities returned by get_port_device_capability()
      98                 :            :  *
      99                 :            :  * Return value: 0 on success, error code on failure
     100                 :            :  */
     101                 :          0 : static int pcie_port_enable_irq_vec(struct pci_dev *dev, int *irqs, int mask)
     102                 :            : {
     103                 :          0 :         int nr_entries, nvec, pcie_irq;
     104                 :          0 :         u32 pme = 0, aer = 0, dpc = 0;
     105                 :            : 
     106                 :            :         /* Allocate the maximum possible number of MSI/MSI-X vectors */
     107                 :          0 :         nr_entries = pci_alloc_irq_vectors(dev, 1, PCIE_PORT_MAX_MSI_ENTRIES,
     108                 :            :                         PCI_IRQ_MSIX | PCI_IRQ_MSI);
     109         [ #  # ]:          0 :         if (nr_entries < 0)
     110                 :            :                 return nr_entries;
     111                 :            : 
     112                 :            :         /* See how many and which Interrupt Message Numbers we actually use */
     113                 :          0 :         nvec = pcie_message_numbers(dev, mask, &pme, &aer, &dpc);
     114         [ #  # ]:          0 :         if (nvec > nr_entries) {
     115                 :          0 :                 pci_free_irq_vectors(dev);
     116                 :          0 :                 return -EIO;
     117                 :            :         }
     118                 :            : 
     119                 :            :         /*
     120                 :            :          * If we allocated more than we need, free them and reallocate fewer.
     121                 :            :          *
     122                 :            :          * Reallocating may change the specific vectors we get, so
     123                 :            :          * pci_irq_vector() must be done *after* the reallocation.
     124                 :            :          *
     125                 :            :          * If we're using MSI, hardware is *allowed* to change the Interrupt
     126                 :            :          * Message Numbers when we free and reallocate the vectors, but we
     127                 :            :          * assume it won't because we allocate enough vectors for the
     128                 :            :          * biggest Message Number we found.
     129                 :            :          */
     130         [ #  # ]:          0 :         if (nvec != nr_entries) {
     131                 :          0 :                 pci_free_irq_vectors(dev);
     132                 :            : 
     133                 :          0 :                 nr_entries = pci_alloc_irq_vectors(dev, nvec, nvec,
     134                 :            :                                 PCI_IRQ_MSIX | PCI_IRQ_MSI);
     135         [ #  # ]:          0 :                 if (nr_entries < 0)
     136                 :            :                         return nr_entries;
     137                 :            :         }
     138                 :            : 
     139                 :            :         /* PME, hotplug and bandwidth notification share an MSI/MSI-X vector */
     140         [ #  # ]:          0 :         if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP |
     141                 :            :                     PCIE_PORT_SERVICE_BWNOTIF)) {
     142                 :          0 :                 pcie_irq = pci_irq_vector(dev, pme);
     143                 :          0 :                 irqs[PCIE_PORT_SERVICE_PME_SHIFT] = pcie_irq;
     144                 :          0 :                 irqs[PCIE_PORT_SERVICE_HP_SHIFT] = pcie_irq;
     145                 :          0 :                 irqs[PCIE_PORT_SERVICE_BWNOTIF_SHIFT] = pcie_irq;
     146                 :            :         }
     147                 :            : 
     148         [ #  # ]:          0 :         if (mask & PCIE_PORT_SERVICE_AER)
     149                 :          0 :                 irqs[PCIE_PORT_SERVICE_AER_SHIFT] = pci_irq_vector(dev, aer);
     150                 :            : 
     151         [ #  # ]:          0 :         if (mask & PCIE_PORT_SERVICE_DPC)
     152                 :          0 :                 irqs[PCIE_PORT_SERVICE_DPC_SHIFT] = pci_irq_vector(dev, dpc);
     153                 :            : 
     154                 :            :         return 0;
     155                 :            : }
     156                 :            : 
     157                 :            : /**
     158                 :            :  * pcie_init_service_irqs - initialize irqs for PCI Express port services
     159                 :            :  * @dev: PCI Express port to handle
     160                 :            :  * @irqs: Array of irqs to populate
     161                 :            :  * @mask: Bitmask of port capabilities returned by get_port_device_capability()
     162                 :            :  *
     163                 :            :  * Return value: Interrupt mode associated with the port
     164                 :            :  */
     165                 :          0 : static int pcie_init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
     166                 :            : {
     167                 :          0 :         int ret, i;
     168                 :            : 
     169         [ #  # ]:          0 :         for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
     170                 :          0 :                 irqs[i] = -1;
     171                 :            : 
     172                 :            :         /*
     173                 :            :          * If we support PME but can't use MSI/MSI-X for it, we have to
     174                 :            :          * fall back to INTx or other interrupts, e.g., a system shared
     175                 :            :          * interrupt.
     176                 :            :          */
     177   [ #  #  #  # ]:          0 :         if ((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi())
     178                 :          0 :                 goto legacy_irq;
     179                 :            : 
     180                 :            :         /* Try to use MSI-X or MSI if supported */
     181         [ #  # ]:          0 :         if (pcie_port_enable_irq_vec(dev, irqs, mask) == 0)
     182                 :            :                 return 0;
     183                 :            : 
     184                 :          0 : legacy_irq:
     185                 :            :         /* fall back to legacy IRQ */
     186                 :          0 :         ret = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY);
     187         [ #  # ]:          0 :         if (ret < 0)
     188                 :            :                 return -ENODEV;
     189                 :            : 
     190         [ #  # ]:          0 :         for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
     191                 :          0 :                 irqs[i] = pci_irq_vector(dev, 0);
     192                 :            : 
     193                 :            :         return 0;
     194                 :            : }
     195                 :            : 
     196                 :            : /**
     197                 :            :  * get_port_device_capability - discover capabilities of a PCI Express port
     198                 :            :  * @dev: PCI Express port to examine
     199                 :            :  *
     200                 :            :  * The capabilities are read from the port's PCI Express configuration registers
     201                 :            :  * as described in PCI Express Base Specification 1.0a sections 7.8.2, 7.8.9 and
     202                 :            :  * 7.9 - 7.11.
     203                 :            :  *
     204                 :            :  * Return value: Bitmask of discovered port capabilities
     205                 :            :  */
     206                 :          0 : static int get_port_device_capability(struct pci_dev *dev)
     207                 :            : {
     208                 :          0 :         struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
     209                 :          0 :         int services = 0;
     210                 :            : 
     211         [ #  # ]:          0 :         if (dev->is_hotplug_bridge &&
     212   [ #  #  #  # ]:          0 :             (pcie_ports_native || host->native_pcie_hotplug)) {
     213                 :          0 :                 services |= PCIE_PORT_SERVICE_HP;
     214                 :            : 
     215                 :            :                 /*
     216                 :            :                  * Disable hot-plug interrupts in case they have been enabled
     217                 :            :                  * by the BIOS and the hot-plug service driver is not loaded.
     218                 :            :                  */
     219                 :          0 :                 pcie_capability_clear_word(dev, PCI_EXP_SLTCTL,
     220                 :            :                           PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
     221                 :            :         }
     222                 :            : 
     223                 :            : #ifdef CONFIG_PCIEAER
     224   [ #  #  #  # ]:          0 :         if (dev->aer_cap && pci_aer_available() &&
     225   [ #  #  #  # ]:          0 :             (pcie_ports_native || host->native_aer)) {
     226                 :          0 :                 services |= PCIE_PORT_SERVICE_AER;
     227                 :            : 
     228                 :            :                 /*
     229                 :            :                  * Disable AER on this port in case it's been enabled by the
     230                 :            :                  * BIOS (the AER service driver will enable it when necessary).
     231                 :            :                  */
     232                 :          0 :                 pci_disable_pcie_error_reporting(dev);
     233                 :            :         }
     234                 :            : #endif
     235                 :            : 
     236                 :            :         /*
     237                 :            :          * Root ports are capable of generating PME too.  Root Complex
     238                 :            :          * Event Collectors can also generate PMEs, but we don't handle
     239                 :            :          * those yet.
     240                 :            :          */
     241         [ #  # ]:          0 :         if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT &&
     242   [ #  #  #  # ]:          0 :             (pcie_ports_native || host->native_pme)) {
     243                 :          0 :                 services |= PCIE_PORT_SERVICE_PME;
     244                 :            : 
     245                 :            :                 /*
     246                 :            :                  * Disable PME interrupt on this port in case it's been enabled
     247                 :            :                  * by the BIOS (the PME service driver will enable it when
     248                 :            :                  * necessary).
     249                 :            :                  */
     250                 :          0 :                 pcie_pme_interrupt_enable(dev, false);
     251                 :            :         }
     252                 :            : 
     253                 :            :         /*
     254                 :            :          * With dpc-native, allow Linux to use DPC even if it doesn't have
     255                 :            :          * permission to use AER.
     256                 :            :          */
     257   [ #  #  #  # ]:          0 :         if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC) &&
     258                 :          0 :             pci_aer_available() &&
     259   [ #  #  #  # ]:          0 :             (pcie_ports_dpc_native || (services & PCIE_PORT_SERVICE_AER)))
     260                 :          0 :                 services |= PCIE_PORT_SERVICE_DPC;
     261                 :            : 
     262   [ #  #  #  # ]:          0 :         if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM ||
     263                 :            :             pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
     264                 :          0 :                 services |= PCIE_PORT_SERVICE_BWNOTIF;
     265                 :            : 
     266                 :          0 :         return services;
     267                 :            : }
     268                 :            : 
     269                 :            : /**
     270                 :            :  * pcie_device_init - allocate and initialize PCI Express port service device
     271                 :            :  * @pdev: PCI Express port to associate the service device with
     272                 :            :  * @service: Type of service to associate with the service device
     273                 :            :  * @irq: Interrupt vector to associate with the service device
     274                 :            :  */
     275                 :          0 : static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
     276                 :            : {
     277                 :          0 :         int retval;
     278                 :          0 :         struct pcie_device *pcie;
     279                 :          0 :         struct device *device;
     280                 :            : 
     281                 :          0 :         pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
     282         [ #  # ]:          0 :         if (!pcie)
     283                 :            :                 return -ENOMEM;
     284                 :          0 :         pcie->port = pdev;
     285                 :          0 :         pcie->irq = irq;
     286                 :          0 :         pcie->service = service;
     287                 :            : 
     288                 :            :         /* Initialize generic device interface */
     289                 :          0 :         device = &pcie->device;
     290                 :          0 :         device->bus = &pcie_port_bus_type;
     291                 :          0 :         device->release = release_pcie_device;       /* callback to free pcie dev */
     292         [ #  # ]:          0 :         dev_set_name(device, "%s:pcie%03x",
     293                 :            :                      pci_name(pdev),
     294         [ #  # ]:          0 :                      get_descriptor_id(pci_pcie_type(pdev), service));
     295                 :          0 :         device->parent = &pdev->dev;
     296         [ #  # ]:          0 :         device_enable_async_suspend(device);
     297                 :            : 
     298                 :          0 :         retval = device_register(device);
     299         [ #  # ]:          0 :         if (retval) {
     300                 :          0 :                 put_device(device);
     301                 :          0 :                 return retval;
     302                 :            :         }
     303                 :            : 
     304                 :          0 :         pm_runtime_no_callbacks(device);
     305                 :            : 
     306                 :          0 :         return 0;
     307                 :            : }
     308                 :            : 
     309                 :            : /**
     310                 :            :  * pcie_port_device_register - register PCI Express port
     311                 :            :  * @dev: PCI Express port to register
     312                 :            :  *
     313                 :            :  * Allocate the port extension structure and register services associated with
     314                 :            :  * the port.
     315                 :            :  */
     316                 :          0 : int pcie_port_device_register(struct pci_dev *dev)
     317                 :            : {
     318                 :          0 :         int status, capabilities, i, nr_service;
     319                 :          0 :         int irqs[PCIE_PORT_DEVICE_MAXSERVICES];
     320                 :            : 
     321                 :            :         /* Enable PCI Express port device */
     322                 :          0 :         status = pci_enable_device(dev);
     323         [ #  # ]:          0 :         if (status)
     324                 :            :                 return status;
     325                 :            : 
     326                 :            :         /* Get and check PCI Express port services */
     327                 :          0 :         capabilities = get_port_device_capability(dev);
     328         [ #  # ]:          0 :         if (!capabilities)
     329                 :            :                 return 0;
     330                 :            : 
     331                 :          0 :         pci_set_master(dev);
     332                 :            :         /*
     333                 :            :          * Initialize service irqs. Don't use service devices that
     334                 :            :          * require interrupts if there is no way to generate them.
     335                 :            :          * However, some drivers may have a polling mode (e.g. pciehp_poll_mode)
     336                 :            :          * that can be used in the absence of irqs.  Allow them to determine
     337                 :            :          * if that is to be used.
     338                 :            :          */
     339                 :          0 :         status = pcie_init_service_irqs(dev, irqs, capabilities);
     340         [ #  # ]:          0 :         if (status) {
     341                 :          0 :                 capabilities &= PCIE_PORT_SERVICE_HP;
     342         [ #  # ]:          0 :                 if (!capabilities)
     343                 :          0 :                         goto error_disable;
     344                 :            :         }
     345                 :            : 
     346                 :            :         /* Allocate child services if any */
     347                 :          0 :         status = -ENODEV;
     348                 :          0 :         nr_service = 0;
     349         [ #  # ]:          0 :         for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
     350                 :          0 :                 int service = 1 << i;
     351         [ #  # ]:          0 :                 if (!(capabilities & service))
     352                 :          0 :                         continue;
     353         [ #  # ]:          0 :                 if (!pcie_device_init(dev, service, irqs[i]))
     354                 :          0 :                         nr_service++;
     355                 :            :         }
     356         [ #  # ]:          0 :         if (!nr_service)
     357                 :          0 :                 goto error_cleanup_irqs;
     358                 :            : 
     359                 :            :         return 0;
     360                 :            : 
     361                 :            : error_cleanup_irqs:
     362                 :          0 :         pci_free_irq_vectors(dev);
     363                 :          0 : error_disable:
     364                 :          0 :         pci_disable_device(dev);
     365                 :          0 :         return status;
     366                 :            : }
     367                 :            : 
     368                 :            : #ifdef CONFIG_PM
     369                 :            : typedef int (*pcie_pm_callback_t)(struct pcie_device *);
     370                 :            : 
     371                 :          0 : static int pm_iter(struct device *dev, void *data)
     372                 :            : {
     373                 :          0 :         struct pcie_port_service_driver *service_driver;
     374                 :          0 :         size_t offset = *(size_t *)data;
     375                 :          0 :         pcie_pm_callback_t cb;
     376                 :            : 
     377   [ #  #  #  # ]:          0 :         if ((dev->bus == &pcie_port_bus_type) && dev->driver) {
     378                 :          0 :                 service_driver = to_service_driver(dev->driver);
     379                 :          0 :                 cb = *(pcie_pm_callback_t *)((void *)service_driver + offset);
     380         [ #  # ]:          0 :                 if (cb)
     381                 :          0 :                         return cb(to_pcie_device(dev));
     382                 :            :         }
     383                 :            :         return 0;
     384                 :            : }
     385                 :            : 
     386                 :            : /**
     387                 :            :  * pcie_port_device_suspend - suspend port services associated with a PCIe port
     388                 :            :  * @dev: PCI Express port to handle
     389                 :            :  */
     390                 :          0 : int pcie_port_device_suspend(struct device *dev)
     391                 :            : {
     392                 :          0 :         size_t off = offsetof(struct pcie_port_service_driver, suspend);
     393                 :          0 :         return device_for_each_child(dev, &off, pm_iter);
     394                 :            : }
     395                 :            : 
     396                 :          0 : int pcie_port_device_resume_noirq(struct device *dev)
     397                 :            : {
     398                 :          0 :         size_t off = offsetof(struct pcie_port_service_driver, resume_noirq);
     399                 :          0 :         return device_for_each_child(dev, &off, pm_iter);
     400                 :            : }
     401                 :            : 
     402                 :            : /**
     403                 :            :  * pcie_port_device_resume - resume port services associated with a PCIe port
     404                 :            :  * @dev: PCI Express port to handle
     405                 :            :  */
     406                 :          0 : int pcie_port_device_resume(struct device *dev)
     407                 :            : {
     408                 :          0 :         size_t off = offsetof(struct pcie_port_service_driver, resume);
     409                 :          0 :         return device_for_each_child(dev, &off, pm_iter);
     410                 :            : }
     411                 :            : 
     412                 :            : /**
     413                 :            :  * pcie_port_device_runtime_suspend - runtime suspend port services
     414                 :            :  * @dev: PCI Express port to handle
     415                 :            :  */
     416                 :          0 : int pcie_port_device_runtime_suspend(struct device *dev)
     417                 :            : {
     418                 :          0 :         size_t off = offsetof(struct pcie_port_service_driver, runtime_suspend);
     419                 :          0 :         return device_for_each_child(dev, &off, pm_iter);
     420                 :            : }
     421                 :            : 
     422                 :            : /**
     423                 :            :  * pcie_port_device_runtime_resume - runtime resume port services
     424                 :            :  * @dev: PCI Express port to handle
     425                 :            :  */
     426                 :          0 : int pcie_port_device_runtime_resume(struct device *dev)
     427                 :            : {
     428                 :          0 :         size_t off = offsetof(struct pcie_port_service_driver, runtime_resume);
     429                 :          0 :         return device_for_each_child(dev, &off, pm_iter);
     430                 :            : }
     431                 :            : #endif /* PM */
     432                 :            : 
     433                 :          0 : static int remove_iter(struct device *dev, void *data)
     434                 :            : {
     435         [ #  # ]:          0 :         if (dev->bus == &pcie_port_bus_type)
     436                 :          0 :                 device_unregister(dev);
     437                 :          0 :         return 0;
     438                 :            : }
     439                 :            : 
     440                 :          0 : static int find_service_iter(struct device *device, void *data)
     441                 :            : {
     442                 :          0 :         struct pcie_port_service_driver *service_driver;
     443                 :          0 :         struct portdrv_service_data *pdrvs;
     444                 :          0 :         u32 service;
     445                 :            : 
     446                 :          0 :         pdrvs = (struct portdrv_service_data *) data;
     447                 :          0 :         service = pdrvs->service;
     448                 :            : 
     449   [ #  #  #  # ]:          0 :         if (device->bus == &pcie_port_bus_type && device->driver) {
     450                 :          0 :                 service_driver = to_service_driver(device->driver);
     451         [ #  # ]:          0 :                 if (service_driver->service == service) {
     452                 :          0 :                         pdrvs->drv = service_driver;
     453                 :          0 :                         pdrvs->dev = device;
     454                 :          0 :                         return 1;
     455                 :            :                 }
     456                 :            :         }
     457                 :            : 
     458                 :            :         return 0;
     459                 :            : }
     460                 :            : 
     461                 :            : /**
     462                 :            :  * pcie_port_find_service - find the service driver
     463                 :            :  * @dev: PCI Express port the service is associated with
     464                 :            :  * @service: Service to find
     465                 :            :  *
     466                 :            :  * Find PCI Express port service driver associated with given service
     467                 :            :  */
     468                 :          0 : struct pcie_port_service_driver *pcie_port_find_service(struct pci_dev *dev,
     469                 :            :                                                         u32 service)
     470                 :            : {
     471                 :          0 :         struct pcie_port_service_driver *drv;
     472                 :          0 :         struct portdrv_service_data pdrvs;
     473                 :            : 
     474                 :          0 :         pdrvs.drv = NULL;
     475                 :          0 :         pdrvs.service = service;
     476                 :          0 :         device_for_each_child(&dev->dev, &pdrvs, find_service_iter);
     477                 :            : 
     478                 :          0 :         drv = pdrvs.drv;
     479                 :          0 :         return drv;
     480                 :            : }
     481                 :            : 
     482                 :            : /**
     483                 :            :  * pcie_port_find_device - find the struct device
     484                 :            :  * @dev: PCI Express port the service is associated with
     485                 :            :  * @service: For the service to find
     486                 :            :  *
     487                 :            :  * Find the struct device associated with given service on a pci_dev
     488                 :            :  */
     489                 :          0 : struct device *pcie_port_find_device(struct pci_dev *dev,
     490                 :            :                                       u32 service)
     491                 :            : {
     492                 :          0 :         struct device *device;
     493                 :          0 :         struct portdrv_service_data pdrvs;
     494                 :            : 
     495                 :          0 :         pdrvs.dev = NULL;
     496                 :          0 :         pdrvs.service = service;
     497                 :          0 :         device_for_each_child(&dev->dev, &pdrvs, find_service_iter);
     498                 :            : 
     499                 :          0 :         device = pdrvs.dev;
     500                 :          0 :         return device;
     501                 :            : }
     502                 :            : EXPORT_SYMBOL_GPL(pcie_port_find_device);
     503                 :            : 
     504                 :            : /**
     505                 :            :  * pcie_port_device_remove - unregister PCI Express port service devices
     506                 :            :  * @dev: PCI Express port the service devices to unregister are associated with
     507                 :            :  *
     508                 :            :  * Remove PCI Express port service devices associated with given port and
     509                 :            :  * disable MSI-X or MSI for the port.
     510                 :            :  */
     511                 :          0 : void pcie_port_device_remove(struct pci_dev *dev)
     512                 :            : {
     513                 :          0 :         device_for_each_child(&dev->dev, NULL, remove_iter);
     514                 :          0 :         pci_free_irq_vectors(dev);
     515                 :          0 :         pci_disable_device(dev);
     516                 :          0 : }
     517                 :            : 
     518                 :            : /**
     519                 :            :  * pcie_port_probe_service - probe driver for given PCI Express port service
     520                 :            :  * @dev: PCI Express port service device to probe against
     521                 :            :  *
     522                 :            :  * If PCI Express port service driver is registered with
     523                 :            :  * pcie_port_service_register(), this function will be called by the driver core
     524                 :            :  * whenever match is found between the driver and a port service device.
     525                 :            :  */
     526                 :          0 : static int pcie_port_probe_service(struct device *dev)
     527                 :            : {
     528                 :          0 :         struct pcie_device *pciedev;
     529                 :          0 :         struct pcie_port_service_driver *driver;
     530                 :          0 :         int status;
     531                 :            : 
     532   [ #  #  #  # ]:          0 :         if (!dev || !dev->driver)
     533                 :            :                 return -ENODEV;
     534                 :            : 
     535                 :          0 :         driver = to_service_driver(dev->driver);
     536   [ #  #  #  # ]:          0 :         if (!driver || !driver->probe)
     537                 :            :                 return -ENODEV;
     538                 :            : 
     539                 :          0 :         pciedev = to_pcie_device(dev);
     540                 :          0 :         status = driver->probe(pciedev);
     541         [ #  # ]:          0 :         if (status)
     542                 :            :                 return status;
     543                 :            : 
     544                 :          0 :         get_device(dev);
     545                 :          0 :         return 0;
     546                 :            : }
     547                 :            : 
     548                 :            : /**
     549                 :            :  * pcie_port_remove_service - detach driver from given PCI Express port service
     550                 :            :  * @dev: PCI Express port service device to handle
     551                 :            :  *
     552                 :            :  * If PCI Express port service driver is registered with
     553                 :            :  * pcie_port_service_register(), this function will be called by the driver core
     554                 :            :  * when device_unregister() is called for the port service device associated
     555                 :            :  * with the driver.
     556                 :            :  */
     557                 :          0 : static int pcie_port_remove_service(struct device *dev)
     558                 :            : {
     559                 :          0 :         struct pcie_device *pciedev;
     560                 :          0 :         struct pcie_port_service_driver *driver;
     561                 :            : 
     562   [ #  #  #  # ]:          0 :         if (!dev || !dev->driver)
     563                 :            :                 return 0;
     564                 :            : 
     565                 :          0 :         pciedev = to_pcie_device(dev);
     566                 :          0 :         driver = to_service_driver(dev->driver);
     567   [ #  #  #  # ]:          0 :         if (driver && driver->remove) {
     568                 :          0 :                 driver->remove(pciedev);
     569                 :          0 :                 put_device(dev);
     570                 :            :         }
     571                 :            :         return 0;
     572                 :            : }
     573                 :            : 
     574                 :            : /**
     575                 :            :  * pcie_port_shutdown_service - shut down given PCI Express port service
     576                 :            :  * @dev: PCI Express port service device to handle
     577                 :            :  *
     578                 :            :  * If PCI Express port service driver is registered with
     579                 :            :  * pcie_port_service_register(), this function will be called by the driver core
     580                 :            :  * when device_shutdown() is called for the port service device associated
     581                 :            :  * with the driver.
     582                 :            :  */
     583                 :          0 : static void pcie_port_shutdown_service(struct device *dev) {}
     584                 :            : 
     585                 :            : /**
     586                 :            :  * pcie_port_service_register - register PCI Express port service driver
     587                 :            :  * @new: PCI Express port service driver to register
     588                 :            :  */
     589                 :         90 : int pcie_port_service_register(struct pcie_port_service_driver *new)
     590                 :            : {
     591         [ +  - ]:         90 :         if (pcie_ports_disabled)
     592                 :            :                 return -ENODEV;
     593                 :            : 
     594                 :         90 :         new->driver.name = new->name;
     595                 :         90 :         new->driver.bus = &pcie_port_bus_type;
     596                 :         90 :         new->driver.probe = pcie_port_probe_service;
     597                 :         90 :         new->driver.remove = pcie_port_remove_service;
     598                 :         90 :         new->driver.shutdown = pcie_port_shutdown_service;
     599                 :            : 
     600                 :         90 :         return driver_register(&new->driver);
     601                 :            : }
     602                 :            : EXPORT_SYMBOL(pcie_port_service_register);
     603                 :            : 
     604                 :            : /**
     605                 :            :  * pcie_port_service_unregister - unregister PCI Express port service driver
     606                 :            :  * @drv: PCI Express port service driver to unregister
     607                 :            :  */
     608                 :          0 : void pcie_port_service_unregister(struct pcie_port_service_driver *drv)
     609                 :            : {
     610                 :          0 :         driver_unregister(&drv->driver);
     611                 :          0 : }
     612                 :            : EXPORT_SYMBOL(pcie_port_service_unregister);

Generated by: LCOV version 1.14