diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-06-15 18:36:26 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-06-19 19:24:29 -0400 |
commit | 66345d5f79fcfa0214f5d98763643d4ee8e6965d (patch) | |
tree | 54e0765b867681dc85c6422a048e1c9a0ae25bd9 | |
parent | d9e455f53f6fb93c764de2399c3894bbdfd2caa7 (diff) |
ACPI / ia64 / sba_iommu: Use ACPI scan handler for device discovery
The IA64 System Bus Adapter (SBA) I/O MMU driver uses an ACPI driver
object to look for device objects it needs in the ACPI namespace, but
that leads to an ordering issue between that driver and the container
scan handler on ia64 HP rx2600.
Namely, on that machine the SBA I/O MMU device object in the ACPI
namespace has a _HID returning its own specific device ID and a
_CID returning a generic container device ID. According to Toshi
Kani, the idea is that if a _HID is not mached by an I/O MMU driver,
the _CID should be matched by a generic container driver, so those
device IDs should be used mutually exclusively.
That is not what happens, however, because the container driver uses
an ACPI scan handler which is matched against the device object in
question before registering the SBA I/O MMU driver object. As a
result, that scan handler claims the device object first. The driver
binds to the same device object later, however, and they both happily
use it simultaneously going forward (fortunately, that doesn't cause
any real breakage to happen).
To avoid that ordering issue, make the SBA I/O MMU code use an ACPI
scan handler instead of an ACPI driver, so that it can claim the SBA
I/O MMU device object before the container driver (thanks to an
improved algorithm of matching ACPI device IDs used for ACPI scan
handlers, which matches device _HIDs against the registered scan
handlers before _CIDs).
This also reduces the kernel's memory footprint slightly by
avoiding to register a driver object that's not used after system
initialization, so having it registered (and present in sysfs)
throughout the system's life time isn't particularly useful.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Tony Luck <tony.luck@gmail.com>
Acked-by: Toshi Kani <toshi.kani@hp.com>
-rw-r--r-- | arch/ia64/hp/common/sba_iommu.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index bcda5b2d121a..d43daf192b21 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c | |||
@@ -2042,7 +2042,8 @@ sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle) | |||
2042 | #endif | 2042 | #endif |
2043 | 2043 | ||
2044 | static int __init | 2044 | static int __init |
2045 | acpi_sba_ioc_add(struct acpi_device *device) | 2045 | acpi_sba_ioc_add(struct acpi_device *device, |
2046 | const struct acpi_device_id *not_used) | ||
2046 | { | 2047 | { |
2047 | struct ioc *ioc; | 2048 | struct ioc *ioc; |
2048 | acpi_status status; | 2049 | acpi_status status; |
@@ -2090,14 +2091,18 @@ static const struct acpi_device_id hp_ioc_iommu_device_ids[] = { | |||
2090 | {"HWP0004", 0}, | 2091 | {"HWP0004", 0}, |
2091 | {"", 0}, | 2092 | {"", 0}, |
2092 | }; | 2093 | }; |
2093 | static struct acpi_driver acpi_sba_ioc_driver = { | 2094 | static struct acpi_scan_handler acpi_sba_ioc_handler = { |
2094 | .name = "IOC IOMMU Driver", | 2095 | .ids = hp_ioc_iommu_device_ids, |
2095 | .ids = hp_ioc_iommu_device_ids, | 2096 | .attach = acpi_sba_ioc_add, |
2096 | .ops = { | ||
2097 | .add = acpi_sba_ioc_add, | ||
2098 | }, | ||
2099 | }; | 2097 | }; |
2100 | 2098 | ||
2099 | static int __init acpi_sba_ioc_init_acpi(void) | ||
2100 | { | ||
2101 | return acpi_scan_add_handler(&acpi_sba_ioc_handler); | ||
2102 | } | ||
2103 | /* This has to run before acpi_scan_init(). */ | ||
2104 | arch_initcall(acpi_sba_ioc_init_acpi); | ||
2105 | |||
2101 | extern struct dma_map_ops swiotlb_dma_ops; | 2106 | extern struct dma_map_ops swiotlb_dma_ops; |
2102 | 2107 | ||
2103 | static int __init | 2108 | static int __init |
@@ -2122,7 +2127,10 @@ sba_init(void) | |||
2122 | } | 2127 | } |
2123 | #endif | 2128 | #endif |
2124 | 2129 | ||
2125 | acpi_bus_register_driver(&acpi_sba_ioc_driver); | 2130 | /* |
2131 | * ioc_list should be populated by the acpi_sba_ioc_handler's .attach() | ||
2132 | * routine, but that only happens if acpi_scan_init() has already run. | ||
2133 | */ | ||
2126 | if (!ioc_list) { | 2134 | if (!ioc_list) { |
2127 | #ifdef CONFIG_IA64_GENERIC | 2135 | #ifdef CONFIG_IA64_GENERIC |
2128 | /* | 2136 | /* |