LCOV - code coverage report
Current view: top level - drivers/pnp - resource.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 34 351 9.7 %
Date: 2022-04-01 14:58:12 Functions: 4 28 14.3 %
Branches: 9 295 3.1 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * resource.c - Contains functions for registering and analyzing resource information
       4                 :            :  *
       5                 :            :  * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
       6                 :            :  * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
       7                 :            :  * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
       8                 :            :  *      Bjorn Helgaas <bjorn.helgaas@hp.com>
       9                 :            :  */
      10                 :            : 
      11                 :            : #include <linux/module.h>
      12                 :            : #include <linux/slab.h>
      13                 :            : #include <linux/errno.h>
      14                 :            : #include <linux/interrupt.h>
      15                 :            : #include <linux/kernel.h>
      16                 :            : #include <asm/io.h>
      17                 :            : #include <asm/dma.h>
      18                 :            : #include <asm/irq.h>
      19                 :            : #include <linux/pci.h>
      20                 :            : #include <linux/ioport.h>
      21                 :            : #include <linux/init.h>
      22                 :            : 
      23                 :            : #include <linux/pnp.h>
      24                 :            : #include "base.h"
      25                 :            : 
      26                 :            : static int pnp_reserve_irq[16] = {[0 ... 15] = -1 };    /* reserve (don't use) some IRQ */
      27                 :            : static int pnp_reserve_dma[8] = {[0 ... 7] = -1 };      /* reserve (don't use) some DMA */
      28                 :            : static int pnp_reserve_io[16] = {[0 ... 15] = -1 };     /* reserve (don't use) some I/O region */
      29                 :            : static int pnp_reserve_mem[16] = {[0 ... 15] = -1 };    /* reserve (don't use) some memory region */
      30                 :            : 
      31                 :            : /*
      32                 :            :  * option registration
      33                 :            :  */
      34                 :            : 
      35                 :          0 : static struct pnp_option *pnp_build_option(struct pnp_dev *dev, unsigned long type,
      36                 :            :                                     unsigned int option_flags)
      37                 :            : {
      38                 :          0 :         struct pnp_option *option;
      39                 :            : 
      40                 :          0 :         option = kzalloc(sizeof(struct pnp_option), GFP_KERNEL);
      41         [ #  # ]:          0 :         if (!option)
      42                 :            :                 return NULL;
      43                 :            : 
      44                 :          0 :         option->flags = option_flags;
      45                 :          0 :         option->type = type;
      46                 :            : 
      47                 :          0 :         list_add_tail(&option->list, &dev->options);
      48                 :          0 :         return option;
      49                 :            : }
      50                 :            : 
      51                 :          0 : int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags,
      52                 :            :                               pnp_irq_mask_t *map, unsigned char flags)
      53                 :            : {
      54                 :          0 :         struct pnp_option *option;
      55                 :          0 :         struct pnp_irq *irq;
      56                 :            : 
      57                 :          0 :         option = pnp_build_option(dev, IORESOURCE_IRQ, option_flags);
      58         [ #  # ]:          0 :         if (!option)
      59                 :            :                 return -ENOMEM;
      60                 :            : 
      61                 :          0 :         irq = &option->u.irq;
      62                 :          0 :         irq->map = *map;
      63                 :          0 :         irq->flags = flags;
      64                 :            : 
      65                 :            : #ifdef CONFIG_PCI
      66                 :            :         {
      67                 :          0 :                 int i;
      68                 :            : 
      69         [ #  # ]:          0 :                 for (i = 0; i < 16; i++)
      70         [ #  # ]:          0 :                         if (test_bit(i, irq->map.bits))
      71                 :          0 :                                 pcibios_penalize_isa_irq(i, 0);
      72                 :            :         }
      73                 :            : #endif
      74                 :            : 
      75                 :          0 :         dbg_pnp_show_option(dev, option);
      76                 :          0 :         return 0;
      77                 :            : }
      78                 :            : 
      79                 :          0 : int pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags,
      80                 :            :                               unsigned char map, unsigned char flags)
      81                 :            : {
      82                 :          0 :         struct pnp_option *option;
      83                 :          0 :         struct pnp_dma *dma;
      84                 :            : 
      85                 :          0 :         option = pnp_build_option(dev, IORESOURCE_DMA, option_flags);
      86         [ #  # ]:          0 :         if (!option)
      87                 :            :                 return -ENOMEM;
      88                 :            : 
      89                 :          0 :         dma = &option->u.dma;
      90                 :          0 :         dma->map = map;
      91                 :          0 :         dma->flags = flags;
      92                 :            : 
      93                 :          0 :         dbg_pnp_show_option(dev, option);
      94                 :          0 :         return 0;
      95                 :            : }
      96                 :            : 
      97                 :          0 : int pnp_register_port_resource(struct pnp_dev *dev, unsigned int option_flags,
      98                 :            :                                resource_size_t min, resource_size_t max,
      99                 :            :                                resource_size_t align, resource_size_t size,
     100                 :            :                                unsigned char flags)
     101                 :            : {
     102                 :          0 :         struct pnp_option *option;
     103                 :          0 :         struct pnp_port *port;
     104                 :            : 
     105                 :          0 :         option = pnp_build_option(dev, IORESOURCE_IO, option_flags);
     106         [ #  # ]:          0 :         if (!option)
     107                 :            :                 return -ENOMEM;
     108                 :            : 
     109                 :          0 :         port = &option->u.port;
     110                 :          0 :         port->min = min;
     111                 :          0 :         port->max = max;
     112                 :          0 :         port->align = align;
     113                 :          0 :         port->size = size;
     114                 :          0 :         port->flags = flags;
     115                 :            : 
     116                 :          0 :         dbg_pnp_show_option(dev, option);
     117                 :          0 :         return 0;
     118                 :            : }
     119                 :            : 
     120                 :          0 : int pnp_register_mem_resource(struct pnp_dev *dev, unsigned int option_flags,
     121                 :            :                               resource_size_t min, resource_size_t max,
     122                 :            :                               resource_size_t align, resource_size_t size,
     123                 :            :                               unsigned char flags)
     124                 :            : {
     125                 :          0 :         struct pnp_option *option;
     126                 :          0 :         struct pnp_mem *mem;
     127                 :            : 
     128                 :          0 :         option = pnp_build_option(dev, IORESOURCE_MEM, option_flags);
     129         [ #  # ]:          0 :         if (!option)
     130                 :            :                 return -ENOMEM;
     131                 :            : 
     132                 :          0 :         mem = &option->u.mem;
     133                 :          0 :         mem->min = min;
     134                 :          0 :         mem->max = max;
     135                 :          0 :         mem->align = align;
     136                 :          0 :         mem->size = size;
     137                 :          0 :         mem->flags = flags;
     138                 :            : 
     139                 :          0 :         dbg_pnp_show_option(dev, option);
     140                 :          0 :         return 0;
     141                 :            : }
     142                 :            : 
     143                 :          0 : void pnp_free_options(struct pnp_dev *dev)
     144                 :            : {
     145                 :          0 :         struct pnp_option *option, *tmp;
     146                 :            : 
     147         [ #  # ]:          0 :         list_for_each_entry_safe(option, tmp, &dev->options, list) {
     148                 :          0 :                 list_del(&option->list);
     149                 :          0 :                 kfree(option);
     150                 :            :         }
     151                 :          0 : }
     152                 :            : 
     153                 :            : /*
     154                 :            :  * resource validity checking
     155                 :            :  */
     156                 :            : 
     157                 :            : #define length(start, end) (*(end) - *(start) + 1)
     158                 :            : 
     159                 :            : /* Two ranges conflict if one doesn't end before the other starts */
     160                 :            : #define ranged_conflict(starta, enda, startb, endb) \
     161                 :            :         !((*(enda) < *(startb)) || (*(endb) < *(starta)))
     162                 :            : 
     163                 :            : #define cannot_compare(flags) \
     164                 :            : ((flags) & IORESOURCE_DISABLED)
     165                 :            : 
     166                 :          0 : int pnp_check_port(struct pnp_dev *dev, struct resource *res)
     167                 :            : {
     168                 :          0 :         int i;
     169                 :          0 :         struct pnp_dev *tdev;
     170                 :          0 :         struct resource *tres;
     171                 :          0 :         resource_size_t *port, *end, *tport, *tend;
     172                 :            : 
     173                 :          0 :         port = &res->start;
     174                 :          0 :         end = &res->end;
     175                 :            : 
     176                 :            :         /* if the resource doesn't exist, don't complain about it */
     177         [ #  # ]:          0 :         if (cannot_compare(res->flags))
     178                 :            :                 return 1;
     179                 :            : 
     180                 :            :         /* check if the resource is already in use, skip if the
     181                 :            :          * device is active because it itself may be in use */
     182         [ #  # ]:          0 :         if (!dev->active) {
     183         [ #  # ]:          0 :                 if (!request_region(*port, length(port, end), "pnp"))
     184                 :            :                         return 0;
     185                 :          0 :                 release_region(*port, length(port, end));
     186                 :            :         }
     187                 :            : 
     188                 :            :         /* check if the resource is reserved */
     189         [ #  # ]:          0 :         for (i = 0; i < 8; i++) {
     190                 :          0 :                 int rport = pnp_reserve_io[i << 1];
     191                 :          0 :                 int rend = pnp_reserve_io[(i << 1) + 1] + rport - 1;
     192   [ #  #  #  # ]:          0 :                 if (ranged_conflict(port, end, &rport, &rend))
     193                 :            :                         return 0;
     194                 :            :         }
     195                 :            : 
     196                 :            :         /* check for internal conflicts */
     197         [ #  # ]:          0 :         for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
     198   [ #  #  #  # ]:          0 :                 if (tres != res && tres->flags & IORESOURCE_IO) {
     199                 :          0 :                         tport = &tres->start;
     200                 :          0 :                         tend = &tres->end;
     201   [ #  #  #  # ]:          0 :                         if (ranged_conflict(port, end, tport, tend))
     202                 :            :                                 return 0;
     203                 :            :                 }
     204                 :            :         }
     205                 :            : 
     206                 :            :         /* check for conflicts with other pnp devices */
     207         [ #  # ]:          0 :         pnp_for_each_dev(tdev) {
     208         [ #  # ]:          0 :                 if (tdev == dev)
     209                 :          0 :                         continue;
     210         [ #  # ]:          0 :                 for (i = 0;
     211                 :          0 :                      (tres = pnp_get_resource(tdev, IORESOURCE_IO, i));
     212                 :          0 :                      i++) {
     213         [ #  # ]:          0 :                         if (tres->flags & IORESOURCE_IO) {
     214         [ #  # ]:          0 :                                 if (cannot_compare(tres->flags))
     215                 :          0 :                                         continue;
     216         [ #  # ]:          0 :                                 if (tres->flags & IORESOURCE_WINDOW)
     217                 :          0 :                                         continue;
     218                 :          0 :                                 tport = &tres->start;
     219                 :          0 :                                 tend = &tres->end;
     220   [ #  #  #  # ]:          0 :                                 if (ranged_conflict(port, end, tport, tend))
     221                 :            :                                         return 0;
     222                 :            :                         }
     223                 :            :                 }
     224                 :            :         }
     225                 :            : 
     226                 :            :         return 1;
     227                 :            : }
     228                 :            : 
     229                 :          0 : int pnp_check_mem(struct pnp_dev *dev, struct resource *res)
     230                 :            : {
     231                 :          0 :         int i;
     232                 :          0 :         struct pnp_dev *tdev;
     233                 :          0 :         struct resource *tres;
     234                 :          0 :         resource_size_t *addr, *end, *taddr, *tend;
     235                 :            : 
     236                 :          0 :         addr = &res->start;
     237                 :          0 :         end = &res->end;
     238                 :            : 
     239                 :            :         /* if the resource doesn't exist, don't complain about it */
     240         [ #  # ]:          0 :         if (cannot_compare(res->flags))
     241                 :            :                 return 1;
     242                 :            : 
     243                 :            :         /* check if the resource is already in use, skip if the
     244                 :            :          * device is active because it itself may be in use */
     245         [ #  # ]:          0 :         if (!dev->active) {
     246         [ #  # ]:          0 :                 if (!request_mem_region(*addr, length(addr, end), "pnp"))
     247                 :            :                         return 0;
     248                 :          0 :                 release_mem_region(*addr, length(addr, end));
     249                 :            :         }
     250                 :            : 
     251                 :            :         /* check if the resource is reserved */
     252         [ #  # ]:          0 :         for (i = 0; i < 8; i++) {
     253                 :          0 :                 int raddr = pnp_reserve_mem[i << 1];
     254                 :          0 :                 int rend = pnp_reserve_mem[(i << 1) + 1] + raddr - 1;
     255   [ #  #  #  # ]:          0 :                 if (ranged_conflict(addr, end, &raddr, &rend))
     256                 :            :                         return 0;
     257                 :            :         }
     258                 :            : 
     259                 :            :         /* check for internal conflicts */
     260         [ #  # ]:          0 :         for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
     261   [ #  #  #  # ]:          0 :                 if (tres != res && tres->flags & IORESOURCE_MEM) {
     262                 :          0 :                         taddr = &tres->start;
     263                 :          0 :                         tend = &tres->end;
     264   [ #  #  #  # ]:          0 :                         if (ranged_conflict(addr, end, taddr, tend))
     265                 :            :                                 return 0;
     266                 :            :                 }
     267                 :            :         }
     268                 :            : 
     269                 :            :         /* check for conflicts with other pnp devices */
     270         [ #  # ]:          0 :         pnp_for_each_dev(tdev) {
     271         [ #  # ]:          0 :                 if (tdev == dev)
     272                 :          0 :                         continue;
     273         [ #  # ]:          0 :                 for (i = 0;
     274                 :          0 :                      (tres = pnp_get_resource(tdev, IORESOURCE_MEM, i));
     275                 :          0 :                      i++) {
     276         [ #  # ]:          0 :                         if (tres->flags & IORESOURCE_MEM) {
     277         [ #  # ]:          0 :                                 if (cannot_compare(tres->flags))
     278                 :          0 :                                         continue;
     279         [ #  # ]:          0 :                                 if (tres->flags & IORESOURCE_WINDOW)
     280                 :          0 :                                         continue;
     281                 :          0 :                                 taddr = &tres->start;
     282                 :          0 :                                 tend = &tres->end;
     283   [ #  #  #  # ]:          0 :                                 if (ranged_conflict(addr, end, taddr, tend))
     284                 :            :                                         return 0;
     285                 :            :                         }
     286                 :            :                 }
     287                 :            :         }
     288                 :            : 
     289                 :            :         return 1;
     290                 :            : }
     291                 :            : 
     292                 :          0 : static irqreturn_t pnp_test_handler(int irq, void *dev_id)
     293                 :            : {
     294                 :          0 :         return IRQ_HANDLED;
     295                 :            : }
     296                 :            : 
     297                 :            : #ifdef CONFIG_PCI
     298                 :          0 : static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
     299                 :            :                             unsigned int irq)
     300                 :            : {
     301                 :          0 :         u32 class;
     302                 :          0 :         u8 progif;
     303                 :            : 
     304         [ #  # ]:          0 :         if (pci->irq == irq) {
     305   [ #  #  #  # ]:          0 :                 pnp_dbg(&pnp->dev, "  device %s using irq %d\n",
     306                 :            :                         pci_name(pci), irq);
     307                 :          0 :                 return 1;
     308                 :            :         }
     309                 :            : 
     310                 :            :         /*
     311                 :            :          * See pci_setup_device() and ata_pci_sff_activate_host() for
     312                 :            :          * similar IDE legacy detection.
     313                 :            :          */
     314                 :          0 :         pci_read_config_dword(pci, PCI_CLASS_REVISION, &class);
     315                 :          0 :         class >>= 8;              /* discard revision ID */
     316                 :          0 :         progif = class & 0xff;
     317                 :          0 :         class >>= 8;
     318                 :            : 
     319         [ #  # ]:          0 :         if (class == PCI_CLASS_STORAGE_IDE) {
     320                 :            :                 /*
     321                 :            :                  * Unless both channels are native-PCI mode only,
     322                 :            :                  * treat the compatibility IRQs as busy.
     323                 :            :                  */
     324         [ #  # ]:          0 :                 if ((progif & 0x5) != 0x5)
     325   [ #  #  #  # ]:          0 :                         if (pci_get_legacy_ide_irq(pci, 0) == irq ||
     326                 :            :                             pci_get_legacy_ide_irq(pci, 1) == irq) {
     327   [ #  #  #  # ]:          0 :                                 pnp_dbg(&pnp->dev, "  legacy IDE device %s "
     328                 :            :                                         "using irq %d\n", pci_name(pci), irq);
     329                 :          0 :                                 return 1;
     330                 :            :                         }
     331                 :            :         }
     332                 :            : 
     333                 :            :         return 0;
     334                 :            : }
     335                 :            : #endif
     336                 :            : 
     337                 :          0 : static int pci_uses_irq(struct pnp_dev *pnp, unsigned int irq)
     338                 :            : {
     339                 :            : #ifdef CONFIG_PCI
     340                 :          0 :         struct pci_dev *pci = NULL;
     341                 :            : 
     342         [ #  # ]:          0 :         for_each_pci_dev(pci) {
     343         [ #  # ]:          0 :                 if (pci_dev_uses_irq(pnp, pci, irq)) {
     344                 :          0 :                         pci_dev_put(pci);
     345                 :          0 :                         return 1;
     346                 :            :                 }
     347                 :            :         }
     348                 :            : #endif
     349                 :            :         return 0;
     350                 :            : }
     351                 :            : 
     352                 :          0 : int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
     353                 :            : {
     354                 :          0 :         int i;
     355                 :          0 :         struct pnp_dev *tdev;
     356                 :          0 :         struct resource *tres;
     357                 :          0 :         resource_size_t *irq;
     358                 :            : 
     359                 :          0 :         irq = &res->start;
     360                 :            : 
     361                 :            :         /* if the resource doesn't exist, don't complain about it */
     362         [ #  # ]:          0 :         if (cannot_compare(res->flags))
     363                 :            :                 return 1;
     364                 :            : 
     365                 :            :         /* check if the resource is valid */
     366         [ #  # ]:          0 :         if (*irq > 15)
     367                 :            :                 return 0;
     368                 :            : 
     369                 :            :         /* check if the resource is reserved */
     370         [ #  # ]:          0 :         for (i = 0; i < 16; i++) {
     371         [ #  # ]:          0 :                 if (pnp_reserve_irq[i] == *irq)
     372                 :            :                         return 0;
     373                 :            :         }
     374                 :            : 
     375                 :            :         /* check for internal conflicts */
     376         [ #  # ]:          0 :         for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
     377   [ #  #  #  # ]:          0 :                 if (tres != res && tres->flags & IORESOURCE_IRQ) {
     378         [ #  # ]:          0 :                         if (tres->start == *irq)
     379                 :            :                                 return 0;
     380                 :            :                 }
     381                 :            :         }
     382                 :            : 
     383                 :            :         /* check if the resource is being used by a pci device */
     384         [ #  # ]:          0 :         if (pci_uses_irq(dev, *irq))
     385                 :            :                 return 0;
     386                 :            : 
     387                 :            :         /* check if the resource is already in use, skip if the
     388                 :            :          * device is active because it itself may be in use */
     389         [ #  # ]:          0 :         if (!dev->active) {
     390         [ #  # ]:          0 :                 if (request_irq(*irq, pnp_test_handler,
     391                 :            :                                 IRQF_PROBE_SHARED, "pnp", NULL))
     392                 :            :                         return 0;
     393                 :          0 :                 free_irq(*irq, NULL);
     394                 :            :         }
     395                 :            : 
     396                 :            :         /* check for conflicts with other pnp devices */
     397         [ #  # ]:          0 :         pnp_for_each_dev(tdev) {
     398         [ #  # ]:          0 :                 if (tdev == dev)
     399                 :          0 :                         continue;
     400         [ #  # ]:          0 :                 for (i = 0;
     401                 :          0 :                      (tres = pnp_get_resource(tdev, IORESOURCE_IRQ, i));
     402                 :          0 :                      i++) {
     403         [ #  # ]:          0 :                         if (tres->flags & IORESOURCE_IRQ) {
     404         [ #  # ]:          0 :                                 if (cannot_compare(tres->flags))
     405                 :          0 :                                         continue;
     406         [ #  # ]:          0 :                                 if (tres->start == *irq)
     407                 :            :                                         return 0;
     408                 :            :                         }
     409                 :            :                 }
     410                 :            :         }
     411                 :            : 
     412                 :            :         return 1;
     413                 :            : }
     414                 :            : 
     415                 :            : #ifdef CONFIG_ISA_DMA_API
     416                 :          0 : int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
     417                 :            : {
     418                 :          0 :         int i;
     419                 :          0 :         struct pnp_dev *tdev;
     420                 :          0 :         struct resource *tres;
     421                 :          0 :         resource_size_t *dma;
     422                 :            : 
     423                 :          0 :         dma = &res->start;
     424                 :            : 
     425                 :            :         /* if the resource doesn't exist, don't complain about it */
     426         [ #  # ]:          0 :         if (cannot_compare(res->flags))
     427                 :            :                 return 1;
     428                 :            : 
     429                 :            :         /* check if the resource is valid */
     430         [ #  # ]:          0 :         if (*dma == 4 || *dma > 7)
     431                 :            :                 return 0;
     432                 :            : 
     433                 :            :         /* check if the resource is reserved */
     434         [ #  # ]:          0 :         for (i = 0; i < 8; i++) {
     435         [ #  # ]:          0 :                 if (pnp_reserve_dma[i] == *dma)
     436                 :            :                         return 0;
     437                 :            :         }
     438                 :            : 
     439                 :            :         /* check for internal conflicts */
     440         [ #  # ]:          0 :         for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
     441   [ #  #  #  # ]:          0 :                 if (tres != res && tres->flags & IORESOURCE_DMA) {
     442         [ #  # ]:          0 :                         if (tres->start == *dma)
     443                 :            :                                 return 0;
     444                 :            :                 }
     445                 :            :         }
     446                 :            : 
     447                 :            :         /* check if the resource is already in use, skip if the
     448                 :            :          * device is active because it itself may be in use */
     449         [ #  # ]:          0 :         if (!dev->active) {
     450         [ #  # ]:          0 :                 if (request_dma(*dma, "pnp"))
     451                 :            :                         return 0;
     452                 :          0 :                 free_dma(*dma);
     453                 :            :         }
     454                 :            : 
     455                 :            :         /* check for conflicts with other pnp devices */
     456         [ #  # ]:          0 :         pnp_for_each_dev(tdev) {
     457         [ #  # ]:          0 :                 if (tdev == dev)
     458                 :          0 :                         continue;
     459         [ #  # ]:          0 :                 for (i = 0;
     460                 :          0 :                      (tres = pnp_get_resource(tdev, IORESOURCE_DMA, i));
     461                 :          0 :                      i++) {
     462         [ #  # ]:          0 :                         if (tres->flags & IORESOURCE_DMA) {
     463         [ #  # ]:          0 :                                 if (cannot_compare(tres->flags))
     464                 :          0 :                                         continue;
     465         [ #  # ]:          0 :                                 if (tres->start == *dma)
     466                 :            :                                         return 0;
     467                 :            :                         }
     468                 :            :                 }
     469                 :            :         }
     470                 :            : 
     471                 :            :         return 1;
     472                 :            : }
     473                 :            : #endif /* CONFIG_ISA_DMA_API */
     474                 :            : 
     475                 :         99 : unsigned long pnp_resource_type(struct resource *res)
     476                 :            : {
     477                 :         99 :         return res->flags & (IORESOURCE_IO  | IORESOURCE_MEM |
     478                 :            :                              IORESOURCE_IRQ | IORESOURCE_DMA |
     479                 :            :                              IORESOURCE_BUS);
     480                 :            : }
     481                 :            : 
     482                 :         63 : struct resource *pnp_get_resource(struct pnp_dev *dev,
     483                 :            :                                   unsigned long type, unsigned int num)
     484                 :            : {
     485                 :         63 :         struct pnp_resource *pnp_res;
     486                 :         63 :         struct resource *res;
     487                 :            : 
     488   [ +  +  -  -  :        105 :         list_for_each_entry(pnp_res, &dev->resources, list) {
          -  -  -  -  -  
          -  -  -  -  -  
             -  -  -  - ]
     489                 :         99 :                 res = &pnp_res->res;
     490   [ +  +  +  +  :         99 :                 if (pnp_resource_type(res) == type && num-- == 0)
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
                   -  - ]
     491                 :         57 :                         return res;
     492                 :            :         }
     493                 :            :         return NULL;
     494                 :            : }
     495                 :            : EXPORT_SYMBOL(pnp_get_resource);
     496                 :            : 
     497                 :         45 : static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
     498                 :            : {
     499                 :         45 :         struct pnp_resource *pnp_res;
     500                 :            : 
     501                 :         45 :         pnp_res = kzalloc(sizeof(struct pnp_resource), GFP_KERNEL);
     502         [ +  - ]:         45 :         if (!pnp_res)
     503                 :            :                 return NULL;
     504                 :            : 
     505                 :         45 :         list_add_tail(&pnp_res->list, &dev->resources);
     506                 :         45 :         return pnp_res;
     507                 :            : }
     508                 :            : 
     509                 :         42 : struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
     510                 :            :                                       struct resource *res)
     511                 :            : {
     512                 :         42 :         struct pnp_resource *pnp_res;
     513                 :            : 
     514                 :         42 :         pnp_res = pnp_new_resource(dev);
     515         [ -  + ]:         42 :         if (!pnp_res) {
     516                 :          0 :                 dev_err(&dev->dev, "can't add resource %pR\n", res);
     517                 :          0 :                 return NULL;
     518                 :            :         }
     519                 :            : 
     520                 :         42 :         pnp_res->res = *res;
     521                 :         42 :         pnp_res->res.name = dev->name;
     522                 :         42 :         dev_dbg(&dev->dev, "%pR\n", res);
     523                 :         42 :         return pnp_res;
     524                 :            : }
     525                 :            : 
     526                 :          0 : struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
     527                 :            :                                           int flags)
     528                 :            : {
     529                 :          0 :         struct pnp_resource *pnp_res;
     530                 :          0 :         struct resource *res;
     531                 :            : 
     532                 :          0 :         pnp_res = pnp_new_resource(dev);
     533         [ #  # ]:          0 :         if (!pnp_res) {
     534                 :          0 :                 dev_err(&dev->dev, "can't add resource for IRQ %d\n", irq);
     535                 :          0 :                 return NULL;
     536                 :            :         }
     537                 :            : 
     538                 :          0 :         res = &pnp_res->res;
     539                 :          0 :         res->flags = IORESOURCE_IRQ | flags;
     540                 :          0 :         res->start = irq;
     541                 :          0 :         res->end = irq;
     542                 :            : 
     543                 :          0 :         dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
     544                 :          0 :         return pnp_res;
     545                 :            : }
     546                 :            : 
     547                 :          3 : struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
     548                 :            :                                           int flags)
     549                 :            : {
     550                 :          3 :         struct pnp_resource *pnp_res;
     551                 :          3 :         struct resource *res;
     552                 :            : 
     553                 :          3 :         pnp_res = pnp_new_resource(dev);
     554         [ -  + ]:          3 :         if (!pnp_res) {
     555                 :          0 :                 dev_err(&dev->dev, "can't add resource for DMA %d\n", dma);
     556                 :          0 :                 return NULL;
     557                 :            :         }
     558                 :            : 
     559                 :          3 :         res = &pnp_res->res;
     560                 :          3 :         res->flags = IORESOURCE_DMA | flags;
     561                 :          3 :         res->start = dma;
     562                 :          3 :         res->end = dma;
     563                 :            : 
     564                 :          3 :         dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
     565                 :          3 :         return pnp_res;
     566                 :            : }
     567                 :            : 
     568                 :          0 : struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
     569                 :            :                                          resource_size_t start,
     570                 :            :                                          resource_size_t end, int flags)
     571                 :            : {
     572                 :          0 :         struct pnp_resource *pnp_res;
     573                 :          0 :         struct resource *res;
     574                 :            : 
     575                 :          0 :         pnp_res = pnp_new_resource(dev);
     576         [ #  # ]:          0 :         if (!pnp_res) {
     577                 :          0 :                 dev_err(&dev->dev, "can't add resource for IO %#llx-%#llx\n",
     578                 :            :                         (unsigned long long) start,
     579                 :            :                         (unsigned long long) end);
     580                 :          0 :                 return NULL;
     581                 :            :         }
     582                 :            : 
     583                 :          0 :         res = &pnp_res->res;
     584                 :          0 :         res->flags = IORESOURCE_IO | flags;
     585                 :          0 :         res->start = start;
     586                 :          0 :         res->end = end;
     587                 :            : 
     588                 :          0 :         dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
     589                 :          0 :         return pnp_res;
     590                 :            : }
     591                 :            : 
     592                 :          0 : struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
     593                 :            :                                           resource_size_t start,
     594                 :            :                                           resource_size_t end, int flags)
     595                 :            : {
     596                 :          0 :         struct pnp_resource *pnp_res;
     597                 :          0 :         struct resource *res;
     598                 :            : 
     599                 :          0 :         pnp_res = pnp_new_resource(dev);
     600         [ #  # ]:          0 :         if (!pnp_res) {
     601                 :          0 :                 dev_err(&dev->dev, "can't add resource for MEM %#llx-%#llx\n",
     602                 :            :                         (unsigned long long) start,
     603                 :            :                         (unsigned long long) end);
     604                 :          0 :                 return NULL;
     605                 :            :         }
     606                 :            : 
     607                 :          0 :         res = &pnp_res->res;
     608                 :          0 :         res->flags = IORESOURCE_MEM | flags;
     609                 :          0 :         res->start = start;
     610                 :          0 :         res->end = end;
     611                 :            : 
     612                 :          0 :         dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
     613                 :          0 :         return pnp_res;
     614                 :            : }
     615                 :            : 
     616                 :          0 : struct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev,
     617                 :            :                                           resource_size_t start,
     618                 :            :                                           resource_size_t end)
     619                 :            : {
     620                 :          0 :         struct pnp_resource *pnp_res;
     621                 :          0 :         struct resource *res;
     622                 :            : 
     623                 :          0 :         pnp_res = pnp_new_resource(dev);
     624         [ #  # ]:          0 :         if (!pnp_res) {
     625                 :          0 :                 dev_err(&dev->dev, "can't add resource for BUS %#llx-%#llx\n",
     626                 :            :                         (unsigned long long) start,
     627                 :            :                         (unsigned long long) end);
     628                 :          0 :                 return NULL;
     629                 :            :         }
     630                 :            : 
     631                 :          0 :         res = &pnp_res->res;
     632                 :          0 :         res->flags = IORESOURCE_BUS;
     633                 :          0 :         res->start = start;
     634                 :          0 :         res->end = end;
     635                 :            : 
     636                 :          0 :         dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
     637                 :          0 :         return pnp_res;
     638                 :            : }
     639                 :            : 
     640                 :            : /*
     641                 :            :  * Determine whether the specified resource is a possible configuration
     642                 :            :  * for this device.
     643                 :            :  */
     644                 :          0 : int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
     645                 :            :                         resource_size_t size)
     646                 :            : {
     647                 :          0 :         struct pnp_option *option;
     648                 :          0 :         struct pnp_port *port;
     649                 :          0 :         struct pnp_mem *mem;
     650                 :          0 :         struct pnp_irq *irq;
     651                 :          0 :         struct pnp_dma *dma;
     652                 :            : 
     653         [ #  # ]:          0 :         list_for_each_entry(option, &dev->options, list) {
     654         [ #  # ]:          0 :                 if (option->type != type)
     655                 :          0 :                         continue;
     656                 :            : 
     657   [ #  #  #  #  :          0 :                 switch (option->type) {
                      # ]
     658                 :          0 :                 case IORESOURCE_IO:
     659                 :          0 :                         port = &option->u.port;
     660   [ #  #  #  # ]:          0 :                         if (port->min == start && port->size == size)
     661                 :            :                                 return 1;
     662                 :            :                         break;
     663                 :          0 :                 case IORESOURCE_MEM:
     664                 :          0 :                         mem = &option->u.mem;
     665   [ #  #  #  # ]:          0 :                         if (mem->min == start && mem->size == size)
     666                 :            :                                 return 1;
     667                 :            :                         break;
     668                 :          0 :                 case IORESOURCE_IRQ:
     669                 :          0 :                         irq = &option->u.irq;
     670   [ #  #  #  # ]:          0 :                         if (start < PNP_IRQ_NR &&
     671                 :          0 :                             test_bit(start, irq->map.bits))
     672                 :            :                                 return 1;
     673                 :            :                         break;
     674                 :          0 :                 case IORESOURCE_DMA:
     675                 :          0 :                         dma = &option->u.dma;
     676         [ #  # ]:          0 :                         if (dma->map & (1 << start))
     677                 :            :                                 return 1;
     678                 :            :                         break;
     679                 :            :                 }
     680                 :          0 :         }
     681                 :            : 
     682                 :            :         return 0;
     683                 :            : }
     684                 :            : EXPORT_SYMBOL(pnp_possible_config);
     685                 :            : 
     686                 :          0 : int pnp_range_reserved(resource_size_t start, resource_size_t end)
     687                 :            : {
     688                 :          0 :         struct pnp_dev *dev;
     689                 :          0 :         struct pnp_resource *pnp_res;
     690                 :          0 :         resource_size_t *dev_start, *dev_end;
     691                 :            : 
     692         [ #  # ]:          0 :         pnp_for_each_dev(dev) {
     693         [ #  # ]:          0 :                 list_for_each_entry(pnp_res, &dev->resources, list) {
     694                 :          0 :                         dev_start = &pnp_res->res.start;
     695                 :          0 :                         dev_end   = &pnp_res->res.end;
     696   [ #  #  #  # ]:          0 :                         if (ranged_conflict(&start, &end, dev_start, dev_end))
     697                 :            :                                 return 1;
     698                 :            :                 }
     699                 :            :         }
     700                 :            :         return 0;
     701                 :            : }
     702                 :            : EXPORT_SYMBOL(pnp_range_reserved);
     703                 :            : 
     704                 :            : /* format is: pnp_reserve_irq=irq1[,irq2] .... */
     705                 :          0 : static int __init pnp_setup_reserve_irq(char *str)
     706                 :            : {
     707                 :          0 :         int i;
     708                 :            : 
     709         [ #  # ]:          0 :         for (i = 0; i < 16; i++)
     710         [ #  # ]:          0 :                 if (get_option(&str, &pnp_reserve_irq[i]) != 2)
     711                 :            :                         break;
     712                 :          0 :         return 1;
     713                 :            : }
     714                 :            : 
     715                 :            : __setup("pnp_reserve_irq=", pnp_setup_reserve_irq);
     716                 :            : 
     717                 :            : /* format is: pnp_reserve_dma=dma1[,dma2] .... */
     718                 :          0 : static int __init pnp_setup_reserve_dma(char *str)
     719                 :            : {
     720                 :          0 :         int i;
     721                 :            : 
     722         [ #  # ]:          0 :         for (i = 0; i < 8; i++)
     723         [ #  # ]:          0 :                 if (get_option(&str, &pnp_reserve_dma[i]) != 2)
     724                 :            :                         break;
     725                 :          0 :         return 1;
     726                 :            : }
     727                 :            : 
     728                 :            : __setup("pnp_reserve_dma=", pnp_setup_reserve_dma);
     729                 :            : 
     730                 :            : /* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */
     731                 :          0 : static int __init pnp_setup_reserve_io(char *str)
     732                 :            : {
     733                 :          0 :         int i;
     734                 :            : 
     735         [ #  # ]:          0 :         for (i = 0; i < 16; i++)
     736         [ #  # ]:          0 :                 if (get_option(&str, &pnp_reserve_io[i]) != 2)
     737                 :            :                         break;
     738                 :          0 :         return 1;
     739                 :            : }
     740                 :            : 
     741                 :            : __setup("pnp_reserve_io=", pnp_setup_reserve_io);
     742                 :            : 
     743                 :            : /* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */
     744                 :          0 : static int __init pnp_setup_reserve_mem(char *str)
     745                 :            : {
     746                 :          0 :         int i;
     747                 :            : 
     748         [ #  # ]:          0 :         for (i = 0; i < 16; i++)
     749         [ #  # ]:          0 :                 if (get_option(&str, &pnp_reserve_mem[i]) != 2)
     750                 :            :                         break;
     751                 :          0 :         return 1;
     752                 :            : }
     753                 :            : 
     754                 :            : __setup("pnp_reserve_mem=", pnp_setup_reserve_mem);

Generated by: LCOV version 1.14