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