aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/pnpacpi/rsparser.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pnp/pnpacpi/rsparser.c')
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 54514aa35b09..35bb44af49b3 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -24,6 +24,7 @@
24#include <linux/acpi.h> 24#include <linux/acpi.h>
25#include <linux/pci.h> 25#include <linux/pci.h>
26#include <linux/pnp.h> 26#include <linux/pnp.h>
27#include <linux/slab.h>
27#include "../base.h" 28#include "../base.h"
28#include "pnpacpi.h" 29#include "pnpacpi.h"
29 30
@@ -273,12 +274,33 @@ static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
273 pnp_add_bus_resource(dev, start, end); 274 pnp_add_bus_resource(dev, start, end);
274} 275}
275 276
277static u64 addr_space_length(struct pnp_dev *dev, u64 min, u64 max, u64 len)
278{
279 u64 max_len;
280
281 max_len = max - min + 1;
282 if (len <= max_len)
283 return len;
284
285 /*
286 * Per 6.4.3.5, _LEN cannot exceed _MAX - _MIN + 1, but some BIOSes
287 * don't do this correctly, e.g.,
288 * https://bugzilla.kernel.org/show_bug.cgi?id=15480
289 */
290 dev_info(&dev->dev,
291 "resource length %#llx doesn't fit in %#llx-%#llx, trimming\n",
292 (unsigned long long) len, (unsigned long long) min,
293 (unsigned long long) max);
294 return max_len;
295}
296
276static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, 297static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
277 struct acpi_resource *res) 298 struct acpi_resource *res)
278{ 299{
279 struct acpi_resource_address64 addr, *p = &addr; 300 struct acpi_resource_address64 addr, *p = &addr;
280 acpi_status status; 301 acpi_status status;
281 int window; 302 int window;
303 u64 len;
282 304
283 status = acpi_resource_to_address64(res, p); 305 status = acpi_resource_to_address64(res, p);
284 if (!ACPI_SUCCESS(status)) { 306 if (!ACPI_SUCCESS(status)) {
@@ -287,20 +309,18 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
287 return; 309 return;
288 } 310 }
289 311
312 len = addr_space_length(dev, p->minimum, p->maximum, p->address_length);
290 window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0; 313 window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
291 314
292 if (p->resource_type == ACPI_MEMORY_RANGE) 315 if (p->resource_type == ACPI_MEMORY_RANGE)
293 pnpacpi_parse_allocated_memresource(dev, 316 pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
294 p->minimum, p->address_length,
295 p->info.mem.write_protect, window); 317 p->info.mem.write_protect, window);
296 else if (p->resource_type == ACPI_IO_RANGE) 318 else if (p->resource_type == ACPI_IO_RANGE)
297 pnpacpi_parse_allocated_ioresource(dev, 319 pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
298 p->minimum, p->address_length,
299 p->granularity == 0xfff ? ACPI_DECODE_10 : 320 p->granularity == 0xfff ? ACPI_DECODE_10 :
300 ACPI_DECODE_16, window); 321 ACPI_DECODE_16, window);
301 else if (p->resource_type == ACPI_BUS_NUMBER_RANGE) 322 else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
302 pnpacpi_parse_allocated_busresource(dev, p->minimum, 323 pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
303 p->address_length);
304} 324}
305 325
306static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev, 326static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
@@ -308,21 +328,20 @@ static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
308{ 328{
309 struct acpi_resource_extended_address64 *p = &res->data.ext_address64; 329 struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
310 int window; 330 int window;
331 u64 len;
311 332
333 len = addr_space_length(dev, p->minimum, p->maximum, p->address_length);
312 window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0; 334 window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
313 335
314 if (p->resource_type == ACPI_MEMORY_RANGE) 336 if (p->resource_type == ACPI_MEMORY_RANGE)
315 pnpacpi_parse_allocated_memresource(dev, 337 pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
316 p->minimum, p->address_length,
317 p->info.mem.write_protect, window); 338 p->info.mem.write_protect, window);
318 else if (p->resource_type == ACPI_IO_RANGE) 339 else if (p->resource_type == ACPI_IO_RANGE)
319 pnpacpi_parse_allocated_ioresource(dev, 340 pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
320 p->minimum, p->address_length,
321 p->granularity == 0xfff ? ACPI_DECODE_10 : 341 p->granularity == 0xfff ? ACPI_DECODE_10 :
322 ACPI_DECODE_16, window); 342 ACPI_DECODE_16, window);
323 else if (p->resource_type == ACPI_BUS_NUMBER_RANGE) 343 else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
324 pnpacpi_parse_allocated_busresource(dev, p->minimum, 344 pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
325 p->address_length);
326} 345}
327 346
328static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, 347static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,