diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt
index b65f0799df48..4d3ee317a4a3 100644
--- a/Documentation/rfkill.txt
+++ b/Documentation/rfkill.txt
@@ -191,12 +191,20 @@ Userspace input handlers (uevents) or kernel input handlers (rfkill-input):
 	  to tell the devices registered with the rfkill class to change
 	  their state (i.e. translates the input layer event into real
 	  action).
+
 	* rfkill-input implements EPO by handling EV_SW SW_RFKILL_ALL 0
 	  (power off all transmitters) in a special way: it ignores any
 	  overrides and local state cache and forces all transmitters to the
 	  RFKILL_STATE_SOFT_BLOCKED state (including those which are already
-	  supposed to be BLOCKED).  Note that the opposite event (power on all
-	  transmitters) is handled normally.
+	  supposed to be BLOCKED).
+	* rfkill EPO will remain active until rfkill-input receives an
+	  EV_SW SW_RFKILL_ALL 1 event.  While the EPO is active, transmitters
+	  are locked in the blocked state (rfkill will refuse to unblock them).
+	* rfkill-input implements different policies that the user can
+	  select for handling EV_SW SW_RFKILL_ALL 1.  It will unlock rfkill,
+	  and either do nothing (leave transmitters blocked, but now unlocked),
+	  restore the transmitters to their state before the EPO, or unblock
+	  them all.
 
 Userspace uevent handler or kernel platform-specific drivers hooked to the
 rfkill notifier chain:
@@ -331,11 +339,9 @@ class to get a sysfs interface :-)
 correct event for your switch/button.  These events are emergency power-off
 events when they are trying to turn the transmitters off.  An example of an
 input device which SHOULD generate *_RFKILL_ALL events is the wireless-kill
-switch in a laptop which is NOT a hotkey, but a real switch that kills radios
-in hardware, even if the O.S. has gone to lunch.  An example of an input device
-which SHOULD NOT generate *_RFKILL_ALL events by default, is any sort of hot
-key that does nothing by itself, as well as any hot key that is type-specific
-(e.g. the one for WLAN).
+switch in a laptop which is NOT a hotkey, but a real sliding/rocker switch.
+An example of an input device which SHOULD NOT generate *_RFKILL_ALL events by
+default, is any sort of hot key that is type-specific (e.g. the one for WLAN).
 
 
 3.1 Guidelines for wireless device drivers
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c
index bfdade72e066..7706541f9f79 100644
--- a/net/rfkill/rfkill-input.c
+++ b/net/rfkill/rfkill-input.c
@@ -24,138 +24,291 @@ MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
 MODULE_DESCRIPTION("Input layer to RF switch connector");
 MODULE_LICENSE("GPL");
 
+enum rfkill_input_master_mode {
+	RFKILL_INPUT_MASTER_DONOTHING = 0,
+	RFKILL_INPUT_MASTER_RESTORE = 1,
+	RFKILL_INPUT_MASTER_UNBLOCKALL = 2,
+	RFKILL_INPUT_MASTER_MAX,	/* marker */
+};
+
+static enum rfkill_input_master_mode rfkill_master_switch_mode =
+					RFKILL_INPUT_MASTER_UNBLOCKALL;
+module_param_named(master_switch_mode, rfkill_master_switch_mode, uint, 0);
+MODULE_PARM_DESC(master_switch_mode,
+	"SW_RFKILL_ALL ON should: 0=do nothing; 1=restore; 2=unblock all");
+
+enum rfkill_global_sched_op {
+	RFKILL_GLOBAL_OP_EPO = 0,
+	RFKILL_GLOBAL_OP_RESTORE,
+	RFKILL_GLOBAL_OP_UNLOCK,
+	RFKILL_GLOBAL_OP_UNBLOCK,
+};
+
+/*
+ * Currently, the code marked with RFKILL_NEED_SWSET is inactive.
+ * If handling of EV_SW SW_WLAN/WWAN/BLUETOOTH/etc is needed in the
+ * future, when such events are added, that code will be necessary.
+ */
+
 struct rfkill_task {
 	struct work_struct work;
-	enum rfkill_type type;
-	struct mutex mutex; /* ensures that task is serialized */
-	spinlock_t lock; /* for accessing last and desired state */
-	unsigned long last; /* last schedule */
-	enum rfkill_state desired_state; /* on/off */
+
+	/* ensures that task is serialized */
+	struct mutex mutex;
+
+	/* protects everything below */
+	spinlock_t lock;
+
+	/* pending regular switch operations (1=pending) */
+	unsigned long sw_pending[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
+
+#ifdef RFKILL_NEED_SWSET
+	/* set operation pending (1=pending) */
+	unsigned long sw_setpending[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
+
+	/* desired state for pending set operation (1=unblock) */
+	unsigned long sw_newstate[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
+#endif
+
+	/* should the state be complemented (1=yes) */
+	unsigned long sw_togglestate[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
+
+	bool global_op_pending;
+	enum rfkill_global_sched_op op;
 };
 
+static void __rfkill_handle_global_op(enum rfkill_global_sched_op op)
+{
+	unsigned int i;
+
+	switch (op) {
+	case RFKILL_GLOBAL_OP_EPO:
+		rfkill_epo();
+		break;
+	case RFKILL_GLOBAL_OP_RESTORE:
+		rfkill_restore_states();
+		break;
+	case RFKILL_GLOBAL_OP_UNLOCK:
+		rfkill_remove_epo_lock();
+		break;
+	case RFKILL_GLOBAL_OP_UNBLOCK:
+		rfkill_remove_epo_lock();
+		for (i = 0; i < RFKILL_TYPE_MAX; i++)
+			rfkill_switch_all(i, RFKILL_STATE_UNBLOCKED);
+		break;
+	default:
+		/* memory corruption or bug, fail safely */
+		rfkill_epo();
+		WARN(1, "Unknown requested operation %d! "
+			"rfkill Emergency Power Off activated\n",
+			op);
+	}
+}
+
+#ifdef RFKILL_NEED_SWSET
+static void __rfkill_handle_normal_op(const enum rfkill_type type,
+			const bool sp, const bool s, const bool c)
+{
+	enum rfkill_state state;
+
+	if (sp)
+		state = (s) ? RFKILL_STATE_UNBLOCKED :
+			      RFKILL_STATE_SOFT_BLOCKED;
+	else
+		state = rfkill_get_global_state(type);
+
+	if (c)
+		state = rfkill_state_complement(state);
+
+	rfkill_switch_all(type, state);
+}
+#else
+static void __rfkill_handle_normal_op(const enum rfkill_type type,
+			const bool c)
+{
+	enum rfkill_state state;
+
+	state = rfkill_get_global_state(type);
+	if (c)
+		state = rfkill_state_complement(state);
+
+	rfkill_switch_all(type, state);
+}
+#endif
+
 static void rfkill_task_handler(struct work_struct *work)
 {
-	struct rfkill_task *task = container_of(work, struct rfkill_task, work);
+	struct rfkill_task *task =
+			container_of(work, struct rfkill_task, work);
+	bool doit = true;
 
 	mutex_lock(&task->mutex);
 
-	rfkill_switch_all(task->type, task->desired_state);
+	spin_lock_irq(&task->lock);
+	while (doit) {
+		if (task->global_op_pending) {
+			enum rfkill_global_sched_op op = task->op;
+			task->global_op_pending = false;
+			memset(task->sw_pending, 0, sizeof(task->sw_pending));
+			spin_unlock_irq(&task->lock);
+
+			__rfkill_handle_global_op(op);
+
+			/* make sure we do at least one pass with
+			 * !task->global_op_pending */
+			spin_lock_irq(&task->lock);
+			continue;
+		} else if (!rfkill_is_epo_lock_active()) {
+			unsigned int i = 0;
+
+			while (!task->global_op_pending &&
+						i < RFKILL_TYPE_MAX) {
+				if (test_and_clear_bit(i, task->sw_pending)) {
+					bool c;
+#ifdef RFKILL_NEED_SWSET
+					bool sp, s;
+					sp = test_and_clear_bit(i,
+							task->sw_setpending);
+					s = test_bit(i, task->sw_newstate);
+#endif
+					c = test_and_clear_bit(i,
+							task->sw_togglestate);
+					spin_unlock_irq(&task->lock);
+
+#ifdef RFKILL_NEED_SWSET
+					__rfkill_handle_normal_op(i, sp, s, c);
+#else
+					__rfkill_handle_normal_op(i, c);
+#endif
+
+					spin_lock_irq(&task->lock);
+				}
+				i++;
+			}
+		}
+		doit = task->global_op_pending;
+	}
+	spin_unlock_irq(&task->lock);
 
 	mutex_unlock(&task->mutex);
 }
 
-static void rfkill_task_epo_handler(struct work_struct *work)
+static struct rfkill_task rfkill_task = {
+	.work = __WORK_INITIALIZER(rfkill_task.work,
+				rfkill_task_handler),
+	.mutex = __MUTEX_INITIALIZER(rfkill_task.mutex),
+	.lock = __SPIN_LOCK_UNLOCKED(rfkill_task.lock),
+};
+
+static void rfkill_schedule_global_op(enum rfkill_global_sched_op op)
 {
-	rfkill_epo();
+	unsigned long flags;
+
+	spin_lock_irqsave(&rfkill_task.lock, flags);
+	rfkill_task.op = op;
+	rfkill_task.global_op_pending = true;
+	schedule_work(&rfkill_task.work);
+	spin_unlock_irqrestore(&rfkill_task.lock, flags);
 }
 
-static DECLARE_WORK(epo_work, rfkill_task_epo_handler);
+#ifdef RFKILL_NEED_SWSET
+/* Use this if you need to add EV_SW SW_WLAN/WWAN/BLUETOOTH/etc handling */
 
-static void rfkill_schedule_epo(void)
-{
-	schedule_work(&epo_work);
-}
-
-static void rfkill_schedule_set(struct rfkill_task *task,
+static void rfkill_schedule_set(enum rfkill_type type,
 				enum rfkill_state desired_state)
 {
 	unsigned long flags;
 
-	if (unlikely(work_pending(&epo_work)))
+	if (rfkill_is_epo_lock_active())
 		return;
 
-	spin_lock_irqsave(&task->lock, flags);
-
-	if (time_after(jiffies, task->last + msecs_to_jiffies(200))) {
-		task->desired_state = desired_state;
-		task->last = jiffies;
-		schedule_work(&task->work);
+	spin_lock_irqsave(&rfkill_task.lock, flags);
+	if (!rfkill_task.global_op_pending) {
+		set_bit(type, rfkill_task.sw_pending);
+		set_bit(type, rfkill_task.sw_setpending);
+		clear_bit(type, rfkill_task.sw_togglestate);
+		if (desired_state)
+			set_bit(type,  rfkill_task.sw_newstate);
+		else
+			clear_bit(type, rfkill_task.sw_newstate);
+		schedule_work(&rfkill_task.work);
 	}
-
-	spin_unlock_irqrestore(&task->lock, flags);
+	spin_unlock_irqrestore(&rfkill_task.lock, flags);
 }
+#endif
 
-static void rfkill_schedule_toggle(struct rfkill_task *task)
+static void rfkill_schedule_toggle(enum rfkill_type type)
 {
 	unsigned long flags;
 
-	if (unlikely(work_pending(&epo_work)))
+	if (rfkill_is_epo_lock_active())
 		return;
 
-	spin_lock_irqsave(&task->lock, flags);
-
-	if (time_after(jiffies, task->last + msecs_to_jiffies(200))) {
-		task->desired_state =
-				rfkill_state_complement(task->desired_state);
-		task->last = jiffies;
-		schedule_work(&task->work);
+	spin_lock_irqsave(&rfkill_task.lock, flags);
+	if (!rfkill_task.global_op_pending) {
+		set_bit(type, rfkill_task.sw_pending);
+		change_bit(type, rfkill_task.sw_togglestate);
+		schedule_work(&rfkill_task.work);
 	}
-
-	spin_unlock_irqrestore(&task->lock, flags);
+	spin_unlock_irqrestore(&rfkill_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_UNBLOCKED,	\
-	}
-
-static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN);
-static DEFINE_RFKILL_TASK(rfkill_bt, RFKILL_TYPE_BLUETOOTH);
-static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB);
-static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX);
-static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN);
-
 static void rfkill_schedule_evsw_rfkillall(int state)
 {
-	/* EVERY radio type. state != 0 means radios ON */
-	/* handle EPO (emergency power off) through shortcut */
 	if (state) {
-		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);
+		switch (rfkill_master_switch_mode) {
+		case RFKILL_INPUT_MASTER_UNBLOCKALL:
+			rfkill_schedule_global_op(RFKILL_GLOBAL_OP_UNBLOCK);
+			break;
+		case RFKILL_INPUT_MASTER_RESTORE:
+			rfkill_schedule_global_op(RFKILL_GLOBAL_OP_RESTORE);
+			break;
+		case RFKILL_INPUT_MASTER_DONOTHING:
+			rfkill_schedule_global_op(RFKILL_GLOBAL_OP_UNLOCK);
+			break;
+		default:
+			/* memory corruption or driver bug! fail safely */
+			rfkill_schedule_global_op(RFKILL_GLOBAL_OP_EPO);
+			WARN(1, "Unknown rfkill_master_switch_mode (%d), "
+				"driver bug or memory corruption detected!\n",
+				rfkill_master_switch_mode);
+			break;
+		}
 	} else
-		rfkill_schedule_epo();
+		rfkill_schedule_global_op(RFKILL_GLOBAL_OP_EPO);
 }
 
 static void rfkill_event(struct input_handle *handle, unsigned int type,
 			unsigned int code, int data)
 {
 	if (type == EV_KEY && data == 1) {
+		enum rfkill_type t;
+
 		switch (code) {
 		case KEY_WLAN:
-			rfkill_schedule_toggle(&rfkill_wlan);
+			t = RFKILL_TYPE_WLAN;
 			break;
 		case KEY_BLUETOOTH:
-			rfkill_schedule_toggle(&rfkill_bt);
+			t = RFKILL_TYPE_BLUETOOTH;
 			break;
 		case KEY_UWB:
-			rfkill_schedule_toggle(&rfkill_uwb);
+			t = RFKILL_TYPE_UWB;
 			break;
 		case KEY_WIMAX:
-			rfkill_schedule_toggle(&rfkill_wimax);
+			t = RFKILL_TYPE_WIMAX;
 			break;
 		default:
-			break;
+			return;
 		}
+		rfkill_schedule_toggle(t);
+		return;
 	} else if (type == EV_SW) {
 		switch (code) {
 		case SW_RFKILL_ALL:
 			rfkill_schedule_evsw_rfkillall(data);
-			break;
+			return;
 		default:
-			break;
+			return;
 		}
 	}
 }
@@ -256,11 +409,9 @@ static struct input_handler rfkill_handler = {
 
 static int __init rfkill_handler_init(void)
 {
-	unsigned long last_run = jiffies - msecs_to_jiffies(500);
-	rfkill_wlan.last = last_run;
-	rfkill_bt.last = last_run;
-	rfkill_uwb.last = last_run;
-	rfkill_wimax.last = last_run;
+	if (rfkill_master_switch_mode >= RFKILL_INPUT_MASTER_MAX)
+		return -EINVAL;
+
 	return input_register_handler(&rfkill_handler);
 }
 
@@ -268,6 +419,7 @@ static void __exit rfkill_handler_exit(void)
 {
 	input_unregister_handler(&rfkill_handler);
 	flush_scheduled_work();
+	rfkill_remove_epo_lock();
 }
 
 module_init(rfkill_handler_init);
diff --git a/net/rfkill/rfkill-input.h b/net/rfkill/rfkill-input.h
index d1e03e85cbed..fe8df6b5b935 100644
--- a/net/rfkill/rfkill-input.h
+++ b/net/rfkill/rfkill-input.h
@@ -14,6 +14,8 @@
 void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state);
 void rfkill_epo(void);
 void rfkill_restore_states(void);
+void rfkill_remove_epo_lock(void);
+bool rfkill_is_epo_lock_active(void);
 enum rfkill_state rfkill_get_global_state(const enum rfkill_type type);
 
 #endif /* __RFKILL_INPUT_H */
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index fdf87d2ab25e..e348eab756f3 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -51,6 +51,7 @@ struct rfkill_gsw_state {
 
 static struct rfkill_gsw_state rfkill_global_states[RFKILL_TYPE_MAX];
 static unsigned long rfkill_states_lockdflt[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
+static bool rfkill_epo_lock_active;
 
 static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list);
 
@@ -264,11 +265,14 @@ static void __rfkill_switch_all(const enum rfkill_type type,
  *
  * Acquires rfkill_global_mutex and calls __rfkill_switch_all(@type, @state).
  * Please refer to __rfkill_switch_all() for details.
+ *
+ * Does nothing if the EPO lock is active.
  */
 void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state)
 {
 	mutex_lock(&rfkill_global_mutex);
-	__rfkill_switch_all(type, state);
+	if (!rfkill_epo_lock_active)
+		__rfkill_switch_all(type, state);
 	mutex_unlock(&rfkill_global_mutex);
 }
 EXPORT_SYMBOL(rfkill_switch_all);
@@ -289,6 +293,7 @@ void rfkill_epo(void)
 
 	mutex_lock(&rfkill_global_mutex);
 
+	rfkill_epo_lock_active = true;
 	list_for_each_entry(rfkill, &rfkill_list, node) {
 		mutex_lock(&rfkill->mutex);
 		rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1);
@@ -317,12 +322,42 @@ void rfkill_restore_states(void)
 
 	mutex_lock(&rfkill_global_mutex);
 
+	rfkill_epo_lock_active = false;
 	for (i = 0; i < RFKILL_TYPE_MAX; i++)
 		__rfkill_switch_all(i, rfkill_global_states[i].default_state);
 	mutex_unlock(&rfkill_global_mutex);
 }
 EXPORT_SYMBOL_GPL(rfkill_restore_states);
 
+/**
+ * rfkill_remove_epo_lock - unlock state changes
+ *
+ * Used by rfkill-input manually unlock state changes, when
+ * the EPO switch is deactivated.
+ */
+void rfkill_remove_epo_lock(void)
+{
+	mutex_lock(&rfkill_global_mutex);
+	rfkill_epo_lock_active = false;
+	mutex_unlock(&rfkill_global_mutex);
+}
+EXPORT_SYMBOL_GPL(rfkill_remove_epo_lock);
+
+/**
+ * rfkill_is_epo_lock_active - returns true EPO is active
+ *
+ * Returns 0 (false) if there is NOT an active EPO contidion,
+ * and 1 (true) if there is an active EPO contition, which
+ * locks all radios in one of the BLOCKED states.
+ *
+ * Can be called in atomic context.
+ */
+bool rfkill_is_epo_lock_active(void)
+{
+	return rfkill_epo_lock_active;
+}
+EXPORT_SYMBOL_GPL(rfkill_is_epo_lock_active);
+
 /**
  * rfkill_get_global_state - returns global state for a type
  * @type: the type to get the global state of
@@ -447,7 +482,12 @@ static ssize_t rfkill_state_store(struct device *dev,
 	error = mutex_lock_killable(&rfkill->mutex);
 	if (error)
 		return error;
-	error = rfkill_toggle_radio(rfkill, state, 0);
+
+	if (!rfkill_epo_lock_active)
+		error = rfkill_toggle_radio(rfkill, state, 0);
+	else
+		error = -EPERM;
+
 	mutex_unlock(&rfkill->mutex);
 
 	return error ? error : count;
@@ -491,7 +531,7 @@ static ssize_t rfkill_claim_store(struct device *dev,
 		return error;
 
 	if (rfkill->user_claim != claim) {
-		if (!claim) {
+		if (!claim && !rfkill_epo_lock_active) {
 			mutex_lock(&rfkill->mutex);
 			rfkill_toggle_radio(rfkill,
 					rfkill_global_states[rfkill->type].current_state,