LCOV - code coverage report
Current view: top level - drivers/pci/pcie - pme.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 2 195 1.0 %
Date: 2022-03-28 15:32:58 Functions: 1 16 6.2 %
Branches: 0 94 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * PCIe Native PME support
       4                 :            :  *
       5                 :            :  * Copyright (C) 2007 - 2009 Intel Corp
       6                 :            :  * Copyright (C) 2007 - 2009 Shaohua Li <shaohua.li@intel.com>
       7                 :            :  * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
       8                 :            :  */
       9                 :            : 
      10                 :            : #define dev_fmt(fmt) "PME: " fmt
      11                 :            : 
      12                 :            : #include <linux/pci.h>
      13                 :            : #include <linux/kernel.h>
      14                 :            : #include <linux/errno.h>
      15                 :            : #include <linux/slab.h>
      16                 :            : #include <linux/init.h>
      17                 :            : #include <linux/interrupt.h>
      18                 :            : #include <linux/device.h>
      19                 :            : #include <linux/pm_runtime.h>
      20                 :            : 
      21                 :            : #include "../pci.h"
      22                 :            : #include "portdrv.h"
      23                 :            : 
      24                 :            : /*
      25                 :            :  * If this switch is set, MSI will not be used for PCIe PME signaling.  This
      26                 :            :  * causes the PCIe port driver to use INTx interrupts only, but it turns out
      27                 :            :  * that using MSI for PCIe PME signaling doesn't play well with PCIe PME-based
      28                 :            :  * wake-up from system sleep states.
      29                 :            :  */
      30                 :            : bool pcie_pme_msi_disabled;
      31                 :            : 
      32                 :          0 : static int __init pcie_pme_setup(char *str)
      33                 :            : {
      34         [ #  # ]:          0 :         if (!strncmp(str, "nomsi", 5))
      35                 :          0 :                 pcie_pme_msi_disabled = true;
      36                 :            : 
      37                 :          0 :         return 1;
      38                 :            : }
      39                 :            : __setup("pcie_pme=", pcie_pme_setup);
      40                 :            : 
      41                 :            : struct pcie_pme_service_data {
      42                 :            :         spinlock_t lock;
      43                 :            :         struct pcie_device *srv;
      44                 :            :         struct work_struct work;
      45                 :            :         bool noirq; /* If set, keep the PME interrupt disabled. */
      46                 :            : };
      47                 :            : 
      48                 :            : /**
      49                 :            :  * pcie_pme_interrupt_enable - Enable/disable PCIe PME interrupt generation.
      50                 :            :  * @dev: PCIe root port or event collector.
      51                 :            :  * @enable: Enable or disable the interrupt.
      52                 :            :  */
      53                 :          0 : void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable)
      54                 :            : {
      55         [ #  # ]:          0 :         if (enable)
      56                 :          0 :                 pcie_capability_set_word(dev, PCI_EXP_RTCTL,
      57                 :            :                                          PCI_EXP_RTCTL_PMEIE);
      58                 :            :         else
      59                 :          0 :                 pcie_capability_clear_word(dev, PCI_EXP_RTCTL,
      60                 :            :                                            PCI_EXP_RTCTL_PMEIE);
      61                 :          0 : }
      62                 :            : 
      63                 :            : /**
      64                 :            :  * pcie_pme_walk_bus - Scan a PCI bus for devices asserting PME#.
      65                 :            :  * @bus: PCI bus to scan.
      66                 :            :  *
      67                 :            :  * Scan given PCI bus and all buses under it for devices asserting PME#.
      68                 :            :  */
      69                 :          0 : static bool pcie_pme_walk_bus(struct pci_bus *bus)
      70                 :            : {
      71                 :          0 :         struct pci_dev *dev;
      72                 :          0 :         bool ret = false;
      73                 :            : 
      74         [ #  # ]:          0 :         list_for_each_entry(dev, &bus->devices, bus_list) {
      75                 :            :                 /* Skip PCIe devices in case we started from a root port. */
      76   [ #  #  #  # ]:          0 :                 if (!pci_is_pcie(dev) && pci_check_pme_status(dev)) {
      77         [ #  # ]:          0 :                         if (dev->pme_poll)
      78                 :          0 :                                 dev->pme_poll = false;
      79                 :            : 
      80                 :          0 :                         pci_wakeup_event(dev);
      81                 :          0 :                         pm_request_resume(&dev->dev);
      82                 :          0 :                         ret = true;
      83                 :            :                 }
      84                 :            : 
      85   [ #  #  #  # ]:          0 :                 if (dev->subordinate && pcie_pme_walk_bus(dev->subordinate))
      86                 :          0 :                         ret = true;
      87                 :            :         }
      88                 :            : 
      89                 :          0 :         return ret;
      90                 :            : }
      91                 :            : 
      92                 :            : /**
      93                 :            :  * pcie_pme_from_pci_bridge - Check if PCIe-PCI bridge generated a PME.
      94                 :            :  * @bus: Secondary bus of the bridge.
      95                 :            :  * @devfn: Device/function number to check.
      96                 :            :  *
      97                 :            :  * PME from PCI devices under a PCIe-PCI bridge may be converted to an in-band
      98                 :            :  * PCIe PME message.  In such that case the bridge should use the Requester ID
      99                 :            :  * of device/function number 0 on its secondary bus.
     100                 :            :  */
     101                 :          0 : static bool pcie_pme_from_pci_bridge(struct pci_bus *bus, u8 devfn)
     102                 :            : {
     103                 :          0 :         struct pci_dev *dev;
     104                 :          0 :         bool found = false;
     105                 :            : 
     106         [ #  # ]:          0 :         if (devfn)
     107                 :            :                 return false;
     108                 :            : 
     109                 :          0 :         dev = pci_dev_get(bus->self);
     110         [ #  # ]:          0 :         if (!dev)
     111                 :            :                 return false;
     112                 :            : 
     113   [ #  #  #  # ]:          0 :         if (pci_is_pcie(dev) && pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE) {
     114                 :          0 :                 down_read(&pci_bus_sem);
     115         [ #  # ]:          0 :                 if (pcie_pme_walk_bus(bus))
     116                 :          0 :                         found = true;
     117                 :          0 :                 up_read(&pci_bus_sem);
     118                 :            :         }
     119                 :            : 
     120                 :          0 :         pci_dev_put(dev);
     121                 :          0 :         return found;
     122                 :            : }
     123                 :            : 
     124                 :            : /**
     125                 :            :  * pcie_pme_handle_request - Find device that generated PME and handle it.
     126                 :            :  * @port: Root port or event collector that generated the PME interrupt.
     127                 :            :  * @req_id: PCIe Requester ID of the device that generated the PME.
     128                 :            :  */
     129                 :          0 : static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id)
     130                 :            : {
     131                 :          0 :         u8 busnr = req_id >> 8, devfn = req_id & 0xff;
     132                 :          0 :         struct pci_bus *bus;
     133                 :          0 :         struct pci_dev *dev;
     134                 :          0 :         bool found = false;
     135                 :            : 
     136                 :            :         /* First, check if the PME is from the root port itself. */
     137   [ #  #  #  # ]:          0 :         if (port->devfn == devfn && port->bus->number == busnr) {
     138         [ #  # ]:          0 :                 if (port->pme_poll)
     139                 :          0 :                         port->pme_poll = false;
     140                 :            : 
     141         [ #  # ]:          0 :                 if (pci_check_pme_status(port)) {
     142                 :          0 :                         pm_request_resume(&port->dev);
     143                 :          0 :                         found = true;
     144                 :            :                 } else {
     145                 :            :                         /*
     146                 :            :                          * Apparently, the root port generated the PME on behalf
     147                 :            :                          * of a non-PCIe device downstream.  If this is done by
     148                 :            :                          * a root port, the Requester ID field in its status
     149                 :            :                          * register may contain either the root port's, or the
     150                 :            :                          * source device's information (PCI Express Base
     151                 :            :                          * Specification, Rev. 2.0, Section 6.1.9).
     152                 :            :                          */
     153                 :          0 :                         down_read(&pci_bus_sem);
     154                 :          0 :                         found = pcie_pme_walk_bus(port->subordinate);
     155                 :          0 :                         up_read(&pci_bus_sem);
     156                 :            :                 }
     157                 :          0 :                 goto out;
     158                 :            :         }
     159                 :            : 
     160                 :            :         /* Second, find the bus the source device is on. */
     161                 :          0 :         bus = pci_find_bus(pci_domain_nr(port->bus), busnr);
     162         [ #  # ]:          0 :         if (!bus)
     163                 :          0 :                 goto out;
     164                 :            : 
     165                 :            :         /* Next, check if the PME is from a PCIe-PCI bridge. */
     166                 :          0 :         found = pcie_pme_from_pci_bridge(bus, devfn);
     167         [ #  # ]:          0 :         if (found)
     168                 :          0 :                 goto out;
     169                 :            : 
     170                 :            :         /* Finally, try to find the PME source on the bus. */
     171                 :          0 :         down_read(&pci_bus_sem);
     172         [ #  # ]:          0 :         list_for_each_entry(dev, &bus->devices, bus_list) {
     173                 :          0 :                 pci_dev_get(dev);
     174         [ #  # ]:          0 :                 if (dev->devfn == devfn) {
     175                 :            :                         found = true;
     176                 :            :                         break;
     177                 :            :                 }
     178                 :          0 :                 pci_dev_put(dev);
     179                 :            :         }
     180                 :          0 :         up_read(&pci_bus_sem);
     181                 :            : 
     182         [ #  # ]:          0 :         if (found) {
     183                 :            :                 /* The device is there, but we have to check its PME status. */
     184                 :          0 :                 found = pci_check_pme_status(dev);
     185         [ #  # ]:          0 :                 if (found) {
     186         [ #  # ]:          0 :                         if (dev->pme_poll)
     187                 :          0 :                                 dev->pme_poll = false;
     188                 :            : 
     189                 :          0 :                         pci_wakeup_event(dev);
     190                 :          0 :                         pm_request_resume(&dev->dev);
     191                 :            :                 }
     192                 :          0 :                 pci_dev_put(dev);
     193         [ #  # ]:          0 :         } else if (devfn) {
     194                 :            :                 /*
     195                 :            :                  * The device is not there, but we can still try to recover by
     196                 :            :                  * assuming that the PME was reported by a PCIe-PCI bridge that
     197                 :            :                  * used devfn different from zero.
     198                 :            :                  */
     199                 :          0 :                 pci_info(port, "interrupt generated for non-existent device %02x:%02x.%d\n",
     200                 :            :                          busnr, PCI_SLOT(devfn), PCI_FUNC(devfn));
     201                 :          0 :                 found = pcie_pme_from_pci_bridge(bus, 0);
     202                 :            :         }
     203                 :            : 
     204                 :          0 :  out:
     205         [ #  # ]:          0 :         if (!found)
     206                 :          0 :                 pci_info(port, "Spurious native interrupt!\n");
     207                 :          0 : }
     208                 :            : 
     209                 :            : /**
     210                 :            :  * pcie_pme_work_fn - Work handler for PCIe PME interrupt.
     211                 :            :  * @work: Work structure giving access to service data.
     212                 :            :  */
     213                 :          0 : static void pcie_pme_work_fn(struct work_struct *work)
     214                 :            : {
     215                 :          0 :         struct pcie_pme_service_data *data =
     216                 :          0 :                         container_of(work, struct pcie_pme_service_data, work);
     217                 :          0 :         struct pci_dev *port = data->srv->port;
     218                 :          0 :         u32 rtsta;
     219                 :            : 
     220                 :          0 :         spin_lock_irq(&data->lock);
     221                 :            : 
     222                 :          0 :         for (;;) {
     223         [ #  # ]:          0 :                 if (data->noirq)
     224                 :            :                         break;
     225                 :            : 
     226                 :          0 :                 pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta);
     227         [ #  # ]:          0 :                 if (rtsta == (u32) ~0)
     228                 :            :                         break;
     229                 :            : 
     230         [ #  # ]:          0 :                 if (rtsta & PCI_EXP_RTSTA_PME) {
     231                 :            :                         /*
     232                 :            :                          * Clear PME status of the port.  If there are other
     233                 :            :                          * pending PMEs, the status will be set again.
     234                 :            :                          */
     235                 :          0 :                         pcie_clear_root_pme_status(port);
     236                 :            : 
     237                 :          0 :                         spin_unlock_irq(&data->lock);
     238                 :          0 :                         pcie_pme_handle_request(port, rtsta & 0xffff);
     239                 :          0 :                         spin_lock_irq(&data->lock);
     240                 :            : 
     241                 :          0 :                         continue;
     242                 :            :                 }
     243                 :            : 
     244                 :            :                 /* No need to loop if there are no more PMEs pending. */
     245         [ #  # ]:          0 :                 if (!(rtsta & PCI_EXP_RTSTA_PENDING))
     246                 :            :                         break;
     247                 :            : 
     248                 :          0 :                 spin_unlock_irq(&data->lock);
     249                 :          0 :                 cpu_relax();
     250                 :          0 :                 spin_lock_irq(&data->lock);
     251                 :            :         }
     252                 :            : 
     253         [ #  # ]:          0 :         if (!data->noirq)
     254                 :          0 :                 pcie_pme_interrupt_enable(port, true);
     255                 :            : 
     256                 :          0 :         spin_unlock_irq(&data->lock);
     257                 :          0 : }
     258                 :            : 
     259                 :            : /**
     260                 :            :  * pcie_pme_irq - Interrupt handler for PCIe root port PME interrupt.
     261                 :            :  * @irq: Interrupt vector.
     262                 :            :  * @context: Interrupt context pointer.
     263                 :            :  */
     264                 :          0 : static irqreturn_t pcie_pme_irq(int irq, void *context)
     265                 :            : {
     266                 :          0 :         struct pci_dev *port;
     267                 :          0 :         struct pcie_pme_service_data *data;
     268                 :          0 :         u32 rtsta;
     269                 :          0 :         unsigned long flags;
     270                 :            : 
     271                 :          0 :         port = ((struct pcie_device *)context)->port;
     272                 :          0 :         data = get_service_data((struct pcie_device *)context);
     273                 :            : 
     274                 :          0 :         spin_lock_irqsave(&data->lock, flags);
     275                 :          0 :         pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta);
     276                 :            : 
     277   [ #  #  #  # ]:          0 :         if (rtsta == (u32) ~0 || !(rtsta & PCI_EXP_RTSTA_PME)) {
     278                 :          0 :                 spin_unlock_irqrestore(&data->lock, flags);
     279                 :          0 :                 return IRQ_NONE;
     280                 :            :         }
     281                 :            : 
     282                 :          0 :         pcie_pme_interrupt_enable(port, false);
     283                 :          0 :         spin_unlock_irqrestore(&data->lock, flags);
     284                 :            : 
     285                 :            :         /* We don't use pm_wq, because it's freezable. */
     286                 :          0 :         schedule_work(&data->work);
     287                 :            : 
     288                 :          0 :         return IRQ_HANDLED;
     289                 :            : }
     290                 :            : 
     291                 :            : /**
     292                 :            :  * pcie_pme_can_wakeup - Set the wakeup capability flag.
     293                 :            :  * @dev: PCI device to handle.
     294                 :            :  * @ign: Ignored.
     295                 :            :  */
     296                 :          0 : static int pcie_pme_can_wakeup(struct pci_dev *dev, void *ign)
     297                 :            : {
     298                 :          0 :         device_set_wakeup_capable(&dev->dev, true);
     299                 :          0 :         return 0;
     300                 :            : }
     301                 :            : 
     302                 :            : /**
     303                 :            :  * pcie_pme_mark_devices - Set the wakeup flag for devices below a port.
     304                 :            :  * @port: PCIe root port or event collector to handle.
     305                 :            :  *
     306                 :            :  * For each device below given root port, including the port itself (or for each
     307                 :            :  * root complex integrated endpoint if @port is a root complex event collector)
     308                 :            :  * set the flag indicating that it can signal run-time wake-up events.
     309                 :            :  */
     310                 :          0 : static void pcie_pme_mark_devices(struct pci_dev *port)
     311                 :            : {
     312                 :          0 :         pcie_pme_can_wakeup(port, NULL);
     313         [ #  # ]:          0 :         if (port->subordinate)
     314                 :          0 :                 pci_walk_bus(port->subordinate, pcie_pme_can_wakeup, NULL);
     315                 :          0 : }
     316                 :            : 
     317                 :            : /**
     318                 :            :  * pcie_pme_probe - Initialize PCIe PME service for given root port.
     319                 :            :  * @srv: PCIe service to initialize.
     320                 :            :  */
     321                 :          0 : static int pcie_pme_probe(struct pcie_device *srv)
     322                 :            : {
     323                 :          0 :         struct pci_dev *port;
     324                 :          0 :         struct pcie_pme_service_data *data;
     325                 :          0 :         int ret;
     326                 :            : 
     327                 :          0 :         data = kzalloc(sizeof(*data), GFP_KERNEL);
     328         [ #  # ]:          0 :         if (!data)
     329                 :            :                 return -ENOMEM;
     330                 :            : 
     331                 :          0 :         spin_lock_init(&data->lock);
     332                 :          0 :         INIT_WORK(&data->work, pcie_pme_work_fn);
     333                 :          0 :         data->srv = srv;
     334                 :          0 :         set_service_data(srv, data);
     335                 :            : 
     336                 :          0 :         port = srv->port;
     337                 :          0 :         pcie_pme_interrupt_enable(port, false);
     338                 :          0 :         pcie_clear_root_pme_status(port);
     339                 :            : 
     340                 :          0 :         ret = request_irq(srv->irq, pcie_pme_irq, IRQF_SHARED, "PCIe PME", srv);
     341         [ #  # ]:          0 :         if (ret) {
     342                 :          0 :                 kfree(data);
     343                 :          0 :                 return ret;
     344                 :            :         }
     345                 :            : 
     346                 :          0 :         pci_info(port, "Signaling with IRQ %d\n", srv->irq);
     347                 :            : 
     348                 :          0 :         pcie_pme_mark_devices(port);
     349                 :          0 :         pcie_pme_interrupt_enable(port, true);
     350                 :          0 :         return 0;
     351                 :            : }
     352                 :            : 
     353                 :          0 : static bool pcie_pme_check_wakeup(struct pci_bus *bus)
     354                 :            : {
     355                 :          0 :         struct pci_dev *dev;
     356                 :            : 
     357         [ #  # ]:          0 :         if (!bus)
     358                 :            :                 return false;
     359                 :            : 
     360         [ #  # ]:          0 :         list_for_each_entry(dev, &bus->devices, bus_list)
     361   [ #  #  #  # ]:          0 :                 if (device_may_wakeup(&dev->dev)
     362         [ #  # ]:          0 :                     || pcie_pme_check_wakeup(dev->subordinate))
     363                 :          0 :                         return true;
     364                 :            : 
     365                 :            :         return false;
     366                 :            : }
     367                 :            : 
     368                 :          0 : static void pcie_pme_disable_interrupt(struct pci_dev *port,
     369                 :            :                                        struct pcie_pme_service_data *data)
     370                 :            : {
     371                 :          0 :         spin_lock_irq(&data->lock);
     372                 :          0 :         pcie_pme_interrupt_enable(port, false);
     373                 :          0 :         pcie_clear_root_pme_status(port);
     374                 :          0 :         data->noirq = true;
     375                 :          0 :         spin_unlock_irq(&data->lock);
     376                 :          0 : }
     377                 :            : 
     378                 :            : /**
     379                 :            :  * pcie_pme_suspend - Suspend PCIe PME service device.
     380                 :            :  * @srv: PCIe service device to suspend.
     381                 :            :  */
     382                 :          0 : static int pcie_pme_suspend(struct pcie_device *srv)
     383                 :            : {
     384         [ #  # ]:          0 :         struct pcie_pme_service_data *data = get_service_data(srv);
     385                 :          0 :         struct pci_dev *port = srv->port;
     386                 :          0 :         bool wakeup;
     387                 :          0 :         int ret;
     388                 :            : 
     389   [ #  #  #  # ]:          0 :         if (device_may_wakeup(&port->dev)) {
     390                 :            :                 wakeup = true;
     391                 :            :         } else {
     392                 :          0 :                 down_read(&pci_bus_sem);
     393                 :          0 :                 wakeup = pcie_pme_check_wakeup(port->subordinate);
     394                 :          0 :                 up_read(&pci_bus_sem);
     395                 :            :         }
     396         [ #  # ]:          0 :         if (wakeup) {
     397                 :          0 :                 ret = enable_irq_wake(srv->irq);
     398         [ #  # ]:          0 :                 if (!ret)
     399                 :            :                         return 0;
     400                 :            :         }
     401                 :            : 
     402                 :          0 :         pcie_pme_disable_interrupt(port, data);
     403                 :            : 
     404                 :          0 :         synchronize_irq(srv->irq);
     405                 :            : 
     406                 :          0 :         return 0;
     407                 :            : }
     408                 :            : 
     409                 :            : /**
     410                 :            :  * pcie_pme_resume - Resume PCIe PME service device.
     411                 :            :  * @srv - PCIe service device to resume.
     412                 :            :  */
     413                 :          0 : static int pcie_pme_resume(struct pcie_device *srv)
     414                 :            : {
     415                 :          0 :         struct pcie_pme_service_data *data = get_service_data(srv);
     416                 :            : 
     417                 :          0 :         spin_lock_irq(&data->lock);
     418         [ #  # ]:          0 :         if (data->noirq) {
     419                 :          0 :                 struct pci_dev *port = srv->port;
     420                 :            : 
     421                 :          0 :                 pcie_clear_root_pme_status(port);
     422                 :          0 :                 pcie_pme_interrupt_enable(port, true);
     423                 :          0 :                 data->noirq = false;
     424                 :            :         } else {
     425                 :          0 :                 disable_irq_wake(srv->irq);
     426                 :            :         }
     427                 :          0 :         spin_unlock_irq(&data->lock);
     428                 :            : 
     429                 :          0 :         return 0;
     430                 :            : }
     431                 :            : 
     432                 :            : /**
     433                 :            :  * pcie_pme_remove - Prepare PCIe PME service device for removal.
     434                 :            :  * @srv - PCIe service device to remove.
     435                 :            :  */
     436                 :          0 : static void pcie_pme_remove(struct pcie_device *srv)
     437                 :            : {
     438                 :          0 :         struct pcie_pme_service_data *data = get_service_data(srv);
     439                 :            : 
     440                 :          0 :         pcie_pme_disable_interrupt(srv->port, data);
     441                 :          0 :         free_irq(srv->irq, srv);
     442                 :          0 :         cancel_work_sync(&data->work);
     443                 :          0 :         kfree(data);
     444                 :          0 : }
     445                 :            : 
     446                 :            : static struct pcie_port_service_driver pcie_pme_driver = {
     447                 :            :         .name           = "pcie_pme",
     448                 :            :         .port_type      = PCI_EXP_TYPE_ROOT_PORT,
     449                 :            :         .service        = PCIE_PORT_SERVICE_PME,
     450                 :            : 
     451                 :            :         .probe          = pcie_pme_probe,
     452                 :            :         .suspend        = pcie_pme_suspend,
     453                 :            :         .resume         = pcie_pme_resume,
     454                 :            :         .remove         = pcie_pme_remove,
     455                 :            : };
     456                 :            : 
     457                 :            : /**
     458                 :            :  * pcie_pme_service_init - Register the PCIe PME service driver.
     459                 :            :  */
     460                 :         28 : int __init pcie_pme_init(void)
     461                 :            : {
     462                 :         28 :         return pcie_port_service_register(&pcie_pme_driver);
     463                 :            : }

Generated by: LCOV version 1.14