test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
                                        STATUS_GEO_CONFIGURED |
                               test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-                                       STATUS_IN_SUSPEND;
+                                       STATUS_IN_SUSPEND |
+                               test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+                                       STATUS_EXIT_PENDING;
                goto exit;
        }
 
                        test_bit(STATUS_IN_SUSPEND, &priv->status) <<
                                STATUS_IN_SUSPEND |
                        test_bit(STATUS_FW_ERROR, &priv->status) <<
-                               STATUS_FW_ERROR;
+                               STATUS_FW_ERROR |
+                       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+                               STATUS_EXIT_PENDING;
 
        spin_lock_irqsave(&priv->lock, flags);
        iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
        else {
                set_bit(STATUS_RF_KILL_HW, &priv->status);
                if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
+                       iwl3945_rfkill_set_hw_state(priv);
                        IWL_WARNING("Radio disabled by HW RF Kill switch\n");
                        return -ENODEV;
                }
        }
-
+       iwl3945_rfkill_set_hw_state(priv);
        iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
 
        rc = iwl3945_hw_nic_init(priv);
 
        set_bit(STATUS_EXIT_PENDING, &priv->status);
        __iwl3945_down(priv);
+       clear_bit(STATUS_EXIT_PENDING, &priv->status);
 
        /* tried to restart and config the device for as long as our
         * patience could withstand */
                                    "Kill switch must be turned off for "
                                    "wireless networking to work.\n");
        }
+
+       iwl3945_rfkill_set_hw_state(priv);
        mutex_unlock(&priv->mutex);
 }
 
 
 #endif /* CONFIG_IWL3945_DEBUG */
 
-static ssize_t show_rf_kill(struct device *d,
-                           struct device_attribute *attr, char *buf)
-{
-       /*
-        * 0 - RF kill not enabled
-        * 1 - SW based RF kill active (sysfs)
-        * 2 - HW based RF kill active
-        * 3 - Both HW and SW based RF kill active
-        */
-       struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
-       int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) |
-                 (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0);
-
-       return sprintf(buf, "%i\n", val);
-}
-
-static ssize_t store_rf_kill(struct device *d,
-                            struct device_attribute *attr,
-                            const char *buf, size_t count)
-{
-       struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
-
-       mutex_lock(&priv->mutex);
-       iwl3945_radio_kill_sw(priv, buf[0] == '1');
-       mutex_unlock(&priv->mutex);
-
-       return count;
-}
-
-static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
-
 static ssize_t show_temperature(struct device *d,
                                struct device_attribute *attr, char *buf)
 {
 #endif
        &dev_attr_power_level.attr,
        &dev_attr_retry_rate.attr,
-       &dev_attr_rf_kill.attr,
        &dev_attr_rs_window.attr,
        &dev_attr_statistics.attr,
        &dev_attr_status.attr,
        pci_save_state(pdev);
        pci_disable_device(pdev);
 
+       err = iwl3945_rfkill_init(priv);
+       if (err)
+               IWL_ERROR("Unable to initialize RFKILL system. "
+                                 "Ignoring error: %d\n", err);
+
        return 0;
 
  out_free_geos:
 
        sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
+       iwl3945_rfkill_unregister(priv);
        iwl3945_dealloc_ucode_pci(priv);
 
        if (priv->rxq.bd)
 
 #endif /* CONFIG_PM */
 
+/*************** RFKILL FUNCTIONS **********/
+#ifdef CONFIG_IWLWIFI_RFKILL
+/* software rf-kill from user */
+static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
+{
+       struct iwl3945_priv *priv = data;
+       int err = 0;
+
+       if (!priv->rfkill_mngr.rfkill)
+       return 0;
+
+       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+               return 0;
+
+       IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state);
+       mutex_lock(&priv->mutex);
+
+       switch (state) {
+       case RFKILL_STATE_ON:
+               iwl3945_radio_kill_sw(priv, 0);
+               /* if HW rf-kill is set dont allow ON state */
+               if (iwl3945_is_rfkill(priv))
+                       err = -EBUSY;
+               break;
+       case RFKILL_STATE_OFF:
+               iwl3945_radio_kill_sw(priv, 1);
+               if (!iwl3945_is_rfkill(priv))
+                       err = -EBUSY;
+               break;
+       }
+       mutex_unlock(&priv->mutex);
+
+       return err;
+}
+
+int iwl3945_rfkill_init(struct iwl3945_priv *priv)
+{
+       struct device *device = wiphy_dev(priv->hw->wiphy);
+       int ret = 0;
+
+       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) {
+               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 = iwl3945_rfkill_soft_rf_kill;
+       priv->rfkill_mngr.rfkill->user_claim_unsupported = 1;
+
+       priv->rfkill_mngr.rfkill->dev.class->suspend = NULL;
+       priv->rfkill_mngr.rfkill->dev.class->resume = NULL;
+
+       priv->rfkill_mngr.input_dev = input_allocate_device();
+       if (!priv->rfkill_mngr.input_dev) {
+               IWL_ERROR("Unable to allocate rfkill input device.\n");
+               ret = -ENOMEM;
+               goto freed_rfkill;
+       }
+
+       priv->rfkill_mngr.input_dev->name = priv->cfg->name;
+       priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy);
+       priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST;
+       priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor;
+       priv->rfkill_mngr.input_dev->dev.parent = device;
+       priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY);
+       set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit);
+
+       ret = rfkill_register(priv->rfkill_mngr.rfkill);
+       if (ret) {
+               IWL_ERROR("Unable to register rfkill: %d\n", ret);
+               goto free_input_dev;
+       }
+
+       ret = input_register_device(priv->rfkill_mngr.input_dev);
+       if (ret) {
+               IWL_ERROR("Unable to register rfkill input device: %d\n", ret);
+               goto unregister_rfkill;
+       }
+
+       IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
+       return ret;
+
+unregister_rfkill:
+       rfkill_unregister(priv->rfkill_mngr.rfkill);
+       priv->rfkill_mngr.rfkill = NULL;
+
+free_input_dev:
+       input_free_device(priv->rfkill_mngr.input_dev);
+       priv->rfkill_mngr.input_dev = NULL;
+
+freed_rfkill:
+       if (priv->rfkill_mngr.rfkill != NULL)
+               rfkill_free(priv->rfkill_mngr.rfkill);
+       priv->rfkill_mngr.rfkill = NULL;
+
+error:
+       IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
+       return ret;
+}
+
+void iwl3945_rfkill_unregister(struct iwl3945_priv *priv)
+{
+
+       if (priv->rfkill_mngr.input_dev)
+               input_unregister_device(priv->rfkill_mngr.input_dev);
+
+       if (priv->rfkill_mngr.rfkill)
+               rfkill_unregister(priv->rfkill_mngr.rfkill);
+
+       priv->rfkill_mngr.input_dev = NULL;
+       priv->rfkill_mngr.rfkill = NULL;
+}
+
+/* set rf-kill to the right state. */
+void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv)
+{
+
+       if (!priv->rfkill_mngr.rfkill)
+               return;
+
+       if (!iwl3945_is_rfkill(priv))
+               priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
+       else
+               priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF;
+}
+#endif
+
 /*****************************************************************************
  *
  * driver and module entry point