aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarren Salt <linux@youmustbejoking.demon.co.uk>2009-10-12 18:13:33 -0400
committerLen Brown <len.brown@intel.com>2009-10-13 01:26:41 -0400
commitb56ab33d68638e6aafdbfc694025e8354a628f49 (patch)
treeb73872ff94882a821523f9c7314eb1a5f8658479
parentdcb73eed70575c68f1389f7fac7cbd0feaeb50f3 (diff)
eeepc-laptop: Prevent a panic when disabling RT2860 wireless when associated
This works around what I think is actually a bug in rt2860sta which is triggered when the hardware "disappears" from beneath the driver, i.e. when wireless is toggled off via ACPI. It does so by ensuring that the rfkill soft-block flag is set before the hardware is disabled. I do not know whether this patch is required if rt2800pci is in use instead of rt2860sta; at the time of submission of this patch, I've not been able to test this. (Ref. http://bugzilla.kernel.org/show_bug.cgi?id=13390) Signed-off-by: Darren Salt <linux@youmustbejoking.demon.co.uk> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/platform/x86/eeepc-laptop.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 789d6ae003f..d379e74a05d 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -150,6 +150,8 @@ struct eeepc_hotk {
150/* The actual device the driver binds to */ 150/* The actual device the driver binds to */
151static struct eeepc_hotk *ehotk; 151static struct eeepc_hotk *ehotk;
152 152
153static void eeepc_rfkill_hotplug(bool real);
154
153/* Platform device/driver */ 155/* Platform device/driver */
154static int eeepc_hotk_thaw(struct device *device); 156static int eeepc_hotk_thaw(struct device *device);
155static int eeepc_hotk_restore(struct device *device); 157static int eeepc_hotk_restore(struct device *device);
@@ -343,7 +345,16 @@ static bool eeepc_wlan_rfkill_blocked(void)
343static int eeepc_rfkill_set(void *data, bool blocked) 345static int eeepc_rfkill_set(void *data, bool blocked)
344{ 346{
345 unsigned long asl = (unsigned long)data; 347 unsigned long asl = (unsigned long)data;
346 return set_acpi(asl, !blocked); 348 int ret;
349
350 if (asl != CM_ASL_WLAN)
351 return set_acpi(asl, !blocked);
352
353 /* hack to avoid panic with rt2860sta */
354 if (blocked)
355 eeepc_rfkill_hotplug(false);
356 ret = set_acpi(asl, !blocked);
357 return ret;
347} 358}
348 359
349static const struct rfkill_ops eeepc_rfkill_ops = { 360static const struct rfkill_ops eeepc_rfkill_ops = {
@@ -643,13 +654,13 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
643 return 0; 654 return 0;
644} 655}
645 656
646static void eeepc_rfkill_hotplug(void) 657static void eeepc_rfkill_hotplug(bool real)
647{ 658{
648 struct pci_dev *dev; 659 struct pci_dev *dev;
649 struct pci_bus *bus; 660 struct pci_bus *bus;
650 bool blocked = eeepc_wlan_rfkill_blocked(); 661 bool blocked = real ? eeepc_wlan_rfkill_blocked() : true;
651 662
652 if (ehotk->wlan_rfkill) 663 if (real && ehotk->wlan_rfkill)
653 rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); 664 rfkill_set_sw_state(ehotk->wlan_rfkill, blocked);
654 665
655 mutex_lock(&ehotk->hotplug_lock); 666 mutex_lock(&ehotk->hotplug_lock);
@@ -692,7 +703,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
692 if (event != ACPI_NOTIFY_BUS_CHECK) 703 if (event != ACPI_NOTIFY_BUS_CHECK)
693 return; 704 return;
694 705
695 eeepc_rfkill_hotplug(); 706 eeepc_rfkill_hotplug(true);
696} 707}
697 708
698static void eeepc_hotk_notify(struct acpi_device *device, u32 event) 709static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
@@ -850,7 +861,7 @@ static int eeepc_hotk_restore(struct device *device)
850{ 861{
851 /* Refresh both wlan rfkill state and pci hotplug */ 862 /* Refresh both wlan rfkill state and pci hotplug */
852 if (ehotk->wlan_rfkill) 863 if (ehotk->wlan_rfkill)
853 eeepc_rfkill_hotplug(); 864 eeepc_rfkill_hotplug(true);
854 865
855 if (ehotk->bluetooth_rfkill) 866 if (ehotk->bluetooth_rfkill)
856 rfkill_set_sw_state(ehotk->bluetooth_rfkill, 867 rfkill_set_sw_state(ehotk->bluetooth_rfkill,
@@ -993,7 +1004,7 @@ static void eeepc_rfkill_exit(void)
993 * Refresh pci hotplug in case the rfkill state was changed after 1004 * Refresh pci hotplug in case the rfkill state was changed after
994 * eeepc_unregister_rfkill_notifier() 1005 * eeepc_unregister_rfkill_notifier()
995 */ 1006 */
996 eeepc_rfkill_hotplug(); 1007 eeepc_rfkill_hotplug(true);
997 if (ehotk->hotplug_slot) 1008 if (ehotk->hotplug_slot)
998 pci_hp_deregister(ehotk->hotplug_slot); 1009 pci_hp_deregister(ehotk->hotplug_slot);
999 1010
@@ -1109,7 +1120,7 @@ static int eeepc_rfkill_init(struct device *dev)
1109 * Refresh pci hotplug in case the rfkill state was changed during 1120 * Refresh pci hotplug in case the rfkill state was changed during
1110 * setup. 1121 * setup.
1111 */ 1122 */
1112 eeepc_rfkill_hotplug(); 1123 eeepc_rfkill_hotplug(true);
1113 1124
1114exit: 1125exit:
1115 if (result && result != -ENODEV) 1126 if (result && result != -ENODEV)