diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.h | 25 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 186 |
2 files changed, 176 insertions, 35 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index a9b3edad3868..a77497809d97 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -36,6 +36,10 @@ | |||
36 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
37 | #include <net/ieee80211_radiotap.h> | 37 | #include <net/ieee80211_radiotap.h> |
38 | 38 | ||
39 | /*used for rfkill*/ | ||
40 | #include <linux/rfkill.h> | ||
41 | #include <linux/input.h> | ||
42 | |||
39 | /* Hardware specific file defines the PCI IDs table for that hardware module */ | 43 | /* Hardware specific file defines the PCI IDs table for that hardware module */ |
40 | extern struct pci_device_id iwl3945_hw_card_ids[]; | 44 | extern struct pci_device_id iwl3945_hw_card_ids[]; |
41 | 45 | ||
@@ -686,6 +690,23 @@ enum { | |||
686 | 690 | ||
687 | #endif | 691 | #endif |
688 | 692 | ||
693 | #ifdef CONFIG_IWLWIFI_RFKILL | ||
694 | struct iwl3945_priv; | ||
695 | |||
696 | struct iwl3945_rfkill_mngr { | ||
697 | struct rfkill *rfkill; | ||
698 | struct input_dev *input_dev; | ||
699 | }; | ||
700 | |||
701 | void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv); | ||
702 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv); | ||
703 | int iwl3945_rfkill_init(struct iwl3945_priv *priv); | ||
704 | #else | ||
705 | static inline void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) {} | ||
706 | static inline void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) {} | ||
707 | static inline int iwl3945_rfkill_init(struct iwl3945_priv *priv) { return 0; } | ||
708 | #endif | ||
709 | |||
689 | #define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES | 710 | #define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES |
690 | 711 | ||
691 | struct iwl3945_priv { | 712 | struct iwl3945_priv { |
@@ -779,6 +800,10 @@ struct iwl3945_priv { | |||
779 | struct iwl3945_init_alive_resp card_alive_init; | 800 | struct iwl3945_init_alive_resp card_alive_init; |
780 | struct iwl3945_alive_resp card_alive; | 801 | struct iwl3945_alive_resp card_alive; |
781 | 802 | ||
803 | #ifdef CONFIG_IWLWIFI_RFKILL | ||
804 | struct iwl3945_rfkill_mngr rfkill_mngr; | ||
805 | #endif | ||
806 | |||
782 | #ifdef CONFIG_IWL3945_LEDS | 807 | #ifdef CONFIG_IWL3945_LEDS |
783 | struct iwl3945_led led[IWL_LED_TRG_MAX]; | 808 | struct iwl3945_led led[IWL_LED_TRG_MAX]; |
784 | unsigned long last_blink_time; | 809 | unsigned long last_blink_time; |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index fe603191c12c..43cb8ff97939 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -5921,7 +5921,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv) | |||
5921 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << | 5921 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << |
5922 | STATUS_GEO_CONFIGURED | | 5922 | STATUS_GEO_CONFIGURED | |
5923 | test_bit(STATUS_IN_SUSPEND, &priv->status) << | 5923 | test_bit(STATUS_IN_SUSPEND, &priv->status) << |
5924 | STATUS_IN_SUSPEND; | 5924 | STATUS_IN_SUSPEND | |
5925 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | ||
5926 | STATUS_EXIT_PENDING; | ||
5925 | goto exit; | 5927 | goto exit; |
5926 | } | 5928 | } |
5927 | 5929 | ||
@@ -5936,7 +5938,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv) | |||
5936 | test_bit(STATUS_IN_SUSPEND, &priv->status) << | 5938 | test_bit(STATUS_IN_SUSPEND, &priv->status) << |
5937 | STATUS_IN_SUSPEND | | 5939 | STATUS_IN_SUSPEND | |
5938 | test_bit(STATUS_FW_ERROR, &priv->status) << | 5940 | test_bit(STATUS_FW_ERROR, &priv->status) << |
5939 | STATUS_FW_ERROR; | 5941 | STATUS_FW_ERROR | |
5942 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | ||
5943 | STATUS_EXIT_PENDING; | ||
5940 | 5944 | ||
5941 | spin_lock_irqsave(&priv->lock, flags); | 5945 | spin_lock_irqsave(&priv->lock, flags); |
5942 | iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 5946 | iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
@@ -6008,11 +6012,12 @@ static int __iwl3945_up(struct iwl3945_priv *priv) | |||
6008 | else { | 6012 | else { |
6009 | set_bit(STATUS_RF_KILL_HW, &priv->status); | 6013 | set_bit(STATUS_RF_KILL_HW, &priv->status); |
6010 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { | 6014 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { |
6015 | iwl3945_rfkill_set_hw_state(priv); | ||
6011 | IWL_WARNING("Radio disabled by HW RF Kill switch\n"); | 6016 | IWL_WARNING("Radio disabled by HW RF Kill switch\n"); |
6012 | return -ENODEV; | 6017 | return -ENODEV; |
6013 | } | 6018 | } |
6014 | } | 6019 | } |
6015 | 6020 | iwl3945_rfkill_set_hw_state(priv); | |
6016 | iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); | 6021 | iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); |
6017 | 6022 | ||
6018 | rc = iwl3945_hw_nic_init(priv); | 6023 | rc = iwl3945_hw_nic_init(priv); |
@@ -6068,6 +6073,7 @@ static int __iwl3945_up(struct iwl3945_priv *priv) | |||
6068 | 6073 | ||
6069 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 6074 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
6070 | __iwl3945_down(priv); | 6075 | __iwl3945_down(priv); |
6076 | clear_bit(STATUS_EXIT_PENDING, &priv->status); | ||
6071 | 6077 | ||
6072 | /* tried to restart and config the device for as long as our | 6078 | /* tried to restart and config the device for as long as our |
6073 | * patience could withstand */ | 6079 | * patience could withstand */ |
@@ -6135,6 +6141,8 @@ static void iwl3945_bg_rf_kill(struct work_struct *work) | |||
6135 | "Kill switch must be turned off for " | 6141 | "Kill switch must be turned off for " |
6136 | "wireless networking to work.\n"); | 6142 | "wireless networking to work.\n"); |
6137 | } | 6143 | } |
6144 | |||
6145 | iwl3945_rfkill_set_hw_state(priv); | ||
6138 | mutex_unlock(&priv->mutex); | 6146 | mutex_unlock(&priv->mutex); |
6139 | } | 6147 | } |
6140 | 6148 | ||
@@ -7412,37 +7420,6 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, | |||
7412 | 7420 | ||
7413 | #endif /* CONFIG_IWL3945_DEBUG */ | 7421 | #endif /* CONFIG_IWL3945_DEBUG */ |
7414 | 7422 | ||
7415 | static ssize_t show_rf_kill(struct device *d, | ||
7416 | struct device_attribute *attr, char *buf) | ||
7417 | { | ||
7418 | /* | ||
7419 | * 0 - RF kill not enabled | ||
7420 | * 1 - SW based RF kill active (sysfs) | ||
7421 | * 2 - HW based RF kill active | ||
7422 | * 3 - Both HW and SW based RF kill active | ||
7423 | */ | ||
7424 | struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; | ||
7425 | int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) | | ||
7426 | (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0); | ||
7427 | |||
7428 | return sprintf(buf, "%i\n", val); | ||
7429 | } | ||
7430 | |||
7431 | static ssize_t store_rf_kill(struct device *d, | ||
7432 | struct device_attribute *attr, | ||
7433 | const char *buf, size_t count) | ||
7434 | { | ||
7435 | struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; | ||
7436 | |||
7437 | mutex_lock(&priv->mutex); | ||
7438 | iwl3945_radio_kill_sw(priv, buf[0] == '1'); | ||
7439 | mutex_unlock(&priv->mutex); | ||
7440 | |||
7441 | return count; | ||
7442 | } | ||
7443 | |||
7444 | static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); | ||
7445 | |||
7446 | static ssize_t show_temperature(struct device *d, | 7423 | static ssize_t show_temperature(struct device *d, |
7447 | struct device_attribute *attr, char *buf) | 7424 | struct device_attribute *attr, char *buf) |
7448 | { | 7425 | { |
@@ -7928,7 +7905,6 @@ static struct attribute *iwl3945_sysfs_entries[] = { | |||
7928 | #endif | 7905 | #endif |
7929 | &dev_attr_power_level.attr, | 7906 | &dev_attr_power_level.attr, |
7930 | &dev_attr_retry_rate.attr, | 7907 | &dev_attr_retry_rate.attr, |
7931 | &dev_attr_rf_kill.attr, | ||
7932 | &dev_attr_rs_window.attr, | 7908 | &dev_attr_rs_window.attr, |
7933 | &dev_attr_statistics.attr, | 7909 | &dev_attr_statistics.attr, |
7934 | &dev_attr_status.attr, | 7910 | &dev_attr_status.attr, |
@@ -8169,6 +8145,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8169 | pci_save_state(pdev); | 8145 | pci_save_state(pdev); |
8170 | pci_disable_device(pdev); | 8146 | pci_disable_device(pdev); |
8171 | 8147 | ||
8148 | err = iwl3945_rfkill_init(priv); | ||
8149 | if (err) | ||
8150 | IWL_ERROR("Unable to initialize RFKILL system. " | ||
8151 | "Ignoring error: %d\n", err); | ||
8152 | |||
8172 | return 0; | 8153 | return 0; |
8173 | 8154 | ||
8174 | out_free_geos: | 8155 | out_free_geos: |
@@ -8231,6 +8212,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | |||
8231 | 8212 | ||
8232 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); | 8213 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); |
8233 | 8214 | ||
8215 | iwl3945_rfkill_unregister(priv); | ||
8234 | iwl3945_dealloc_ucode_pci(priv); | 8216 | iwl3945_dealloc_ucode_pci(priv); |
8235 | 8217 | ||
8236 | if (priv->rxq.bd) | 8218 | if (priv->rxq.bd) |
@@ -8299,6 +8281,140 @@ static int iwl3945_pci_resume(struct pci_dev *pdev) | |||
8299 | 8281 | ||
8300 | #endif /* CONFIG_PM */ | 8282 | #endif /* CONFIG_PM */ |
8301 | 8283 | ||
8284 | /*************** RFKILL FUNCTIONS **********/ | ||
8285 | #ifdef CONFIG_IWLWIFI_RFKILL | ||
8286 | /* software rf-kill from user */ | ||
8287 | static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | ||
8288 | { | ||
8289 | struct iwl3945_priv *priv = data; | ||
8290 | int err = 0; | ||
8291 | |||
8292 | if (!priv->rfkill_mngr.rfkill) | ||
8293 | return 0; | ||
8294 | |||
8295 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
8296 | return 0; | ||
8297 | |||
8298 | IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state); | ||
8299 | mutex_lock(&priv->mutex); | ||
8300 | |||
8301 | switch (state) { | ||
8302 | case RFKILL_STATE_ON: | ||
8303 | iwl3945_radio_kill_sw(priv, 0); | ||
8304 | /* if HW rf-kill is set dont allow ON state */ | ||
8305 | if (iwl3945_is_rfkill(priv)) | ||
8306 | err = -EBUSY; | ||
8307 | break; | ||
8308 | case RFKILL_STATE_OFF: | ||
8309 | iwl3945_radio_kill_sw(priv, 1); | ||
8310 | if (!iwl3945_is_rfkill(priv)) | ||
8311 | err = -EBUSY; | ||
8312 | break; | ||
8313 | } | ||
8314 | mutex_unlock(&priv->mutex); | ||
8315 | |||
8316 | return err; | ||
8317 | } | ||
8318 | |||
8319 | int iwl3945_rfkill_init(struct iwl3945_priv *priv) | ||
8320 | { | ||
8321 | struct device *device = wiphy_dev(priv->hw->wiphy); | ||
8322 | int ret = 0; | ||
8323 | |||
8324 | BUG_ON(device == NULL); | ||
8325 | |||
8326 | IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); | ||
8327 | priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); | ||
8328 | if (!priv->rfkill_mngr.rfkill) { | ||
8329 | IWL_ERROR("Unable to allocate rfkill device.\n"); | ||
8330 | ret = -ENOMEM; | ||
8331 | goto error; | ||
8332 | } | ||
8333 | |||
8334 | priv->rfkill_mngr.rfkill->name = priv->cfg->name; | ||
8335 | priv->rfkill_mngr.rfkill->data = priv; | ||
8336 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | ||
8337 | priv->rfkill_mngr.rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill; | ||
8338 | priv->rfkill_mngr.rfkill->user_claim_unsupported = 1; | ||
8339 | |||
8340 | priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; | ||
8341 | priv->rfkill_mngr.rfkill->dev.class->resume = NULL; | ||
8342 | |||
8343 | priv->rfkill_mngr.input_dev = input_allocate_device(); | ||
8344 | if (!priv->rfkill_mngr.input_dev) { | ||
8345 | IWL_ERROR("Unable to allocate rfkill input device.\n"); | ||
8346 | ret = -ENOMEM; | ||
8347 | goto freed_rfkill; | ||
8348 | } | ||
8349 | |||
8350 | priv->rfkill_mngr.input_dev->name = priv->cfg->name; | ||
8351 | priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy); | ||
8352 | priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST; | ||
8353 | priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor; | ||
8354 | priv->rfkill_mngr.input_dev->dev.parent = device; | ||
8355 | priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY); | ||
8356 | set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit); | ||
8357 | |||
8358 | ret = rfkill_register(priv->rfkill_mngr.rfkill); | ||
8359 | if (ret) { | ||
8360 | IWL_ERROR("Unable to register rfkill: %d\n", ret); | ||
8361 | goto free_input_dev; | ||
8362 | } | ||
8363 | |||
8364 | ret = input_register_device(priv->rfkill_mngr.input_dev); | ||
8365 | if (ret) { | ||
8366 | IWL_ERROR("Unable to register rfkill input device: %d\n", ret); | ||
8367 | goto unregister_rfkill; | ||
8368 | } | ||
8369 | |||
8370 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | ||
8371 | return ret; | ||
8372 | |||
8373 | unregister_rfkill: | ||
8374 | rfkill_unregister(priv->rfkill_mngr.rfkill); | ||
8375 | priv->rfkill_mngr.rfkill = NULL; | ||
8376 | |||
8377 | free_input_dev: | ||
8378 | input_free_device(priv->rfkill_mngr.input_dev); | ||
8379 | priv->rfkill_mngr.input_dev = NULL; | ||
8380 | |||
8381 | freed_rfkill: | ||
8382 | if (priv->rfkill_mngr.rfkill != NULL) | ||
8383 | rfkill_free(priv->rfkill_mngr.rfkill); | ||
8384 | priv->rfkill_mngr.rfkill = NULL; | ||
8385 | |||
8386 | error: | ||
8387 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | ||
8388 | return ret; | ||
8389 | } | ||
8390 | |||
8391 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) | ||
8392 | { | ||
8393 | |||
8394 | if (priv->rfkill_mngr.input_dev) | ||
8395 | input_unregister_device(priv->rfkill_mngr.input_dev); | ||
8396 | |||
8397 | if (priv->rfkill_mngr.rfkill) | ||
8398 | rfkill_unregister(priv->rfkill_mngr.rfkill); | ||
8399 | |||
8400 | priv->rfkill_mngr.input_dev = NULL; | ||
8401 | priv->rfkill_mngr.rfkill = NULL; | ||
8402 | } | ||
8403 | |||
8404 | /* set rf-kill to the right state. */ | ||
8405 | void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) | ||
8406 | { | ||
8407 | |||
8408 | if (!priv->rfkill_mngr.rfkill) | ||
8409 | return; | ||
8410 | |||
8411 | if (!iwl3945_is_rfkill(priv)) | ||
8412 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | ||
8413 | else | ||
8414 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; | ||
8415 | } | ||
8416 | #endif | ||
8417 | |||
8302 | /***************************************************************************** | 8418 | /***************************************************************************** |
8303 | * | 8419 | * |
8304 | * driver and module entry point | 8420 | * driver and module entry point |