aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAbhijeet Kolekar <abhijeet.kolekar@intel.com>2008-06-30 05:23:18 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-30 17:37:42 -0400
commitebef2008082f579d8a40cc92e868fe8bf1296a60 (patch)
tree7e4b21c4306e6c32e8121a72413cb3f594217617 /drivers/net
parent2ff75b7877c40b1917f23cc5fafccaf3c1ab4745 (diff)
iwlwifi : Patch adds rfkill subsystem for 3945
The patch removes the sysfs interface from iwl3945 and uses the rfkill subsystem instead. Original patch by Adel, I fixed the patch to work it properly. Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com> Signed-off-by: Abhijeet Kolekar <abhijeet.kolekar@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h25
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c186
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 */
40extern struct pci_device_id iwl3945_hw_card_ids[]; 44extern 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
694struct iwl3945_priv;
695
696struct iwl3945_rfkill_mngr {
697 struct rfkill *rfkill;
698 struct input_dev *input_dev;
699};
700
701void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv);
702void iwl3945_rfkill_unregister(struct iwl3945_priv *priv);
703int iwl3945_rfkill_init(struct iwl3945_priv *priv);
704#else
705static inline void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) {}
706static inline void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) {}
707static 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
691struct iwl3945_priv { 712struct 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
7415static 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
7431static 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
7444static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
7445
7446static ssize_t show_temperature(struct device *d, 7423static 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 */
8287static 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
8319int 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
8373unregister_rfkill:
8374 rfkill_unregister(priv->rfkill_mngr.rfkill);
8375 priv->rfkill_mngr.rfkill = NULL;
8376
8377free_input_dev:
8378 input_free_device(priv->rfkill_mngr.input_dev);
8379 priv->rfkill_mngr.input_dev = NULL;
8380
8381freed_rfkill:
8382 if (priv->rfkill_mngr.rfkill != NULL)
8383 rfkill_free(priv->rfkill_mngr.rfkill);
8384 priv->rfkill_mngr.rfkill = NULL;
8385
8386error:
8387 IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
8388 return ret;
8389}
8390
8391void 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. */
8405void 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