LCOV - code coverage report
Current view: top level - drivers/pnp - quirks.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 6 203 3.0 %
Date: 2022-04-01 14:35:51 Functions: 1 12 8.3 %
Branches: 3 134 2.2 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  *  This file contains quirk handling code for PnP devices
       4                 :            :  *  Some devices do not report all their resources, and need to have extra
       5                 :            :  *  resources added. This is most easily accomplished at initialisation time
       6                 :            :  *  when building up the resource structure for the first time.
       7                 :            :  *
       8                 :            :  *  Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk>
       9                 :            :  *  Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
      10                 :            :  *      Bjorn Helgaas <bjorn.helgaas@hp.com>
      11                 :            :  *
      12                 :            :  *  Heavily based on PCI quirks handling which is
      13                 :            :  *
      14                 :            :  *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <linux/types.h>
      18                 :            : #include <linux/kernel.h>
      19                 :            : #include <linux/pci.h>
      20                 :            : #include <linux/string.h>
      21                 :            : #include <linux/slab.h>
      22                 :            : #include <linux/pnp.h>
      23                 :            : #include <linux/io.h>
      24                 :            : #include "base.h"
      25                 :            : 
      26                 :          0 : static void quirk_awe32_add_ports(struct pnp_dev *dev,
      27                 :            :                                   struct pnp_option *option,
      28                 :            :                                   unsigned int offset)
      29                 :            : {
      30                 :          0 :         struct pnp_option *new_option;
      31                 :            : 
      32                 :          0 :         new_option = kmalloc(sizeof(struct pnp_option), GFP_KERNEL);
      33         [ #  # ]:          0 :         if (!new_option) {
      34                 :          0 :                 dev_err(&dev->dev, "couldn't add ioport region to option set "
      35                 :            :                         "%d\n", pnp_option_set(option));
      36                 :          0 :                 return;
      37                 :            :         }
      38                 :            : 
      39                 :          0 :         *new_option = *option;
      40                 :          0 :         new_option->u.port.min += offset;
      41                 :          0 :         new_option->u.port.max += offset;
      42                 :          0 :         list_add(&new_option->list, &option->list);
      43                 :            : 
      44                 :          0 :         dev_info(&dev->dev, "added ioport region %#llx-%#llx to set %d\n",
      45                 :            :                 (unsigned long long) new_option->u.port.min,
      46                 :            :                 (unsigned long long) new_option->u.port.max,
      47                 :            :                 pnp_option_set(option));
      48                 :            : }
      49                 :            : 
      50                 :          0 : static void quirk_awe32_resources(struct pnp_dev *dev)
      51                 :            : {
      52                 :          0 :         struct pnp_option *option;
      53                 :          0 :         unsigned int set = ~0;
      54                 :            : 
      55                 :            :         /*
      56                 :            :          * Add two extra ioport regions (at offset 0x400 and 0x800 from the
      57                 :            :          * one given) to every dependent option set.
      58                 :            :          */
      59         [ #  # ]:          0 :         list_for_each_entry(option, &dev->options, list) {
      60   [ #  #  #  # ]:          0 :                 if (pnp_option_is_dependent(option) &&
      61                 :            :                     pnp_option_set(option) != set) {
      62                 :          0 :                         set = pnp_option_set(option);
      63                 :          0 :                         quirk_awe32_add_ports(dev, option, 0x800);
      64                 :          0 :                         quirk_awe32_add_ports(dev, option, 0x400);
      65                 :            :                 }
      66                 :            :         }
      67                 :          0 : }
      68                 :            : 
      69                 :          0 : static void quirk_cmi8330_resources(struct pnp_dev *dev)
      70                 :            : {
      71                 :          0 :         struct pnp_option *option;
      72                 :          0 :         struct pnp_irq *irq;
      73                 :          0 :         struct pnp_dma *dma;
      74                 :            : 
      75         [ #  # ]:          0 :         list_for_each_entry(option, &dev->options, list) {
      76         [ #  # ]:          0 :                 if (!pnp_option_is_dependent(option))
      77                 :          0 :                         continue;
      78                 :            : 
      79         [ #  # ]:          0 :                 if (option->type == IORESOURCE_IRQ) {
      80                 :          0 :                         irq = &option->u.irq;
      81                 :          0 :                         bitmap_zero(irq->map.bits, PNP_IRQ_NR);
      82                 :          0 :                         __set_bit(5, irq->map.bits);
      83                 :          0 :                         __set_bit(7, irq->map.bits);
      84                 :          0 :                         __set_bit(10, irq->map.bits);
      85                 :          0 :                         dev_info(&dev->dev, "set possible IRQs in "
      86                 :            :                                  "option set %d to 5, 7, 10\n",
      87                 :            :                                  pnp_option_set(option));
      88         [ #  # ]:          0 :                 } else if (option->type == IORESOURCE_DMA) {
      89                 :          0 :                         dma = &option->u.dma;
      90         [ #  # ]:          0 :                         if ((dma->flags & IORESOURCE_DMA_TYPE_MASK) ==
      91                 :          0 :                                                 IORESOURCE_DMA_8BIT &&
      92         [ #  # ]:          0 :                             dma->map != 0x0A) {
      93                 :          0 :                                 dev_info(&dev->dev, "changing possible "
      94                 :            :                                          "DMA channel mask in option set %d "
      95                 :            :                                          "from %#02x to 0x0A (1, 3)\n",
      96                 :            :                                          pnp_option_set(option), dma->map);
      97                 :          0 :                                 dma->map = 0x0A;
      98                 :            :                         }
      99                 :            :                 }
     100                 :            :         }
     101                 :          0 : }
     102                 :            : 
     103                 :          0 : static void quirk_sb16audio_resources(struct pnp_dev *dev)
     104                 :            : {
     105                 :          0 :         struct pnp_option *option;
     106                 :          0 :         unsigned int prev_option_flags = ~0, n = 0;
     107                 :          0 :         struct pnp_port *port;
     108                 :            : 
     109                 :            :         /*
     110                 :            :          * The default range on the OPL port for these devices is 0x388-0x388.
     111                 :            :          * Here we increase that range so that two such cards can be
     112                 :            :          * auto-configured.
     113                 :            :          */
     114         [ #  # ]:          0 :         list_for_each_entry(option, &dev->options, list) {
     115         [ #  # ]:          0 :                 if (prev_option_flags != option->flags) {
     116                 :          0 :                         prev_option_flags = option->flags;
     117                 :          0 :                         n = 0;
     118                 :            :                 }
     119                 :            : 
     120         [ #  # ]:          0 :                 if (pnp_option_is_dependent(option) &&
     121         [ #  # ]:          0 :                     option->type == IORESOURCE_IO) {
     122                 :          0 :                         n++;
     123                 :          0 :                         port = &option->u.port;
     124   [ #  #  #  # ]:          0 :                         if (n == 3 && port->min == port->max) {
     125                 :          0 :                                 port->max += 0x70;
     126                 :          0 :                                 dev_info(&dev->dev, "increased option port "
     127                 :            :                                          "range from %#llx-%#llx to "
     128                 :            :                                          "%#llx-%#llx\n",
     129                 :            :                                          (unsigned long long) port->min,
     130                 :            :                                          (unsigned long long) port->min,
     131                 :            :                                          (unsigned long long) port->min,
     132                 :            :                                          (unsigned long long) port->max);
     133                 :            :                         }
     134                 :            :                 }
     135                 :            :         }
     136                 :          0 : }
     137                 :            : 
     138                 :          0 : static struct pnp_option *pnp_clone_dependent_set(struct pnp_dev *dev,
     139                 :            :                                                   unsigned int set)
     140                 :            : {
     141                 :          0 :         struct pnp_option *tail = NULL, *first_new_option = NULL;
     142                 :          0 :         struct pnp_option *option, *new_option;
     143                 :          0 :         unsigned int flags;
     144                 :            : 
     145         [ #  # ]:          0 :         list_for_each_entry(option, &dev->options, list) {
     146         [ #  # ]:          0 :                 if (pnp_option_is_dependent(option))
     147                 :          0 :                         tail = option;
     148                 :            :         }
     149         [ #  # ]:          0 :         if (!tail) {
     150                 :          0 :                 dev_err(&dev->dev, "no dependent option sets\n");
     151                 :          0 :                 return NULL;
     152                 :            :         }
     153                 :            : 
     154                 :          0 :         flags = pnp_new_dependent_set(dev, PNP_RES_PRIORITY_FUNCTIONAL);
     155         [ #  # ]:          0 :         list_for_each_entry(option, &dev->options, list) {
     156   [ #  #  #  # ]:          0 :                 if (pnp_option_is_dependent(option) &&
     157                 :            :                     pnp_option_set(option) == set) {
     158                 :          0 :                         new_option = kmalloc(sizeof(struct pnp_option),
     159                 :            :                                              GFP_KERNEL);
     160         [ #  # ]:          0 :                         if (!new_option) {
     161                 :          0 :                                 dev_err(&dev->dev, "couldn't clone dependent "
     162                 :            :                                         "set %d\n", set);
     163                 :          0 :                                 return NULL;
     164                 :            :                         }
     165                 :            : 
     166                 :          0 :                         *new_option = *option;
     167                 :          0 :                         new_option->flags = flags;
     168         [ #  # ]:          0 :                         if (!first_new_option)
     169                 :          0 :                                 first_new_option = new_option;
     170                 :            : 
     171                 :          0 :                         list_add(&new_option->list, &tail->list);
     172                 :          0 :                         tail = new_option;
     173                 :            :                 }
     174                 :            :         }
     175                 :            : 
     176                 :            :         return first_new_option;
     177                 :            : }
     178                 :            : 
     179                 :            : 
     180                 :          0 : static void quirk_add_irq_optional_dependent_sets(struct pnp_dev *dev)
     181                 :            : {
     182                 :          0 :         struct pnp_option *new_option;
     183                 :          0 :         unsigned int num_sets, i, set;
     184                 :          0 :         struct pnp_irq *irq;
     185                 :            : 
     186                 :          0 :         num_sets = dev->num_dependent_sets;
     187         [ #  # ]:          0 :         for (i = 0; i < num_sets; i++) {
     188                 :          0 :                 new_option = pnp_clone_dependent_set(dev, i);
     189         [ #  # ]:          0 :                 if (!new_option)
     190                 :            :                         return;
     191                 :            : 
     192                 :          0 :                 set = pnp_option_set(new_option);
     193   [ #  #  #  # ]:          0 :                 while (new_option && pnp_option_set(new_option) == set) {
     194         [ #  # ]:          0 :                         if (new_option->type == IORESOURCE_IRQ) {
     195                 :          0 :                                 irq = &new_option->u.irq;
     196                 :          0 :                                 irq->flags |= IORESOURCE_IRQ_OPTIONAL;
     197                 :            :                         }
     198                 :          0 :                         dbg_pnp_show_option(dev, new_option);
     199                 :          0 :                         new_option = list_entry(new_option->list.next,
     200                 :            :                                                 struct pnp_option, list);
     201                 :            :                 }
     202                 :            : 
     203                 :          0 :                 dev_info(&dev->dev, "added dependent option set %d (same as "
     204                 :            :                          "set %d except IRQ optional)\n", set, i);
     205                 :            :         }
     206                 :            : }
     207                 :            : 
     208                 :          0 : static void quirk_ad1815_mpu_resources(struct pnp_dev *dev)
     209                 :            : {
     210                 :          0 :         struct pnp_option *option;
     211                 :          0 :         struct pnp_irq *irq = NULL;
     212                 :          0 :         unsigned int independent_irqs = 0;
     213                 :            : 
     214         [ #  # ]:          0 :         list_for_each_entry(option, &dev->options, list) {
     215   [ #  #  #  # ]:          0 :                 if (option->type == IORESOURCE_IRQ &&
     216         [ #  # ]:          0 :                     !pnp_option_is_dependent(option)) {
     217                 :          0 :                         independent_irqs++;
     218                 :          0 :                         irq = &option->u.irq;
     219                 :            :                 }
     220                 :            :         }
     221                 :            : 
     222         [ #  # ]:          0 :         if (independent_irqs != 1)
     223                 :            :                 return;
     224                 :            : 
     225                 :          0 :         irq->flags |= IORESOURCE_IRQ_OPTIONAL;
     226                 :          0 :         dev_info(&dev->dev, "made independent IRQ optional\n");
     227                 :            : }
     228                 :            : 
     229                 :            : #include <linux/pci.h>
     230                 :            : 
     231                 :          0 : static void quirk_system_pci_resources(struct pnp_dev *dev)
     232                 :            : {
     233                 :          0 :         struct pci_dev *pdev = NULL;
     234                 :          0 :         struct resource *res;
     235                 :          0 :         resource_size_t pnp_start, pnp_end, pci_start, pci_end;
     236                 :          0 :         int i, j;
     237                 :            : 
     238                 :            :         /*
     239                 :            :          * Some BIOSes have PNP motherboard devices with resources that
     240                 :            :          * partially overlap PCI BARs.  The PNP system driver claims these
     241                 :            :          * motherboard resources, which prevents the normal PCI driver from
     242                 :            :          * requesting them later.
     243                 :            :          *
     244                 :            :          * This patch disables the PNP resources that conflict with PCI BARs
     245                 :            :          * so they won't be claimed by the PNP system driver.
     246                 :            :          */
     247         [ #  # ]:          0 :         for_each_pci_dev(pdev) {
     248         [ #  # ]:          0 :                 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
     249                 :          0 :                         unsigned long flags, type;
     250                 :            : 
     251                 :          0 :                         flags = pci_resource_flags(pdev, i);
     252                 :          0 :                         type = flags & (IORESOURCE_IO | IORESOURCE_MEM);
     253   [ #  #  #  #  :          0 :                         if (!type || pci_resource_len(pdev, i) == 0)
             #  #  #  # ]
     254                 :          0 :                                 continue;
     255                 :            : 
     256         [ #  # ]:          0 :                         if (flags & IORESOURCE_UNSET)
     257                 :          0 :                                 continue;
     258                 :            : 
     259                 :            :                         pci_start = pci_resource_start(pdev, i);
     260                 :            :                         pci_end = pci_resource_end(pdev, i);
     261         [ #  # ]:          0 :                         for (j = 0;
     262                 :          0 :                              (res = pnp_get_resource(dev, type, j)); j++) {
     263   [ #  #  #  # ]:          0 :                                 if (res->start == 0 && res->end == 0)
     264                 :          0 :                                         continue;
     265                 :            : 
     266                 :          0 :                                 pnp_start = res->start;
     267                 :          0 :                                 pnp_end = res->end;
     268                 :            : 
     269                 :            :                                 /*
     270                 :            :                                  * If the PNP region doesn't overlap the PCI
     271                 :            :                                  * region at all, there's no problem.
     272                 :            :                                  */
     273         [ #  # ]:          0 :                                 if (pnp_end < pci_start || pnp_start > pci_end)
     274                 :          0 :                                         continue;
     275                 :            : 
     276                 :            :                                 /*
     277                 :            :                                  * If the PNP region completely encloses (or is
     278                 :            :                                  * at least as large as) the PCI region, that's
     279                 :            :                                  * also OK.  For example, this happens when the
     280                 :            :                                  * PNP device describes a bridge with PCI
     281                 :            :                                  * behind it.
     282                 :            :                                  */
     283                 :          0 :                                 if (pnp_start <= pci_start &&
     284         [ #  # ]:          0 :                                     pnp_end >= pci_end)
     285                 :          0 :                                         continue;
     286                 :            : 
     287                 :            :                                 /*
     288                 :            :                                  * Otherwise, the PNP region overlaps *part* of
     289                 :            :                                  * the PCI region, and that might prevent a PCI
     290                 :            :                                  * driver from requesting its resources.
     291                 :            :                                  */
     292         [ #  # ]:          0 :                                 dev_warn(&dev->dev,
     293                 :            :                                          "disabling %pR because it overlaps "
     294                 :            :                                          "%s BAR %d %pR\n", res,
     295                 :            :                                          pci_name(pdev), i, &pdev->resource[i]);
     296                 :          0 :                                 res->flags |= IORESOURCE_DISABLED;
     297                 :            :                         }
     298                 :            :                 }
     299                 :            :         }
     300                 :          0 : }
     301                 :            : 
     302                 :            : #ifdef CONFIG_AMD_NB
     303                 :            : 
     304                 :            : #include <asm/amd_nb.h>
     305                 :            : 
     306                 :          0 : static void quirk_amd_mmconfig_area(struct pnp_dev *dev)
     307                 :            : {
     308                 :          0 :         resource_size_t start, end;
     309                 :          0 :         struct pnp_resource *pnp_res;
     310                 :          0 :         struct resource *res;
     311                 :          0 :         struct resource mmconfig_res, *mmconfig;
     312                 :            : 
     313                 :          0 :         mmconfig = amd_get_mmconfig_range(&mmconfig_res);
     314         [ #  # ]:          0 :         if (!mmconfig)
     315                 :          0 :                 return;
     316                 :            : 
     317         [ #  # ]:          0 :         list_for_each_entry(pnp_res, &dev->resources, list) {
     318                 :          0 :                 res = &pnp_res->res;
     319   [ #  #  #  #  :          0 :                 if (res->end < mmconfig->start || res->start > mmconfig->end ||
                   #  # ]
     320         [ #  # ]:          0 :                     (res->start == mmconfig->start && res->end == mmconfig->end))
     321                 :          0 :                         continue;
     322                 :            : 
     323                 :          0 :                 dev_info(&dev->dev, FW_BUG
     324                 :            :                          "%pR covers only part of AMD MMCONFIG area %pR; adding more reservations\n",
     325                 :            :                          res, mmconfig);
     326         [ #  # ]:          0 :                 if (mmconfig->start < res->start) {
     327                 :          0 :                         start = mmconfig->start;
     328                 :          0 :                         end = res->start - 1;
     329                 :          0 :                         pnp_add_mem_resource(dev, start, end, 0);
     330                 :            :                 }
     331         [ #  # ]:          0 :                 if (mmconfig->end > res->end) {
     332                 :          0 :                         start = res->end + 1;
     333                 :          0 :                         end = mmconfig->end;
     334                 :          0 :                         pnp_add_mem_resource(dev, start, end, 0);
     335                 :            :                 }
     336                 :            :                 break;
     337                 :            :         }
     338                 :            : }
     339                 :            : #endif
     340                 :            : 
     341                 :            : #ifdef CONFIG_PCI
     342                 :            : /* Device IDs of parts that have 32KB MCH space */
     343                 :            : static const unsigned int mch_quirk_devices[] = {
     344                 :            :         0x0154, /* Ivy Bridge */
     345                 :            :         0x0a04, /* Haswell-ULT */
     346                 :            :         0x0c00, /* Haswell */
     347                 :            :         0x1604, /* Broadwell */
     348                 :            : };
     349                 :            : 
     350                 :          0 : static struct pci_dev *get_intel_host(void)
     351                 :            : {
     352                 :          0 :         int i;
     353                 :          0 :         struct pci_dev *host;
     354                 :            : 
     355         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(mch_quirk_devices); i++) {
     356                 :          0 :                 host = pci_get_device(PCI_VENDOR_ID_INTEL, mch_quirk_devices[i],
     357                 :            :                                       NULL);
     358         [ #  # ]:          0 :                 if (host)
     359                 :          0 :                         return host;
     360                 :            :         }
     361                 :            :         return NULL;
     362                 :            : }
     363                 :            : 
     364                 :          0 : static void quirk_intel_mch(struct pnp_dev *dev)
     365                 :            : {
     366                 :          0 :         struct pci_dev *host;
     367                 :          0 :         u32 addr_lo, addr_hi;
     368                 :          0 :         struct pci_bus_region region;
     369                 :          0 :         struct resource mch;
     370                 :          0 :         struct pnp_resource *pnp_res;
     371                 :          0 :         struct resource *res;
     372                 :            : 
     373                 :          0 :         host = get_intel_host();
     374         [ #  # ]:          0 :         if (!host)
     375                 :          0 :                 return;
     376                 :            : 
     377                 :            :         /*
     378                 :            :          * MCHBAR is not an architected PCI BAR, so MCH space is usually
     379                 :            :          * reported as a PNP0C02 resource.  The MCH space was originally
     380                 :            :          * 16KB, but is 32KB in newer parts.  Some BIOSes still report a
     381                 :            :          * PNP0C02 resource that is only 16KB, which means the rest of the
     382                 :            :          * MCH space is consumed but unreported.
     383                 :            :          */
     384                 :            : 
     385                 :            :         /*
     386                 :            :          * Read MCHBAR for Host Member Mapped Register Range Base
     387                 :            :          * https://www-ssl.intel.com/content/www/us/en/processors/core/4th-gen-core-family-desktop-vol-2-datasheet
     388                 :            :          * Sec 3.1.12.
     389                 :            :          */
     390                 :          0 :         pci_read_config_dword(host, 0x48, &addr_lo);
     391                 :          0 :         region.start = addr_lo & ~0x7fff;
     392                 :          0 :         pci_read_config_dword(host, 0x4c, &addr_hi);
     393                 :          0 :         region.start |= (u64) addr_hi << 32;
     394                 :          0 :         region.end = region.start + 32*1024 - 1;
     395                 :            : 
     396                 :          0 :         memset(&mch, 0, sizeof(mch));
     397                 :          0 :         mch.flags = IORESOURCE_MEM;
     398                 :          0 :         pcibios_bus_to_resource(host->bus, &mch, &region);
     399                 :            : 
     400         [ #  # ]:          0 :         list_for_each_entry(pnp_res, &dev->resources, list) {
     401                 :          0 :                 res = &pnp_res->res;
     402   [ #  #  #  # ]:          0 :                 if (res->end < mch.start || res->start > mch.end)
     403                 :          0 :                         continue;       /* no overlap */
     404   [ #  #  #  # ]:          0 :                 if (res->start == mch.start && res->end == mch.end)
     405                 :          0 :                         continue;       /* exact match */
     406                 :            : 
     407         [ #  # ]:          0 :                 dev_info(&dev->dev, FW_BUG "PNP resource %pR covers only part of %s Intel MCH; extending to %pR\n",
     408                 :            :                          res, pci_name(host), &mch);
     409                 :          0 :                 res->start = mch.start;
     410                 :          0 :                 res->end = mch.end;
     411                 :          0 :                 break;
     412                 :            :         }
     413                 :            : 
     414                 :          0 :         pci_dev_put(host);
     415                 :            : }
     416                 :            : #endif
     417                 :            : 
     418                 :            : /*
     419                 :            :  *  PnP Quirks
     420                 :            :  *  Cards or devices that need some tweaking due to incomplete resource info
     421                 :            :  */
     422                 :            : 
     423                 :            : static struct pnp_fixup pnp_fixups[] = {
     424                 :            :         /* Soundblaster awe io port quirk */
     425                 :            :         {"CTL0021", quirk_awe32_resources},
     426                 :            :         {"CTL0022", quirk_awe32_resources},
     427                 :            :         {"CTL0023", quirk_awe32_resources},
     428                 :            :         /* CMI 8330 interrupt and dma fix */
     429                 :            :         {"@X@0001", quirk_cmi8330_resources},
     430                 :            :         /* Soundblaster audio device io port range quirk */
     431                 :            :         {"CTL0001", quirk_sb16audio_resources},
     432                 :            :         {"CTL0031", quirk_sb16audio_resources},
     433                 :            :         {"CTL0041", quirk_sb16audio_resources},
     434                 :            :         {"CTL0042", quirk_sb16audio_resources},
     435                 :            :         {"CTL0043", quirk_sb16audio_resources},
     436                 :            :         {"CTL0044", quirk_sb16audio_resources},
     437                 :            :         {"CTL0045", quirk_sb16audio_resources},
     438                 :            :         /* Add IRQ-optional MPU options */
     439                 :            :         {"ADS7151", quirk_ad1815_mpu_resources},
     440                 :            :         {"ADS7181", quirk_add_irq_optional_dependent_sets},
     441                 :            :         {"AZT0002", quirk_add_irq_optional_dependent_sets},
     442                 :            :         /* PnP resources that might overlap PCI BARs */
     443                 :            :         {"PNP0c01", quirk_system_pci_resources},
     444                 :            :         {"PNP0c02", quirk_system_pci_resources},
     445                 :            : #ifdef CONFIG_AMD_NB
     446                 :            :         {"PNP0c01", quirk_amd_mmconfig_area},
     447                 :            : #endif
     448                 :            : #ifdef CONFIG_PCI
     449                 :            :         {"PNP0c02", quirk_intel_mch},
     450                 :            : #endif
     451                 :            :         {""}
     452                 :            : };
     453                 :            : 
     454                 :        126 : void pnp_fixup_device(struct pnp_dev *dev)
     455                 :            : {
     456                 :        126 :         struct pnp_fixup *f;
     457                 :            : 
     458         [ +  + ]:       2394 :         for (f = pnp_fixups; *f->id; f++) {
     459         [ +  - ]:       2268 :                 if (!compare_pnp_id(dev->id, f->id))
     460                 :       2268 :                         continue;
     461         [ #  # ]:          0 :                 pnp_dbg(&dev->dev, "%s: calling %pS\n", f->id,
     462                 :            :                         f->quirk_function);
     463                 :          0 :                 f->quirk_function(dev);
     464                 :            :         }
     465                 :        126 : }

Generated by: LCOV version 1.14