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>wifi-calibration
parent
6b1972493a
commit
d35165a955
|
@ -1942,21 +1942,48 @@ static int dmar_hotplug_remove(acpi_handle handle)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static acpi_status dmar_get_dsm_handle(acpi_handle handle, u32 lvl,
|
||||||
|
void *context, void **retval)
|
||||||
|
{
|
||||||
|
acpi_handle *phdl = retval;
|
||||||
|
|
||||||
|
if (dmar_detect_dsm(handle, DMAR_DSM_FUNC_DRHD)) {
|
||||||
|
*phdl = handle;
|
||||||
|
return AE_CTRL_TERMINATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int dmar_device_hotplug(acpi_handle handle, bool insert)
|
static int dmar_device_hotplug(acpi_handle handle, bool insert)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
acpi_handle tmp = NULL;
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
if (!dmar_in_use())
|
if (!dmar_in_use())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!dmar_detect_dsm(handle, DMAR_DSM_FUNC_DRHD))
|
if (dmar_detect_dsm(handle, DMAR_DSM_FUNC_DRHD)) {
|
||||||
|
tmp = handle;
|
||||||
|
} else {
|
||||||
|
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
|
||||||
|
ACPI_UINT32_MAX,
|
||||||
|
dmar_get_dsm_handle,
|
||||||
|
NULL, NULL, &tmp);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
pr_warn("Failed to locate _DSM method.\n");
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tmp == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
down_write(&dmar_global_lock);
|
down_write(&dmar_global_lock);
|
||||||
if (insert)
|
if (insert)
|
||||||
ret = dmar_hotplug_insert(handle);
|
ret = dmar_hotplug_insert(tmp);
|
||||||
else
|
else
|
||||||
ret = dmar_hotplug_remove(handle);
|
ret = dmar_hotplug_remove(tmp);
|
||||||
up_write(&dmar_global_lock);
|
up_write(&dmar_global_lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in New Issue