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 | } |