Fix acpi_memory_get_device(). A case of "memory object is not onlined at boot time but hot-added" is managed. Signed-Off-By: KAMEZAWA Hiroyuki Index: linux-2.6.14-mm1/drivers/acpi/acpi_memhotplug.c =================================================================== --- linux-2.6.14-mm1.orig/drivers/acpi/acpi_memhotplug.c +++ linux-2.6.14-mm1/drivers/acpi/acpi_memhotplug.c @@ -77,6 +77,24 @@ struct acpi_memory_device { u64 end_addr; /* Memory Range end physical addr */ }; +/* Maybe the same function in acpi_contaiener.c should be exported ..*/ +#define ACPI_STA_PRESENT (0x00000001) +static int is_memory_device_present(acpi_handle handle) +{ + acpi_status status; + unsigned long sta; + acpi_handle temp; + ACPI_FUNCTION_TRACE("is_memory_device_present"); + status = acpi_get_handle(handle, "_STA", &temp); + if (ACPI_FAILURE(status)) + return_VALUE(1); /* _STA not found, assume present */ + status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); + if (ACPI_FAILURE(status)) + return_VALUE(0); + return_VALUE((sta & ACPI_STA_PRESENT) == ACPI_STA_PRESENT); +} + + static int acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) { @@ -112,18 +130,14 @@ acpi_memory_get_device_resources(struct static int acpi_memory_get_device(acpi_handle handle, - struct acpi_memory_device **mem_device) + struct acpi_device **device) { acpi_status status; acpi_handle phandle; - struct acpi_device *device = NULL; struct acpi_device *pdevice = NULL; ACPI_FUNCTION_TRACE("acpi_memory_get_device"); - if (!acpi_bus_get_device(handle, &device) && device) - goto end; - status = acpi_get_parent(handle, &phandle); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error in acpi_get_parent\n")); @@ -138,23 +152,12 @@ acpi_memory_get_device(acpi_handle handl return_VALUE(-EINVAL); } - /* - * Now add the notified device. This creates the acpi_device - * and invokes .add function - */ - status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); + status = acpi_bus_add(device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error in acpi_bus_add\n")); return_VALUE(-EINVAL); } - end: - *mem_device = acpi_driver_data(device); - if (!(*mem_device)) { - printk(KERN_ERR "\n driver data not found"); - return_VALUE(-ENODEV); - } - return_VALUE(0); } @@ -282,9 +285,11 @@ static void acpi_memory_device_notify(ac { struct acpi_memory_device *mem_device; struct acpi_device *device; + acpi_status status; + int present; ACPI_FUNCTION_TRACE("acpi_memory_device_notify"); - + present = is_memory_device_present(handle); switch (event) { case ACPI_NOTIFY_BUS_CHECK: ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -294,12 +299,26 @@ static void acpi_memory_device_notify(ac if (event == ACPI_NOTIFY_DEVICE_CHECK) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "\nReceived DEVICE CHECK notification for device\n")); - if (acpi_memory_get_device(handle, &mem_device)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + status = acpi_bus_get_device(handle, &device); + if (ACPI_FAILURE(status) || !device) { + if (present) { + status = acpi_memory_get_device(handle, &device); + if (ACPI_FAILURE(status) || !device) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error in finding driver data\n")); + return_VOID; + } + } else { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "notified handle seems not present")); + return_VOID; + } + } + mem_device = acpi_driver_data(device); + if (!mem_device) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "error acpi_memhotplug: device has no mem_device")); return_VOID; } - if (!acpi_memory_check_device(mem_device)) { if (acpi_memory_enable_device(mem_device)) ACPI_DEBUG_PRINT((ACPI_DB_ERROR,