LCOV - code coverage report
Current view: top level - drivers/acpi - resource.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 182 293 62.1 %
Date: 2022-04-01 14:17:54 Functions: 14 21 66.7 %
Branches: 64 169 37.9 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * drivers/acpi/resource.c - ACPI device resources interpretation.
       4                 :            :  *
       5                 :            :  * Copyright (C) 2012, Intel Corp.
       6                 :            :  * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
       7                 :            :  *
       8                 :            :  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       9                 :            :  *
      10                 :            :  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      11                 :            :  */
      12                 :            : 
      13                 :            : #include <linux/acpi.h>
      14                 :            : #include <linux/device.h>
      15                 :            : #include <linux/export.h>
      16                 :            : #include <linux/ioport.h>
      17                 :            : #include <linux/slab.h>
      18                 :            : #include <linux/irq.h>
      19                 :            : 
      20                 :            : #ifdef CONFIG_X86
      21                 :            : #define valid_IRQ(i) (((i) != 0) && ((i) != 2))
      22                 :        132 : static inline bool acpi_iospace_resource_valid(struct resource *res)
      23                 :            : {
      24                 :            :         /* On X86 IO space is limited to the [0 - 64K] IO port range */
      25                 :        132 :         return res->end < 0x10003;
      26                 :            : }
      27                 :            : #else
      28                 :            : #define valid_IRQ(i) (true)
      29                 :            : /*
      30                 :            :  * ACPI IO descriptors on arches other than X86 contain MMIO CPU physical
      31                 :            :  * addresses mapping IO space in CPU physical address space, IO space
      32                 :            :  * resources can be placed anywhere in the 64-bit physical address space.
      33                 :            :  */
      34                 :            : static inline bool
      35                 :            : acpi_iospace_resource_valid(struct resource *res) { return true; }
      36                 :            : #endif
      37                 :            : 
      38                 :            : #if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI)
      39                 :            : static inline bool is_gsi(struct acpi_resource_extended_irq *ext_irq)
      40                 :            : {
      41                 :            :         return ext_irq->resource_source.string_length == 0 &&
      42                 :            :                ext_irq->producer_consumer == ACPI_CONSUMER;
      43                 :            : }
      44                 :            : #else
      45                 :          0 : static inline bool is_gsi(struct acpi_resource_extended_irq *ext_irq)
      46                 :            : {
      47                 :          0 :         return true;
      48                 :            : }
      49                 :            : #endif
      50                 :            : 
      51                 :        165 : static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
      52                 :            : {
      53                 :        165 :         u64 reslen = end - start + 1;
      54                 :            : 
      55                 :            :         /*
      56                 :            :          * CHECKME: len might be required to check versus a minimum
      57                 :            :          * length as well. 1 for io is fine, but for memory it does
      58                 :            :          * not make any sense at all.
      59                 :            :          * Note: some BIOSes report incorrect length for ACPI address space
      60                 :            :          * descriptor, so remove check of 'reslen == len' to avoid regression.
      61                 :            :          */
      62   [ -  +  -  +  :        165 :         if (len && reslen && start <= end)
          -  -  -  -  -  
                      + ]
      63                 :            :                 return true;
      64                 :            : 
      65                 :            :         pr_debug("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
      66                 :            :                 io ? "io" : "mem", start, end, len);
      67                 :            : 
      68                 :            :         return false;
      69                 :            : }
      70                 :            : 
      71                 :         33 : static void acpi_dev_memresource_flags(struct resource *res, u64 len,
      72                 :            :                                        u8 write_protect)
      73                 :            : {
      74                 :         33 :         res->flags = IORESOURCE_MEM;
      75                 :            : 
      76                 :         33 :         if (!acpi_dev_resource_len_valid(res->start, res->end, len, false))
      77                 :          0 :                 res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
      78                 :            : 
      79   [ +  -  -  -  :         33 :         if (write_protect == ACPI_READ_WRITE_MEMORY)
             -  -  -  + ]
      80                 :         22 :                 res->flags |= IORESOURCE_MEM_WRITEABLE;
      81                 :            : }
      82                 :            : 
      83                 :         11 : static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
      84                 :            :                                      u8 write_protect)
      85                 :            : {
      86                 :         11 :         res->start = start;
      87                 :         11 :         res->end = start + len - 1;
      88                 :         11 :         acpi_dev_memresource_flags(res, len, write_protect);
      89                 :            : }
      90                 :            : 
      91                 :            : /**
      92                 :            :  * acpi_dev_resource_memory - Extract ACPI memory resource information.
      93                 :            :  * @ares: Input ACPI resource object.
      94                 :            :  * @res: Output generic resource object.
      95                 :            :  *
      96                 :            :  * Check if the given ACPI resource object represents a memory resource and
      97                 :            :  * if that's the case, use the information in it to populate the generic
      98                 :            :  * resource object pointed to by @res.
      99                 :            :  *
     100                 :            :  * Return:
     101                 :            :  * 1) false with res->flags setting to zero: not the expected resource type
     102                 :            :  * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
     103                 :            :  * 3) true: valid assigned resource
     104                 :            :  */
     105                 :         99 : bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
     106                 :            : {
     107                 :         99 :         struct acpi_resource_memory24 *memory24;
     108                 :         99 :         struct acpi_resource_memory32 *memory32;
     109                 :         99 :         struct acpi_resource_fixed_memory32 *fixed_memory32;
     110                 :            : 
     111   [ -  -  +  + ]:         99 :         switch (ares->type) {
     112                 :          0 :         case ACPI_RESOURCE_TYPE_MEMORY24:
     113                 :          0 :                 memory24 = &ares->data.memory24;
     114                 :          0 :                 acpi_dev_get_memresource(res, memory24->minimum << 8,
     115                 :          0 :                                          memory24->address_length << 8,
     116         [ #  # ]:          0 :                                          memory24->write_protect);
     117                 :            :                 break;
     118                 :          0 :         case ACPI_RESOURCE_TYPE_MEMORY32:
     119                 :          0 :                 memory32 = &ares->data.memory32;
     120                 :          0 :                 acpi_dev_get_memresource(res, memory32->minimum,
     121                 :          0 :                                          memory32->address_length,
     122         [ #  # ]:          0 :                                          memory32->write_protect);
     123                 :            :                 break;
     124                 :         11 :         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
     125                 :         11 :                 fixed_memory32 = &ares->data.fixed_memory32;
     126                 :         11 :                 acpi_dev_get_memresource(res, fixed_memory32->address,
     127                 :         11 :                                          fixed_memory32->address_length,
     128         [ +  - ]:         11 :                                          fixed_memory32->write_protect);
     129                 :            :                 break;
     130                 :         88 :         default:
     131                 :         88 :                 res->flags = 0;
     132                 :         88 :                 return false;
     133                 :            :         }
     134                 :            : 
     135                 :         11 :         return !(res->flags & IORESOURCE_DISABLED);
     136                 :            : }
     137                 :            : EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
     138                 :            : 
     139                 :        132 : static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
     140                 :            :                                       u8 io_decode, u8 translation_type)
     141                 :            : {
     142                 :        132 :         res->flags = IORESOURCE_IO;
     143                 :            : 
     144         [ +  - ]:        132 :         if (!acpi_dev_resource_len_valid(res->start, res->end, len, true))
     145                 :          0 :                 res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
     146                 :            : 
     147         [ -  + ]:        132 :         if (!acpi_iospace_resource_valid(res))
     148                 :          0 :                 res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
     149                 :            : 
     150         [ +  - ]:        132 :         if (io_decode == ACPI_DECODE_16)
     151                 :        132 :                 res->flags |= IORESOURCE_IO_16BIT_ADDR;
     152         [ -  + ]:        132 :         if (translation_type == ACPI_SPARSE_TRANSLATION)
     153                 :          0 :                 res->flags |= IORESOURCE_IO_SPARSE;
     154                 :        132 : }
     155                 :            : 
     156                 :        110 : static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
     157                 :            :                                     u8 io_decode)
     158                 :            : {
     159                 :        110 :         res->start = start;
     160                 :        110 :         res->end = start + len - 1;
     161                 :        110 :         acpi_dev_ioresource_flags(res, len, io_decode, 0);
     162                 :        110 : }
     163                 :            : 
     164                 :            : /**
     165                 :            :  * acpi_dev_resource_io - Extract ACPI I/O resource information.
     166                 :            :  * @ares: Input ACPI resource object.
     167                 :            :  * @res: Output generic resource object.
     168                 :            :  *
     169                 :            :  * Check if the given ACPI resource object represents an I/O resource and
     170                 :            :  * if that's the case, use the information in it to populate the generic
     171                 :            :  * resource object pointed to by @res.
     172                 :            :  *
     173                 :            :  * Return:
     174                 :            :  * 1) false with res->flags setting to zero: not the expected resource type
     175                 :            :  * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
     176                 :            :  * 3) true: valid assigned resource
     177                 :            :  */
     178                 :        176 : bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
     179                 :            : {
     180                 :        176 :         struct acpi_resource_io *io;
     181                 :        176 :         struct acpi_resource_fixed_io *fixed_io;
     182                 :            : 
     183      [ +  -  + ]:        176 :         switch (ares->type) {
     184                 :        110 :         case ACPI_RESOURCE_TYPE_IO:
     185                 :        110 :                 io = &ares->data.io;
     186                 :        110 :                 acpi_dev_get_ioresource(res, io->minimum,
     187                 :        110 :                                         io->address_length,
     188                 :        110 :                                         io->io_decode);
     189                 :            :                 break;
     190                 :          0 :         case ACPI_RESOURCE_TYPE_FIXED_IO:
     191                 :          0 :                 fixed_io = &ares->data.fixed_io;
     192                 :          0 :                 acpi_dev_get_ioresource(res, fixed_io->address,
     193                 :          0 :                                         fixed_io->address_length,
     194                 :            :                                         ACPI_DECODE_10);
     195                 :            :                 break;
     196                 :         66 :         default:
     197                 :         66 :                 res->flags = 0;
     198                 :         66 :                 return false;
     199                 :            :         }
     200                 :            : 
     201                 :        110 :         return !(res->flags & IORESOURCE_DISABLED);
     202                 :            : }
     203                 :            : EXPORT_SYMBOL_GPL(acpi_dev_resource_io);
     204                 :            : 
     205                 :         44 : static bool acpi_decode_space(struct resource_win *win,
     206                 :            :                               struct acpi_resource_address *addr,
     207                 :            :                               struct acpi_address64_attribute *attr)
     208                 :            : {
     209                 :         44 :         u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16;
     210                 :         44 :         bool wp = addr->info.mem.write_protect;
     211                 :         44 :         u64 len = attr->address_length;
     212                 :         44 :         u64 start, end, offset = 0;
     213                 :         44 :         struct resource *res = &win->res;
     214                 :            : 
     215                 :            :         /*
     216                 :            :          * Filter out invalid descriptor according to ACPI Spec 5.0, section
     217                 :            :          * 6.4.3.5 Address Space Resource Descriptors.
     218                 :            :          */
     219                 :         44 :         if ((addr->min_address_fixed != addr->max_address_fixed && len) ||
     220                 :            :             (addr->min_address_fixed && addr->max_address_fixed && !len))
     221                 :            :                 pr_debug("ACPI: Invalid address space min_addr_fix %d, max_addr_fix %d, len %llx\n",
     222                 :            :                          addr->min_address_fixed, addr->max_address_fixed, len);
     223                 :            : 
     224                 :            :         /*
     225                 :            :          * For bridges that translate addresses across the bridge,
     226                 :            :          * translation_offset is the offset that must be added to the
     227                 :            :          * address on the secondary side to obtain the address on the
     228                 :            :          * primary side. Non-bridge devices must list 0 for all Address
     229                 :            :          * Translation offset bits.
     230                 :            :          */
     231         [ +  - ]:         44 :         if (addr->producer_consumer == ACPI_PRODUCER)
     232                 :         44 :                 offset = attr->translation_offset;
     233                 :            :         else if (attr->translation_offset)
     234                 :            :                 pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n",
     235                 :            :                          attr->translation_offset);
     236                 :         44 :         start = attr->minimum + offset;
     237                 :         44 :         end = attr->maximum + offset;
     238                 :            : 
     239                 :         44 :         win->offset = offset;
     240                 :         44 :         res->start = start;
     241                 :         44 :         res->end = end;
     242                 :         44 :         if (sizeof(resource_size_t) < sizeof(u64) &&
     243                 :            :             (offset != win->offset || start != res->start || end != res->end)) {
     244                 :            :                 pr_warn("acpi resource window ([%#llx-%#llx] ignored, not CPU addressable)\n",
     245                 :            :                         attr->minimum, attr->maximum);
     246                 :            :                 return false;
     247                 :            :         }
     248                 :            : 
     249   [ +  +  -  - ]:         44 :         switch (addr->resource_type) {
     250                 :         22 :         case ACPI_MEMORY_RANGE:
     251         [ +  - ]:         22 :                 acpi_dev_memresource_flags(res, len, wp);
     252                 :            :                 break;
     253                 :         22 :         case ACPI_IO_RANGE:
     254                 :         22 :                 acpi_dev_ioresource_flags(res, len, iodec,
     255                 :         22 :                                           addr->info.io.translation_type);
     256                 :         22 :                 break;
     257                 :          0 :         case ACPI_BUS_NUMBER_RANGE:
     258                 :          0 :                 res->flags = IORESOURCE_BUS;
     259                 :          0 :                 break;
     260                 :            :         default:
     261                 :            :                 return false;
     262                 :            :         }
     263                 :            : 
     264         [ +  - ]:         44 :         if (addr->producer_consumer == ACPI_PRODUCER)
     265                 :         44 :                 res->flags |= IORESOURCE_WINDOW;
     266                 :            : 
     267         [ -  + ]:         44 :         if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
     268                 :          0 :                 res->flags |= IORESOURCE_PREFETCH;
     269                 :            : 
     270                 :         44 :         return !(res->flags & IORESOURCE_DISABLED);
     271                 :            : }
     272                 :            : 
     273                 :            : /**
     274                 :            :  * acpi_dev_resource_address_space - Extract ACPI address space information.
     275                 :            :  * @ares: Input ACPI resource object.
     276                 :            :  * @win: Output generic resource object.
     277                 :            :  *
     278                 :            :  * Check if the given ACPI resource object represents an address space resource
     279                 :            :  * and if that's the case, use the information in it to populate the generic
     280                 :            :  * resource object pointed to by @win.
     281                 :            :  *
     282                 :            :  * Return:
     283                 :            :  * 1) false with win->res.flags setting to zero: not the expected resource type
     284                 :            :  * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned
     285                 :            :  *    resource
     286                 :            :  * 3) true: valid assigned resource
     287                 :            :  */
     288                 :        297 : bool acpi_dev_resource_address_space(struct acpi_resource *ares,
     289                 :            :                                      struct resource_win *win)
     290                 :            : {
     291                 :        297 :         struct acpi_resource_address64 addr;
     292                 :            : 
     293                 :        297 :         win->res.flags = 0;
     294         [ +  + ]:        297 :         if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr)))
     295                 :            :                 return false;
     296                 :            : 
     297                 :         44 :         return acpi_decode_space(win, (struct acpi_resource_address *)&addr,
     298                 :            :                                  &addr.address);
     299                 :            : }
     300                 :            : EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);
     301                 :            : 
     302                 :            : /**
     303                 :            :  * acpi_dev_resource_ext_address_space - Extract ACPI address space information.
     304                 :            :  * @ares: Input ACPI resource object.
     305                 :            :  * @win: Output generic resource object.
     306                 :            :  *
     307                 :            :  * Check if the given ACPI resource object represents an extended address space
     308                 :            :  * resource and if that's the case, use the information in it to populate the
     309                 :            :  * generic resource object pointed to by @win.
     310                 :            :  *
     311                 :            :  * Return:
     312                 :            :  * 1) false with win->res.flags setting to zero: not the expected resource type
     313                 :            :  * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned
     314                 :            :  *    resource
     315                 :            :  * 3) true: valid assigned resource
     316                 :            :  */
     317                 :        253 : bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
     318                 :            :                                          struct resource_win *win)
     319                 :            : {
     320                 :        253 :         struct acpi_resource_extended_address64 *ext_addr;
     321                 :            : 
     322                 :        253 :         win->res.flags = 0;
     323   [ -  -  +  -  :        253 :         if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
                   -  + ]
     324                 :            :                 return false;
     325                 :            : 
     326                 :          0 :         ext_addr = &ares->data.ext_address64;
     327                 :            : 
     328                 :          0 :         return acpi_decode_space(win, (struct acpi_resource_address *)ext_addr,
     329                 :            :                                  &ext_addr->address);
     330                 :            : }
     331                 :            : EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);
     332                 :            : 
     333                 :            : /**
     334                 :            :  * acpi_dev_irq_flags - Determine IRQ resource flags.
     335                 :            :  * @triggering: Triggering type as provided by ACPI.
     336                 :            :  * @polarity: Interrupt polarity as provided by ACPI.
     337                 :            :  * @shareable: Whether or not the interrupt is shareable.
     338                 :            :  */
     339                 :         66 : unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable)
     340                 :            : {
     341                 :         66 :         unsigned long flags;
     342                 :            : 
     343         [ #  # ]:          0 :         if (triggering == ACPI_LEVEL_SENSITIVE)
     344                 :          0 :                 flags = polarity == ACPI_ACTIVE_LOW ?
     345   [ #  #  #  # ]:          0 :                         IORESOURCE_IRQ_LOWLEVEL : IORESOURCE_IRQ_HIGHLEVEL;
     346                 :            :         else
     347                 :         66 :                 flags = polarity == ACPI_ACTIVE_LOW ?
     348   [ +  -  -  - ]:         66 :                         IORESOURCE_IRQ_LOWEDGE : IORESOURCE_IRQ_HIGHEDGE;
     349                 :            : 
     350   [ -  +  -  - ]:         66 :         if (shareable == ACPI_SHARED)
     351                 :          0 :                 flags |= IORESOURCE_IRQ_SHAREABLE;
     352                 :            : 
     353                 :         66 :         return flags | IORESOURCE_IRQ;
     354                 :            : }
     355                 :            : EXPORT_SYMBOL_GPL(acpi_dev_irq_flags);
     356                 :            : 
     357                 :            : /**
     358                 :            :  * acpi_dev_get_irq_type - Determine irq type.
     359                 :            :  * @triggering: Triggering type as provided by ACPI.
     360                 :            :  * @polarity: Interrupt polarity as provided by ACPI.
     361                 :            :  */
     362                 :          0 : unsigned int acpi_dev_get_irq_type(int triggering, int polarity)
     363                 :            : {
     364   [ #  #  #  # ]:          0 :         switch (polarity) {
     365                 :          0 :         case ACPI_ACTIVE_LOW:
     366                 :          0 :                 return triggering == ACPI_EDGE_SENSITIVE ?
     367         [ #  # ]:          0 :                        IRQ_TYPE_EDGE_FALLING :
     368                 :            :                        IRQ_TYPE_LEVEL_LOW;
     369                 :          0 :         case ACPI_ACTIVE_HIGH:
     370                 :          0 :                 return triggering == ACPI_EDGE_SENSITIVE ?
     371         [ #  # ]:          0 :                        IRQ_TYPE_EDGE_RISING :
     372                 :            :                        IRQ_TYPE_LEVEL_HIGH;
     373                 :          0 :         case ACPI_ACTIVE_BOTH:
     374         [ #  # ]:          0 :                 if (triggering == ACPI_EDGE_SENSITIVE)
     375                 :          0 :                         return IRQ_TYPE_EDGE_BOTH;
     376                 :            :                 /* fall through */
     377                 :            :         default:
     378                 :            :                 return IRQ_TYPE_NONE;
     379                 :            :         }
     380                 :            : }
     381                 :            : EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type);
     382                 :            : 
     383                 :         66 : static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
     384                 :            : {
     385                 :         66 :         res->start = gsi;
     386                 :         66 :         res->end = gsi;
     387                 :         66 :         res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET;
     388                 :          0 : }
     389                 :            : 
     390                 :         66 : static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
     391                 :            :                                      u8 triggering, u8 polarity, u8 shareable,
     392                 :            :                                      bool legacy)
     393                 :            : {
     394                 :         66 :         int irq, p, t;
     395                 :            : 
     396         [ -  + ]:         66 :         if (!valid_IRQ(gsi)) {
     397                 :          0 :                 acpi_dev_irqresource_disabled(res, gsi);
     398                 :          0 :                 return;
     399                 :            :         }
     400                 :            : 
     401                 :            :         /*
     402                 :            :          * In IO-APIC mode, use overridden attribute. Two reasons:
     403                 :            :          * 1. BIOS bug in DSDT
     404                 :            :          * 2. BIOS uses IO-APIC mode Interrupt Source Override
     405                 :            :          *
     406                 :            :          * We do this only if we are dealing with IRQ() or IRQNoFlags()
     407                 :            :          * resource (the legacy ISA resources). With modern ACPI 5 devices
     408                 :            :          * using extended IRQ descriptors we take the IRQ configuration
     409                 :            :          * from _CRS directly.
     410                 :            :          */
     411   [ +  -  +  - ]:         66 :         if (legacy && !acpi_get_override_irq(gsi, &t, &p)) {
     412                 :         66 :                 u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
     413                 :         66 :                 u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
     414                 :            : 
     415         [ -  + ]:         66 :                 if (triggering != trig || polarity != pol) {
     416   [ #  #  #  # ]:          0 :                         pr_warn("ACPI: IRQ %d override to %s, %s\n", gsi,
     417                 :            :                                 t ? "level" : "edge", p ? "low" : "high");
     418                 :          0 :                         triggering = trig;
     419                 :          0 :                         polarity = pol;
     420                 :            :                 }
     421                 :            :         }
     422                 :            : 
     423         [ -  + ]:         66 :         res->flags = acpi_dev_irq_flags(triggering, polarity, shareable);
     424                 :         66 :         irq = acpi_register_gsi(NULL, gsi, triggering, polarity);
     425         [ +  - ]:         66 :         if (irq >= 0) {
     426                 :         66 :                 res->start = irq;
     427                 :         66 :                 res->end = irq;
     428                 :            :         } else {
     429                 :          0 :                 acpi_dev_irqresource_disabled(res, gsi);
     430                 :            :         }
     431                 :            : }
     432                 :            : 
     433                 :            : /**
     434                 :            :  * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information.
     435                 :            :  * @ares: Input ACPI resource object.
     436                 :            :  * @index: Index into the array of GSIs represented by the resource.
     437                 :            :  * @res: Output generic resource object.
     438                 :            :  *
     439                 :            :  * Check if the given ACPI resource object represents an interrupt resource
     440                 :            :  * and @index does not exceed the resource's interrupt count (true is returned
     441                 :            :  * in that case regardless of the results of the other checks)).  If that's the
     442                 :            :  * case, register the GSI corresponding to @index from the array of interrupts
     443                 :            :  * represented by the resource and populate the generic resource object pointed
     444                 :            :  * to by @res accordingly.  If the registration of the GSI is not successful,
     445                 :            :  * IORESOURCE_DISABLED will be set it that object's flags.
     446                 :            :  *
     447                 :            :  * Return:
     448                 :            :  * 1) false with res->flags setting to zero: not the expected resource type
     449                 :            :  * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
     450                 :            :  * 3) true: valid assigned resource
     451                 :            :  */
     452                 :        319 : bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
     453                 :            :                                  struct resource *res)
     454                 :            : {
     455                 :        319 :         struct acpi_resource_irq *irq;
     456                 :        319 :         struct acpi_resource_extended_irq *ext_irq;
     457                 :            : 
     458      [ +  -  + ]:        319 :         switch (ares->type) {
     459                 :        132 :         case ACPI_RESOURCE_TYPE_IRQ:
     460                 :            :                 /*
     461                 :            :                  * Per spec, only one interrupt per descriptor is allowed in
     462                 :            :                  * _CRS, but some firmware violates this, so parse them all.
     463                 :            :                  */
     464                 :        132 :                 irq = &ares->data.irq;
     465         [ +  + ]:        132 :                 if (index >= irq->interrupt_count) {
     466                 :         66 :                         acpi_dev_irqresource_disabled(res, 0);
     467                 :         66 :                         return false;
     468                 :            :                 }
     469                 :         66 :                 acpi_dev_get_irqresource(res, irq->interrupts[index],
     470                 :         66 :                                          irq->triggering, irq->polarity,
     471                 :         66 :                                          irq->shareable, true);
     472                 :         66 :                 break;
     473                 :          0 :         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
     474                 :          0 :                 ext_irq = &ares->data.extended_irq;
     475         [ #  # ]:          0 :                 if (index >= ext_irq->interrupt_count) {
     476                 :          0 :                         acpi_dev_irqresource_disabled(res, 0);
     477                 :          0 :                         return false;
     478                 :            :                 }
     479                 :          0 :                 if (is_gsi(ext_irq))
     480                 :          0 :                         acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
     481                 :          0 :                                          ext_irq->triggering, ext_irq->polarity,
     482                 :          0 :                                          ext_irq->shareable, false);
     483                 :            :                 else
     484                 :            :                         acpi_dev_irqresource_disabled(res, 0);
     485                 :            :                 break;
     486                 :        187 :         default:
     487                 :        187 :                 res->flags = 0;
     488                 :        187 :                 return false;
     489                 :            :         }
     490                 :            : 
     491                 :            :         return true;
     492                 :            : }
     493                 :            : EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt);
     494                 :            : 
     495                 :            : /**
     496                 :            :  * acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources().
     497                 :            :  * @list: The head of the resource list to free.
     498                 :            :  */
     499                 :        660 : void acpi_dev_free_resource_list(struct list_head *list)
     500                 :            : {
     501                 :        660 :         resource_list_free(list);
     502                 :        660 : }
     503                 :            : EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list);
     504                 :            : 
     505                 :            : struct res_proc_context {
     506                 :            :         struct list_head *list;
     507                 :            :         int (*preproc)(struct acpi_resource *, void *);
     508                 :            :         void *preproc_data;
     509                 :            :         int count;
     510                 :            :         int error;
     511                 :            : };
     512                 :            : 
     513                 :         77 : static acpi_status acpi_dev_new_resource_entry(struct resource_win *win,
     514                 :            :                                                struct res_proc_context *c)
     515                 :            : {
     516                 :         77 :         struct resource_entry *rentry;
     517                 :            : 
     518                 :         77 :         rentry = resource_list_create_entry(NULL, 0);
     519         [ -  + ]:         77 :         if (!rentry) {
     520                 :          0 :                 c->error = -ENOMEM;
     521                 :          0 :                 return AE_NO_MEMORY;
     522                 :            :         }
     523                 :         77 :         *rentry->res = win->res;
     524                 :         77 :         rentry->offset = win->offset;
     525                 :         77 :         resource_list_add_tail(rentry, c->list);
     526                 :         77 :         c->count++;
     527                 :         77 :         return AE_OK;
     528                 :            : }
     529                 :            : 
     530                 :        682 : static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
     531                 :            :                                              void *context)
     532                 :            : {
     533                 :        682 :         struct res_proc_context *c = context;
     534                 :        682 :         struct resource_win win;
     535                 :        682 :         struct resource *res = &win.res;
     536                 :        682 :         int i;
     537                 :            : 
     538         [ +  + ]:        682 :         if (c->preproc) {
     539                 :        638 :                 int ret;
     540                 :            : 
     541                 :        638 :                 ret = c->preproc(ares, c->preproc_data);
     542         [ -  + ]:        638 :                 if (ret < 0) {
     543                 :          0 :                         c->error = ret;
     544                 :          0 :                         return AE_CTRL_TERMINATE;
     545         [ +  + ]:        638 :                 } else if (ret > 0) {
     546                 :            :                         return AE_OK;
     547                 :            :                 }
     548                 :            :         }
     549                 :            : 
     550                 :         99 :         memset(&win, 0, sizeof(win));
     551                 :            : 
     552         [ +  + ]:         99 :         if (acpi_dev_resource_memory(ares, res)
     553         [ +  + ]:         88 :             || acpi_dev_resource_io(ares, res)
     554         [ +  + ]:         66 :             || acpi_dev_resource_address_space(ares, &win)
     555         [ #  # ]:          0 :             || acpi_dev_resource_ext_address_space(ares, &win))
     556                 :         77 :                 return acpi_dev_new_resource_entry(&win, c);
     557                 :            : 
     558         [ -  + ]:         22 :         for (i = 0; acpi_dev_resource_interrupt(ares, i, res); i++) {
     559                 :          0 :                 acpi_status status;
     560                 :            : 
     561                 :          0 :                 status = acpi_dev_new_resource_entry(&win, c);
     562         [ #  # ]:          0 :                 if (ACPI_FAILURE(status))
     563                 :          0 :                         return status;
     564                 :            :         }
     565                 :            : 
     566                 :            :         return AE_OK;
     567                 :            : }
     568                 :            : 
     569                 :        671 : static int __acpi_dev_get_resources(struct acpi_device *adev,
     570                 :            :                                     struct list_head *list,
     571                 :            :                                     int (*preproc)(struct acpi_resource *, void *),
     572                 :            :                                     void *preproc_data, char *method)
     573                 :            : {
     574                 :        671 :         struct res_proc_context c;
     575                 :        671 :         acpi_status status;
     576                 :            : 
     577   [ +  -  +  +  :        671 :         if (!adev || !adev->handle || !list_empty(list))
                   +  - ]
     578                 :            :                 return -EINVAL;
     579                 :            : 
     580         [ +  + ]:        660 :         if (!acpi_has_method(adev->handle, method))
     581                 :            :                 return 0;
     582                 :            : 
     583                 :        231 :         c.list = list;
     584                 :        231 :         c.preproc = preproc;
     585                 :        231 :         c.preproc_data = preproc_data;
     586                 :        231 :         c.count = 0;
     587                 :        231 :         c.error = 0;
     588                 :        231 :         status = acpi_walk_resources(adev->handle, method,
     589                 :            :                                      acpi_dev_process_resource, &c);
     590         [ -  + ]:        231 :         if (ACPI_FAILURE(status)) {
     591                 :          0 :                 acpi_dev_free_resource_list(list);
     592         [ #  # ]:          0 :                 return c.error ? c.error : -EIO;
     593                 :            :         }
     594                 :            : 
     595                 :        231 :         return c.count;
     596                 :            : }
     597                 :            : 
     598                 :            : /**
     599                 :            :  * acpi_dev_get_resources - Get current resources of a device.
     600                 :            :  * @adev: ACPI device node to get the resources for.
     601                 :            :  * @list: Head of the resultant list of resources (must be empty).
     602                 :            :  * @preproc: The caller's preprocessing routine.
     603                 :            :  * @preproc_data: Pointer passed to the caller's preprocessing routine.
     604                 :            :  *
     605                 :            :  * Evaluate the _CRS method for the given device node and process its output by
     606                 :            :  * (1) executing the @preproc() rountine provided by the caller, passing the
     607                 :            :  * resource pointer and @preproc_data to it as arguments, for each ACPI resource
     608                 :            :  * returned and (2) converting all of the returned ACPI resources into struct
     609                 :            :  * resource objects if possible.  If the return value of @preproc() in step (1)
     610                 :            :  * is different from 0, step (2) is not applied to the given ACPI resource and
     611                 :            :  * if that value is negative, the whole processing is aborted and that value is
     612                 :            :  * returned as the final error code.
     613                 :            :  *
     614                 :            :  * The resultant struct resource objects are put on the list pointed to by
     615                 :            :  * @list, that must be empty initially, as members of struct resource_entry
     616                 :            :  * objects.  Callers of this routine should use %acpi_dev_free_resource_list() to
     617                 :            :  * free that list.
     618                 :            :  *
     619                 :            :  * The number of resources in the output list is returned on success, an error
     620                 :            :  * code reflecting the error condition is returned otherwise.
     621                 :            :  */
     622                 :        671 : int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
     623                 :            :                            int (*preproc)(struct acpi_resource *, void *),
     624                 :            :                            void *preproc_data)
     625                 :            : {
     626                 :        671 :         return __acpi_dev_get_resources(adev, list, preproc, preproc_data,
     627                 :            :                                         METHOD_NAME__CRS);
     628                 :            : }
     629                 :            : EXPORT_SYMBOL_GPL(acpi_dev_get_resources);
     630                 :            : 
     631                 :          0 : static int is_memory(struct acpi_resource *ares, void *not_used)
     632                 :            : {
     633                 :          0 :         struct resource_win win;
     634                 :          0 :         struct resource *res = &win.res;
     635                 :            : 
     636                 :          0 :         memset(&win, 0, sizeof(win));
     637                 :            : 
     638   [ #  #  #  # ]:          0 :         return !(acpi_dev_resource_memory(ares, res)
     639         [ #  # ]:          0 :                || acpi_dev_resource_address_space(ares, &win)
     640                 :            :                || acpi_dev_resource_ext_address_space(ares, &win));
     641                 :            : }
     642                 :            : 
     643                 :            : /**
     644                 :            :  * acpi_dev_get_dma_resources - Get current DMA resources of a device.
     645                 :            :  * @adev: ACPI device node to get the resources for.
     646                 :            :  * @list: Head of the resultant list of resources (must be empty).
     647                 :            :  *
     648                 :            :  * Evaluate the _DMA method for the given device node and process its
     649                 :            :  * output.
     650                 :            :  *
     651                 :            :  * The resultant struct resource objects are put on the list pointed to
     652                 :            :  * by @list, that must be empty initially, as members of struct
     653                 :            :  * resource_entry objects.  Callers of this routine should use
     654                 :            :  * %acpi_dev_free_resource_list() to free that list.
     655                 :            :  *
     656                 :            :  * The number of resources in the output list is returned on success,
     657                 :            :  * an error code reflecting the error condition is returned otherwise.
     658                 :            :  */
     659                 :          0 : int acpi_dev_get_dma_resources(struct acpi_device *adev, struct list_head *list)
     660                 :            : {
     661                 :          0 :         return __acpi_dev_get_resources(adev, list, is_memory, NULL,
     662                 :            :                                         METHOD_NAME__DMA);
     663                 :            : }
     664                 :            : EXPORT_SYMBOL_GPL(acpi_dev_get_dma_resources);
     665                 :            : 
     666                 :            : /**
     667                 :            :  * acpi_dev_filter_resource_type - Filter ACPI resource according to resource
     668                 :            :  *                                 types
     669                 :            :  * @ares: Input ACPI resource object.
     670                 :            :  * @types: Valid resource types of IORESOURCE_XXX
     671                 :            :  *
     672                 :            :  * This is a helper function to support acpi_dev_get_resources(), which filters
     673                 :            :  * ACPI resource objects according to resource types.
     674                 :            :  */
     675                 :         77 : int acpi_dev_filter_resource_type(struct acpi_resource *ares,
     676                 :            :                                   unsigned long types)
     677                 :            : {
     678                 :         77 :         unsigned long type = 0;
     679                 :            : 
     680   [ -  +  -  -  :         77 :         switch (ares->type) {
                -  +  + ]
     681                 :          0 :         case ACPI_RESOURCE_TYPE_MEMORY24:
     682                 :            :         case ACPI_RESOURCE_TYPE_MEMORY32:
     683                 :            :         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
     684                 :          0 :                 type = IORESOURCE_MEM;
     685                 :          0 :                 break;
     686                 :         11 :         case ACPI_RESOURCE_TYPE_IO:
     687                 :            :         case ACPI_RESOURCE_TYPE_FIXED_IO:
     688                 :         11 :                 type = IORESOURCE_IO;
     689                 :         11 :                 break;
     690                 :          0 :         case ACPI_RESOURCE_TYPE_IRQ:
     691                 :            :         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
     692                 :          0 :                 type = IORESOURCE_IRQ;
     693                 :          0 :                 break;
     694                 :          0 :         case ACPI_RESOURCE_TYPE_DMA:
     695                 :            :         case ACPI_RESOURCE_TYPE_FIXED_DMA:
     696                 :          0 :                 type = IORESOURCE_DMA;
     697                 :          0 :                 break;
     698                 :          0 :         case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
     699                 :          0 :                 type = IORESOURCE_REG;
     700                 :          0 :                 break;
     701                 :         55 :         case ACPI_RESOURCE_TYPE_ADDRESS16:
     702                 :            :         case ACPI_RESOURCE_TYPE_ADDRESS32:
     703                 :            :         case ACPI_RESOURCE_TYPE_ADDRESS64:
     704                 :            :         case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
     705         [ +  + ]:         55 :                 if (ares->data.address.resource_type == ACPI_MEMORY_RANGE)
     706                 :            :                         type = IORESOURCE_MEM;
     707         [ +  + ]:         33 :                 else if (ares->data.address.resource_type == ACPI_IO_RANGE)
     708                 :            :                         type = IORESOURCE_IO;
     709         [ +  - ]:         11 :                 else if (ares->data.address.resource_type ==
     710                 :            :                          ACPI_BUS_NUMBER_RANGE)
     711                 :         11 :                         type = IORESOURCE_BUS;
     712                 :            :                 break;
     713                 :            :         default:
     714                 :            :                 break;
     715                 :            :         }
     716                 :            : 
     717                 :         77 :         return (type & types) ? 0 : 1;
     718                 :            : }
     719                 :            : EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
     720                 :            : 
     721                 :          0 : static int acpi_dev_consumes_res(struct acpi_device *adev, struct resource *res)
     722                 :            : {
     723                 :          0 :         struct list_head resource_list;
     724                 :          0 :         struct resource_entry *rentry;
     725                 :          0 :         int ret, found = 0;
     726                 :            : 
     727                 :          0 :         INIT_LIST_HEAD(&resource_list);
     728                 :          0 :         ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
     729         [ #  # ]:          0 :         if (ret < 0)
     730                 :            :                 return 0;
     731                 :            : 
     732         [ #  # ]:          0 :         list_for_each_entry(rentry, &resource_list, node) {
     733   [ #  #  #  # ]:          0 :                 if (resource_contains(rentry->res, res)) {
     734                 :            :                         found = 1;
     735                 :            :                         break;
     736                 :            :                 }
     737                 :            : 
     738                 :            :         }
     739                 :            : 
     740                 :          0 :         acpi_dev_free_resource_list(&resource_list);
     741                 :          0 :         return found;
     742                 :            : }
     743                 :            : 
     744                 :          0 : static acpi_status acpi_res_consumer_cb(acpi_handle handle, u32 depth,
     745                 :            :                                          void *context, void **ret)
     746                 :            : {
     747                 :          0 :         struct resource *res = context;
     748                 :          0 :         struct acpi_device **consumer = (struct acpi_device **) ret;
     749                 :          0 :         struct acpi_device *adev;
     750                 :            : 
     751         [ #  # ]:          0 :         if (acpi_bus_get_device(handle, &adev))
     752                 :            :                 return AE_OK;
     753                 :            : 
     754         [ #  # ]:          0 :         if (acpi_dev_consumes_res(adev, res)) {
     755                 :          0 :                 *consumer = adev;
     756                 :          0 :                 return AE_CTRL_TERMINATE;
     757                 :            :         }
     758                 :            : 
     759                 :            :         return AE_OK;
     760                 :            : }
     761                 :            : 
     762                 :            : /**
     763                 :            :  * acpi_resource_consumer - Find the ACPI device that consumes @res.
     764                 :            :  * @res: Resource to search for.
     765                 :            :  *
     766                 :            :  * Search the current resource settings (_CRS) of every ACPI device node
     767                 :            :  * for @res.  If we find an ACPI device whose _CRS includes @res, return
     768                 :            :  * it.  Otherwise, return NULL.
     769                 :            :  */
     770                 :          0 : struct acpi_device *acpi_resource_consumer(struct resource *res)
     771                 :            : {
     772                 :          0 :         struct acpi_device *consumer = NULL;
     773                 :            : 
     774                 :          0 :         acpi_get_devices(NULL, acpi_res_consumer_cb, res, (void **) &consumer);
     775                 :          0 :         return consumer;
     776                 :            : }

Generated by: LCOV version 1.14