return 0;
 }
 
-static int
-acpi_memory_get_device(acpi_handle handle,
-                      struct acpi_memory_device **mem_device)
+static int acpi_memory_get_device(acpi_handle handle,
+                                 struct acpi_memory_device **mem_device)
 {
        struct acpi_device *device = NULL;
-       int result;
+       int result = 0;
 
-       if (!acpi_bus_get_device(handle, &device) && device)
+       acpi_scan_lock_acquire();
+
+       acpi_bus_get_device(handle, &device);
+       if (device)
                goto end;
 
        /*
         */
        result = acpi_bus_scan(handle);
        if (result) {
-               acpi_handle_warn(handle, "Cannot add acpi bus\n");
-               return -EINVAL;
+               acpi_handle_warn(handle, "ACPI namespace scan failed\n");
+               result = -EINVAL;
+               goto out;
        }
        result = acpi_bus_get_device(handle, &device);
        if (result) {
                acpi_handle_warn(handle, "Missing device object\n");
-               return -EINVAL;
+               result = -EINVAL;
+               goto out;
        }
 
-      end:
+ end:
        *mem_device = acpi_driver_data(device);
        if (!(*mem_device)) {
                dev_err(&device->dev, "driver data not found\n");
-               return -ENODEV;
+               result = -ENODEV;
+               goto out;
        }
 
-       return 0;
+ out:
+       acpi_scan_lock_release();
+       return result;
 }
 
 static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
        struct acpi_device *device;
        struct acpi_eject_event *ej_event = NULL;
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
+       acpi_status status;
 
        switch (event) {
        case ACPI_NOTIFY_BUS_CHECK:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "\nReceived EJECT REQUEST notification for device\n"));
 
+               status = AE_ERROR;
+               acpi_scan_lock_acquire();
+
                if (acpi_bus_get_device(handle, &device)) {
                        acpi_handle_err(handle, "Device doesn't exist\n");
-                       break;
+                       goto unlock;
                }
                mem_device = acpi_driver_data(device);
                if (!mem_device) {
                        acpi_handle_err(handle, "Driver Data is NULL\n");
-                       break;
+                       goto unlock;
                }
 
                ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
                if (!ej_event) {
                        pr_err(PREFIX "No memory, dropping EJECT\n");
-                       break;
+                       goto unlock;
                }
 
+               get_device(&device->dev);
                ej_event->device = device;
                ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
-               acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
-                                       (void *)ej_event);
+               /* The eject is carried out asynchronously. */
+               status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
+                                                ej_event);
+               if (ACPI_FAILURE(status)) {
+                       put_device(&device->dev);
+                       kfree(ej_event);
+               }
 
-               /* eject is performed asynchronously */
-               return;
+ unlock:
+               acpi_scan_lock_release();
+               if (ACPI_SUCCESS(status))
+                       return;
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Unsupported event [0x%x]\n", event));
 
        /* Inform firmware that the hotplug operation has completed */
        (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL);
-       return;
 }
 
 static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
 
        acpi_status status;
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
 
+       acpi_scan_lock_acquire();
+
        switch (type) {
        case ACPI_NOTIFY_BUS_CHECK:
                /* Fall through */
                                /* device exist and this is a remove request */
                                device->flags.eject_pending = 1;
                                kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
-                               return;
+                               goto out;
                        }
                        break;
                }
                if (!acpi_bus_get_device(handle, &device) && device) {
                        device->flags.eject_pending = 1;
                        kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
-                       return;
+                       goto out;
                }
                break;
 
        default:
                /* non-hotplug event; possibly handled by other handler */
-               return;
+               goto out;
        }
 
        /* Inform firmware that the hotplug operation has completed */
        (void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-       return;
+
+ out:
+       acpi_scan_lock_release();
 }
 
 static bool is_container(acpi_handle handle)
 
 {
        struct dock_data *data = context;
 
+       acpi_scan_lock_acquire();
        dock_notify(data->handle, data->event, data->ds);
+       acpi_scan_lock_release();
        kfree(data);
 }
 
        if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
           && event != ACPI_NOTIFY_EJECT_REQUEST)
                return 0;
+
+       acpi_scan_lock_acquire();
+
        list_for_each_entry(dock_station, &dock_stations, sibling) {
                if (dock_station->handle == handle) {
                        struct dock_data *dd;
+                       acpi_status status;
 
                        dd = kmalloc(sizeof(*dd), GFP_KERNEL);
                        if (!dd)
-                               return 0;
+                               break;
+
                        dd->handle = handle;
                        dd->event = event;
                        dd->ds = dock_station;
-                       acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd);
-                       return 0 ;
+                       status = acpi_os_hotplug_execute(acpi_dock_deferred_cb,
+                                                        dd);
+                       if (ACPI_FAILURE(status))
+                               kfree(dd);
+
+                       break;
                }
        }
+
+       acpi_scan_lock_release();
        return 0;
 }
 
 
        struct acpi_device *device = NULL;
        struct acpi_eject_event *ej_event = NULL;
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
+       acpi_status status;
        int result;
 
+       acpi_scan_lock_acquire();
+
        switch (event) {
        case ACPI_NOTIFY_BUS_CHECK:
        case ACPI_NOTIFY_DEVICE_CHECK:
                        break;
                }
 
+               get_device(&device->dev);
                ej_event->device = device;
                ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
-               acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
-                                       (void *)ej_event);
-
-               /* eject is performed asynchronously */
-               return;
+               /* The eject is carried out asynchronously. */
+               status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
+                                                ej_event);
+               if (ACPI_FAILURE(status)) {
+                       put_device(&device->dev);
+                       kfree(ej_event);
+                       break;
+               }
+               goto out;
 
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Unsupported event [0x%x]\n", event));
 
                /* non-hotplug event; possibly handled by other handler */
-               return;
+               goto out;
        }
 
        /* Inform firmware that the hotplug operation has completed */
        (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL);
-       return;
+
+ out:
+       acpi_scan_lock_release();
 }
 
 static acpi_status is_processor_device(acpi_handle handle)
 
        struct list_head node;
 };
 
+void acpi_scan_lock_acquire(void)
+{
+       mutex_lock(&acpi_scan_lock);
+}
+EXPORT_SYMBOL_GPL(acpi_scan_lock_acquire);
+
+void acpi_scan_lock_release(void)
+{
+       mutex_unlock(&acpi_scan_lock);
+}
+EXPORT_SYMBOL_GPL(acpi_scan_lock_release);
+
 int acpi_scan_add_handler(struct acpi_scan_handler *handler)
 {
        if (!handler || !handler->attach)
 }
 static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
 
-static void __acpi_bus_trim(struct acpi_device *start);
-
 /**
  * acpi_bus_hot_remove_device: hot-remove a device and its children
  * @context: struct acpi_eject_event pointer (freed in this func)
  */
 void acpi_bus_hot_remove_device(void *context)
 {
-       struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context;
+       struct acpi_eject_event *ej_event = context;
        struct acpi_device *device = ej_event->device;
        acpi_handle handle = device->handle;
        acpi_handle temp;
 
        mutex_lock(&acpi_scan_lock);
 
+       /* If there is no handle, the device node has been unregistered. */
+       if (!device->handle) {
+               dev_dbg(&device->dev, "ACPI handle missing\n");
+               put_device(&device->dev);
+               goto out;
+       }
+
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                "Hot-removing device %s...\n", dev_name(&device->dev)));
 
-       __acpi_bus_trim(device);
-       /* Device node has been released. */
+       acpi_bus_trim(device);
+       /* Device node has been unregistered. */
+       put_device(&device->dev);
        device = NULL;
 
        if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) {
                                          ost_code, NULL);
        }
 
+ out:
        mutex_unlock(&acpi_scan_lock);
        kfree(context);
        return;
                goto err;
        }
 
+       get_device(&acpi_device->dev);
        ej_event->device = acpi_device;
        if (acpi_device->flags.eject_pending) {
                /* event originated from ACPI eject notification */
                        ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
        }
 
-       acpi_os_hotplug_execute(acpi_bus_hot_remove_device, (void *)ej_event);
+       status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event);
+       if (ACPI_FAILURE(status)) {
+               put_device(&acpi_device->dev);
+               kfree(ej_event);
+       }
 err:
        return ret;
 }
         * no more references.
         */
        acpi_device_set_power(device, ACPI_STATE_D3_COLD);
+       device->handle = NULL;
        put_device(&device->dev);
 }
 
  * there has been a real error.  There just have been no suitable ACPI objects
  * in the table trunk from which the kernel could create a device and add an
  * appropriate driver.
+ *
+ * Must be called under acpi_scan_lock.
  */
 int acpi_bus_scan(acpi_handle handle)
 {
        void *device = NULL;
        int error = 0;
 
-       mutex_lock(&acpi_scan_lock);
-
        if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device)))
                acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
                                    acpi_bus_check_add, NULL, NULL, &device);
                acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
                                    acpi_bus_device_attach, NULL, NULL, NULL);
 
-       mutex_unlock(&acpi_scan_lock);
        return error;
 }
 EXPORT_SYMBOL(acpi_bus_scan);
        return AE_OK;
 }
 
-static void __acpi_bus_trim(struct acpi_device *start)
+/**
+ * acpi_bus_trim - Remove ACPI device node and all of its descendants
+ * @start: Root of the ACPI device nodes subtree to remove.
+ *
+ * Must be called under acpi_scan_lock.
+ */
+void acpi_bus_trim(struct acpi_device *start)
 {
        /*
         * Execute acpi_bus_device_detach() as a post-order callback to detach
                            acpi_bus_remove, NULL, NULL);
        acpi_bus_remove(start->handle, 0, NULL, NULL);
 }
-
-void acpi_bus_trim(struct acpi_device *start)
-{
-       mutex_lock(&acpi_scan_lock);
-       __acpi_bus_trim(start);
-       mutex_unlock(&acpi_scan_lock);
-}
 EXPORT_SYMBOL_GPL(acpi_bus_trim);
 
 static int acpi_bus_scan_fixed(void)
        acpi_csrt_init();
        acpi_container_init();
 
+       mutex_lock(&acpi_scan_lock);
        /*
         * Enumerate devices in the ACPI namespace.
         */
        result = acpi_bus_scan(ACPI_ROOT_OBJECT);
        if (result)
-               return result;
+               goto out;
 
        result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root);
        if (result)
-               return result;
+               goto out;
 
        result = acpi_bus_scan_fixed();
        if (result) {
                acpi_device_unregister(acpi_root);
-               return result;
+               goto out;
        }
 
        acpi_update_all_gpes();
-       return 0;
+
+ out:
+       mutex_unlock(&acpi_scan_lock);
+       return result;
 }
 
        handle = hp_work->handle;
        type = hp_work->type;
 
+       acpi_scan_lock_acquire();
+
        if (acpi_bus_get_device(handle, &device)) {
                /* This bridge must have just been physically inserted */
                handle_bridge_insertion(handle, type);
        }
 
 out:
+       acpi_scan_lock_release();
        kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
 }
 
 
        func = (struct acpiphp_func *)context;
 
+       acpi_scan_lock_acquire();
+
        switch (type) {
        case ACPI_NOTIFY_BUS_CHECK:
                /* bus re-enumerate */
                break;
        }
 
+       acpi_scan_lock_release();
        kfree(hp_work); /* allocated in handle_hotplug_event_func */
 }
 
 
                        pdevice = NULL;
                }
 
+               acpi_scan_lock_acquire();
                /*
                 * Walk the rootbus node's immediate children looking for
                 * the slot's device node(s). There can be more than
                                }
                        }
                }
+               acpi_scan_lock_release();
        }
 
        /* Call the driver for the new device */
                /* Get the rootbus node pointer */
                phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle;
 
+               acpi_scan_lock_acquire();
                /*
                 * Walk the rootbus node's immediate children looking for
                 * the slot's device node(s). There can be more than
                                        acpi_bus_trim(device);
                        }
                }
-
+               acpi_scan_lock_release();
        }
 
        /* Free the SN resources assigned to the Linux device.*/
 
 static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
        { return 0; }
 #endif
+
+void acpi_scan_lock_acquire(void);
+void acpi_scan_lock_release(void);
 int acpi_scan_add_handler(struct acpi_scan_handler *handler);
 int acpi_bus_register_driver(struct acpi_driver *driver);
 void acpi_bus_unregister_driver(struct acpi_driver *driver);