Commit 046d9ce6820e99087e81511284045eada94950e8

Authored by Rafael J. Wysocki
1 parent b4b6cae2f3

ACPI: Move device resources interpretation code from PNP to ACPI core

Move some code used for parsing ACPI device resources from the PNP
subsystem to the ACPI core, so that other bus types (platform, SPI,
I2C) can use the same routines for parsing resources in a consistent
way, without duplicating code.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>

Showing 6 changed files with 454 additions and 264 deletions Side-by-side Diff

drivers/acpi/Makefile
... ... @@ -32,6 +32,7 @@
32 32 #
33 33 acpi-y += bus.o glue.o
34 34 acpi-y += scan.o
  35 +acpi-y += resource.o
35 36 acpi-y += processor_core.o
36 37 acpi-y += ec.o
37 38 acpi-$(CONFIG_ACPI_DOCK) += dock.o
drivers/acpi/resource.c
  1 +/*
  2 + * drivers/acpi/resource.c - ACPI device resources interpretation.
  3 + *
  4 + * Copyright (C) 2012, Intel Corp.
  5 + * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  6 + *
  7 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8 + *
  9 + * This program is free software; you can redistribute it and/or modify
  10 + * it under the terms of the GNU General Public License version 2 as published
  11 + * by the Free Software Foundation.
  12 + *
  13 + * This program is distributed in the hope that it will be useful, but
  14 + * WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU General Public License along
  19 + * with this program; if not, write to the Free Software Foundation, Inc.,
  20 + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  21 + *
  22 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  23 + */
  24 +
  25 +#include <linux/acpi.h>
  26 +#include <linux/device.h>
  27 +#include <linux/export.h>
  28 +#include <linux/ioport.h>
  29 +
  30 +#ifdef CONFIG_X86
  31 +#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
  32 +#else
  33 +#define valid_IRQ(i) (true)
  34 +#endif
  35 +
  36 +static unsigned long acpi_dev_memresource_flags(u64 len, u8 write_protect,
  37 + bool window)
  38 +{
  39 + unsigned long flags = IORESOURCE_MEM;
  40 +
  41 + if (len == 0)
  42 + flags |= IORESOURCE_DISABLED;
  43 +
  44 + if (write_protect == ACPI_READ_WRITE_MEMORY)
  45 + flags |= IORESOURCE_MEM_WRITEABLE;
  46 +
  47 + if (window)
  48 + flags |= IORESOURCE_WINDOW;
  49 +
  50 + return flags;
  51 +}
  52 +
  53 +static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
  54 + u8 write_protect)
  55 +{
  56 + res->start = start;
  57 + res->end = start + len - 1;
  58 + res->flags = acpi_dev_memresource_flags(len, write_protect, false);
  59 +}
  60 +
  61 +/**
  62 + * acpi_dev_resource_memory - Extract ACPI memory resource information.
  63 + * @ares: Input ACPI resource object.
  64 + * @res: Output generic resource object.
  65 + *
  66 + * Check if the given ACPI resource object represents a memory resource and
  67 + * if that's the case, use the information in it to populate the generic
  68 + * resource object pointed to by @res.
  69 + */
  70 +bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
  71 +{
  72 + struct acpi_resource_memory24 *memory24;
  73 + struct acpi_resource_memory32 *memory32;
  74 + struct acpi_resource_fixed_memory32 *fixed_memory32;
  75 +
  76 + switch (ares->type) {
  77 + case ACPI_RESOURCE_TYPE_MEMORY24:
  78 + memory24 = &ares->data.memory24;
  79 + acpi_dev_get_memresource(res, memory24->minimum,
  80 + memory24->address_length,
  81 + memory24->write_protect);
  82 + break;
  83 + case ACPI_RESOURCE_TYPE_MEMORY32:
  84 + memory32 = &ares->data.memory32;
  85 + acpi_dev_get_memresource(res, memory32->minimum,
  86 + memory32->address_length,
  87 + memory32->write_protect);
  88 + break;
  89 + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
  90 + fixed_memory32 = &ares->data.fixed_memory32;
  91 + acpi_dev_get_memresource(res, fixed_memory32->address,
  92 + fixed_memory32->address_length,
  93 + fixed_memory32->write_protect);
  94 + break;
  95 + default:
  96 + return false;
  97 + }
  98 + return true;
  99 +}
  100 +EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
  101 +
  102 +static unsigned int acpi_dev_ioresource_flags(u64 start, u64 end, u8 io_decode,
  103 + bool window)
  104 +{
  105 + int flags = IORESOURCE_IO;
  106 +
  107 + if (io_decode == ACPI_DECODE_16)
  108 + flags |= IORESOURCE_IO_16BIT_ADDR;
  109 +
  110 + if (start > end || end >= 0x10003)
  111 + flags |= IORESOURCE_DISABLED;
  112 +
  113 + if (window)
  114 + flags |= IORESOURCE_WINDOW;
  115 +
  116 + return flags;
  117 +}
  118 +
  119 +static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
  120 + u8 io_decode)
  121 +{
  122 + u64 end = start + len - 1;
  123 +
  124 + res->start = start;
  125 + res->end = end;
  126 + res->flags = acpi_dev_ioresource_flags(start, end, io_decode, false);
  127 +}
  128 +
  129 +/**
  130 + * acpi_dev_resource_io - Extract ACPI I/O resource information.
  131 + * @ares: Input ACPI resource object.
  132 + * @res: Output generic resource object.
  133 + *
  134 + * Check if the given ACPI resource object represents an I/O resource and
  135 + * if that's the case, use the information in it to populate the generic
  136 + * resource object pointed to by @res.
  137 + */
  138 +bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
  139 +{
  140 + struct acpi_resource_io *io;
  141 + struct acpi_resource_fixed_io *fixed_io;
  142 +
  143 + switch (ares->type) {
  144 + case ACPI_RESOURCE_TYPE_IO:
  145 + io = &ares->data.io;
  146 + acpi_dev_get_ioresource(res, io->minimum,
  147 + io->address_length,
  148 + io->io_decode);
  149 + break;
  150 + case ACPI_RESOURCE_TYPE_FIXED_IO:
  151 + fixed_io = &ares->data.fixed_io;
  152 + acpi_dev_get_ioresource(res, fixed_io->address,
  153 + fixed_io->address_length,
  154 + ACPI_DECODE_10);
  155 + break;
  156 + default:
  157 + return false;
  158 + }
  159 + return true;
  160 +}
  161 +EXPORT_SYMBOL_GPL(acpi_dev_resource_io);
  162 +
  163 +/**
  164 + * acpi_dev_resource_address_space - Extract ACPI address space information.
  165 + * @ares: Input ACPI resource object.
  166 + * @res: Output generic resource object.
  167 + *
  168 + * Check if the given ACPI resource object represents an address space resource
  169 + * and if that's the case, use the information in it to populate the generic
  170 + * resource object pointed to by @res.
  171 + */
  172 +bool acpi_dev_resource_address_space(struct acpi_resource *ares,
  173 + struct resource *res)
  174 +{
  175 + acpi_status status;
  176 + struct acpi_resource_address64 addr;
  177 + bool window;
  178 + u64 len;
  179 + u8 io_decode;
  180 +
  181 + switch (ares->type) {
  182 + case ACPI_RESOURCE_TYPE_ADDRESS16:
  183 + case ACPI_RESOURCE_TYPE_ADDRESS32:
  184 + case ACPI_RESOURCE_TYPE_ADDRESS64:
  185 + break;
  186 + default:
  187 + return false;
  188 + }
  189 +
  190 + status = acpi_resource_to_address64(ares, &addr);
  191 + if (ACPI_FAILURE(status))
  192 + return true;
  193 +
  194 + res->start = addr.minimum;
  195 + res->end = addr.maximum;
  196 + window = addr.producer_consumer == ACPI_PRODUCER;
  197 +
  198 + switch(addr.resource_type) {
  199 + case ACPI_MEMORY_RANGE:
  200 + len = addr.maximum - addr.minimum + 1;
  201 + res->flags = acpi_dev_memresource_flags(len,
  202 + addr.info.mem.write_protect,
  203 + window);
  204 + break;
  205 + case ACPI_IO_RANGE:
  206 + io_decode = addr.granularity == 0xfff ?
  207 + ACPI_DECODE_10 : ACPI_DECODE_16;
  208 + res->flags = acpi_dev_ioresource_flags(addr.minimum,
  209 + addr.maximum,
  210 + io_decode, window);
  211 + break;
  212 + case ACPI_BUS_NUMBER_RANGE:
  213 + res->flags = IORESOURCE_BUS;
  214 + break;
  215 + default:
  216 + res->flags = 0;
  217 + }
  218 +
  219 + return true;
  220 +}
  221 +EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);
  222 +
  223 +/**
  224 + * acpi_dev_resource_ext_address_space - Extract ACPI address space information.
  225 + * @ares: Input ACPI resource object.
  226 + * @res: Output generic resource object.
  227 + *
  228 + * Check if the given ACPI resource object represents an extended address space
  229 + * resource and if that's the case, use the information in it to populate the
  230 + * generic resource object pointed to by @res.
  231 + */
  232 +bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
  233 + struct resource *res)
  234 +{
  235 + struct acpi_resource_extended_address64 *ext_addr;
  236 + bool window;
  237 + u64 len;
  238 + u8 io_decode;
  239 +
  240 + if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
  241 + return false;
  242 +
  243 + ext_addr = &ares->data.ext_address64;
  244 +
  245 + res->start = ext_addr->minimum;
  246 + res->end = ext_addr->maximum;
  247 + window = ext_addr->producer_consumer == ACPI_PRODUCER;
  248 +
  249 + switch(ext_addr->resource_type) {
  250 + case ACPI_MEMORY_RANGE:
  251 + len = ext_addr->maximum - ext_addr->minimum + 1;
  252 + res->flags = acpi_dev_memresource_flags(len,
  253 + ext_addr->info.mem.write_protect,
  254 + window);
  255 + break;
  256 + case ACPI_IO_RANGE:
  257 + io_decode = ext_addr->granularity == 0xfff ?
  258 + ACPI_DECODE_10 : ACPI_DECODE_16;
  259 + res->flags = acpi_dev_ioresource_flags(ext_addr->minimum,
  260 + ext_addr->maximum,
  261 + io_decode, window);
  262 + break;
  263 + case ACPI_BUS_NUMBER_RANGE:
  264 + res->flags = IORESOURCE_BUS;
  265 + break;
  266 + default:
  267 + res->flags = 0;
  268 + }
  269 +
  270 + return true;
  271 +}
  272 +EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);
  273 +
  274 +/**
  275 + * acpi_dev_irq_flags - Determine IRQ resource flags.
  276 + * @triggering: Triggering type as provided by ACPI.
  277 + * @polarity: Interrupt polarity as provided by ACPI.
  278 + * @shareable: Whether or not the interrupt is shareable.
  279 + */
  280 +unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable)
  281 +{
  282 + unsigned long flags;
  283 +
  284 + if (triggering == ACPI_LEVEL_SENSITIVE)
  285 + flags = polarity == ACPI_ACTIVE_LOW ?
  286 + IORESOURCE_IRQ_LOWLEVEL : IORESOURCE_IRQ_HIGHLEVEL;
  287 + else
  288 + flags = polarity == ACPI_ACTIVE_LOW ?
  289 + IORESOURCE_IRQ_LOWEDGE : IORESOURCE_IRQ_HIGHEDGE;
  290 +
  291 + if (shareable == ACPI_SHARED)
  292 + flags |= IORESOURCE_IRQ_SHAREABLE;
  293 +
  294 + return flags | IORESOURCE_IRQ;
  295 +}
  296 +EXPORT_SYMBOL_GPL(acpi_dev_irq_flags);
  297 +
  298 +static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
  299 +{
  300 + res->start = gsi;
  301 + res->end = gsi;
  302 + res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED;
  303 +}
  304 +
  305 +static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
  306 + u8 triggering, u8 polarity, u8 shareable)
  307 +{
  308 + int irq, p, t;
  309 +
  310 + if (!valid_IRQ(gsi)) {
  311 + acpi_dev_irqresource_disabled(res, gsi);
  312 + return;
  313 + }
  314 +
  315 + /*
  316 + * In IO-APIC mode, use overrided attribute. Two reasons:
  317 + * 1. BIOS bug in DSDT
  318 + * 2. BIOS uses IO-APIC mode Interrupt Source Override
  319 + */
  320 + if (!acpi_get_override_irq(gsi, &t, &p)) {
  321 + u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
  322 + u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
  323 +
  324 + if (triggering != trig || polarity != pol) {
  325 + pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi,
  326 + t ? "edge" : "level", p ? "low" : "high");
  327 + triggering = trig;
  328 + polarity = pol;
  329 + }
  330 + }
  331 +
  332 + res->flags = acpi_dev_irq_flags(triggering, polarity, shareable);
  333 + irq = acpi_register_gsi(NULL, gsi, triggering, polarity);
  334 + if (irq >= 0) {
  335 + res->start = irq;
  336 + res->end = irq;
  337 + } else {
  338 + acpi_dev_irqresource_disabled(res, gsi);
  339 + }
  340 +}
  341 +
  342 +/**
  343 + * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information.
  344 + * @ares: Input ACPI resource object.
  345 + * @index: Index into the array of GSIs represented by the resource.
  346 + * @res: Output generic resource object.
  347 + *
  348 + * Check if the given ACPI resource object represents an interrupt resource
  349 + * and @index does not exceed the resource's interrupt count (true is returned
  350 + * in that case regardless of the results of the other checks)). If that's the
  351 + * case, register the GSI corresponding to @index from the array of interrupts
  352 + * represented by the resource and populate the generic resource object pointed
  353 + * to by @res accordingly. If the registration of the GSI is not successful,
  354 + * IORESOURCE_DISABLED will be set it that object's flags.
  355 + */
  356 +bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
  357 + struct resource *res)
  358 +{
  359 + struct acpi_resource_irq *irq;
  360 + struct acpi_resource_extended_irq *ext_irq;
  361 +
  362 + switch (ares->type) {
  363 + case ACPI_RESOURCE_TYPE_IRQ:
  364 + /*
  365 + * Per spec, only one interrupt per descriptor is allowed in
  366 + * _CRS, but some firmware violates this, so parse them all.
  367 + */
  368 + irq = &ares->data.irq;
  369 + if (index >= irq->interrupt_count) {
  370 + acpi_dev_irqresource_disabled(res, 0);
  371 + return false;
  372 + }
  373 + acpi_dev_get_irqresource(res, irq->interrupts[index],
  374 + irq->triggering, irq->polarity,
  375 + irq->sharable);
  376 + break;
  377 + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
  378 + ext_irq = &ares->data.extended_irq;
  379 + if (index >= ext_irq->interrupt_count) {
  380 + acpi_dev_irqresource_disabled(res, 0);
  381 + return false;
  382 + }
  383 + acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
  384 + ext_irq->triggering, ext_irq->polarity,
  385 + ext_irq->sharable);
  386 + break;
  387 + default:
  388 + return false;
  389 + }
  390 +
  391 + return true;
  392 +}
  393 +EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt);
... ... @@ -159,6 +159,8 @@
159 159  
160 160 void pnp_free_resource(struct pnp_resource *pnp_res);
161 161  
  162 +struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
  163 + struct resource *res);
162 164 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
163 165 int flags);
164 166 struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
drivers/pnp/pnpacpi/rsparser.c
... ... @@ -28,37 +28,6 @@
28 28 #include "../base.h"
29 29 #include "pnpacpi.h"
30 30  
31   -#ifdef CONFIG_IA64
32   -#define valid_IRQ(i) (1)
33   -#else
34   -#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
35   -#endif
36   -
37   -/*
38   - * Allocated Resources
39   - */
40   -static int irq_flags(int triggering, int polarity, int shareable)
41   -{
42   - int flags;
43   -
44   - if (triggering == ACPI_LEVEL_SENSITIVE) {
45   - if (polarity == ACPI_ACTIVE_LOW)
46   - flags = IORESOURCE_IRQ_LOWLEVEL;
47   - else
48   - flags = IORESOURCE_IRQ_HIGHLEVEL;
49   - } else {
50   - if (polarity == ACPI_ACTIVE_LOW)
51   - flags = IORESOURCE_IRQ_LOWEDGE;
52   - else
53   - flags = IORESOURCE_IRQ_HIGHEDGE;
54   - }
55   -
56   - if (shareable == ACPI_SHARED)
57   - flags |= IORESOURCE_IRQ_SHAREABLE;
58   -
59   - return flags;
60   -}
61   -
62 31 static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
63 32 int *polarity, int *shareable)
64 33 {
... ... @@ -94,45 +63,6 @@
94 63 *shareable = ACPI_EXCLUSIVE;
95 64 }
96 65  
97   -static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
98   - u32 gsi, int triggering,
99   - int polarity, int shareable)
100   -{
101   - int irq, flags;
102   - int p, t;
103   -
104   - if (!valid_IRQ(gsi)) {
105   - pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED);
106   - return;
107   - }
108   -
109   - /*
110   - * in IO-APIC mode, use overrided attribute. Two reasons:
111   - * 1. BIOS bug in DSDT
112   - * 2. BIOS uses IO-APIC mode Interrupt Source Override
113   - */
114   - if (!acpi_get_override_irq(gsi, &t, &p)) {
115   - t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
116   - p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
117   -
118   - if (triggering != t || polarity != p) {
119   - dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
120   - gsi, t ? "edge":"level", p ? "low":"high");
121   - triggering = t;
122   - polarity = p;
123   - }
124   - }
125   -
126   - flags = irq_flags(triggering, polarity, shareable);
127   - irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
128   - if (irq >= 0)
129   - pcibios_penalize_isa_irq(irq, 1);
130   - else
131   - flags |= IORESOURCE_DISABLED;
132   -
133   - pnp_add_irq_resource(dev, irq, flags);
134   -}
135   -
136 66 static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
137 67 int transfer)
138 68 {
139 69  
140 70  
... ... @@ -177,21 +107,16 @@
177 107 return flags;
178 108 }
179 109  
180   -static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
181   - u64 len, int io_decode,
182   - int window)
  110 +/*
  111 + * Allocated Resources
  112 + */
  113 +
  114 +static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r)
183 115 {
184   - int flags = 0;
185   - u64 end = start + len - 1;
  116 + if (!(r->flags & IORESOURCE_DISABLED))
  117 + pcibios_penalize_isa_irq(r->start, 1);
186 118  
187   - if (io_decode == ACPI_DECODE_16)
188   - flags |= IORESOURCE_IO_16BIT_ADDR;
189   - if (len == 0 || end >= 0x10003)
190   - flags |= IORESOURCE_DISABLED;
191   - if (window)
192   - flags |= IORESOURCE_WINDOW;
193   -
194   - pnp_add_io_resource(dev, start, end, flags);
  119 + pnp_add_resource(dev, r);
195 120 }
196 121  
197 122 /*
198 123  
199 124  
200 125  
201 126  
202 127  
203 128  
204 129  
205 130  
... ... @@ -249,130 +174,49 @@
249 174 }
250 175 }
251 176  
252   -static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
253   - u64 start, u64 len,
254   - int write_protect, int window)
255   -{
256   - int flags = 0;
257   - u64 end = start + len - 1;
258   -
259   - if (len == 0)
260   - flags |= IORESOURCE_DISABLED;
261   - if (write_protect == ACPI_READ_WRITE_MEMORY)
262   - flags |= IORESOURCE_MEM_WRITEABLE;
263   - if (window)
264   - flags |= IORESOURCE_WINDOW;
265   -
266   - pnp_add_mem_resource(dev, start, end, flags);
267   -}
268   -
269   -static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
270   - u64 start, u64 len)
271   -{
272   - u64 end = start + len - 1;
273   -
274   - pnp_add_bus_resource(dev, start, end);
275   -}
276   -
277   -static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
278   - struct acpi_resource *res)
279   -{
280   - struct acpi_resource_address64 addr, *p = &addr;
281   - acpi_status status;
282   - int window;
283   - u64 len;
284   -
285   - status = acpi_resource_to_address64(res, p);
286   - if (!ACPI_SUCCESS(status)) {
287   - dev_warn(&dev->dev, "failed to convert resource type %d\n",
288   - res->type);
289   - return;
290   - }
291   -
292   - /* Windows apparently computes length rather than using _LEN */
293   - len = p->maximum - p->minimum + 1;
294   - window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
295   -
296   - if (p->resource_type == ACPI_MEMORY_RANGE)
297   - pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
298   - p->info.mem.write_protect, window);
299   - else if (p->resource_type == ACPI_IO_RANGE)
300   - pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
301   - p->granularity == 0xfff ? ACPI_DECODE_10 :
302   - ACPI_DECODE_16, window);
303   - else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
304   - pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
305   -}
306   -
307   -static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
308   - struct acpi_resource *res)
309   -{
310   - struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
311   - int window;
312   - u64 len;
313   -
314   - /* Windows apparently computes length rather than using _LEN */
315   - len = p->maximum - p->minimum + 1;
316   - window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
317   -
318   - if (p->resource_type == ACPI_MEMORY_RANGE)
319   - pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
320   - p->info.mem.write_protect, window);
321   - else if (p->resource_type == ACPI_IO_RANGE)
322   - pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
323   - p->granularity == 0xfff ? ACPI_DECODE_10 :
324   - ACPI_DECODE_16, window);
325   - else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
326   - pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
327   -}
328   -
329 177 static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
330 178 void *data)
331 179 {
332 180 struct pnp_dev *dev = data;
333   - struct acpi_resource_irq *irq;
334 181 struct acpi_resource_dma *dma;
335   - struct acpi_resource_io *io;
336   - struct acpi_resource_fixed_io *fixed_io;
337 182 struct acpi_resource_vendor_typed *vendor_typed;
338   - struct acpi_resource_memory24 *memory24;
339   - struct acpi_resource_memory32 *memory32;
340   - struct acpi_resource_fixed_memory32 *fixed_memory32;
341   - struct acpi_resource_extended_irq *extended_irq;
  183 + struct resource r;
342 184 int i, flags;
343 185  
344   - switch (res->type) {
345   - case ACPI_RESOURCE_TYPE_IRQ:
346   - /*
347   - * Per spec, only one interrupt per descriptor is allowed in
348   - * _CRS, but some firmware violates this, so parse them all.
349   - */
350   - irq = &res->data.irq;
351   - if (irq->interrupt_count == 0)
352   - pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
353   - else {
354   - for (i = 0; i < irq->interrupt_count; i++) {
355   - pnpacpi_parse_allocated_irqresource(dev,
356   - irq->interrupts[i],
357   - irq->triggering,
358   - irq->polarity,
359   - irq->sharable);
360   - }
  186 + if (acpi_dev_resource_memory(res, &r)
  187 + || acpi_dev_resource_io(res, &r)
  188 + || acpi_dev_resource_address_space(res, &r)
  189 + || acpi_dev_resource_ext_address_space(res, &r)) {
  190 + pnp_add_resource(dev, &r);
  191 + return AE_OK;
  192 + }
361 193  
  194 + r.flags = 0;
  195 + if (acpi_dev_resource_interrupt(res, 0, &r)) {
  196 + pnpacpi_add_irqresource(dev, &r);
  197 + for (i = 1; acpi_dev_resource_interrupt(res, i, &r); i++)
  198 + pnpacpi_add_irqresource(dev, &r);
  199 +
  200 + if (i > 1) {
362 201 /*
363 202 * The IRQ encoder puts a single interrupt in each
364 203 * descriptor, so if a _CRS descriptor has more than
365 204 * one interrupt, we won't be able to re-encode it.
366 205 */
367   - if (pnp_can_write(dev) && irq->interrupt_count > 1) {
  206 + if (pnp_can_write(dev)) {
368 207 dev_warn(&dev->dev, "multiple interrupts in "
369 208 "_CRS descriptor; configuration can't "
370 209 "be changed\n");
371 210 dev->capabilities &= ~PNP_WRITE;
372 211 }
373 212 }
374   - break;
  213 + return AE_OK;
  214 + } else if (r.flags & IORESOURCE_DISABLED) {
  215 + pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
  216 + return AE_OK;
  217 + }
375 218  
  219 + switch (res->type) {
376 220 case ACPI_RESOURCE_TYPE_DMA:
377 221 dma = &res->data.dma;
378 222 if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
379 223  
... ... @@ -383,26 +227,10 @@
383 227 pnp_add_dma_resource(dev, dma->channels[0], flags);
384 228 break;
385 229  
386   - case ACPI_RESOURCE_TYPE_IO:
387   - io = &res->data.io;
388   - pnpacpi_parse_allocated_ioresource(dev,
389   - io->minimum,
390   - io->address_length,
391   - io->io_decode, 0);
392   - break;
393   -
394 230 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
395 231 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
396 232 break;
397 233  
398   - case ACPI_RESOURCE_TYPE_FIXED_IO:
399   - fixed_io = &res->data.fixed_io;
400   - pnpacpi_parse_allocated_ioresource(dev,
401   - fixed_io->address,
402   - fixed_io->address_length,
403   - ACPI_DECODE_10, 0);
404   - break;
405   -
406 234 case ACPI_RESOURCE_TYPE_VENDOR:
407 235 vendor_typed = &res->data.vendor_typed;
408 236 pnpacpi_parse_allocated_vendor(dev, vendor_typed);
... ... @@ -411,66 +239,6 @@
411 239 case ACPI_RESOURCE_TYPE_END_TAG:
412 240 break;
413 241  
414   - case ACPI_RESOURCE_TYPE_MEMORY24:
415   - memory24 = &res->data.memory24;
416   - pnpacpi_parse_allocated_memresource(dev,
417   - memory24->minimum,
418   - memory24->address_length,
419   - memory24->write_protect, 0);
420   - break;
421   - case ACPI_RESOURCE_TYPE_MEMORY32:
422   - memory32 = &res->data.memory32;
423   - pnpacpi_parse_allocated_memresource(dev,
424   - memory32->minimum,
425   - memory32->address_length,
426   - memory32->write_protect, 0);
427   - break;
428   - case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
429   - fixed_memory32 = &res->data.fixed_memory32;
430   - pnpacpi_parse_allocated_memresource(dev,
431   - fixed_memory32->address,
432   - fixed_memory32->address_length,
433   - fixed_memory32->write_protect, 0);
434   - break;
435   - case ACPI_RESOURCE_TYPE_ADDRESS16:
436   - case ACPI_RESOURCE_TYPE_ADDRESS32:
437   - case ACPI_RESOURCE_TYPE_ADDRESS64:
438   - pnpacpi_parse_allocated_address_space(dev, res);
439   - break;
440   -
441   - case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
442   - pnpacpi_parse_allocated_ext_address_space(dev, res);
443   - break;
444   -
445   - case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
446   - extended_irq = &res->data.extended_irq;
447   -
448   - if (extended_irq->interrupt_count == 0)
449   - pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
450   - else {
451   - for (i = 0; i < extended_irq->interrupt_count; i++) {
452   - pnpacpi_parse_allocated_irqresource(dev,
453   - extended_irq->interrupts[i],
454   - extended_irq->triggering,
455   - extended_irq->polarity,
456   - extended_irq->sharable);
457   - }
458   -
459   - /*
460   - * The IRQ encoder puts a single interrupt in each
461   - * descriptor, so if a _CRS descriptor has more than
462   - * one interrupt, we won't be able to re-encode it.
463   - */
464   - if (pnp_can_write(dev) &&
465   - extended_irq->interrupt_count > 1) {
466   - dev_warn(&dev->dev, "multiple interrupts in "
467   - "_CRS descriptor; configuration can't "
468   - "be changed\n");
469   - dev->capabilities &= ~PNP_WRITE;
470   - }
471   - }
472   - break;
473   -
474 242 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
475 243 break;
476 244  
... ... @@ -531,7 +299,7 @@
531 299 if (p->interrupts[i])
532 300 __set_bit(p->interrupts[i], map.bits);
533 301  
534   - flags = irq_flags(p->triggering, p->polarity, p->sharable);
  302 + flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
535 303 pnp_register_irq_resource(dev, option_flags, &map, flags);
536 304 }
537 305  
... ... @@ -555,7 +323,7 @@
555 323 }
556 324 }
557 325  
558   - flags = irq_flags(p->triggering, p->polarity, p->sharable);
  326 + flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
559 327 pnp_register_irq_resource(dev, option_flags, &map, flags);
560 328 }
561 329  
drivers/pnp/resource.c
... ... @@ -503,6 +503,22 @@
503 503 return pnp_res;
504 504 }
505 505  
  506 +struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
  507 + struct resource *res)
  508 +{
  509 + struct pnp_resource *pnp_res;
  510 +
  511 + pnp_res = pnp_new_resource(dev);
  512 + if (!pnp_res) {
  513 + dev_err(&dev->dev, "can't add resource %pR\n", res);
  514 + return NULL;
  515 + }
  516 +
  517 + pnp_res->res = *res;
  518 + dev_dbg(&dev->dev, "%pR\n", res);
  519 + return pnp_res;
  520 +}
  521 +
506 522 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
507 523 int flags)
508 524 {
include/linux/acpi.h
... ... @@ -251,6 +251,16 @@
251 251  
252 252 #define PXM_INVAL (-1)
253 253  
  254 +bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res);
  255 +bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res);
  256 +bool acpi_dev_resource_address_space(struct acpi_resource *ares,
  257 + struct resource *res);
  258 +bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
  259 + struct resource *res);
  260 +unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable);
  261 +bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
  262 + struct resource *res);
  263 +
254 264 int acpi_check_resource_conflict(const struct resource *res);
255 265  
256 266 int acpi_check_region(resource_size_t start, resource_size_t n,