iwlwifi: remove input device and fix rfkill state

This patch fixes the iwlwifi rfkill. It removes the input device from iwl3945,
adds support for RFKILL_STATE_HARD_BLOCKED and calls rfkill_force_state() to
update the state rather than accessing it directly.
The calls to iwl|iwl3945_rfkill_set_hw_state() had to be moved because
rfkill_force_state() cannot be called from an atomic context.
Tested on iwl3945 and seems to work fine.

Cc: Randy Dunlap <randy.dunlap@oracle.com>
Cc: Ivo van Doorn <ivdoorn@gmail.com>
Cc: Fabien Crespel <fcrespel@gmail.com>
Cc: Zhu Yi <yi.zhu@intel.com>
Cc: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
index eebaf43..e5e5846 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
@@ -44,7 +44,7 @@
 	struct iwl_priv *priv = data;
 	int err = 0;
 
-	if (!priv->rfkill_mngr.rfkill)
+	if (!priv->rfkill)
 		return 0;
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
@@ -55,20 +55,20 @@
 
 	switch (state) {
 	case RFKILL_STATE_UNBLOCKED:
-		iwl_radio_kill_sw_enable_radio(priv);
-		/* if HW rf-kill is set dont allow ON state */
-		if (iwl_is_rfkill(priv))
+		if (iwl_is_rfkill_hw(priv)) {
 			err = -EBUSY;
+			goto out_unlock;
+		}
+		iwl_radio_kill_sw_enable_radio(priv);
 		break;
 	case RFKILL_STATE_SOFT_BLOCKED:
 		iwl_radio_kill_sw_disable_radio(priv);
-		if (!iwl_is_rfkill(priv))
-			err = -EBUSY;
 		break;
 	default:
 		IWL_WARNING("we recieved unexpected RFKILL state %d\n", state);
 		break;
 	}
+out_unlock:
 	mutex_unlock(&priv->mutex);
 
 	return err;
@@ -82,23 +82,23 @@
 	BUG_ON(device == NULL);
 
 	IWL_DEBUG_RF_KILL("Initializing RFKILL.\n");
-	priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
-	if (!priv->rfkill_mngr.rfkill) {
+	priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
+	if (!priv->rfkill) {
 		IWL_ERROR("Unable to allocate rfkill device.\n");
 		ret = -ENOMEM;
 		goto error;
 	}
 
-	priv->rfkill_mngr.rfkill->name = priv->cfg->name;
-	priv->rfkill_mngr.rfkill->data = priv;
-	priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
-	priv->rfkill_mngr.rfkill->toggle_radio = iwl_rfkill_soft_rf_kill;
-	priv->rfkill_mngr.rfkill->user_claim_unsupported = 1;
+	priv->rfkill->name = priv->cfg->name;
+	priv->rfkill->data = priv;
+	priv->rfkill->state = RFKILL_STATE_UNBLOCKED;
+	priv->rfkill->toggle_radio = iwl_rfkill_soft_rf_kill;
+	priv->rfkill->user_claim_unsupported = 1;
 
-	priv->rfkill_mngr.rfkill->dev.class->suspend = NULL;
-	priv->rfkill_mngr.rfkill->dev.class->resume = NULL;
+	priv->rfkill->dev.class->suspend = NULL;
+	priv->rfkill->dev.class->resume = NULL;
 
-	ret = rfkill_register(priv->rfkill_mngr.rfkill);
+	ret = rfkill_register(priv->rfkill);
 	if (ret) {
 		IWL_ERROR("Unable to register rfkill: %d\n", ret);
 		goto free_rfkill;
@@ -108,9 +108,9 @@
 	return ret;
 
 free_rfkill:
-	if (priv->rfkill_mngr.rfkill != NULL)
-		rfkill_free(priv->rfkill_mngr.rfkill);
-	priv->rfkill_mngr.rfkill = NULL;
+	if (priv->rfkill != NULL)
+		rfkill_free(priv->rfkill);
+	priv->rfkill = NULL;
 
 error:
 	IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
@@ -121,22 +121,27 @@
 void iwl_rfkill_unregister(struct iwl_priv *priv)
 {
 
-	if (priv->rfkill_mngr.rfkill)
-		rfkill_unregister(priv->rfkill_mngr.rfkill);
+	if (priv->rfkill)
+		rfkill_unregister(priv->rfkill);
 
-	priv->rfkill_mngr.rfkill = NULL;
+	priv->rfkill = NULL;
 }
 EXPORT_SYMBOL(iwl_rfkill_unregister);
 
 /* set rf-kill to the right state. */
 void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
 {
-	if (!priv->rfkill_mngr.rfkill)
+	if (!priv->rfkill)
 		return;
 
-	if (!iwl_is_rfkill(priv))
-		priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
+	if (iwl_is_rfkill_hw(priv)) {
+		rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED);
+		return;
+	}
+
+	if (!iwl_is_rfkill_sw(priv))
+		rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
 	else
-		priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF;
+		rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
 }
 EXPORT_SYMBOL(iwl_rfkill_set_hw_state);