]> err.no Git - linux-2.6/blobdiff - net/rfkill/rfkill-input.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6] / net / rfkill / rfkill-input.c
index d285f9a9d8299b82342b34a21c558cc3c9b508d0..8aa82273014516a14a8184bd44cdcdff70f972af 100644 (file)
@@ -43,11 +43,26 @@ static void rfkill_task_handler(struct work_struct *work)
        mutex_unlock(&task->mutex);
 }
 
+static void rfkill_task_epo_handler(struct work_struct *work)
+{
+       rfkill_epo();
+}
+
+static DECLARE_WORK(epo_work, rfkill_task_epo_handler);
+
+static void rfkill_schedule_epo(void)
+{
+       schedule_work(&epo_work);
+}
+
 static void rfkill_schedule_set(struct rfkill_task *task,
                                enum rfkill_state desired_state)
 {
        unsigned long flags;
 
+       if (unlikely(work_pending(&epo_work)))
+               return;
+
        spin_lock_irqsave(&task->lock, flags);
 
        if (time_after(jiffies, task->last + msecs_to_jiffies(200))) {
@@ -63,10 +78,14 @@ static void rfkill_schedule_toggle(struct rfkill_task *task)
 {
        unsigned long flags;
 
+       if (unlikely(work_pending(&epo_work)))
+               return;
+
        spin_lock_irqsave(&task->lock, flags);
 
        if (time_after(jiffies, task->last + msecs_to_jiffies(200))) {
-               task->desired_state = !task->desired_state;
+               task->desired_state =
+                               rfkill_state_complement(task->desired_state);
                task->last = jiffies;
                schedule_work(&task->work);
        }
@@ -74,14 +93,14 @@ static void rfkill_schedule_toggle(struct rfkill_task *task)
        spin_unlock_irqrestore(&task->lock, flags);
 }
 
-#define DEFINE_RFKILL_TASK(n, t)                       \
-       struct rfkill_task n = {                        \
-               .work = __WORK_INITIALIZER(n.work,      \
-                               rfkill_task_handler),   \
-               .type = t,                              \
-               .mutex = __MUTEX_INITIALIZER(n.mutex),  \
-               .lock = __SPIN_LOCK_UNLOCKED(n.lock),   \
-               .desired_state = RFKILL_STATE_ON,       \
+#define DEFINE_RFKILL_TASK(n, t)                               \
+       struct rfkill_task n = {                                \
+               .work = __WORK_INITIALIZER(n.work,              \
+                               rfkill_task_handler),           \
+               .type = t,                                      \
+               .mutex = __MUTEX_INITIALIZER(n.mutex),          \
+               .lock = __SPIN_LOCK_UNLOCKED(n.lock),           \
+               .desired_state = RFKILL_STATE_UNBLOCKED,        \
        }
 
 static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN);
@@ -114,21 +133,20 @@ static void rfkill_event(struct input_handle *handle, unsigned int type,
                switch (code) {
                case SW_RFKILL_ALL:
                        /* EVERY radio type. data != 0 means radios ON */
-                       rfkill_schedule_set(&rfkill_wwan,
-                                           (data)? RFKILL_STATE_ON:
-                                                   RFKILL_STATE_OFF);
-                       rfkill_schedule_set(&rfkill_wimax,
-                                           (data)? RFKILL_STATE_ON:
-                                                   RFKILL_STATE_OFF);
-                       rfkill_schedule_set(&rfkill_uwb,
-                                           (data)? RFKILL_STATE_ON:
-                                                   RFKILL_STATE_OFF);
-                       rfkill_schedule_set(&rfkill_bt,
-                                           (data)? RFKILL_STATE_ON:
-                                                   RFKILL_STATE_OFF);
-                       rfkill_schedule_set(&rfkill_wlan,
-                                           (data)? RFKILL_STATE_ON:
-                                                   RFKILL_STATE_OFF);
+                       /* handle EPO (emergency power off) through shortcut */
+                       if (data) {
+                               rfkill_schedule_set(&rfkill_wwan,
+                                                   RFKILL_STATE_UNBLOCKED);
+                               rfkill_schedule_set(&rfkill_wimax,
+                                                   RFKILL_STATE_UNBLOCKED);
+                               rfkill_schedule_set(&rfkill_uwb,
+                                                   RFKILL_STATE_UNBLOCKED);
+                               rfkill_schedule_set(&rfkill_bt,
+                                                   RFKILL_STATE_UNBLOCKED);
+                               rfkill_schedule_set(&rfkill_wlan,
+                                                   RFKILL_STATE_UNBLOCKED);
+                       } else
+                               rfkill_schedule_epo();
                        break;
                default:
                        break;