diff options
author | Jiang Liu <jiang.liu@linux.intel.com> | 2014-11-09 09:47:59 -0500 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2014-11-18 05:18:36 -0500 |
commit | d35165a955f095095cdb8512cb7cd8f63101649a (patch) | |
tree | ca0bb611b16966cc5c5daf52b5821f401454c5e5 /drivers/iommu/dmar.c | |
parent | 6b1972493a84f8fe13ff9d202745590f6c53d670 (diff) |
iommu/vt-d: Search for ACPI _DSM method for DMAR hotplug
According to Intel VT-d specification, _DSM method to support DMAR
hotplug should exist directly under corresponding ACPI object
representing PCI host bridge. But some BIOSes doesn't conform to
this, so search for _DSM method in the subtree starting from the
ACPI object representing the PCI host bridge.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Reviewed-by: Yijing Wang <wangyijing@huawei.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/dmar.c')
-rw-r--r-- | drivers/iommu/dmar.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 0bd536d769a9..9847613085e1 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c | |||
@@ -1942,21 +1942,48 @@ static int dmar_hotplug_remove(acpi_handle handle) | |||
1942 | return ret; | 1942 | return ret; |
1943 | } | 1943 | } |
1944 | 1944 | ||
1945 | static acpi_status dmar_get_dsm_handle(acpi_handle handle, u32 lvl, | ||
1946 | void *context, void **retval) | ||
1947 | { | ||
1948 | acpi_handle *phdl = retval; | ||
1949 | |||
1950 | if (dmar_detect_dsm(handle, DMAR_DSM_FUNC_DRHD)) { | ||
1951 | *phdl = handle; | ||
1952 | return AE_CTRL_TERMINATE; | ||
1953 | } | ||
1954 | |||
1955 | return AE_OK; | ||
1956 | } | ||
1957 | |||
1945 | static int dmar_device_hotplug(acpi_handle handle, bool insert) | 1958 | static int dmar_device_hotplug(acpi_handle handle, bool insert) |
1946 | { | 1959 | { |
1947 | int ret; | 1960 | int ret; |
1961 | acpi_handle tmp = NULL; | ||
1962 | acpi_status status; | ||
1948 | 1963 | ||
1949 | if (!dmar_in_use()) | 1964 | if (!dmar_in_use()) |
1950 | return 0; | 1965 | return 0; |
1951 | 1966 | ||
1952 | if (!dmar_detect_dsm(handle, DMAR_DSM_FUNC_DRHD)) | 1967 | if (dmar_detect_dsm(handle, DMAR_DSM_FUNC_DRHD)) { |
1968 | tmp = handle; | ||
1969 | } else { | ||
1970 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | ||
1971 | ACPI_UINT32_MAX, | ||
1972 | dmar_get_dsm_handle, | ||
1973 | NULL, NULL, &tmp); | ||
1974 | if (ACPI_FAILURE(status)) { | ||
1975 | pr_warn("Failed to locate _DSM method.\n"); | ||
1976 | return -ENXIO; | ||
1977 | } | ||
1978 | } | ||
1979 | if (tmp == NULL) | ||
1953 | return 0; | 1980 | return 0; |
1954 | 1981 | ||
1955 | down_write(&dmar_global_lock); | 1982 | down_write(&dmar_global_lock); |
1956 | if (insert) | 1983 | if (insert) |
1957 | ret = dmar_hotplug_insert(handle); | 1984 | ret = dmar_hotplug_insert(tmp); |
1958 | else | 1985 | else |
1959 | ret = dmar_hotplug_remove(handle); | 1986 | ret = dmar_hotplug_remove(tmp); |
1960 | up_write(&dmar_global_lock); | 1987 | up_write(&dmar_global_lock); |
1961 | 1988 | ||
1962 | return ret; | 1989 | return ret; |