LCOV - code coverage report
Current view: top level - drivers/acpi - pci_irq.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 80 130 61.5 %
Date: 2022-03-28 15:32:58 Functions: 5 5 100.0 %
Branches: 32 86 37.2 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  *  pci_irq.c - ACPI PCI Interrupt Routing ($Revision: 11 $)
       4                 :            :  *
       5                 :            :  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
       6                 :            :  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
       7                 :            :  *  Copyright (C) 2002       Dominik Brodowski <devel@brodo.de>
       8                 :            :  *  (c) Copyright 2008 Hewlett-Packard Development Company, L.P.
       9                 :            :  *      Bjorn Helgaas <bjorn.helgaas@hp.com>
      10                 :            :  */
      11                 :            : 
      12                 :            : 
      13                 :            : #include <linux/dmi.h>
      14                 :            : #include <linux/kernel.h>
      15                 :            : #include <linux/module.h>
      16                 :            : #include <linux/init.h>
      17                 :            : #include <linux/types.h>
      18                 :            : #include <linux/spinlock.h>
      19                 :            : #include <linux/pm.h>
      20                 :            : #include <linux/pci.h>
      21                 :            : #include <linux/acpi.h>
      22                 :            : #include <linux/slab.h>
      23                 :            : #include <linux/interrupt.h>
      24                 :            : 
      25                 :            : #define PREFIX "ACPI: "
      26                 :            : 
      27                 :            : #define _COMPONENT              ACPI_PCI_COMPONENT
      28                 :            : ACPI_MODULE_NAME("pci_irq");
      29                 :            : 
      30                 :            : struct acpi_prt_entry {
      31                 :            :         struct acpi_pci_id      id;
      32                 :            :         u8                      pin;
      33                 :            :         acpi_handle             link;
      34                 :            :         u32                     index;          /* GSI, or link _CRS index */
      35                 :            : };
      36                 :            : 
      37                 :          0 : static inline char pin_name(int pin)
      38                 :            : {
      39                 :          0 :         return 'A' + pin - 1;
      40                 :            : }
      41                 :            : 
      42                 :            : /* --------------------------------------------------------------------------
      43                 :            :                          PCI IRQ Routing Table (PRT) Support
      44                 :            :    -------------------------------------------------------------------------- */
      45                 :            : 
      46                 :            : /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */
      47                 :            : static const struct dmi_system_id medion_md9580[] = {
      48                 :            :         {
      49                 :            :                 .ident = "Medion MD9580-F laptop",
      50                 :            :                 .matches = {
      51                 :            :                         DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
      52                 :            :                         DMI_MATCH(DMI_PRODUCT_NAME, "A555"),
      53                 :            :                 },
      54                 :            :         },
      55                 :            :         { }
      56                 :            : };
      57                 :            : 
      58                 :            : /* http://bugzilla.kernel.org/show_bug.cgi?id=5044 */
      59                 :            : static const struct dmi_system_id dell_optiplex[] = {
      60                 :            :         {
      61                 :            :                 .ident = "Dell Optiplex GX1",
      62                 :            :                 .matches = {
      63                 :            :                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
      64                 :            :                         DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX1 600S+"),
      65                 :            :                 },
      66                 :            :         },
      67                 :            :         { }
      68                 :            : };
      69                 :            : 
      70                 :            : /* http://bugzilla.kernel.org/show_bug.cgi?id=10138 */
      71                 :            : static const struct dmi_system_id hp_t5710[] = {
      72                 :            :         {
      73                 :            :                 .ident = "HP t5710",
      74                 :            :                 .matches = {
      75                 :            :                         DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
      76                 :            :                         DMI_MATCH(DMI_PRODUCT_NAME, "hp t5000 series"),
      77                 :            :                         DMI_MATCH(DMI_BOARD_NAME, "098Ch"),
      78                 :            :                 },
      79                 :            :         },
      80                 :            :         { }
      81                 :            : };
      82                 :            : 
      83                 :            : struct prt_quirk {
      84                 :            :         const struct dmi_system_id *system;
      85                 :            :         unsigned int            segment;
      86                 :            :         unsigned int            bus;
      87                 :            :         unsigned int            device;
      88                 :            :         unsigned char           pin;
      89                 :            :         const char              *source;        /* according to BIOS */
      90                 :            :         const char              *actual_source;
      91                 :            : };
      92                 :            : 
      93                 :            : #define PCI_INTX_PIN(c)         (c - 'A' + 1)
      94                 :            : 
      95                 :            : /*
      96                 :            :  * These systems have incorrect _PRT entries.  The BIOS claims the PCI
      97                 :            :  * interrupt at the listed segment/bus/device/pin is connected to the first
      98                 :            :  * link device, but it is actually connected to the second.
      99                 :            :  */
     100                 :            : static const struct prt_quirk prt_quirks[] = {
     101                 :            :         { medion_md9580, 0, 0, 9, PCI_INTX_PIN('A'),
     102                 :            :                 "\\_SB_.PCI0.ISA_.LNKA",
     103                 :            :                 "\\_SB_.PCI0.ISA_.LNKB"},
     104                 :            :         { dell_optiplex, 0, 0, 0xd, PCI_INTX_PIN('A'),
     105                 :            :                 "\\_SB_.LNKB",
     106                 :            :                 "\\_SB_.LNKA"},
     107                 :            :         { hp_t5710, 0, 0, 1, PCI_INTX_PIN('A'),
     108                 :            :                 "\\_SB_.PCI0.LNK1",
     109                 :            :                 "\\_SB_.PCI0.LNK3"},
     110                 :            : };
     111                 :            : 
     112                 :         31 : static void do_prt_fixups(struct acpi_prt_entry *entry,
     113                 :            :                           struct acpi_pci_routing_table *prt)
     114                 :            : {
     115                 :         31 :         int i;
     116                 :         31 :         const struct prt_quirk *quirk;
     117                 :            : 
     118         [ +  + ]:        124 :         for (i = 0; i < ARRAY_SIZE(prt_quirks); i++) {
     119                 :         93 :                 quirk = &prt_quirks[i];
     120                 :            : 
     121                 :            :                 /* All current quirks involve link devices, not GSIs */
     122         [ -  + ]:         93 :                 if (dmi_check_system(quirk->system) &&
     123         [ #  # ]:          0 :                     entry->id.segment == quirk->segment &&
     124         [ #  # ]:          0 :                     entry->id.bus == quirk->bus &&
     125         [ #  # ]:          0 :                     entry->id.device == quirk->device &&
     126         [ #  # ]:          0 :                     entry->pin == quirk->pin &&
     127         [ #  # ]:          0 :                     !strcmp(prt->source, quirk->source) &&
     128         [ #  # ]:          0 :                     strlen(prt->source) >= strlen(quirk->actual_source)) {
     129                 :          0 :                         printk(KERN_WARNING PREFIX "firmware reports "
     130                 :            :                                 "%04x:%02x:%02x PCI INT %c connected to %s; "
     131                 :            :                                 "changing to %s\n",
     132                 :            :                                 entry->id.segment, entry->id.bus,
     133                 :            :                                 entry->id.device, pin_name(entry->pin),
     134                 :            :                                 prt->source, quirk->actual_source);
     135                 :          0 :                         strcpy(prt->source, quirk->actual_source);
     136                 :            :                 }
     137                 :            :         }
     138                 :         31 : }
     139                 :            : 
     140                 :            : static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev,
     141                 :            :                                   int pin, struct acpi_pci_routing_table *prt,
     142                 :            :                                   struct acpi_prt_entry **entry_ptr)
     143                 :            : {
     144                 :            :         int segment = pci_domain_nr(dev->bus);
     145                 :            :         int bus = dev->bus->number;
     146                 :            :         int device = pci_ari_enabled(dev->bus) ? 0 : PCI_SLOT(dev->devfn);
     147                 :            :         struct acpi_prt_entry *entry;
     148                 :            : 
     149                 :            :         if (((prt->address >> 16) & 0xffff) != device ||
     150                 :            :             prt->pin + 1 != pin)
     151                 :            :                 return -ENODEV;
     152                 :            : 
     153                 :            :         entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
     154                 :            :         if (!entry)
     155                 :            :                 return -ENOMEM;
     156                 :            : 
     157                 :            :         /*
     158                 :            :          * Note that the _PRT uses 0=INTA, 1=INTB, etc, while PCI uses
     159                 :            :          * 1=INTA, 2=INTB.  We use the PCI encoding throughout, so convert
     160                 :            :          * it here.
     161                 :            :          */
     162                 :            :         entry->id.segment = segment;
     163                 :            :         entry->id.bus = bus;
     164                 :            :         entry->id.device = (prt->address >> 16) & 0xFFFF;
     165                 :            :         entry->pin = prt->pin + 1;
     166                 :            : 
     167                 :            :         do_prt_fixups(entry, prt);
     168                 :            : 
     169                 :            :         entry->index = prt->source_index;
     170                 :            : 
     171                 :            :         /*
     172                 :            :          * Type 1: Dynamic
     173                 :            :          * ---------------
     174                 :            :          * The 'source' field specifies the PCI interrupt link device used to
     175                 :            :          * configure the IRQ assigned to this slot|dev|pin.  The 'source_index'
     176                 :            :          * indicates which resource descriptor in the resource template (of
     177                 :            :          * the link device) this interrupt is allocated from.
     178                 :            :          * 
     179                 :            :          * NOTE: Don't query the Link Device for IRQ information at this time
     180                 :            :          *       because Link Device enumeration may not have occurred yet
     181                 :            :          *       (e.g. exists somewhere 'below' this _PRT entry in the ACPI
     182                 :            :          *       namespace).
     183                 :            :          */
     184                 :            :         if (prt->source[0])
     185                 :            :                 acpi_get_handle(handle, prt->source, &entry->link);
     186                 :            : 
     187                 :            :         /*
     188                 :            :          * Type 2: Static
     189                 :            :          * --------------
     190                 :            :          * The 'source' field is NULL, and the 'source_index' field specifies
     191                 :            :          * the IRQ value, which is hardwired to specific interrupt inputs on
     192                 :            :          * the interrupt controller.
     193                 :            :          */
     194                 :            : 
     195                 :            :         ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
     196                 :            :                               "      %04x:%02x:%02x[%c] -> %s[%d]\n",
     197                 :            :                               entry->id.segment, entry->id.bus,
     198                 :            :                               entry->id.device, pin_name(entry->pin),
     199                 :            :                               prt->source, entry->index));
     200                 :            : 
     201                 :            :         *entry_ptr = entry;
     202                 :            : 
     203                 :            :         return 0;
     204                 :            : }
     205                 :            : 
     206                 :         31 : static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
     207                 :            :                           int pin, struct acpi_prt_entry **entry_ptr)
     208                 :            : {
     209                 :         31 :         acpi_status status;
     210                 :         31 :         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
     211                 :         31 :         struct acpi_pci_routing_table *entry;
     212                 :         31 :         acpi_handle handle = NULL;
     213                 :            : 
     214         [ +  - ]:         31 :         if (dev->bus->bridge)
     215   [ +  -  +  - ]:         31 :                 handle = ACPI_HANDLE(dev->bus->bridge);
     216                 :            : 
     217         [ -  + ]:         31 :         if (!handle)
     218                 :          0 :                 return -ENODEV;
     219                 :            : 
     220                 :            :         /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
     221                 :         31 :         status = acpi_get_irq_routing_table(handle, &buffer);
     222         [ -  + ]:         31 :         if (ACPI_FAILURE(status)) {
     223                 :          0 :                 kfree(buffer.pointer);
     224                 :          0 :                 return -ENODEV;
     225                 :            :         }
     226                 :            : 
     227                 :         31 :         entry = buffer.pointer;
     228   [ +  -  +  - ]:        403 :         while (entry && (entry->length > 0)) {
     229         [ +  + ]:        403 :                 if (!acpi_pci_irq_check_entry(handle, dev, pin,
     230                 :            :                                                  entry, entry_ptr))
     231                 :            :                         break;
     232                 :        372 :                 entry = (struct acpi_pci_routing_table *)
     233                 :        372 :                     ((unsigned long)entry + entry->length);
     234                 :            :         }
     235                 :            : 
     236                 :         31 :         kfree(buffer.pointer);
     237                 :         31 :         return 0;
     238                 :            : }
     239                 :            : 
     240                 :            : /* --------------------------------------------------------------------------
     241                 :            :                           PCI Interrupt Routing Support
     242                 :            :    -------------------------------------------------------------------------- */
     243                 :            : #ifdef CONFIG_X86_IO_APIC
     244                 :            : extern int noioapicquirk;
     245                 :            : extern int noioapicreroute;
     246                 :            : 
     247                 :            : static int bridge_has_boot_interrupt_variant(struct pci_bus *bus)
     248                 :            : {
     249                 :            :         struct pci_bus *bus_it;
     250                 :            : 
     251                 :            :         for (bus_it = bus ; bus_it ; bus_it = bus_it->parent) {
     252                 :            :                 if (!bus_it->self)
     253                 :            :                         return 0;
     254                 :            :                 if (bus_it->self->irq_reroute_variant)
     255                 :            :                         return bus_it->self->irq_reroute_variant;
     256                 :            :         }
     257                 :            :         return 0;
     258                 :            : }
     259                 :            : 
     260                 :            : /*
     261                 :            :  * Some chipsets (e.g. Intel 6700PXH) generate a legacy INTx when the IRQ
     262                 :            :  * entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel does
     263                 :            :  * during interrupt handling). When this INTx generation cannot be disabled,
     264                 :            :  * we reroute these interrupts to their legacy equivalent to get rid of
     265                 :            :  * spurious interrupts.
     266                 :            :  */
     267                 :            : static int acpi_reroute_boot_interrupt(struct pci_dev *dev,
     268                 :            :                                        struct acpi_prt_entry *entry)
     269                 :            : {
     270                 :            :         if (noioapicquirk || noioapicreroute) {
     271                 :            :                 return 0;
     272                 :            :         } else {
     273                 :            :                 switch (bridge_has_boot_interrupt_variant(dev->bus)) {
     274                 :            :                 case 0:
     275                 :            :                         /* no rerouting necessary */
     276                 :            :                         return 0;
     277                 :            :                 case INTEL_IRQ_REROUTE_VARIANT:
     278                 :            :                         /*
     279                 :            :                          * Remap according to INTx routing table in 6700PXH
     280                 :            :                          * specs, intel order number 302628-002, section
     281                 :            :                          * 2.15.2. Other chipsets (80332, ...) have the same
     282                 :            :                          * mapping and are handled here as well.
     283                 :            :                          */
     284                 :            :                         dev_info(&dev->dev, "PCI IRQ %d -> rerouted to legacy "
     285                 :            :                                  "IRQ %d\n", entry->index,
     286                 :            :                                  (entry->index % 4) + 16);
     287                 :            :                         entry->index = (entry->index % 4) + 16;
     288                 :            :                         return 1;
     289                 :            :                 default:
     290                 :            :                         dev_warn(&dev->dev, "Cannot reroute IRQ %d to legacy "
     291                 :            :                                  "IRQ: unknown mapping\n", entry->index);
     292                 :            :                         return -1;
     293                 :            :                 }
     294                 :            :         }
     295                 :            : }
     296                 :            : #endif /* CONFIG_X86_IO_APIC */
     297                 :            : 
     298                 :         31 : static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
     299                 :            : {
     300                 :         31 :         struct acpi_prt_entry *entry = NULL;
     301                 :         31 :         struct pci_dev *bridge;
     302                 :         31 :         u8 bridge_pin, orig_pin = pin;
     303                 :         31 :         int ret;
     304                 :            : 
     305                 :         31 :         ret = acpi_pci_irq_find_prt_entry(dev, pin, &entry);
     306   [ +  -  +  - ]:         31 :         if (!ret && entry) {
     307                 :            : #ifdef CONFIG_X86_IO_APIC
     308                 :         31 :                 acpi_reroute_boot_interrupt(dev, entry);
     309                 :            : #endif /* CONFIG_X86_IO_APIC */
     310                 :            :                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n",
     311                 :         31 :                                   pci_name(dev), pin_name(pin)));
     312                 :         31 :                 return entry;
     313                 :            :         }
     314                 :            : 
     315                 :            :         /*
     316                 :            :          * Attempt to derive an IRQ for this device from a parent bridge's
     317                 :            :          * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).
     318                 :            :          */
     319                 :          0 :         bridge = dev->bus->self;
     320         [ #  # ]:          0 :         while (bridge) {
     321                 :          0 :                 pin = pci_swizzle_interrupt_pin(dev, pin);
     322                 :            : 
     323         [ #  # ]:          0 :                 if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) {
     324                 :            :                         /* PC card has the same IRQ as its cardbridge */
     325                 :          0 :                         bridge_pin = bridge->pin;
     326         [ #  # ]:          0 :                         if (!bridge_pin) {
     327                 :            :                                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
     328                 :            :                                                   "No interrupt pin configured for device %s\n",
     329                 :            :                                                   pci_name(bridge)));
     330                 :            :                                 return NULL;
     331                 :            :                         }
     332                 :          0 :                         pin = bridge_pin;
     333                 :            :                 }
     334                 :            : 
     335                 :          0 :                 ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry);
     336   [ #  #  #  # ]:          0 :                 if (!ret && entry) {
     337                 :            :                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
     338                 :            :                                          "Derived GSI for %s INT %c from %s\n",
     339                 :            :                                          pci_name(dev), pin_name(orig_pin),
     340                 :          0 :                                          pci_name(bridge)));
     341                 :          0 :                         return entry;
     342                 :            :                 }
     343                 :            : 
     344                 :          0 :                 dev = bridge;
     345                 :          0 :                 bridge = dev->bus->self;
     346                 :            :         }
     347                 :            : 
     348                 :          0 :         dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n",
     349                 :            :                  pin_name(orig_pin));
     350                 :          0 :         return NULL;
     351                 :            : }
     352                 :            : 
     353                 :            : #if IS_ENABLED(CONFIG_ISA) || IS_ENABLED(CONFIG_EISA)
     354                 :            : static int acpi_isa_register_gsi(struct pci_dev *dev)
     355                 :            : {
     356                 :            :         u32 dev_gsi;
     357                 :            : 
     358                 :            :         /* Interrupt Line values above 0xF are forbidden */
     359                 :            :         if (dev->irq > 0 && (dev->irq <= 0xF) &&
     360                 :            :             acpi_isa_irq_available(dev->irq) &&
     361                 :            :             (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) {
     362                 :            :                 dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n",
     363                 :            :                          pin_name(dev->pin), dev->irq);
     364                 :            :                 acpi_register_gsi(&dev->dev, dev_gsi,
     365                 :            :                                   ACPI_LEVEL_SENSITIVE,
     366                 :            :                                   ACPI_ACTIVE_LOW);
     367                 :            :                 return 0;
     368                 :            :         }
     369                 :            :         return -EINVAL;
     370                 :            : }
     371                 :            : #else
     372                 :          0 : static inline int acpi_isa_register_gsi(struct pci_dev *dev)
     373                 :            : {
     374                 :          0 :         return -ENODEV;
     375                 :            : }
     376                 :            : #endif
     377                 :            : 
     378                 :          0 : static inline bool acpi_pci_irq_valid(struct pci_dev *dev, u8 pin)
     379                 :            : {
     380                 :            : #ifdef CONFIG_X86
     381                 :            :         /*
     382                 :            :          * On x86 irq line 0xff means "unknown" or "no connection"
     383                 :            :          * (PCI 3.0, Section 6.2.4, footnote on page 223).
     384                 :            :          */
     385                 :          0 :         if (dev->irq == 0xff) {
     386                 :          0 :                 dev->irq = IRQ_NOTCONNECTED;
     387                 :          0 :                 dev_warn(&dev->dev, "PCI INT %c: not connected\n",
     388                 :            :                          pin_name(pin));
     389                 :          0 :                 return false;
     390                 :            :         }
     391                 :            : #endif
     392                 :            :         return true;
     393                 :            : }
     394                 :            : 
     395                 :        112 : int acpi_pci_irq_enable(struct pci_dev *dev)
     396                 :            : {
     397                 :        112 :         struct acpi_prt_entry *entry;
     398                 :        112 :         int gsi;
     399                 :        112 :         u8 pin;
     400                 :        112 :         int triggering = ACPI_LEVEL_SENSITIVE;
     401                 :            :         /*
     402                 :            :          * On ARM systems with the GIC interrupt model, level interrupts
     403                 :            :          * are always polarity high by specification; PCI legacy
     404                 :            :          * IRQs lines are inverted before reaching the interrupt
     405                 :            :          * controller and must therefore be considered active high
     406                 :            :          * as default.
     407                 :            :          */
     408                 :        112 :         int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ?
     409                 :        112 :                                       ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW;
     410                 :        112 :         char *link = NULL;
     411                 :        112 :         char link_desc[16];
     412                 :        112 :         int rc;
     413                 :            : 
     414                 :        112 :         pin = dev->pin;
     415         [ +  + ]:        112 :         if (!pin) {
     416                 :            :                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
     417                 :            :                                   "No interrupt pin configured for device %s\n",
     418                 :            :                                   pci_name(dev)));
     419                 :            :                 return 0;
     420                 :            :         }
     421                 :            : 
     422   [ -  +  -  - ]:         28 :         if (dev->irq_managed && dev->irq > 0)
     423                 :            :                 return 0;
     424                 :            : 
     425                 :         28 :         entry = acpi_pci_irq_lookup(dev, pin);
     426         [ -  + ]:         28 :         if (!entry) {
     427                 :            :                 /*
     428                 :            :                  * IDE legacy mode controller IRQs are magic. Why do compat
     429                 :            :                  * extensions always make such a nasty mess.
     430                 :            :                  */
     431         [ #  # ]:          0 :                 if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE &&
     432         [ #  # ]:          0 :                                 (dev->class & 0x05) == 0)
     433                 :            :                         return 0;
     434                 :            :         }
     435                 :            : 
     436         [ +  - ]:         28 :         if (entry) {
     437         [ +  - ]:         28 :                 if (entry->link)
     438                 :         28 :                         gsi = acpi_pci_link_allocate_irq(entry->link,
     439                 :         28 :                                                          entry->index,
     440                 :            :                                                          &triggering, &polarity,
     441                 :            :                                                          &link);
     442                 :            :                 else
     443                 :          0 :                         gsi = entry->index;
     444                 :            :         } else
     445                 :            :                 gsi = -1;
     446                 :            : 
     447         [ -  + ]:         28 :         if (gsi < 0) {
     448                 :            :                 /*
     449                 :            :                  * No IRQ known to the ACPI subsystem - maybe the BIOS /
     450                 :            :                  * driver reported one, then use it. Exit in any case.
     451                 :            :                  */
     452         [ #  # ]:          0 :                 if (!acpi_pci_irq_valid(dev, pin)) {
     453                 :          0 :                         kfree(entry);
     454                 :          0 :                         return 0;
     455                 :            :                 }
     456                 :            : 
     457                 :          0 :                 if (acpi_isa_register_gsi(dev))
     458                 :          0 :                         dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
     459                 :            :                                  pin_name(pin));
     460                 :            : 
     461                 :          0 :                 kfree(entry);
     462                 :          0 :                 return 0;
     463                 :            :         }
     464                 :            : 
     465                 :         28 :         rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
     466         [ -  + ]:         28 :         if (rc < 0) {
     467                 :          0 :                 dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
     468                 :            :                          pin_name(pin));
     469                 :          0 :                 kfree(entry);
     470                 :          0 :                 return rc;
     471                 :            :         }
     472                 :         28 :         dev->irq = rc;
     473                 :         28 :         dev->irq_managed = 1;
     474                 :            : 
     475         [ +  - ]:         28 :         if (link)
     476                 :         28 :                 snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
     477                 :            :         else
     478                 :          0 :                 link_desc[0] = '\0';
     479                 :            : 
     480                 :         28 :         dev_dbg(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n",
     481                 :            :                 pin_name(pin), link_desc, gsi,
     482                 :            :                 (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
     483                 :            :                 (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
     484                 :            : 
     485                 :         28 :         kfree(entry);
     486                 :         28 :         return 0;
     487                 :            : }
     488                 :            : 
     489                 :         31 : void acpi_pci_irq_disable(struct pci_dev *dev)
     490                 :            : {
     491                 :         31 :         struct acpi_prt_entry *entry;
     492                 :         31 :         int gsi;
     493                 :         31 :         u8 pin;
     494                 :            : 
     495                 :         31 :         pin = dev->pin;
     496   [ +  +  +  -  :         31 :         if (!pin || !dev->irq_managed || dev->irq <= 0)
                   +  - ]
     497                 :            :                 return;
     498                 :            : 
     499                 :            :         /* Keep IOAPIC pin configuration when suspending */
     500         [ +  - ]:          3 :         if (dev->dev.power.is_prepared)
     501                 :            :                 return;
     502                 :            : #ifdef  CONFIG_PM
     503         [ +  - ]:          3 :         if (dev->dev.power.runtime_status == RPM_SUSPENDING)
     504                 :            :                 return;
     505                 :            : #endif
     506                 :            : 
     507                 :          3 :         entry = acpi_pci_irq_lookup(dev, pin);
     508         [ +  - ]:          3 :         if (!entry)
     509                 :            :                 return;
     510                 :            : 
     511         [ +  - ]:          3 :         if (entry->link)
     512                 :          3 :                 gsi = acpi_pci_link_free_irq(entry->link);
     513                 :            :         else
     514                 :          0 :                 gsi = entry->index;
     515                 :            : 
     516                 :          3 :         kfree(entry);
     517                 :            : 
     518                 :            :         /*
     519                 :            :          * TBD: It might be worth clearing dev->irq by magic constant
     520                 :            :          * (e.g. PCI_UNDEFINED_IRQ).
     521                 :            :          */
     522                 :            : 
     523                 :          3 :         dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
     524         [ +  - ]:          3 :         if (gsi >= 0) {
     525                 :          3 :                 acpi_unregister_gsi(gsi);
     526                 :          3 :                 dev->irq_managed = 0;
     527                 :            :         }
     528                 :            : }

Generated by: LCOV version 1.14