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 : 252 : 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 : 252 : 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 : 315 : static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
52 : : {
53 : 315 : 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 [ - + - + : 315 : 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 : 63 : static void acpi_dev_memresource_flags(struct resource *res, u64 len,
72 : : u8 write_protect)
73 : : {
74 : 63 : res->flags = IORESOURCE_MEM;
75 : :
76 : 63 : if (!acpi_dev_resource_len_valid(res->start, res->end, len, false))
77 : 0 : res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
78 : :
79 [ + - - - : 63 : if (write_protect == ACPI_READ_WRITE_MEMORY)
- - - + ]
80 : 42 : res->flags |= IORESOURCE_MEM_WRITEABLE;
81 : : }
82 : :
83 : 21 : static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
84 : : u8 write_protect)
85 : : {
86 : 21 : res->start = start;
87 : 21 : res->end = start + len - 1;
88 : 21 : 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 : 189 : bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
106 : : {
107 : 189 : struct acpi_resource_memory24 *memory24;
108 : 189 : struct acpi_resource_memory32 *memory32;
109 : 189 : struct acpi_resource_fixed_memory32 *fixed_memory32;
110 : :
111 [ - - + + ]: 189 : 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 : 21 : case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
125 : 21 : fixed_memory32 = &ares->data.fixed_memory32;
126 : 21 : acpi_dev_get_memresource(res, fixed_memory32->address,
127 : 21 : fixed_memory32->address_length,
128 [ + - ]: 21 : fixed_memory32->write_protect);
129 : : break;
130 : 168 : default:
131 : 168 : res->flags = 0;
132 : 168 : return false;
133 : : }
134 : :
135 : 21 : return !(res->flags & IORESOURCE_DISABLED);
136 : : }
137 : : EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
138 : :
139 : 252 : static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
140 : : u8 io_decode, u8 translation_type)
141 : : {
142 : 252 : res->flags = IORESOURCE_IO;
143 : :
144 [ + - ]: 252 : if (!acpi_dev_resource_len_valid(res->start, res->end, len, true))
145 : 0 : res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
146 : :
147 [ - + ]: 252 : if (!acpi_iospace_resource_valid(res))
148 : 0 : res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
149 : :
150 [ + - ]: 252 : if (io_decode == ACPI_DECODE_16)
151 : 252 : res->flags |= IORESOURCE_IO_16BIT_ADDR;
152 [ - + ]: 252 : if (translation_type == ACPI_SPARSE_TRANSLATION)
153 : 0 : res->flags |= IORESOURCE_IO_SPARSE;
154 : 252 : }
155 : :
156 : 210 : static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
157 : : u8 io_decode)
158 : : {
159 : 210 : res->start = start;
160 : 210 : res->end = start + len - 1;
161 : 210 : acpi_dev_ioresource_flags(res, len, io_decode, 0);
162 : 210 : }
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 : 336 : bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
179 : : {
180 : 336 : struct acpi_resource_io *io;
181 : 336 : struct acpi_resource_fixed_io *fixed_io;
182 : :
183 [ + - + ]: 336 : switch (ares->type) {
184 : 210 : case ACPI_RESOURCE_TYPE_IO:
185 : 210 : io = &ares->data.io;
186 : 210 : acpi_dev_get_ioresource(res, io->minimum,
187 : 210 : io->address_length,
188 : 210 : 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 : 126 : default:
197 : 126 : res->flags = 0;
198 : 126 : return false;
199 : : }
200 : :
201 : 210 : return !(res->flags & IORESOURCE_DISABLED);
202 : : }
203 : : EXPORT_SYMBOL_GPL(acpi_dev_resource_io);
204 : :
205 : 84 : static bool acpi_decode_space(struct resource_win *win,
206 : : struct acpi_resource_address *addr,
207 : : struct acpi_address64_attribute *attr)
208 : : {
209 : 84 : u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16;
210 : 84 : bool wp = addr->info.mem.write_protect;
211 : 84 : u64 len = attr->address_length;
212 : 84 : u64 start, end, offset = 0;
213 : 84 : 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 : 84 : 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 [ + - ]: 84 : if (addr->producer_consumer == ACPI_PRODUCER)
232 : 84 : 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 : 84 : start = attr->minimum + offset;
237 : 84 : end = attr->maximum + offset;
238 : :
239 : 84 : win->offset = offset;
240 : 84 : res->start = start;
241 : 84 : res->end = end;
242 : 84 : 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 [ + + - - ]: 84 : switch (addr->resource_type) {
250 : 42 : case ACPI_MEMORY_RANGE:
251 [ + - ]: 42 : acpi_dev_memresource_flags(res, len, wp);
252 : : break;
253 : 42 : case ACPI_IO_RANGE:
254 : 42 : acpi_dev_ioresource_flags(res, len, iodec,
255 : 42 : addr->info.io.translation_type);
256 : 42 : 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 [ + - ]: 84 : if (addr->producer_consumer == ACPI_PRODUCER)
265 : 84 : res->flags |= IORESOURCE_WINDOW;
266 : :
267 [ - + ]: 84 : if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
268 : 0 : res->flags |= IORESOURCE_PREFETCH;
269 : :
270 : 84 : 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 : 567 : bool acpi_dev_resource_address_space(struct acpi_resource *ares,
289 : : struct resource_win *win)
290 : : {
291 : 567 : struct acpi_resource_address64 addr;
292 : :
293 : 567 : win->res.flags = 0;
294 [ + + ]: 567 : if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr)))
295 : : return false;
296 : :
297 : 84 : 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 : 483 : bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
318 : : struct resource_win *win)
319 : : {
320 : 483 : struct acpi_resource_extended_address64 *ext_addr;
321 : :
322 : 483 : win->res.flags = 0;
323 [ - - + - : 483 : 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 : 126 : unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable)
340 : : {
341 : 126 : 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 : 126 : flags = polarity == ACPI_ACTIVE_LOW ?
348 [ + - - - ]: 126 : IORESOURCE_IRQ_LOWEDGE : IORESOURCE_IRQ_HIGHEDGE;
349 : :
350 [ - + - - ]: 126 : if (shareable == ACPI_SHARED)
351 : 0 : flags |= IORESOURCE_IRQ_SHAREABLE;
352 : :
353 : 126 : 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 : 126 : static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
384 : : {
385 : 126 : res->start = gsi;
386 : 126 : res->end = gsi;
387 : 126 : res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET;
388 : 0 : }
389 : :
390 : 126 : static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
391 : : u8 triggering, u8 polarity, u8 shareable,
392 : : bool legacy)
393 : : {
394 : 126 : int irq, p, t;
395 : :
396 [ - + ]: 126 : 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 [ + - + - ]: 126 : if (legacy && !acpi_get_override_irq(gsi, &t, &p)) {
412 : 126 : u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
413 : 126 : u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
414 : :
415 [ - + ]: 126 : 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 [ - + ]: 126 : res->flags = acpi_dev_irq_flags(triggering, polarity, shareable);
424 : 126 : irq = acpi_register_gsi(NULL, gsi, triggering, polarity);
425 [ + - ]: 126 : if (irq >= 0) {
426 : 126 : res->start = irq;
427 : 126 : 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 : 609 : bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
453 : : struct resource *res)
454 : : {
455 : 609 : struct acpi_resource_irq *irq;
456 : 609 : struct acpi_resource_extended_irq *ext_irq;
457 : :
458 [ + - + ]: 609 : switch (ares->type) {
459 : 252 : 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 : 252 : irq = &ares->data.irq;
465 [ + + ]: 252 : if (index >= irq->interrupt_count) {
466 : 126 : acpi_dev_irqresource_disabled(res, 0);
467 : 126 : return false;
468 : : }
469 : 126 : acpi_dev_get_irqresource(res, irq->interrupts[index],
470 : 126 : irq->triggering, irq->polarity,
471 : 126 : irq->shareable, true);
472 : 126 : 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 : 357 : default:
487 : 357 : res->flags = 0;
488 : 357 : 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 : 1260 : void acpi_dev_free_resource_list(struct list_head *list)
500 : : {
501 : 1260 : resource_list_free(list);
502 : 1260 : }
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 : 147 : static acpi_status acpi_dev_new_resource_entry(struct resource_win *win,
514 : : struct res_proc_context *c)
515 : : {
516 : 147 : struct resource_entry *rentry;
517 : :
518 : 147 : rentry = resource_list_create_entry(NULL, 0);
519 [ - + ]: 147 : if (!rentry) {
520 : 0 : c->error = -ENOMEM;
521 : 0 : return AE_NO_MEMORY;
522 : : }
523 : 147 : *rentry->res = win->res;
524 : 147 : rentry->offset = win->offset;
525 : 147 : resource_list_add_tail(rentry, c->list);
526 : 147 : c->count++;
527 : 147 : return AE_OK;
528 : : }
529 : :
530 : 1302 : static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
531 : : void *context)
532 : : {
533 : 1302 : struct res_proc_context *c = context;
534 : 1302 : struct resource_win win;
535 : 1302 : struct resource *res = &win.res;
536 : 1302 : int i;
537 : :
538 [ + + ]: 1302 : if (c->preproc) {
539 : 1218 : int ret;
540 : :
541 : 1218 : ret = c->preproc(ares, c->preproc_data);
542 [ - + ]: 1218 : if (ret < 0) {
543 : 0 : c->error = ret;
544 : 0 : return AE_CTRL_TERMINATE;
545 [ + + ]: 1218 : } else if (ret > 0) {
546 : : return AE_OK;
547 : : }
548 : : }
549 : :
550 : 189 : memset(&win, 0, sizeof(win));
551 : :
552 [ + + ]: 189 : if (acpi_dev_resource_memory(ares, res)
553 [ + + ]: 168 : || acpi_dev_resource_io(ares, res)
554 [ + + ]: 126 : || acpi_dev_resource_address_space(ares, &win)
555 [ # # ]: 0 : || acpi_dev_resource_ext_address_space(ares, &win))
556 : 147 : return acpi_dev_new_resource_entry(&win, c);
557 : :
558 [ - + ]: 42 : 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 : 1281 : 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 : 1281 : struct res_proc_context c;
575 : 1281 : acpi_status status;
576 : :
577 [ + - + + : 1281 : if (!adev || !adev->handle || !list_empty(list))
+ - ]
578 : : return -EINVAL;
579 : :
580 [ + + ]: 1260 : if (!acpi_has_method(adev->handle, method))
581 : : return 0;
582 : :
583 : 441 : c.list = list;
584 : 441 : c.preproc = preproc;
585 : 441 : c.preproc_data = preproc_data;
586 : 441 : c.count = 0;
587 : 441 : c.error = 0;
588 : 441 : status = acpi_walk_resources(adev->handle, method,
589 : : acpi_dev_process_resource, &c);
590 [ - + ]: 441 : if (ACPI_FAILURE(status)) {
591 : 0 : acpi_dev_free_resource_list(list);
592 [ # # ]: 0 : return c.error ? c.error : -EIO;
593 : : }
594 : :
595 : 441 : 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 : 1281 : 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 : 1281 : 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 : 147 : int acpi_dev_filter_resource_type(struct acpi_resource *ares,
676 : : unsigned long types)
677 : : {
678 : 147 : unsigned long type = 0;
679 : :
680 [ - + - - : 147 : 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 : 21 : case ACPI_RESOURCE_TYPE_IO:
687 : : case ACPI_RESOURCE_TYPE_FIXED_IO:
688 : 21 : type = IORESOURCE_IO;
689 : 21 : 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 : 105 : 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 [ + + ]: 105 : if (ares->data.address.resource_type == ACPI_MEMORY_RANGE)
706 : : type = IORESOURCE_MEM;
707 [ + + ]: 63 : else if (ares->data.address.resource_type == ACPI_IO_RANGE)
708 : : type = IORESOURCE_IO;
709 [ + - ]: 21 : else if (ares->data.address.resource_type ==
710 : : ACPI_BUS_NUMBER_RANGE)
711 : 21 : type = IORESOURCE_BUS;
712 : : break;
713 : : default:
714 : : break;
715 : : }
716 : :
717 : 147 : 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 : : }
|