Comment 0 for bug 429635

Revision history for this message
meijer.o (meijer-o) wrote :

When turning off the Wireless device with Fn+F2 on EeePC 100h and others, usually the kernel
freezes completely.

Steps to reproduce:
1. Boot EeePC 901 with WiFi off
2. On the text console press Fn+F2: the blue WiFi feedback LED turns on and
some messages appears on the dmesg (see attached).
3. After having established a connection to a wireless network, press the Fn+F2 again: the blue WiFi LED turns off and the system freezes. A hard reset is needed to restart the computer.

Workaround

Patch the kernel source, (eeepc-laptop.c) with this patch, see also this bug report: http://bugzilla.kernel.org/show_bug.cgi?id=13390
-----------------------------------------------------------------------------------------------------------------------------------
Avoid an eeepc-laptop/rt2860sta panic if associated when the hw disappears.

This is a workaround. It is expected to become unnecessary when rt2800pci
makes it into a kernel release.

Signed-off-by: Darren Salt <email address hidden>
-----------------------------------------------------------------------------------------------------------------------------------
--- ./drivers/platform/x86/eeepc-laptop.c.dist 2009-08-14 12:30:30.385461620 +0100
+++ ./drivers/platform/x86/eeepc-laptop.c 2009-08-14 16:33:17.113557519 +0100
@@ -32,6 +32,7 @@
 #include <linux/uaccess.h>
 #include <linux/input.h>
 #include <linux/rfkill.h>
+#include <linux/semaphore.h>
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>

@@ -139,6 +140,7 @@
  u16 event_count[128]; /* count for each event */
  struct input_dev *inputdev;
  u16 *keycode_map;
+ struct semaphore rfkill_sem;
  struct rfkill *wlan_rfkill;
  struct rfkill *bluetooth_rfkill;
  struct rfkill *wwan3g_rfkill;
@@ -223,6 +225,8 @@
  .get_power_status = eeepc_get_adapter_status,
 };

+static void eeepc_hotplug_work(struct work_struct *work);
+
 /* The backlight device /sys/class/backlight */
 static struct backlight_device *eeepc_backlight_device;

@@ -335,7 +339,16 @@
 static int eeepc_rfkill_set(void *data, bool blocked)
 {
  unsigned long asl = (unsigned long)data;
- return set_acpi(asl, !blocked);
+ int ret;
+
+ if (asl != CM_ASL_WLAN)
+ return set_acpi(asl, !blocked);
+
+ /* hack to avoid panic with rt2860sta */
+ if (blocked)
+ eeepc_hotplug_work(NULL);
+ ret = set_acpi(asl, !blocked);
+ return ret;
 }

 static const struct rfkill_ops eeepc_rfkill_ops = {
@@ -667,18 +680,20 @@
  struct pci_bus *bus = pci_find_bus(0, 1);
  bool blocked;

+ while (down_interruptible(&ehotk->rfkill_sem)) /**/;
+
  if (!bus) {
   pr_warning("Unable to find PCI bus 1?\n");
- return;
+ goto done;
  }

- blocked = eeepc_wlan_rfkill_blocked();
+ blocked = work ? eeepc_wlan_rfkill_blocked() : true;
  if (!blocked) {
   dev = pci_get_slot(bus, 0);
   if (dev) {
    /* Device already present */
    pci_dev_put(dev);
- return;
+ goto done;
   }
   dev = pci_scan_single_device(bus, 0);
   if (dev) {
@@ -695,6 +710,8 @@
  }

  rfkill_set_sw_state(ehotk->wlan_rfkill, blocked);
+done:
+ up(&ehotk->rfkill_sem);
 }

 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
@@ -849,6 +866,7 @@
  ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
  if (!ehotk)
   return -ENOMEM;
+ sema_init(&ehotk->rfkill_sem, 1);
  ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
  ehotk->handle = device->handle;
  strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);