diff options
| author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2009-05-21 17:49:59 -0400 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2009-05-27 21:25:00 -0400 |
| commit | 8cb24c8fd70ea8431744de1ca0ca34ab45fbbdaa (patch) | |
| tree | cf7d65c56112edda3fb92d0e61349339753c918e /drivers/pnp | |
| parent | cd86a536c81e9300d984327517548ca0652eebf9 (diff) | |
PNPACPI: parse Extended Address Space Descriptors
Extended Address Space Descriptors are new in ACPI 3.0 and allow the
BIOS to communicate device resource cacheability attributes (write-back,
write-through, uncacheable, etc) to the OS.
Previously, PNPACPI ignored these descriptors, so if a BIOS used them,
a device could be responding at addresses the OS doesn't know about.
This patch adds support for these descriptors in _CRS and _PRS. We
don't attempt to encode them for _SRS (just like we don't attempt to
encode the existing 16-, 32-, and 64-bit Address Space Descriptors).
Unfortunately, I don't have a way to test this.
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/pnp')
| -rw-r--r-- | drivers/pnp/pnpacpi/rsparser.c | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index adf17856bacc..e2a87fcfa6cf 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
| @@ -287,6 +287,25 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, | |||
| 287 | ACPI_DECODE_16); | 287 | ACPI_DECODE_16); |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev, | ||
| 291 | struct acpi_resource *res) | ||
| 292 | { | ||
| 293 | struct acpi_resource_extended_address64 *p = &res->data.ext_address64; | ||
| 294 | |||
| 295 | if (p->producer_consumer == ACPI_PRODUCER) | ||
| 296 | return; | ||
| 297 | |||
| 298 | if (p->resource_type == ACPI_MEMORY_RANGE) | ||
| 299 | pnpacpi_parse_allocated_memresource(dev, | ||
| 300 | p->minimum, p->address_length, | ||
| 301 | p->info.mem.write_protect); | ||
| 302 | else if (p->resource_type == ACPI_IO_RANGE) | ||
| 303 | pnpacpi_parse_allocated_ioresource(dev, | ||
| 304 | p->minimum, p->address_length, | ||
| 305 | p->granularity == 0xfff ? ACPI_DECODE_10 : | ||
| 306 | ACPI_DECODE_16); | ||
| 307 | } | ||
| 308 | |||
| 290 | static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | 309 | static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, |
| 291 | void *data) | 310 | void *data) |
| 292 | { | 311 | { |
| @@ -400,8 +419,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
| 400 | break; | 419 | break; |
| 401 | 420 | ||
| 402 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | 421 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: |
| 403 | if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER) | 422 | pnpacpi_parse_allocated_ext_address_space(dev, res); |
| 404 | return AE_OK; | ||
| 405 | break; | 423 | break; |
| 406 | 424 | ||
| 407 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 425 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
| @@ -630,6 +648,28 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, | |||
| 630 | IORESOURCE_IO_FIXED); | 648 | IORESOURCE_IO_FIXED); |
| 631 | } | 649 | } |
| 632 | 650 | ||
| 651 | static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev, | ||
| 652 | unsigned int option_flags, | ||
| 653 | struct acpi_resource *r) | ||
| 654 | { | ||
| 655 | struct acpi_resource_extended_address64 *p = &r->data.ext_address64; | ||
| 656 | unsigned char flags = 0; | ||
| 657 | |||
| 658 | if (p->address_length == 0) | ||
| 659 | return; | ||
| 660 | |||
| 661 | if (p->resource_type == ACPI_MEMORY_RANGE) { | ||
| 662 | if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) | ||
| 663 | flags = IORESOURCE_MEM_WRITEABLE; | ||
| 664 | pnp_register_mem_resource(dev, option_flags, p->minimum, | ||
| 665 | p->minimum, 0, p->address_length, | ||
| 666 | flags); | ||
| 667 | } else if (p->resource_type == ACPI_IO_RANGE) | ||
| 668 | pnp_register_port_resource(dev, option_flags, p->minimum, | ||
| 669 | p->minimum, 0, p->address_length, | ||
| 670 | IORESOURCE_IO_FIXED); | ||
| 671 | } | ||
| 672 | |||
| 633 | struct acpipnp_parse_option_s { | 673 | struct acpipnp_parse_option_s { |
| 634 | struct pnp_dev *dev; | 674 | struct pnp_dev *dev; |
| 635 | unsigned int option_flags; | 675 | unsigned int option_flags; |
| @@ -711,6 +751,7 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, | |||
| 711 | break; | 751 | break; |
| 712 | 752 | ||
| 713 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | 753 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: |
| 754 | pnpacpi_parse_ext_address_option(dev, option_flags, res); | ||
| 714 | break; | 755 | break; |
| 715 | 756 | ||
| 716 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 757 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
| @@ -765,6 +806,7 @@ static int pnpacpi_supported_resource(struct acpi_resource *res) | |||
| 765 | case ACPI_RESOURCE_TYPE_ADDRESS16: | 806 | case ACPI_RESOURCE_TYPE_ADDRESS16: |
| 766 | case ACPI_RESOURCE_TYPE_ADDRESS32: | 807 | case ACPI_RESOURCE_TYPE_ADDRESS32: |
| 767 | case ACPI_RESOURCE_TYPE_ADDRESS64: | 808 | case ACPI_RESOURCE_TYPE_ADDRESS64: |
| 809 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | ||
| 768 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 810 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
| 769 | return 1; | 811 | return 1; |
| 770 | } | 812 | } |
