summaryrefslogtreecommitdiffstats
path: root/drivers/pnp/pnpacpi/rsparser.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-04-26 16:08:27 +0900
committerPaul Mundt <lethal@linux-sh.org>2010-04-26 16:08:27 +0900
commite19553427c2e8fdb04fdd98e407164bb59a840ba (patch)
tree5332234b2dad07c03c27e4608afb16f297f41e61 /drivers/pnp/pnpacpi/rsparser.c
parent35f6cd4a06432034665a1499ca4b022437423aac (diff)
parent83515bc7df812555e20cda48614674e2f346f9f5 (diff)
downloadop-kernel-dev-e19553427c2e8fdb04fdd98e407164bb59a840ba.zip
op-kernel-dev-e19553427c2e8fdb04fdd98e407164bb59a840ba.tar.gz
Merge branch 'sh/stable-updates'
Conflicts: arch/sh/kernel/dwarf.c drivers/dma/shdma.c Signed-off-by: Paul Mundt <lethal@linux-sh.org>
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 54514aa3..35bb44a 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -24,6 +24,7 @@
#include <linux/acpi.h>
#include <linux/pci.h>
#include <linux/pnp.h>
+#include <linux/slab.h>
#include "../base.h"
#include "pnpacpi.h"
@@ -273,12 +274,33 @@ static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
pnp_add_bus_resource(dev, start, end);
}
+static u64 addr_space_length(struct pnp_dev *dev, u64 min, u64 max, u64 len)
+{
+ u64 max_len;
+
+ max_len = max - min + 1;
+ if (len <= max_len)
+ return len;
+
+ /*
+ * Per 6.4.3.5, _LEN cannot exceed _MAX - _MIN + 1, but some BIOSes
+ * don't do this correctly, e.g.,
+ * https://bugzilla.kernel.org/show_bug.cgi?id=15480
+ */
+ dev_info(&dev->dev,
+ "resource length %#llx doesn't fit in %#llx-%#llx, trimming\n",
+ (unsigned long long) len, (unsigned long long) min,
+ (unsigned long long) max);
+ return max_len;
+}
+
static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
struct acpi_resource *res)
{
struct acpi_resource_address64 addr, *p = &addr;
acpi_status status;
int window;
+ u64 len;
status = acpi_resource_to_address64(res, p);
if (!ACPI_SUCCESS(status)) {
@@ -287,20 +309,18 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
return;
}
+ len = addr_space_length(dev, p->minimum, p->maximum, p->address_length);
window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
if (p->resource_type == ACPI_MEMORY_RANGE)
- pnpacpi_parse_allocated_memresource(dev,
- p->minimum, p->address_length,
+ pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
p->info.mem.write_protect, window);
else if (p->resource_type == ACPI_IO_RANGE)
- pnpacpi_parse_allocated_ioresource(dev,
- p->minimum, p->address_length,
+ pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
p->granularity == 0xfff ? ACPI_DECODE_10 :
ACPI_DECODE_16, window);
else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
- pnpacpi_parse_allocated_busresource(dev, p->minimum,
- p->address_length);
+ pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
}
static 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,
{
struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
int window;
+ u64 len;
+ len = addr_space_length(dev, p->minimum, p->maximum, p->address_length);
window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
if (p->resource_type == ACPI_MEMORY_RANGE)
- pnpacpi_parse_allocated_memresource(dev,
- p->minimum, p->address_length,
+ pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
p->info.mem.write_protect, window);
else if (p->resource_type == ACPI_IO_RANGE)
- pnpacpi_parse_allocated_ioresource(dev,
- p->minimum, p->address_length,
+ pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
p->granularity == 0xfff ? ACPI_DECODE_10 :
ACPI_DECODE_16, window);
else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
- pnpacpi_parse_allocated_busresource(dev, p->minimum,
- p->address_length);
+ pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
}
static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
OpenPOWER on IntegriCloud