1121 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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#include <linux/dmi.h>20 21#ifdef CONFIG_X8622#define valid_IRQ(i) (((i) != 0) && ((i) != 2))23static inline bool acpi_iospace_resource_valid(struct resource *res)24{25 /* On X86 IO space is limited to the [0 - 64K] IO port range */26 return res->end < 0x10003;27}28#else29#define valid_IRQ(i) (true)30/*31 * ACPI IO descriptors on arches other than X86 contain MMIO CPU physical32 * addresses mapping IO space in CPU physical address space, IO space33 * resources can be placed anywhere in the 64-bit physical address space.34 */35static inline bool36acpi_iospace_resource_valid(struct resource *res) { return true; }37#endif38 39#if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI)40static inline bool is_gsi(struct acpi_resource_extended_irq *ext_irq)41{42 return ext_irq->resource_source.string_length == 0 &&43 ext_irq->producer_consumer == ACPI_CONSUMER;44}45#else46static inline bool is_gsi(struct acpi_resource_extended_irq *ext_irq)47{48 return true;49}50#endif51 52static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)53{54 u64 reslen = end - start + 1;55 56 /*57 * CHECKME: len might be required to check versus a minimum58 * length as well. 1 for io is fine, but for memory it does59 * not make any sense at all.60 * Note: some BIOSes report incorrect length for ACPI address space61 * descriptor, so remove check of 'reslen == len' to avoid regression.62 */63 if (len && reslen && start <= end)64 return true;65 66 pr_debug("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",67 io ? "io" : "mem", start, end, len);68 69 return false;70}71 72static void acpi_dev_memresource_flags(struct resource *res, u64 len,73 u8 write_protect)74{75 res->flags = IORESOURCE_MEM;76 77 if (!acpi_dev_resource_len_valid(res->start, res->end, len, false))78 res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;79 80 if (write_protect == ACPI_READ_WRITE_MEMORY)81 res->flags |= IORESOURCE_MEM_WRITEABLE;82}83 84static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,85 u8 write_protect)86{87 res->start = start;88 res->end = start + len - 1;89 acpi_dev_memresource_flags(res, len, write_protect);90}91 92/**93 * acpi_dev_resource_memory - Extract ACPI memory resource information.94 * @ares: Input ACPI resource object.95 * @res: Output generic resource object.96 *97 * Check if the given ACPI resource object represents a memory resource and98 * if that's the case, use the information in it to populate the generic99 * resource object pointed to by @res.100 *101 * Return:102 * 1) false with res->flags setting to zero: not the expected resource type103 * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource104 * 3) true: valid assigned resource105 */106bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)107{108 struct acpi_resource_memory24 *memory24;109 struct acpi_resource_memory32 *memory32;110 struct acpi_resource_fixed_memory32 *fixed_memory32;111 112 switch (ares->type) {113 case ACPI_RESOURCE_TYPE_MEMORY24:114 memory24 = &ares->data.memory24;115 acpi_dev_get_memresource(res, memory24->minimum << 8,116 memory24->address_length << 8,117 memory24->write_protect);118 break;119 case ACPI_RESOURCE_TYPE_MEMORY32:120 memory32 = &ares->data.memory32;121 acpi_dev_get_memresource(res, memory32->minimum,122 memory32->address_length,123 memory32->write_protect);124 break;125 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:126 fixed_memory32 = &ares->data.fixed_memory32;127 acpi_dev_get_memresource(res, fixed_memory32->address,128 fixed_memory32->address_length,129 fixed_memory32->write_protect);130 break;131 default:132 res->flags = 0;133 return false;134 }135 136 return !(res->flags & IORESOURCE_DISABLED);137}138EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);139 140static void acpi_dev_ioresource_flags(struct resource *res, u64 len,141 u8 io_decode, u8 translation_type)142{143 res->flags = IORESOURCE_IO;144 145 if (!acpi_dev_resource_len_valid(res->start, res->end, len, true))146 res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;147 148 if (!acpi_iospace_resource_valid(res))149 res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;150 151 if (io_decode == ACPI_DECODE_16)152 res->flags |= IORESOURCE_IO_16BIT_ADDR;153 if (translation_type == ACPI_SPARSE_TRANSLATION)154 res->flags |= IORESOURCE_IO_SPARSE;155}156 157static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,158 u8 io_decode)159{160 res->start = start;161 res->end = start + len - 1;162 acpi_dev_ioresource_flags(res, len, io_decode, 0);163}164 165/**166 * acpi_dev_resource_io - Extract ACPI I/O resource information.167 * @ares: Input ACPI resource object.168 * @res: Output generic resource object.169 *170 * Check if the given ACPI resource object represents an I/O resource and171 * if that's the case, use the information in it to populate the generic172 * resource object pointed to by @res.173 *174 * Return:175 * 1) false with res->flags setting to zero: not the expected resource type176 * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource177 * 3) true: valid assigned resource178 */179bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)180{181 struct acpi_resource_io *io;182 struct acpi_resource_fixed_io *fixed_io;183 184 switch (ares->type) {185 case ACPI_RESOURCE_TYPE_IO:186 io = &ares->data.io;187 acpi_dev_get_ioresource(res, io->minimum,188 io->address_length,189 io->io_decode);190 break;191 case ACPI_RESOURCE_TYPE_FIXED_IO:192 fixed_io = &ares->data.fixed_io;193 acpi_dev_get_ioresource(res, fixed_io->address,194 fixed_io->address_length,195 ACPI_DECODE_10);196 break;197 default:198 res->flags = 0;199 return false;200 }201 202 return !(res->flags & IORESOURCE_DISABLED);203}204EXPORT_SYMBOL_GPL(acpi_dev_resource_io);205 206static bool acpi_decode_space(struct resource_win *win,207 struct acpi_resource_address *addr,208 struct acpi_address64_attribute *attr)209{210 u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16;211 bool wp = addr->info.mem.write_protect;212 u64 len = attr->address_length;213 u64 start, end, offset = 0;214 struct resource *res = &win->res;215 216 /*217 * Filter out invalid descriptor according to ACPI Spec 5.0, section218 * 6.4.3.5 Address Space Resource Descriptors.219 */220 if ((addr->min_address_fixed != addr->max_address_fixed && len) ||221 (addr->min_address_fixed && addr->max_address_fixed && !len))222 pr_debug("ACPI: Invalid address space min_addr_fix %d, max_addr_fix %d, len %llx\n",223 addr->min_address_fixed, addr->max_address_fixed, len);224 225 /*226 * For bridges that translate addresses across the bridge,227 * translation_offset is the offset that must be added to the228 * address on the secondary side to obtain the address on the229 * primary side. Non-bridge devices must list 0 for all Address230 * Translation offset bits.231 */232 if (addr->producer_consumer == ACPI_PRODUCER)233 offset = attr->translation_offset;234 else if (attr->translation_offset)235 pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n",236 attr->translation_offset);237 start = attr->minimum + offset;238 end = attr->maximum + offset;239 240 win->offset = offset;241 res->start = start;242 res->end = end;243 if (sizeof(resource_size_t) < sizeof(u64) &&244 (offset != win->offset || start != res->start || end != res->end)) {245 pr_warn("acpi resource window ([%#llx-%#llx] ignored, not CPU addressable)\n",246 attr->minimum, attr->maximum);247 return false;248 }249 250 switch (addr->resource_type) {251 case ACPI_MEMORY_RANGE:252 acpi_dev_memresource_flags(res, len, wp);253 break;254 case ACPI_IO_RANGE:255 acpi_dev_ioresource_flags(res, len, iodec,256 addr->info.io.translation_type);257 break;258 case ACPI_BUS_NUMBER_RANGE:259 res->flags = IORESOURCE_BUS;260 break;261 default:262 return false;263 }264 265 if (addr->producer_consumer == ACPI_PRODUCER)266 res->flags |= IORESOURCE_WINDOW;267 268 if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)269 res->flags |= IORESOURCE_PREFETCH;270 271 return !(res->flags & IORESOURCE_DISABLED);272}273 274/**275 * acpi_dev_resource_address_space - Extract ACPI address space information.276 * @ares: Input ACPI resource object.277 * @win: Output generic resource object.278 *279 * Check if the given ACPI resource object represents an address space resource280 * and if that's the case, use the information in it to populate the generic281 * resource object pointed to by @win.282 *283 * Return:284 * 1) false with win->res.flags setting to zero: not the expected resource type285 * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned286 * resource287 * 3) true: valid assigned resource288 */289bool acpi_dev_resource_address_space(struct acpi_resource *ares,290 struct resource_win *win)291{292 struct acpi_resource_address64 addr;293 294 win->res.flags = 0;295 if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr)))296 return false;297 298 return acpi_decode_space(win, (struct acpi_resource_address *)&addr,299 &addr.address);300}301EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);302 303/**304 * acpi_dev_resource_ext_address_space - Extract ACPI address space information.305 * @ares: Input ACPI resource object.306 * @win: Output generic resource object.307 *308 * Check if the given ACPI resource object represents an extended address space309 * resource and if that's the case, use the information in it to populate the310 * generic resource object pointed to by @win.311 *312 * Return:313 * 1) false with win->res.flags setting to zero: not the expected resource type314 * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned315 * resource316 * 3) true: valid assigned resource317 */318bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,319 struct resource_win *win)320{321 struct acpi_resource_extended_address64 *ext_addr;322 323 win->res.flags = 0;324 if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)325 return false;326 327 ext_addr = &ares->data.ext_address64;328 329 return acpi_decode_space(win, (struct acpi_resource_address *)ext_addr,330 &ext_addr->address);331}332EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);333 334/**335 * acpi_dev_irq_flags - Determine IRQ resource flags.336 * @triggering: Triggering type as provided by ACPI.337 * @polarity: Interrupt polarity as provided by ACPI.338 * @shareable: Whether or not the interrupt is shareable.339 * @wake_capable: Wake capability as provided by ACPI.340 */341unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable, u8 wake_capable)342{343 unsigned long flags;344 345 if (triggering == ACPI_LEVEL_SENSITIVE)346 flags = polarity == ACPI_ACTIVE_LOW ?347 IORESOURCE_IRQ_LOWLEVEL : IORESOURCE_IRQ_HIGHLEVEL;348 else349 flags = polarity == ACPI_ACTIVE_LOW ?350 IORESOURCE_IRQ_LOWEDGE : IORESOURCE_IRQ_HIGHEDGE;351 352 if (shareable == ACPI_SHARED)353 flags |= IORESOURCE_IRQ_SHAREABLE;354 355 if (wake_capable == ACPI_WAKE_CAPABLE)356 flags |= IORESOURCE_IRQ_WAKECAPABLE;357 358 return flags | IORESOURCE_IRQ;359}360EXPORT_SYMBOL_GPL(acpi_dev_irq_flags);361 362/**363 * acpi_dev_get_irq_type - Determine irq type.364 * @triggering: Triggering type as provided by ACPI.365 * @polarity: Interrupt polarity as provided by ACPI.366 */367unsigned int acpi_dev_get_irq_type(int triggering, int polarity)368{369 switch (polarity) {370 case ACPI_ACTIVE_LOW:371 return triggering == ACPI_EDGE_SENSITIVE ?372 IRQ_TYPE_EDGE_FALLING :373 IRQ_TYPE_LEVEL_LOW;374 case ACPI_ACTIVE_HIGH:375 return triggering == ACPI_EDGE_SENSITIVE ?376 IRQ_TYPE_EDGE_RISING :377 IRQ_TYPE_LEVEL_HIGH;378 case ACPI_ACTIVE_BOTH:379 if (triggering == ACPI_EDGE_SENSITIVE)380 return IRQ_TYPE_EDGE_BOTH;381 fallthrough;382 default:383 return IRQ_TYPE_NONE;384 }385}386EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type);387 388/*389 * DMI matches for boards where the DSDT specifies the kbd IRQ as390 * level active-low and using the override changes this to rising edge,391 * stopping the keyboard from working.392 */393static const struct dmi_system_id irq1_level_low_skip_override[] = {394 {395 /* MEDION P15651 */396 .matches = {397 DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),398 DMI_MATCH(DMI_BOARD_NAME, "M15T"),399 },400 },401 {402 /* MEDION S17405 */403 .matches = {404 DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),405 DMI_MATCH(DMI_BOARD_NAME, "M17T"),406 },407 },408 {409 /* MEDION S17413 */410 .matches = {411 DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),412 DMI_MATCH(DMI_BOARD_NAME, "M1xA"),413 },414 },415 {416 /* Asus Vivobook K3402ZA */417 .matches = {418 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),419 DMI_MATCH(DMI_BOARD_NAME, "K3402ZA"),420 },421 },422 {423 /* Asus Vivobook K3502ZA */424 .matches = {425 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),426 DMI_MATCH(DMI_BOARD_NAME, "K3502ZA"),427 },428 },429 {430 /* Asus Vivobook S5402ZA */431 .matches = {432 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),433 DMI_MATCH(DMI_BOARD_NAME, "S5402ZA"),434 },435 },436 {437 /* Asus Vivobook S5602ZA */438 .matches = {439 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),440 DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"),441 },442 },443 {444 /* Asus Vivobook X1704VAP */445 .matches = {446 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),447 DMI_MATCH(DMI_BOARD_NAME, "X1704VAP"),448 },449 },450 {451 /* Asus ExpertBook B1402C* */452 .matches = {453 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),454 DMI_MATCH(DMI_BOARD_NAME, "B1402C"),455 },456 },457 {458 /* Asus ExpertBook B1502C* */459 .matches = {460 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),461 DMI_MATCH(DMI_BOARD_NAME, "B1502C"),462 },463 },464 {465 /* Asus ExpertBook B2402 (B2402CBA / B2402FBA / B2402CVA / B2402FVA) */466 .matches = {467 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),468 DMI_MATCH(DMI_BOARD_NAME, "B2402"),469 },470 },471 {472 /* Asus ExpertBook B2502 (B2502CBA / B2502FBA / B2502CVA / B2502FVA) */473 .matches = {474 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),475 DMI_MATCH(DMI_BOARD_NAME, "B2502"),476 },477 },478 {479 /* Asus Vivobook Go E1404GA* */480 .matches = {481 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),482 DMI_MATCH(DMI_BOARD_NAME, "E1404GA"),483 },484 },485 {486 /* Asus Vivobook E1504GA* */487 .matches = {488 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),489 DMI_MATCH(DMI_BOARD_NAME, "E1504GA"),490 },491 },492 {493 /* Asus Vivobook Pro N6506M* */494 .matches = {495 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),496 DMI_MATCH(DMI_BOARD_NAME, "N6506M"),497 },498 },499 {500 /* LG Electronics 17U70P */501 .matches = {502 DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),503 DMI_MATCH(DMI_BOARD_NAME, "17U70P"),504 },505 },506 {507 /* LG Electronics 16T90SP */508 .matches = {509 DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),510 DMI_MATCH(DMI_BOARD_NAME, "16T90SP"),511 },512 },513 { }514};515 516/*517 * DMI matches for AMD Zen boards where the DSDT specifies the kbd IRQ518 * as falling edge and this must be overridden to rising edge,519 * to have a working keyboard.520 */521static const struct dmi_system_id irq1_edge_low_force_override[] = {522 {523 /* MECHREV Jiaolong17KS Series GM7XG0M */524 .matches = {525 DMI_MATCH(DMI_BOARD_NAME, "GM7XG0M"),526 },527 },528 {529 /* XMG APEX 17 (M23) */530 .matches = {531 DMI_MATCH(DMI_BOARD_NAME, "GMxBGxx"),532 },533 },534 {535 /* TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD */536 .matches = {537 DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"),538 },539 },540 {541 /* TongFang GMxXGxx/TUXEDO Polaris 15 Gen5 AMD */542 .matches = {543 DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"),544 },545 },546 {547 /* TongFang GMxXGxX/TUXEDO Polaris 15 Gen5 AMD */548 .matches = {549 DMI_MATCH(DMI_BOARD_NAME, "GMxXGxX"),550 },551 },552 {553 /* TongFang GMxXGxx sold as Eluktronics Inc. RP-15 */554 .matches = {555 DMI_MATCH(DMI_SYS_VENDOR, "Eluktronics Inc."),556 DMI_MATCH(DMI_BOARD_NAME, "RP-15"),557 },558 },559 {560 /* TongFang GM6XGxX/TUXEDO Stellaris 16 Gen5 AMD */561 .matches = {562 DMI_MATCH(DMI_BOARD_NAME, "GM6XGxX"),563 },564 },565 {566 /* MAINGEAR Vector Pro 2 15 */567 .matches = {568 DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),569 DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-15A3070T"),570 }571 },572 {573 /* MAINGEAR Vector Pro 2 17 */574 .matches = {575 DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),576 DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-17A3070T"),577 },578 },579 {580 /* TongFang GM6BGEQ / PCSpecialist Elimina Pro 16 M, RTX 3050 */581 .matches = {582 DMI_MATCH(DMI_BOARD_NAME, "GM6BGEQ"),583 },584 },585 {586 /* TongFang GM6BG5Q, RTX 4050 */587 .matches = {588 DMI_MATCH(DMI_BOARD_NAME, "GM6BG5Q"),589 },590 },591 {592 /* TongFang GM6BG0Q / PCSpecialist Elimina Pro 16 M, RTX 4060 */593 .matches = {594 DMI_MATCH(DMI_BOARD_NAME, "GM6BG0Q"),595 },596 },597 {598 /* Infinity E15-5A165-BM */599 .matches = {600 DMI_MATCH(DMI_BOARD_NAME, "GM5RG1E0009COM"),601 },602 },603 {604 /* Infinity E15-5A305-1M */605 .matches = {606 DMI_MATCH(DMI_BOARD_NAME, "GM5RGEE0016COM"),607 },608 },609 {610 /* Lunnen Ground 15 / AMD Ryzen 5 5500U */611 .matches = {612 DMI_MATCH(DMI_SYS_VENDOR, "Lunnen"),613 DMI_MATCH(DMI_BOARD_NAME, "LLL5DAW"),614 },615 },616 {617 /* Lunnen Ground 16 / AMD Ryzen 7 5800U */618 .matches = {619 DMI_MATCH(DMI_SYS_VENDOR, "Lunnen"),620 DMI_MATCH(DMI_BOARD_NAME, "LL6FA"),621 },622 },623 {624 /* MAIBENBEN X577 */625 .matches = {626 DMI_MATCH(DMI_SYS_VENDOR, "MAIBENBEN"),627 DMI_MATCH(DMI_BOARD_NAME, "X577"),628 },629 },630 {631 /* Maibenben X565 */632 .matches = {633 DMI_MATCH(DMI_SYS_VENDOR, "MAIBENBEN"),634 DMI_MATCH(DMI_BOARD_NAME, "X565"),635 },636 },637 {638 /* TongFang GXxHRXx/TUXEDO InfinityBook Pro Gen9 AMD */639 .matches = {640 DMI_MATCH(DMI_BOARD_NAME, "GXxHRXx"),641 },642 },643 {644 /* TongFang GMxHGxx/TUXEDO Stellaris Slim Gen1 AMD */645 .matches = {646 DMI_MATCH(DMI_BOARD_NAME, "GMxHGxx"),647 },648 },649 { }650};651 652struct irq_override_cmp {653 const struct dmi_system_id *system;654 unsigned char irq;655 unsigned char triggering;656 unsigned char polarity;657 unsigned char shareable;658 bool override;659};660 661static const struct irq_override_cmp override_table[] = {662 { irq1_level_low_skip_override, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },663 { irq1_edge_low_force_override, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },664};665 666static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,667 u8 shareable)668{669 int i;670 671 for (i = 0; i < ARRAY_SIZE(override_table); i++) {672 const struct irq_override_cmp *entry = &override_table[i];673 674 if (dmi_check_system(entry->system) &&675 entry->irq == gsi &&676 entry->triggering == triggering &&677 entry->polarity == polarity &&678 entry->shareable == shareable)679 return entry->override;680 }681 682#ifdef CONFIG_X86683 /*684 * Always use the MADT override info, except for the i8042 PS/2 ctrl685 * IRQs (1 and 12). For these the DSDT IRQ settings should sometimes686 * be used otherwise PS/2 keyboards / mice will not work.687 */688 if (gsi != 1 && gsi != 12)689 return true;690 691 /* If the override comes from an INT_SRC_OVR MADT entry, honor it. */692 if (acpi_int_src_ovr[gsi])693 return true;694 695 /*696 * IRQ override isn't needed on modern AMD Zen systems and697 * this override breaks active low IRQs on AMD Ryzen 6000 and698 * newer systems. Skip it.699 */700 if (boot_cpu_has(X86_FEATURE_ZEN))701 return false;702#endif703 704 return true;705}706 707static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,708 u8 triggering, u8 polarity, u8 shareable,709 u8 wake_capable, bool check_override)710{711 int irq, p, t;712 713 if (!valid_IRQ(gsi)) {714 irqresource_disabled(res, gsi);715 return;716 }717 718 /*719 * In IO-APIC mode, use overridden attribute. Two reasons:720 * 1. BIOS bug in DSDT721 * 2. BIOS uses IO-APIC mode Interrupt Source Override722 *723 * We do this only if we are dealing with IRQ() or IRQNoFlags()724 * resource (the legacy ISA resources). With modern ACPI 5 devices725 * using extended IRQ descriptors we take the IRQ configuration726 * from _CRS directly.727 */728 if (check_override &&729 acpi_dev_irq_override(gsi, triggering, polarity, shareable) &&730 !acpi_get_override_irq(gsi, &t, &p)) {731 u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;732 u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;733 734 if (triggering != trig || polarity != pol) {735 pr_warn("ACPI: IRQ %d override to %s%s, %s%s\n", gsi,736 t ? "level" : "edge",737 trig == triggering ? "" : "(!)",738 p ? "low" : "high",739 pol == polarity ? "" : "(!)");740 triggering = trig;741 polarity = pol;742 }743 }744 745 res->flags = acpi_dev_irq_flags(triggering, polarity, shareable, wake_capable);746 irq = acpi_register_gsi(NULL, gsi, triggering, polarity);747 if (irq >= 0) {748 res->start = irq;749 res->end = irq;750 } else {751 irqresource_disabled(res, gsi);752 }753}754 755/**756 * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information.757 * @ares: Input ACPI resource object.758 * @index: Index into the array of GSIs represented by the resource.759 * @res: Output generic resource object.760 *761 * Check if the given ACPI resource object represents an interrupt resource762 * and @index does not exceed the resource's interrupt count (true is returned763 * in that case regardless of the results of the other checks)). If that's the764 * case, register the GSI corresponding to @index from the array of interrupts765 * represented by the resource and populate the generic resource object pointed766 * to by @res accordingly. If the registration of the GSI is not successful,767 * IORESOURCE_DISABLED will be set it that object's flags.768 *769 * Return:770 * 1) false with res->flags setting to zero: not the expected resource type771 * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource772 * 3) true: valid assigned resource773 */774bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,775 struct resource *res)776{777 struct acpi_resource_irq *irq;778 struct acpi_resource_extended_irq *ext_irq;779 780 switch (ares->type) {781 case ACPI_RESOURCE_TYPE_IRQ:782 /*783 * Per spec, only one interrupt per descriptor is allowed in784 * _CRS, but some firmware violates this, so parse them all.785 */786 irq = &ares->data.irq;787 if (index >= irq->interrupt_count) {788 irqresource_disabled(res, 0);789 return false;790 }791 acpi_dev_get_irqresource(res, irq->interrupts[index],792 irq->triggering, irq->polarity,793 irq->shareable, irq->wake_capable,794 true);795 break;796 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:797 ext_irq = &ares->data.extended_irq;798 if (index >= ext_irq->interrupt_count) {799 irqresource_disabled(res, 0);800 return false;801 }802 if (is_gsi(ext_irq))803 acpi_dev_get_irqresource(res, ext_irq->interrupts[index],804 ext_irq->triggering, ext_irq->polarity,805 ext_irq->shareable, ext_irq->wake_capable,806 false);807 else808 irqresource_disabled(res, 0);809 break;810 default:811 res->flags = 0;812 return false;813 }814 815 return true;816}817EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt);818 819/**820 * acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources().821 * @list: The head of the resource list to free.822 */823void acpi_dev_free_resource_list(struct list_head *list)824{825 resource_list_free(list);826}827EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list);828 829struct res_proc_context {830 struct list_head *list;831 int (*preproc)(struct acpi_resource *, void *);832 void *preproc_data;833 int count;834 int error;835};836 837static acpi_status acpi_dev_new_resource_entry(struct resource_win *win,838 struct res_proc_context *c)839{840 struct resource_entry *rentry;841 842 rentry = resource_list_create_entry(NULL, 0);843 if (!rentry) {844 c->error = -ENOMEM;845 return AE_NO_MEMORY;846 }847 *rentry->res = win->res;848 rentry->offset = win->offset;849 resource_list_add_tail(rentry, c->list);850 c->count++;851 return AE_OK;852}853 854static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,855 void *context)856{857 struct res_proc_context *c = context;858 struct resource_win win;859 struct resource *res = &win.res;860 int i;861 862 if (c->preproc) {863 int ret;864 865 ret = c->preproc(ares, c->preproc_data);866 if (ret < 0) {867 c->error = ret;868 return AE_ABORT_METHOD;869 } else if (ret > 0) {870 return AE_OK;871 }872 }873 874 memset(&win, 0, sizeof(win));875 876 if (acpi_dev_resource_memory(ares, res)877 || acpi_dev_resource_io(ares, res)878 || acpi_dev_resource_address_space(ares, &win)879 || acpi_dev_resource_ext_address_space(ares, &win))880 return acpi_dev_new_resource_entry(&win, c);881 882 for (i = 0; acpi_dev_resource_interrupt(ares, i, res); i++) {883 acpi_status status;884 885 status = acpi_dev_new_resource_entry(&win, c);886 if (ACPI_FAILURE(status))887 return status;888 }889 890 return AE_OK;891}892 893static int __acpi_dev_get_resources(struct acpi_device *adev,894 struct list_head *list,895 int (*preproc)(struct acpi_resource *, void *),896 void *preproc_data, char *method)897{898 struct res_proc_context c;899 acpi_status status;900 901 if (!adev || !adev->handle || !list_empty(list))902 return -EINVAL;903 904 if (!acpi_has_method(adev->handle, method))905 return 0;906 907 c.list = list;908 c.preproc = preproc;909 c.preproc_data = preproc_data;910 c.count = 0;911 c.error = 0;912 status = acpi_walk_resources(adev->handle, method,913 acpi_dev_process_resource, &c);914 if (ACPI_FAILURE(status)) {915 acpi_dev_free_resource_list(list);916 return c.error ? c.error : -EIO;917 }918 919 return c.count;920}921 922/**923 * acpi_dev_get_resources - Get current resources of a device.924 * @adev: ACPI device node to get the resources for.925 * @list: Head of the resultant list of resources (must be empty).926 * @preproc: The caller's preprocessing routine.927 * @preproc_data: Pointer passed to the caller's preprocessing routine.928 *929 * Evaluate the _CRS method for the given device node and process its output by930 * (1) executing the @preproc() routine provided by the caller, passing the931 * resource pointer and @preproc_data to it as arguments, for each ACPI resource932 * returned and (2) converting all of the returned ACPI resources into struct933 * resource objects if possible. If the return value of @preproc() in step (1)934 * is different from 0, step (2) is not applied to the given ACPI resource and935 * if that value is negative, the whole processing is aborted and that value is936 * returned as the final error code.937 *938 * The resultant struct resource objects are put on the list pointed to by939 * @list, that must be empty initially, as members of struct resource_entry940 * objects. Callers of this routine should use %acpi_dev_free_resource_list() to941 * free that list.942 *943 * The number of resources in the output list is returned on success, an error944 * code reflecting the error condition is returned otherwise.945 */946int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,947 int (*preproc)(struct acpi_resource *, void *),948 void *preproc_data)949{950 return __acpi_dev_get_resources(adev, list, preproc, preproc_data,951 METHOD_NAME__CRS);952}953EXPORT_SYMBOL_GPL(acpi_dev_get_resources);954 955static int is_memory(struct acpi_resource *ares, void *not_used)956{957 struct resource_win win;958 struct resource *res = &win.res;959 960 memset(&win, 0, sizeof(win));961 962 if (acpi_dev_filter_resource_type(ares, IORESOURCE_MEM))963 return 1;964 965 return !(acpi_dev_resource_memory(ares, res)966 || acpi_dev_resource_address_space(ares, &win)967 || acpi_dev_resource_ext_address_space(ares, &win));968}969 970/**971 * acpi_dev_get_dma_resources - Get current DMA resources of a device.972 * @adev: ACPI device node to get the resources for.973 * @list: Head of the resultant list of resources (must be empty).974 *975 * Evaluate the _DMA method for the given device node and process its976 * output.977 *978 * The resultant struct resource objects are put on the list pointed to979 * by @list, that must be empty initially, as members of struct980 * resource_entry objects. Callers of this routine should use981 * %acpi_dev_free_resource_list() to free that list.982 *983 * The number of resources in the output list is returned on success,984 * an error code reflecting the error condition is returned otherwise.985 */986int acpi_dev_get_dma_resources(struct acpi_device *adev, struct list_head *list)987{988 return __acpi_dev_get_resources(adev, list, is_memory, NULL,989 METHOD_NAME__DMA);990}991EXPORT_SYMBOL_GPL(acpi_dev_get_dma_resources);992 993/**994 * acpi_dev_get_memory_resources - Get current memory resources of a device.995 * @adev: ACPI device node to get the resources for.996 * @list: Head of the resultant list of resources (must be empty).997 *998 * This is a helper function that locates all memory type resources of @adev999 * with acpi_dev_get_resources().1000 *1001 * The number of resources in the output list is returned on success, an error1002 * code reflecting the error condition is returned otherwise.1003 */1004int acpi_dev_get_memory_resources(struct acpi_device *adev, struct list_head *list)1005{1006 return acpi_dev_get_resources(adev, list, is_memory, NULL);1007}1008EXPORT_SYMBOL_GPL(acpi_dev_get_memory_resources);1009 1010/**1011 * acpi_dev_filter_resource_type - Filter ACPI resource according to resource1012 * types1013 * @ares: Input ACPI resource object.1014 * @types: Valid resource types of IORESOURCE_XXX1015 *1016 * This is a helper function to support acpi_dev_get_resources(), which filters1017 * ACPI resource objects according to resource types.1018 */1019int acpi_dev_filter_resource_type(struct acpi_resource *ares,1020 unsigned long types)1021{1022 unsigned long type = 0;1023 1024 switch (ares->type) {1025 case ACPI_RESOURCE_TYPE_MEMORY24:1026 case ACPI_RESOURCE_TYPE_MEMORY32:1027 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:1028 type = IORESOURCE_MEM;1029 break;1030 case ACPI_RESOURCE_TYPE_IO:1031 case ACPI_RESOURCE_TYPE_FIXED_IO:1032 type = IORESOURCE_IO;1033 break;1034 case ACPI_RESOURCE_TYPE_IRQ:1035 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:1036 type = IORESOURCE_IRQ;1037 break;1038 case ACPI_RESOURCE_TYPE_DMA:1039 case ACPI_RESOURCE_TYPE_FIXED_DMA:1040 type = IORESOURCE_DMA;1041 break;1042 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:1043 type = IORESOURCE_REG;1044 break;1045 case ACPI_RESOURCE_TYPE_ADDRESS16:1046 case ACPI_RESOURCE_TYPE_ADDRESS32:1047 case ACPI_RESOURCE_TYPE_ADDRESS64:1048 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:1049 if (ares->data.address.resource_type == ACPI_MEMORY_RANGE)1050 type = IORESOURCE_MEM;1051 else if (ares->data.address.resource_type == ACPI_IO_RANGE)1052 type = IORESOURCE_IO;1053 else if (ares->data.address.resource_type ==1054 ACPI_BUS_NUMBER_RANGE)1055 type = IORESOURCE_BUS;1056 break;1057 default:1058 break;1059 }1060 1061 return (type & types) ? 0 : 1;1062}1063EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);1064 1065static int acpi_dev_consumes_res(struct acpi_device *adev, struct resource *res)1066{1067 struct list_head resource_list;1068 struct resource_entry *rentry;1069 int ret, found = 0;1070 1071 INIT_LIST_HEAD(&resource_list);1072 ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);1073 if (ret < 0)1074 return 0;1075 1076 list_for_each_entry(rentry, &resource_list, node) {1077 if (resource_contains(rentry->res, res)) {1078 found = 1;1079 break;1080 }1081 1082 }1083 1084 acpi_dev_free_resource_list(&resource_list);1085 return found;1086}1087 1088static acpi_status acpi_res_consumer_cb(acpi_handle handle, u32 depth,1089 void *context, void **ret)1090{1091 struct resource *res = context;1092 struct acpi_device **consumer = (struct acpi_device **) ret;1093 struct acpi_device *adev = acpi_fetch_acpi_dev(handle);1094 1095 if (!adev)1096 return AE_OK;1097 1098 if (acpi_dev_consumes_res(adev, res)) {1099 *consumer = adev;1100 return AE_CTRL_TERMINATE;1101 }1102 1103 return AE_OK;1104}1105 1106/**1107 * acpi_resource_consumer - Find the ACPI device that consumes @res.1108 * @res: Resource to search for.1109 *1110 * Search the current resource settings (_CRS) of every ACPI device node1111 * for @res. If we find an ACPI device whose _CRS includes @res, return1112 * it. Otherwise, return NULL.1113 */1114struct acpi_device *acpi_resource_consumer(struct resource *res)1115{1116 struct acpi_device *consumer = NULL;1117 1118 acpi_get_devices(NULL, acpi_res_consumer_cb, res, (void **) &consumer);1119 return consumer;1120}1121