From c793504de3de484076e1eb96d5187af55f47945c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 2 Feb 2015 10:42:47 +0800 Subject: ACPI: Remove redundant check in function acpi_dev_resource_address_space() The ACPI type is checked in acpi_resource_to_address64() anyway. Signed-off-by: Thomas Gleixner Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index d0a4d90c6bcc..1c616a56e007 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -189,15 +189,6 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares, u64 len; u8 io_decode; - switch (ares->type) { - case ACPI_RESOURCE_TYPE_ADDRESS16: - case ACPI_RESOURCE_TYPE_ADDRESS32: - case ACPI_RESOURCE_TYPE_ADDRESS64: - break; - default: - return false; - } - status = acpi_resource_to_address64(ares, &addr); if (ACPI_FAILURE(status)) return false; -- cgit v1.2.3 From c420dbd13ef7f399a865498496ac9ce2755b8007 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 2 Feb 2015 10:42:48 +0800 Subject: ACPI: Implement proper length checks for mem resources Check whether the resulting length is the same as the given length. Check for start <= end as well. We need to hand in the resource for this, so we can apply the flags directly. [Jiang] Remove enforcement that resource starting address must be non-zero. Signed-off-by: Thomas Gleixner Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 62 ++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 27 deletions(-) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 1c616a56e007..3e7d9f6eb875 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -34,21 +34,37 @@ #define valid_IRQ(i) (true) #endif -static unsigned long acpi_dev_memresource_flags(u64 len, u8 write_protect, - bool window) +static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io) { - unsigned long flags = IORESOURCE_MEM; + u64 reslen = end - start + 1; - if (len == 0) - flags |= IORESOURCE_DISABLED; + /* + * CHECKME: len might be required to check versus a minimum + * length as well. 1 for io is fine, but for memory it does + * not make any sense at all. + */ + if (len && reslen && reslen == len && start <= end) + return true; + + pr_info("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n", + io ? "io" : "mem", start, end, len); + + return false; +} + +static void acpi_dev_memresource_flags(struct resource *res, u64 len, + u8 write_protect, bool window) +{ + res->flags = IORESOURCE_MEM; + + if (!acpi_dev_resource_len_valid(res->start, res->end, len, false)) + res->flags |= IORESOURCE_DISABLED; if (write_protect == ACPI_READ_WRITE_MEMORY) - flags |= IORESOURCE_MEM_WRITEABLE; + res->flags |= IORESOURCE_MEM_WRITEABLE; if (window) - flags |= IORESOURCE_WINDOW; - - return flags; + res->flags |= IORESOURCE_WINDOW; } static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len, @@ -56,7 +72,7 @@ static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len, { res->start = start; res->end = start + len - 1; - res->flags = acpi_dev_memresource_flags(len, write_protect, false); + acpi_dev_memresource_flags(res, len, write_protect, false); } /** @@ -77,24 +93,18 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) switch (ares->type) { case ACPI_RESOURCE_TYPE_MEMORY24: memory24 = &ares->data.memory24; - if (!memory24->minimum && !memory24->address_length) - return false; acpi_dev_get_memresource(res, memory24->minimum, memory24->address_length, memory24->write_protect); break; case ACPI_RESOURCE_TYPE_MEMORY32: memory32 = &ares->data.memory32; - if (!memory32->minimum && !memory32->address_length) - return false; acpi_dev_get_memresource(res, memory32->minimum, memory32->address_length, memory32->write_protect); break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: fixed_memory32 = &ares->data.fixed_memory32; - if (!fixed_memory32->address && !fixed_memory32->address_length) - return false; acpi_dev_get_memresource(res, fixed_memory32->address, fixed_memory32->address_length, fixed_memory32->write_protect); @@ -102,7 +112,8 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) default: return false; } - return true; + + return !(res->flags & IORESOURCE_DISABLED); } EXPORT_SYMBOL_GPL(acpi_dev_resource_memory); @@ -186,7 +197,6 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares, acpi_status status; struct acpi_resource_address64 addr; bool window; - u64 len; u8 io_decode; status = acpi_resource_to_address64(ares, &addr); @@ -199,10 +209,9 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares, switch(addr.resource_type) { case ACPI_MEMORY_RANGE: - len = addr.address.maximum - addr.address.minimum + 1; - res->flags = acpi_dev_memresource_flags(len, - addr.info.mem.write_protect, - window); + acpi_dev_memresource_flags(res, addr.address.address_length, + addr.info.mem.write_protect, + window); break; case ACPI_IO_RANGE: io_decode = addr.address.granularity == 0xfff ? @@ -236,7 +245,6 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, { struct acpi_resource_extended_address64 *ext_addr; bool window; - u64 len; u8 io_decode; if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64) @@ -250,10 +258,10 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, switch(ext_addr->resource_type) { case ACPI_MEMORY_RANGE: - len = ext_addr->address.maximum - ext_addr->address.minimum + 1; - res->flags = acpi_dev_memresource_flags(len, - ext_addr->info.mem.write_protect, - window); + acpi_dev_memresource_flags(res, + ext_addr->address.address_length, + ext_addr->info.mem.write_protect, + window); break; case ACPI_IO_RANGE: io_decode = ext_addr->address.granularity == 0xfff ? -- cgit v1.2.3 From 1d0420f1cfc4763a8c5bfc617e0a40f710c2f74d Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 2 Feb 2015 10:42:49 +0800 Subject: ACPI: Use the length check for io resources as well Also apply length check to IO resources. [Jiang] Remove enforcement that resource starting address must be non-zero. Signed-off-by: Thomas Gleixner Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 3e7d9f6eb875..16d291c60277 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -117,31 +117,30 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) } EXPORT_SYMBOL_GPL(acpi_dev_resource_memory); -static unsigned int acpi_dev_ioresource_flags(u64 start, u64 end, u8 io_decode, - bool window) +static void acpi_dev_ioresource_flags(struct resource *res, u64 len, + u8 io_decode, bool window) { - int flags = IORESOURCE_IO; + res->flags = IORESOURCE_IO; - if (io_decode == ACPI_DECODE_16) - flags |= IORESOURCE_IO_16BIT_ADDR; + if (!acpi_dev_resource_len_valid(res->start, res->end, len, true)) + res->flags |= IORESOURCE_DISABLED; - if (start > end || end >= 0x10003) - flags |= IORESOURCE_DISABLED; + if (res->end >= 0x10003) + res->flags |= IORESOURCE_DISABLED; - if (window) - flags |= IORESOURCE_WINDOW; + if (io_decode == ACPI_DECODE_16) + res->flags |= IORESOURCE_IO_16BIT_ADDR; - return flags; + if (window) + res->flags |= IORESOURCE_WINDOW; } static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len, u8 io_decode) { - u64 end = start + len - 1; - res->start = start; - res->end = end; - res->flags = acpi_dev_ioresource_flags(start, end, io_decode, false); + res->end = start + len - 1; + acpi_dev_ioresource_flags(res, len, io_decode, false); } /** @@ -161,16 +160,12 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) switch (ares->type) { case ACPI_RESOURCE_TYPE_IO: io = &ares->data.io; - if (!io->minimum && !io->address_length) - return false; acpi_dev_get_ioresource(res, io->minimum, io->address_length, io->io_decode); break; case ACPI_RESOURCE_TYPE_FIXED_IO: fixed_io = &ares->data.fixed_io; - if (!fixed_io->address && !fixed_io->address_length) - return false; acpi_dev_get_ioresource(res, fixed_io->address, fixed_io->address_length, ACPI_DECODE_10); @@ -178,7 +173,8 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) default: return false; } - return true; + + return !(res->flags & IORESOURCE_DISABLED); } EXPORT_SYMBOL_GPL(acpi_dev_resource_io); @@ -216,9 +212,8 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares, case ACPI_IO_RANGE: io_decode = addr.address.granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16; - res->flags = acpi_dev_ioresource_flags(addr.address.minimum, - addr.address.maximum, - io_decode, window); + acpi_dev_ioresource_flags(res, addr.address.address_length, + io_decode, window); break; case ACPI_BUS_NUMBER_RANGE: res->flags = IORESOURCE_BUS; @@ -266,9 +261,8 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, case ACPI_IO_RANGE: io_decode = ext_addr->address.granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16; - res->flags = acpi_dev_ioresource_flags(ext_addr->address.minimum, - ext_addr->address.maximum, - io_decode, window); + acpi_dev_ioresource_flags(res, ext_addr->address.address_length, + io_decode, window); break; case ACPI_BUS_NUMBER_RANGE: res->flags = IORESOURCE_BUS; -- cgit v1.2.3 From e814f6deee6188265b5af9f1190e5734f116860e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 2 Feb 2015 10:42:50 +0800 Subject: ACPI: Let the parser return false for disabled resources If the parser disables a resource during parsing, let it return false, so the calling code does not need to implement further checks. Signed-off-by: Thomas Gleixner Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 16d291c60277..cdb1a3c4a0b9 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -219,10 +219,10 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares, res->flags = IORESOURCE_BUS; break; default: - res->flags = 0; + return false; } - return true; + return !(res->flags & IORESOURCE_DISABLED); } EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space); @@ -268,10 +268,10 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, res->flags = IORESOURCE_BUS; break; default: - res->flags = 0; + return false; } - return true; + return !(res->flags & IORESOURCE_DISABLED); } EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space); -- cgit v1.2.3 From eb76d55e66a9bed2359cc5a0f08168b287c4dea8 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 2 Feb 2015 10:42:51 +0800 Subject: ACPI: Unify the parsing of address_space and ext_address_space With the unions in place which let us identify the substructs we can use a single parser for address_space and ext_address_space. Signed-off-by: Thomas Gleixner Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 90 +++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 56 deletions(-) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index cdb1a3c4a0b9..99903d196024 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -178,6 +178,35 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) } EXPORT_SYMBOL_GPL(acpi_dev_resource_io); +static bool acpi_decode_space(struct resource *res, + struct acpi_resource_address *addr, + struct acpi_address64_attribute *attr) +{ + u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16; + bool window = addr->producer_consumer == ACPI_PRODUCER; + bool wp = addr->info.mem.write_protect; + u64 len = attr->address_length; + + res->start = attr->minimum; + res->end = attr->maximum; + + switch (addr->resource_type) { + case ACPI_MEMORY_RANGE: + acpi_dev_memresource_flags(res, len, wp, window); + break; + case ACPI_IO_RANGE: + acpi_dev_ioresource_flags(res, len, iodec, window); + break; + case ACPI_BUS_NUMBER_RANGE: + res->flags = IORESOURCE_BUS; + break; + default: + return false; + } + + return !(res->flags & IORESOURCE_DISABLED); +} + /** * acpi_dev_resource_address_space - Extract ACPI address space information. * @ares: Input ACPI resource object. @@ -190,39 +219,13 @@ EXPORT_SYMBOL_GPL(acpi_dev_resource_io); bool acpi_dev_resource_address_space(struct acpi_resource *ares, struct resource *res) { - acpi_status status; struct acpi_resource_address64 addr; - bool window; - u8 io_decode; - - status = acpi_resource_to_address64(ares, &addr); - if (ACPI_FAILURE(status)) - return false; - res->start = addr.address.minimum; - res->end = addr.address.maximum; - window = addr.producer_consumer == ACPI_PRODUCER; - - switch(addr.resource_type) { - case ACPI_MEMORY_RANGE: - acpi_dev_memresource_flags(res, addr.address.address_length, - addr.info.mem.write_protect, - window); - break; - case ACPI_IO_RANGE: - io_decode = addr.address.granularity == 0xfff ? - ACPI_DECODE_10 : ACPI_DECODE_16; - acpi_dev_ioresource_flags(res, addr.address.address_length, - io_decode, window); - break; - case ACPI_BUS_NUMBER_RANGE: - res->flags = IORESOURCE_BUS; - break; - default: + if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr))) return false; - } - return !(res->flags & IORESOURCE_DISABLED); + return acpi_decode_space(res, (struct acpi_resource_address *)&addr, + &addr.address); } EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space); @@ -239,39 +242,14 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, struct resource *res) { struct acpi_resource_extended_address64 *ext_addr; - bool window; - u8 io_decode; if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64) return false; ext_addr = &ares->data.ext_address64; - res->start = ext_addr->address.minimum; - res->end = ext_addr->address.maximum; - window = ext_addr->producer_consumer == ACPI_PRODUCER; - - switch(ext_addr->resource_type) { - case ACPI_MEMORY_RANGE: - acpi_dev_memresource_flags(res, - ext_addr->address.address_length, - ext_addr->info.mem.write_protect, - window); - break; - case ACPI_IO_RANGE: - io_decode = ext_addr->address.granularity == 0xfff ? - ACPI_DECODE_10 : ACPI_DECODE_16; - acpi_dev_ioresource_flags(res, ext_addr->address.address_length, - io_decode, window); - break; - case ACPI_BUS_NUMBER_RANGE: - res->flags = IORESOURCE_BUS; - break; - default: - return false; - } - - return !(res->flags & IORESOURCE_DISABLED); + return acpi_decode_space(res, (struct acpi_resource_address *)ext_addr, + &ext_addr->address); } EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space); -- cgit v1.2.3 From 72e26b0d487fc494f40aa61e10a0757791e62e36 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 2 Feb 2015 10:42:52 +0800 Subject: ACPI: Move the window flag logic to the combined parser Normal memory and io resources have window always set to false. Move the flag logic to the unified address space parser. Signed-off-by: Thomas Gleixner Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 99903d196024..15d17937c431 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -53,7 +53,7 @@ static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io) } static void acpi_dev_memresource_flags(struct resource *res, u64 len, - u8 write_protect, bool window) + u8 write_protect) { res->flags = IORESOURCE_MEM; @@ -62,9 +62,6 @@ static void acpi_dev_memresource_flags(struct resource *res, u64 len, if (write_protect == ACPI_READ_WRITE_MEMORY) res->flags |= IORESOURCE_MEM_WRITEABLE; - - if (window) - res->flags |= IORESOURCE_WINDOW; } static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len, @@ -72,7 +69,7 @@ static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len, { res->start = start; res->end = start + len - 1; - acpi_dev_memresource_flags(res, len, write_protect, false); + acpi_dev_memresource_flags(res, len, write_protect); } /** @@ -118,7 +115,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) EXPORT_SYMBOL_GPL(acpi_dev_resource_memory); static void acpi_dev_ioresource_flags(struct resource *res, u64 len, - u8 io_decode, bool window) + u8 io_decode) { res->flags = IORESOURCE_IO; @@ -130,9 +127,6 @@ static void acpi_dev_ioresource_flags(struct resource *res, u64 len, if (io_decode == ACPI_DECODE_16) res->flags |= IORESOURCE_IO_16BIT_ADDR; - - if (window) - res->flags |= IORESOURCE_WINDOW; } static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len, @@ -140,7 +134,7 @@ static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len, { res->start = start; res->end = start + len - 1; - acpi_dev_ioresource_flags(res, len, io_decode, false); + acpi_dev_ioresource_flags(res, len, io_decode); } /** @@ -183,7 +177,6 @@ static bool acpi_decode_space(struct resource *res, struct acpi_address64_attribute *attr) { u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16; - bool window = addr->producer_consumer == ACPI_PRODUCER; bool wp = addr->info.mem.write_protect; u64 len = attr->address_length; @@ -192,10 +185,10 @@ static bool acpi_decode_space(struct resource *res, switch (addr->resource_type) { case ACPI_MEMORY_RANGE: - acpi_dev_memresource_flags(res, len, wp, window); + acpi_dev_memresource_flags(res, len, wp); break; case ACPI_IO_RANGE: - acpi_dev_ioresource_flags(res, len, iodec, window); + acpi_dev_ioresource_flags(res, len, iodec); break; case ACPI_BUS_NUMBER_RANGE: res->flags = IORESOURCE_BUS; @@ -204,6 +197,9 @@ static bool acpi_decode_space(struct resource *res, return false; } + if (addr->producer_consumer == ACPI_PRODUCER) + res->flags |= IORESOURCE_WINDOW; + return !(res->flags & IORESOURCE_DISABLED); } -- cgit v1.2.3 From fcb29bbcd5404494eb46ad24908a4843b5a32060 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 2 Feb 2015 10:42:53 +0800 Subject: ACPI: Add prefetch decoding to the address space parser Add support of PREFETCH attributre to ACPI address space and extended address space parser. Signed-off-by: Thomas Gleixner Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 15d17937c431..7ce00a63f695 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -200,6 +200,9 @@ static bool acpi_decode_space(struct resource *res, if (addr->producer_consumer == ACPI_PRODUCER) res->flags |= IORESOURCE_WINDOW; + if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY) + res->flags |= IORESOURCE_PREFETCH; + return !(res->flags & IORESOURCE_DISABLED); } -- cgit v1.2.3 From 8515f9368161730655b64ddaf8b11a3d20049610 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Feb 2015 10:42:54 +0800 Subject: ACPI: Fix a bug in parsing ACPI Memory24 resource According to ACPI spec 5, section 6.4.3.1 "24-Bit Memory Range Descriptor", minimum, maximum and address_length field in struct acpi_resource_memory24 is in granularity of 256-bytes. So shift 8-bit left to get correct address. Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 7ce00a63f695..5544c6d26f32 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -90,8 +90,8 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) switch (ares->type) { case ACPI_RESOURCE_TYPE_MEMORY24: memory24 = &ares->data.memory24; - acpi_dev_get_memresource(res, memory24->minimum, - memory24->address_length, + acpi_dev_get_memresource(res, memory24->minimum << 8, + memory24->address_length << 8, memory24->write_protect); break; case ACPI_RESOURCE_TYPE_MEMORY32: -- cgit v1.2.3 From 581c19f3a72ae9ff7f24f2a6c2e67f269ed4392a Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Feb 2015 10:42:55 +0800 Subject: ACPI: Normalize return value of resource parser functions Normalize return value of resource parse functions as: 1) return "true" if resource is assigned. 2) return "false" and IORESOURCE_DISABLED setting in res->flags if resource is unassigned. 3) return "false" and zeroing res->flags if it's not an valid or expected resource. Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 5544c6d26f32..32561290a4a0 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -80,6 +80,11 @@ static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len, * Check if the given ACPI resource object represents a memory resource and * if that's the case, use the information in it to populate the generic * resource object pointed to by @res. + * + * Return: + * 1) false with res->flags setting to zero: not the expected resource type + * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource + * 3) true: valid assigned resource */ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) { @@ -107,6 +112,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) fixed_memory32->write_protect); break; default: + res->flags = 0; return false; } @@ -145,6 +151,11 @@ static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len, * Check if the given ACPI resource object represents an I/O resource and * if that's the case, use the information in it to populate the generic * resource object pointed to by @res. + * + * Return: + * 1) false with res->flags setting to zero: not the expected resource type + * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource + * 3) true: valid assigned resource */ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) { @@ -165,6 +176,7 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) ACPI_DECODE_10); break; default: + res->flags = 0; return false; } @@ -214,12 +226,18 @@ static bool acpi_decode_space(struct resource *res, * Check if the given ACPI resource object represents an address space resource * and if that's the case, use the information in it to populate the generic * resource object pointed to by @res. + * + * Return: + * 1) false with res->flags setting to zero: not the expected resource type + * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource + * 3) true: valid assigned resource */ bool acpi_dev_resource_address_space(struct acpi_resource *ares, struct resource *res) { struct acpi_resource_address64 addr; + res->flags = 0; if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr))) return false; @@ -236,12 +254,18 @@ EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space); * Check if the given ACPI resource object represents an extended address space * resource and if that's the case, use the information in it to populate the * generic resource object pointed to by @res. + * + * Return: + * 1) false with res->flags setting to zero: not the expected resource type + * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource + * 3) true: valid assigned resource */ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, struct resource *res) { struct acpi_resource_extended_address64 *ext_addr; + res->flags = 0; if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64) return false; @@ -339,6 +363,11 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, * represented by the resource and populate the generic resource object pointed * to by @res accordingly. If the registration of the GSI is not successful, * IORESOURCE_DISABLED will be set it that object's flags. + * + * Return: + * 1) false with res->flags setting to zero: not the expected resource type + * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource + * 3) true: valid assigned resource */ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, struct resource *res) @@ -372,6 +401,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, ext_irq->sharable, false); break; default: + res->flags = 0; return false; } -- cgit v1.2.3 From c78b688561e684098a11012ca21a6d578f9dfb67 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Feb 2015 10:42:56 +0800 Subject: ACPI: Set flag IORESOURCE_UNSET for unassigned resources Also set flag IORESOURCE_UNSET for unassigned resource in addition to IORESOURCE_DISABLED to mark resource as unassigned. Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 32561290a4a0..5bf73a9f26d9 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -58,7 +58,7 @@ static void acpi_dev_memresource_flags(struct resource *res, u64 len, res->flags = IORESOURCE_MEM; if (!acpi_dev_resource_len_valid(res->start, res->end, len, false)) - res->flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET; if (write_protect == ACPI_READ_WRITE_MEMORY) res->flags |= IORESOURCE_MEM_WRITEABLE; @@ -126,10 +126,10 @@ static void acpi_dev_ioresource_flags(struct resource *res, u64 len, res->flags = IORESOURCE_IO; if (!acpi_dev_resource_len_valid(res->start, res->end, len, true)) - res->flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET; if (res->end >= 0x10003) - res->flags |= IORESOURCE_DISABLED; + res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET; if (io_decode == ACPI_DECODE_16) res->flags |= IORESOURCE_IO_16BIT_ADDR; @@ -304,7 +304,7 @@ static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi) { res->start = gsi; res->end = gsi; - res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED; + res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET; } static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, -- cgit v1.2.3 From a274019fc332d7b4dcb85735978c2018522be312 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Feb 2015 10:42:57 +0800 Subject: ACPI: Enforce stricter checks for address space descriptors Enforce stricter checks for address space descriptors according to ACPI spec. Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 5bf73a9f26d9..57891a621b96 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -192,6 +192,15 @@ static bool acpi_decode_space(struct resource *res, bool wp = addr->info.mem.write_protect; u64 len = attr->address_length; + /* + * Filter out invalid descriptor according to ACPI Spec 5.0, section + * 6.4.3.5 Address Space Resource Descriptors. + */ + if ((addr->min_address_fixed != addr->max_address_fixed && len) || + (addr->min_address_fixed && addr->max_address_fixed && !len)) + pr_debug("ACPI: Invalid address space min_addr_fix %d, max_addr_fix %d, len %llx\n", + addr->min_address_fixed, addr->max_address_fixed, len); + res->start = attr->minimum; res->end = attr->maximum; -- cgit v1.2.3 From a49170b552423a3e85fc4f0d778c707402ee4863 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Feb 2015 10:42:58 +0800 Subject: ACPI: Return translation offset when parsing ACPI address space resources Change function acpi_dev_resource_address_space() and acpi_dev_resource_ext_address_space() to return address space translation offset. It's based on a patch from Yinghai Lu . Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 58 +++++++++++++++++++++++------------------- drivers/pnp/pnpacpi/rsparser.c | 29 +++++++++++---------- include/linux/acpi.h | 9 +++++-- 3 files changed, 54 insertions(+), 42 deletions(-) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 57891a621b96..c902c8eece81 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -184,13 +184,14 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) } EXPORT_SYMBOL_GPL(acpi_dev_resource_io); -static bool acpi_decode_space(struct resource *res, +static bool acpi_decode_space(struct resource_win *win, struct acpi_resource_address *addr, struct acpi_address64_attribute *attr) { u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16; bool wp = addr->info.mem.write_protect; u64 len = attr->address_length; + struct resource *res = &win->res; /* * Filter out invalid descriptor according to ACPI Spec 5.0, section @@ -218,6 +219,8 @@ static bool acpi_decode_space(struct resource *res, return false; } + win->offset = attr->translation_offset; + if (addr->producer_consumer == ACPI_PRODUCER) res->flags |= IORESOURCE_WINDOW; @@ -230,27 +233,28 @@ static bool acpi_decode_space(struct resource *res, /** * acpi_dev_resource_address_space - Extract ACPI address space information. * @ares: Input ACPI resource object. - * @res: Output generic resource object. + * @win: Output generic resource object. * * Check if the given ACPI resource object represents an address space resource * and if that's the case, use the information in it to populate the generic - * resource object pointed to by @res. + * resource object pointed to by @win. * * Return: - * 1) false with res->flags setting to zero: not the expected resource type - * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource + * 1) false with win->res.flags setting to zero: not the expected resource type + * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned + * resource * 3) true: valid assigned resource */ bool acpi_dev_resource_address_space(struct acpi_resource *ares, - struct resource *res) + struct resource_win *win) { struct acpi_resource_address64 addr; - res->flags = 0; + win->res.flags = 0; if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr))) return false; - return acpi_decode_space(res, (struct acpi_resource_address *)&addr, + return acpi_decode_space(win, (struct acpi_resource_address *)&addr, &addr.address); } EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space); @@ -258,29 +262,30 @@ EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space); /** * acpi_dev_resource_ext_address_space - Extract ACPI address space information. * @ares: Input ACPI resource object. - * @res: Output generic resource object. + * @win: Output generic resource object. * * Check if the given ACPI resource object represents an extended address space * resource and if that's the case, use the information in it to populate the - * generic resource object pointed to by @res. + * generic resource object pointed to by @win. * * Return: - * 1) false with res->flags setting to zero: not the expected resource type - * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource + * 1) false with win->res.flags setting to zero: not the expected resource type + * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned + * resource * 3) true: valid assigned resource */ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, - struct resource *res) + struct resource_win *win) { struct acpi_resource_extended_address64 *ext_addr; - res->flags = 0; + win->res.flags = 0; if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64) return false; ext_addr = &ares->data.ext_address64; - return acpi_decode_space(res, (struct acpi_resource_address *)ext_addr, + return acpi_decode_space(win, (struct acpi_resource_address *)ext_addr, &ext_addr->address); } EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space); @@ -441,7 +446,7 @@ struct res_proc_context { int error; }; -static acpi_status acpi_dev_new_resource_entry(struct resource *r, +static acpi_status acpi_dev_new_resource_entry(struct resource_win *win, struct res_proc_context *c) { struct resource_list_entry *rentry; @@ -451,7 +456,7 @@ static acpi_status acpi_dev_new_resource_entry(struct resource *r, c->error = -ENOMEM; return AE_NO_MEMORY; } - rentry->res = *r; + rentry->res = win->res; list_add_tail(&rentry->node, c->list); c->count++; return AE_OK; @@ -461,7 +466,8 @@ static acpi_status acpi_dev_process_resource(struct acpi_resource *ares, void *context) { struct res_proc_context *c = context; - struct resource r; + struct resource_win win; + struct resource *res = &win.res; int i; if (c->preproc) { @@ -476,18 +482,18 @@ static acpi_status acpi_dev_process_resource(struct acpi_resource *ares, } } - memset(&r, 0, sizeof(r)); + memset(&win, 0, sizeof(win)); - if (acpi_dev_resource_memory(ares, &r) - || acpi_dev_resource_io(ares, &r) - || acpi_dev_resource_address_space(ares, &r) - || acpi_dev_resource_ext_address_space(ares, &r)) - return acpi_dev_new_resource_entry(&r, c); + if (acpi_dev_resource_memory(ares, res) + || acpi_dev_resource_io(ares, res) + || acpi_dev_resource_address_space(ares, &win) + || acpi_dev_resource_ext_address_space(ares, &win)) + return acpi_dev_new_resource_entry(&win, c); - for (i = 0; acpi_dev_resource_interrupt(ares, i, &r); i++) { + for (i = 0; acpi_dev_resource_interrupt(ares, i, res); i++) { acpi_status status; - status = acpi_dev_new_resource_entry(&r, c); + status = acpi_dev_new_resource_entry(&win, c); if (ACPI_FAILURE(status)) return status; } diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 2d9bc789af0f..ff0356fb378f 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -180,20 +180,21 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, struct pnp_dev *dev = data; struct acpi_resource_dma *dma; struct acpi_resource_vendor_typed *vendor_typed; - struct resource r = {0}; + struct resource_win win = {{0}, 0}; + struct resource *r = &win.res; int i, flags; - if (acpi_dev_resource_address_space(res, &r) - || acpi_dev_resource_ext_address_space(res, &r)) { - pnp_add_resource(dev, &r); + if (acpi_dev_resource_address_space(res, &win) + || acpi_dev_resource_ext_address_space(res, &win)) { + pnp_add_resource(dev, &win.res); return AE_OK; } - r.flags = 0; - if (acpi_dev_resource_interrupt(res, 0, &r)) { - pnpacpi_add_irqresource(dev, &r); - for (i = 1; acpi_dev_resource_interrupt(res, i, &r); i++) - pnpacpi_add_irqresource(dev, &r); + r->flags = 0; + if (acpi_dev_resource_interrupt(res, 0, r)) { + pnpacpi_add_irqresource(dev, r); + for (i = 1; acpi_dev_resource_interrupt(res, i, r); i++) + pnpacpi_add_irqresource(dev, r); if (i > 1) { /* @@ -209,7 +210,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, } } return AE_OK; - } else if (r.flags & IORESOURCE_DISABLED) { + } else if (r->flags & IORESOURCE_DISABLED) { pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED); return AE_OK; } @@ -218,13 +219,13 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_MEMORY24: case ACPI_RESOURCE_TYPE_MEMORY32: case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: - if (acpi_dev_resource_memory(res, &r)) - pnp_add_resource(dev, &r); + if (acpi_dev_resource_memory(res, r)) + pnp_add_resource(dev, r); break; case ACPI_RESOURCE_TYPE_IO: case ACPI_RESOURCE_TYPE_FIXED_IO: - if (acpi_dev_resource_io(res, &r)) - pnp_add_resource(dev, &r); + if (acpi_dev_resource_io(res, r)) + pnp_add_resource(dev, r); break; case ACPI_RESOURCE_TYPE_DMA: dma = &res->data.dma; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index d459cd17b477..be9eaee8f4ae 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -285,12 +285,17 @@ extern int pnpacpi_disabled; #define PXM_INVAL (-1) +struct resource_win { + struct resource res; + resource_size_t offset; +}; + bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res); bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res); bool acpi_dev_resource_address_space(struct acpi_resource *ares, - struct resource *res); + struct resource_win *win); bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, - struct resource *res); + struct resource_win *win); unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable); bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, struct resource *res); -- cgit v1.2.3 From 2ea3d266bab3b497238113b20136f7c3f69ad9c0 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Feb 2015 10:42:59 +0800 Subject: ACPI: Translate resource into master side address for bridge window resources Add translation_offset into the result address for bridge window resources to form the master side address. Currently acpi_dev_resource_{ext_}address_space() are only used for devices instead of bridges, so it won't break current users. Later it will be used to support PCI host bridge drivers. Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index c902c8eece81..4dc8cfb2e94e 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -205,6 +205,21 @@ static bool acpi_decode_space(struct resource_win *win, res->start = attr->minimum; res->end = attr->maximum; + /* + * For bridges that translate addresses across the bridge, + * translation_offset is the offset that must be added to the + * address on the secondary side to obtain the address on the + * primary side. Non-bridge devices must list 0 for all Address + * Translation offset bits. + */ + if (addr->producer_consumer == ACPI_PRODUCER) { + res->start += attr->translation_offset; + res->end += attr->translation_offset; + } else if (attr->translation_offset) { + pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n", + attr->translation_offset); + } + switch (addr->resource_type) { case ACPI_MEMORY_RANGE: acpi_dev_memresource_flags(res, len, wp); -- cgit v1.2.3 From 93286f4798590e711aa395503401f8632fb74f9a Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Feb 2015 10:43:00 +0800 Subject: ACPI: Add field offset to struct resource_list_entry Add field offset to struct resource_list_entry to host address space translation offset so it could be used to represent bridge resources. Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 1 + include/linux/acpi.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 4dc8cfb2e94e..1c3abae6f2fa 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -472,6 +472,7 @@ static acpi_status acpi_dev_new_resource_entry(struct resource_win *win, return AE_NO_MEMORY; } rentry->res = win->res; + rentry->offset = win->offset; list_add_tail(&rentry->node, c->list); c->count++; return AE_OK; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index be9eaee8f4ae..21dac3cb62d2 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -303,6 +303,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, struct resource_list_entry { struct list_head node; struct resource res; + resource_size_t offset; }; void acpi_dev_free_resource_list(struct list_head *list); -- cgit v1.2.3 From 62d1141ff34e35de496ba06491c8e854b23b3f3e Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 2 Feb 2015 10:43:01 +0800 Subject: ACPI: Introduce helper function acpi_dev_filter_resource_type() Introduce helper function acpi_dev_filter_resource_type(), which may be used by acpi_dev_get_resources() to filer out resource based on resource type. Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/resource.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 8 +++++++ 2 files changed, 63 insertions(+) (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 1c3abae6f2fa..3ea0d17eb951 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -569,3 +569,58 @@ int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list, return c.count; } EXPORT_SYMBOL_GPL(acpi_dev_get_resources); + +/** + * acpi_dev_filter_resource_type - Filter ACPI resource according to resource + * types + * @ares: Input ACPI resource object. + * @types: Valid resource types of IORESOURCE_XXX + * + * This is a hepler function to support acpi_dev_get_resources(), which filters + * ACPI resource objects according to resource types. + */ +int acpi_dev_filter_resource_type(struct acpi_resource *ares, + unsigned long types) +{ + unsigned long type = 0; + + switch (ares->type) { + case ACPI_RESOURCE_TYPE_MEMORY24: + case ACPI_RESOURCE_TYPE_MEMORY32: + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + type = IORESOURCE_MEM; + break; + case ACPI_RESOURCE_TYPE_IO: + case ACPI_RESOURCE_TYPE_FIXED_IO: + type = IORESOURCE_IO; + break; + case ACPI_RESOURCE_TYPE_IRQ: + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + type = IORESOURCE_IRQ; + break; + case ACPI_RESOURCE_TYPE_DMA: + case ACPI_RESOURCE_TYPE_FIXED_DMA: + type = IORESOURCE_DMA; + break; + case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: + type = IORESOURCE_REG; + break; + case ACPI_RESOURCE_TYPE_ADDRESS16: + case ACPI_RESOURCE_TYPE_ADDRESS32: + case ACPI_RESOURCE_TYPE_ADDRESS64: + case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: + if (ares->data.address.resource_type == ACPI_MEMORY_RANGE) + type = IORESOURCE_MEM; + else if (ares->data.address.resource_type == ACPI_IO_RANGE) + type = IORESOURCE_IO; + else if (ares->data.address.resource_type == + ACPI_BUS_NUMBER_RANGE) + type = IORESOURCE_BUS; + break; + default: + break; + } + + return (type & types) ? 0 : 1; +} +EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 21dac3cb62d2..e818decb631f 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -310,6 +310,14 @@ void acpi_dev_free_resource_list(struct list_head *list); int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list, int (*preproc)(struct acpi_resource *, void *), void *preproc_data); +int acpi_dev_filter_resource_type(struct acpi_resource *ares, + unsigned long types); + +static inline int acpi_dev_filter_resource_type_cb(struct acpi_resource *ares, + void *arg) +{ + return acpi_dev_filter_resource_type(ares, (unsigned long)arg); +} int acpi_check_resource_conflict(const struct resource *res); -- cgit v1.2.3 From 90e97820619dc912b52cc9d103272819d8b51259 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Thu, 5 Feb 2015 13:44:43 +0800 Subject: resources: Move struct resource_list_entry from ACPI into resource core Currently ACPI, PCI and pnp all implement the same resource list management with different data structure. We need to transfer from one data structure into another when passing resources from one subsystem into another subsystem. So move struct resource_list_entry from ACPI into resource core and rename it as resource_entry, then it could be reused by different subystems and avoid the data structure conversion. Introduce dedicated header file resource_ext.h instead of embedding it into ioport.h to avoid header file inclusion order issues. Signed-off-by: Jiang Liu Acked-by: Vinod Koul Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 8 ++--- drivers/acpi/acpi_platform.c | 4 +-- drivers/acpi/resource.c | 17 ++++------ drivers/dma/acpi-dma.c | 10 +++--- include/linux/acpi.h | 12 +------ include/linux/resource_ext.h | 77 ++++++++++++++++++++++++++++++++++++++++++++ kernel/resource.c | 25 ++++++++++++++ 7 files changed, 120 insertions(+), 33 deletions(-) create mode 100644 include/linux/resource_ext.h (limited to 'drivers/acpi/resource.c') diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 4f3febf8a589..dfd1b8095dad 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -313,7 +313,7 @@ static int acpi_lpss_create_device(struct acpi_device *adev, { struct lpss_device_desc *dev_desc; struct lpss_private_data *pdata; - struct resource_list_entry *rentry; + struct resource_entry *rentry; struct list_head resource_list; struct platform_device *pdev; int ret; @@ -333,12 +333,12 @@ static int acpi_lpss_create_device(struct acpi_device *adev, goto err_out; list_for_each_entry(rentry, &resource_list, node) - if (resource_type(&rentry->res) == IORESOURCE_MEM) { + if (resource_type(rentry->res) == IORESOURCE_MEM) { if (dev_desc->prv_size_override) pdata->mmio_size = dev_desc->prv_size_override; else - pdata->mmio_size = resource_size(&rentry->res); - pdata->mmio_base = ioremap(rentry->res.start, + pdata->mmio_size = resource_size(rentry->res); + pdata->mmio_base = ioremap(rentry->res->start, pdata->mmio_size); break; } diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 6ba8beb6b9d2..1284138e42ab 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -45,7 +45,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev) struct platform_device *pdev = NULL; struct acpi_device *acpi_parent; struct platform_device_info pdevinfo; - struct resource_list_entry *rentry; + struct resource_entry *rentry; struct list_head resource_list; struct resource *resources = NULL; int count; @@ -71,7 +71,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev) } count = 0; list_for_each_entry(rentry, &resource_list, node) - resources[count++] = rentry->res; + resources[count++] = *rentry->res; acpi_dev_free_resource_list(&resource_list); } diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 3ea0d17eb951..4752b9939987 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -444,12 +444,7 @@ EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt); */ void acpi_dev_free_resource_list(struct list_head *list) { - struct resource_list_entry *rentry, *re; - - list_for_each_entry_safe(rentry, re, list, node) { - list_del(&rentry->node); - kfree(rentry); - } + resource_list_free(list); } EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list); @@ -464,16 +459,16 @@ struct res_proc_context { static acpi_status acpi_dev_new_resource_entry(struct resource_win *win, struct res_proc_context *c) { - struct resource_list_entry *rentry; + struct resource_entry *rentry; - rentry = kmalloc(sizeof(*rentry), GFP_KERNEL); + rentry = resource_list_create_entry(NULL, 0); if (!rentry) { c->error = -ENOMEM; return AE_NO_MEMORY; } - rentry->res = win->res; + *rentry->res = win->res; rentry->offset = win->offset; - list_add_tail(&rentry->node, c->list); + resource_list_add_tail(rentry, c->list); c->count++; return AE_OK; } @@ -534,7 +529,7 @@ static acpi_status acpi_dev_process_resource(struct acpi_resource *ares, * returned as the final error code. * * The resultant struct resource objects are put on the list pointed to by - * @list, that must be empty initially, as members of struct resource_list_entry + * @list, that must be empty initially, as members of struct resource_entry * objects. Callers of this routine should use %acpi_dev_free_resource_list() to * free that list. * diff --git a/drivers/dma/acpi-dma.c b/drivers/dma/acpi-dma.c index de361a156b34..5a635646e05c 100644 --- a/drivers/dma/acpi-dma.c +++ b/drivers/dma/acpi-dma.c @@ -43,7 +43,7 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp, { const struct acpi_csrt_shared_info *si; struct list_head resource_list; - struct resource_list_entry *rentry; + struct resource_entry *rentry; resource_size_t mem = 0, irq = 0; int ret; @@ -56,10 +56,10 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp, return 0; list_for_each_entry(rentry, &resource_list, node) { - if (resource_type(&rentry->res) == IORESOURCE_MEM) - mem = rentry->res.start; - else if (resource_type(&rentry->res) == IORESOURCE_IRQ) - irq = rentry->res.start; + if (resource_type(rentry->res) == IORESOURCE_MEM) + mem = rentry->res->start; + else if (resource_type(rentry->res) == IORESOURCE_IRQ) + irq = rentry->res->start; } acpi_dev_free_resource_list(&resource_list); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index e818decb631f..e53822148b6a 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -27,6 +27,7 @@ #include #include /* for struct resource */ +#include #include #include @@ -285,11 +286,6 @@ extern int pnpacpi_disabled; #define PXM_INVAL (-1) -struct resource_win { - struct resource res; - resource_size_t offset; -}; - bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res); bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res); bool acpi_dev_resource_address_space(struct acpi_resource *ares, @@ -300,12 +296,6 @@ unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable); bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, struct resource *res); -struct resource_list_entry { - struct list_head node; - struct resource res; - resource_size_t offset; -}; - void acpi_dev_free_resource_list(struct list_head *list); int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list, int (*preproc)(struct acpi_resource *, void *), diff --git a/include/linux/resource_ext.h b/include/linux/resource_ext.h new file mode 100644 index 000000000000..e2bf63d881d4 --- /dev/null +++ b/include/linux/resource_ext.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2015, Intel Corporation + * Author: Jiang Liu + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ +#ifndef _LINUX_RESOURCE_EXT_H +#define _LINUX_RESOURCE_EXT_H +#include +#include +#include +#include + +/* Represent resource window for bridge devices */ +struct resource_win { + struct resource res; /* In master (CPU) address space */ + resource_size_t offset; /* Translation offset for bridge */ +}; + +/* + * Common resource list management data structure and interfaces to support + * ACPI, PNP and PCI host bridge etc. + */ +struct resource_entry { + struct list_head node; + struct resource *res; /* In master (CPU) address space */ + resource_size_t offset; /* Translation offset for bridge */ + struct resource __res; /* Default storage for res */ +}; + +extern struct resource_entry * +resource_list_create_entry(struct resource *res, size_t extra_size); +extern void resource_list_free(struct list_head *head); + +static inline void resource_list_add(struct resource_entry *entry, + struct list_head *head) +{ + list_add(&entry->node, head); +} + +static inline void resource_list_add_tail(struct resource_entry *entry, + struct list_head *head) +{ + list_add_tail(&entry->node, head); +} + +static inline void resource_list_del(struct resource_entry *entry) +{ + list_del(&entry->node); +} + +static inline void resource_list_free_entry(struct resource_entry *entry) +{ + kfree(entry); +} + +static inline void +resource_list_destroy_entry(struct resource_entry *entry) +{ + resource_list_del(entry); + resource_list_free_entry(entry); +} + +#define resource_list_for_each_entry(entry, list) \ + list_for_each_entry((entry), (list), node) + +#define resource_list_for_each_entry_safe(entry, tmp, list) \ + list_for_each_entry_safe((entry), (tmp), (list), node) + +#endif /* _LINUX_RESOURCE_EXT_H */ diff --git a/kernel/resource.c b/kernel/resource.c index 0bcebffc4e77..19f2357dfda3 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -1529,6 +1530,30 @@ int iomem_is_exclusive(u64 addr) return err; } +struct resource_entry *resource_list_create_entry(struct resource *res, + size_t extra_size) +{ + struct resource_entry *entry; + + entry = kzalloc(sizeof(*entry) + extra_size, GFP_KERNEL); + if (entry) { + INIT_LIST_HEAD(&entry->node); + entry->res = res ? res : &entry->__res; + } + + return entry; +} +EXPORT_SYMBOL(resource_list_create_entry); + +void resource_list_free(struct list_head *head) +{ + struct resource_entry *entry, *tmp; + + list_for_each_entry_safe(entry, tmp, head, node) + resource_list_destroy_entry(entry); +} +EXPORT_SYMBOL(resource_list_free); + static int __init strict_iomem(char *str) { if (strstr(str, "relaxed")) -- cgit v1.2.3