Skip to content

Commit

Permalink
eeepc-laptop: fix hot-unplug on resume
Browse files Browse the repository at this point in the history
OOPS on resume when the wireless adaptor is disabled during suspend was
introduced by "eeepc-laptop: read rfkill soft-blocked state on resume".

Unable to handle kernel NULL pointer dereference

Process s2disk
Tainted: G W
IP: klist_put

Call trace:
? klist_del
? device_del
? device_unregister
? pci_stop_dev
? pci_stop_bus
? pci_remove_device
? eeepc_rfkill_hotplug [eeepc_laptop]
? eeepc_hotk_resume [eeepc_laptop]
? acpi_device_resume
? device_resume
? hibernation_snapshot

It appears the PCI device is removed twice.  The eeepc_rfkill_hotplug()
call from the resume handler is racing against the call from the ACPI
notifier callback.  The ACPI notification is triggered by the resume
handler when it refreshes the value of CM_ASL_WLAN.

The fix is to serialize hotplug calls using a workqueue.

http://bugzilla.kernel.org/show_bug.cgi?id=13825

Signed-off-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
Acked-by: Corentin Chary <corentin.chary@gmail.com>
Signed-off-by: Len Brown <len.brown@intel.com>
  • Loading branch information
Alan Jenkins authored and Len Brown committed Aug 2, 2009
1 parent ed680c4 commit 7334546
Showing 1 changed file with 6 additions and 3 deletions.
9 changes: 6 additions & 3 deletions drivers/platform/x86/eeepc-laptop.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ struct eeepc_hotk {
struct rfkill *bluetooth_rfkill;
struct rfkill *wwan3g_rfkill;
struct hotplug_slot *hotplug_slot;
struct work_struct hotplug_work;
};

/* The actual device the driver binds to */
Expand Down Expand Up @@ -660,7 +661,7 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
return 0;
}

static void eeepc_rfkill_hotplug(void)
static void eeepc_hotplug_work(struct work_struct *work)
{
struct pci_dev *dev;
struct pci_bus *bus = pci_find_bus(0, 1);
Expand Down Expand Up @@ -701,7 +702,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
if (event != ACPI_NOTIFY_BUS_CHECK)
return;

eeepc_rfkill_hotplug();
schedule_work(&ehotk->hotplug_work);
}

static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
Expand Down Expand Up @@ -892,7 +893,7 @@ static int eeepc_hotk_resume(struct acpi_device *device)

rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1);

eeepc_rfkill_hotplug();
schedule_work(&ehotk->hotplug_work);
}

if (ehotk->bluetooth_rfkill)
Expand Down Expand Up @@ -1093,6 +1094,8 @@ static int eeepc_rfkill_init(struct device *dev)
{
int result = 0;

INIT_WORK(&ehotk->hotplug_work, eeepc_hotplug_work);

eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");

Expand Down

0 comments on commit 7334546

Please sign in to comment.