Skip to content

Commit

Permalink
PNPACPI: compute Address Space length rather than using _LEN
Browse files Browse the repository at this point in the history
ACPI _CRS Address Space Descriptors have _MIN, _MAX, and _LEN.  Linux has
been computing Address Spaces as [_MIN to _MIN + _LEN - 1].  Based on the
tests in the bug reports below, Windows apparently uses [_MIN to _MAX].

Per spec (ACPI 4.0, Table 6-40), for _CRS fixed-size, fixed location
descriptors, "_LEN must be (_MAX - _MIN + 1)", and when that's true, it
doesn't matter which way we compute the end.  But of course, there are
BIOSes that don't follow this rule, and we're better off if Linux handles
those exceptions the same way as Windows.

This patch makes Linux use [_MIN to _MAX], as Windows seems to do.  This
effectively reverts 3162b6f and replaces it with simpler code.

    https://bugzilla.kernel.org/show_bug.cgi?id=14337 (round)
    https://bugzilla.kernel.org/show_bug.cgi?id=15480 (truncate)

Signed-off-by: Bjorn Helgaas <[email protected]>
Signed-off-by: Len Brown <[email protected]>
  • Loading branch information
Bjorn Helgaas authored and lenb committed Apr 29, 2010
1 parent 01bf0b6 commit f238b41
Showing 1 changed file with 4 additions and 22 deletions.
26 changes: 4 additions & 22 deletions drivers/pnp/pnpacpi/rsparser.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,26 +274,6 @@ 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)
{
Expand All @@ -309,7 +289,8 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
return;
}

len = addr_space_length(dev, p->minimum, p->maximum, p->address_length);
/* Windows apparently computes length rather than using _LEN */
len = p->maximum - p->minimum + 1;
window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;

if (p->resource_type == ACPI_MEMORY_RANGE)
Expand All @@ -330,7 +311,8 @@ static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
int window;
u64 len;

len = addr_space_length(dev, p->minimum, p->maximum, p->address_length);
/* Windows apparently computes length rather than using _LEN */
len = p->maximum - p->minimum + 1;
window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;

if (p->resource_type == ACPI_MEMORY_RANGE)
Expand Down

0 comments on commit f238b41

Please sign in to comment.