|
@@ -1942,21 +1942,48 @@ static int dmar_hotplug_remove(acpi_handle handle)
|
|
|
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)
|
|
|
{
|
|
|
int ret;
|
|
|
+ acpi_handle tmp = NULL;
|
|
|
+ acpi_status status;
|
|
|
|
|
|
if (!dmar_in_use())
|
|
|
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;
|
|
|
|
|
|
down_write(&dmar_global_lock);
|
|
|
if (insert)
|
|
|
- ret = dmar_hotplug_insert(handle);
|
|
|
+ ret = dmar_hotplug_insert(tmp);
|
|
|
else
|
|
|
- ret = dmar_hotplug_remove(handle);
|
|
|
+ ret = dmar_hotplug_remove(tmp);
|
|
|
up_write(&dmar_global_lock);
|
|
|
|
|
|
return ret;
|