diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/Kconfig | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/Makefile | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rfkill.c | 174 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rfkill.h | 56 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 54 |
9 files changed, 271 insertions, 34 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index c26ca749fc1e..4a5c8c0d007d 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -9,6 +9,12 @@ config IWLWIFI_LEDS | |||
9 | This option enables LEDS for the iwlwifi drivers | 9 | This option enables LEDS for the iwlwifi drivers |
10 | 10 | ||
11 | 11 | ||
12 | config IWLCORE_RFKILL | ||
13 | boolean "IWLWIFI RF kill support" | ||
14 | depends on IWLCORE | ||
15 | select RFKILL | ||
16 | select RFKILL_INPUT | ||
17 | |||
12 | config IWL4965 | 18 | config IWL4965 |
13 | tristate "Intel Wireless WiFi 4965AGN" | 19 | tristate "Intel Wireless WiFi 4965AGN" |
14 | depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL | 20 | depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL |
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 64fca4d9ac76..2751e8aa97d7 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -9,6 +9,10 @@ ifeq ($(CONFIG_IWLWIFI_LEDS),y) | |||
9 | iwlcore-objs += iwl-led.o | 9 | iwlcore-objs += iwl-led.o |
10 | endif | 10 | endif |
11 | 11 | ||
12 | ifeq ($(CONFIG_IWLCORE_RFKILL),y) | ||
13 | iwlcore-objs += iwl-rfkill.o | ||
14 | endif | ||
15 | |||
12 | obj-$(CONFIG_IWL3945) += iwl3945.o | 16 | obj-$(CONFIG_IWL3945) += iwl3945.o |
13 | iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o | 17 | iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o |
14 | 18 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index e5f64d7fbfde..3ab5d8292502 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -4961,6 +4961,7 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
4961 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 4961 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
4962 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 4962 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
4963 | }, | 4963 | }, |
4964 | .radio_kill_sw = iwl4965_radio_kill_sw, | ||
4964 | }; | 4965 | }; |
4965 | 4966 | ||
4966 | static struct iwl_ops iwl4965_ops = { | 4967 | static struct iwl_ops iwl4965_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 069e591981b2..ca864fa65ca4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h | |||
@@ -40,6 +40,7 @@ | |||
40 | extern struct pci_device_id iwl4965_hw_card_ids[]; | 40 | extern struct pci_device_id iwl4965_hw_card_ids[]; |
41 | 41 | ||
42 | #define DRV_NAME "iwl4965" | 42 | #define DRV_NAME "iwl4965" |
43 | #include "iwl-rfkill.h" | ||
43 | #include "iwl-eeprom.h" | 44 | #include "iwl-eeprom.h" |
44 | #include "iwl-4965-hw.h" | 45 | #include "iwl-4965-hw.h" |
45 | #include "iwl-csr.h" | 46 | #include "iwl-csr.h" |
@@ -739,6 +740,7 @@ extern int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index | |||
739 | extern int iwl4965_queue_space(const struct iwl4965_queue *q); | 740 | extern int iwl4965_queue_space(const struct iwl4965_queue *q); |
740 | struct iwl_priv; | 741 | struct iwl_priv; |
741 | 742 | ||
743 | extern void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio); | ||
742 | /* | 744 | /* |
743 | * Forward declare iwl-4965.c functions for iwl-base.c | 745 | * Forward declare iwl-4965.c functions for iwl-base.c |
744 | */ | 746 | */ |
@@ -1050,6 +1052,9 @@ struct iwl_priv { | |||
1050 | * 4965's initialize alive response contains some calibration data. */ | 1052 | * 4965's initialize alive response contains some calibration data. */ |
1051 | struct iwl4965_init_alive_resp card_alive_init; | 1053 | struct iwl4965_init_alive_resp card_alive_init; |
1052 | struct iwl4965_alive_resp card_alive; | 1054 | struct iwl4965_alive_resp card_alive; |
1055 | #ifdef CONFIG_IWLCORE_RFKILL | ||
1056 | struct iwl_rfkill_mngr rfkill_mngr; | ||
1057 | #endif | ||
1053 | 1058 | ||
1054 | #ifdef CONFIG_IWL4965_LEDS | 1059 | #ifdef CONFIG_IWL4965_LEDS |
1055 | struct iwl4965_led led[IWL_LED_TRG_MAX]; | 1060 | struct iwl4965_led led[IWL_LED_TRG_MAX]; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 342a269b8abb..49fb52f07354 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -35,6 +35,7 @@ struct iwl_priv; /* FIXME: remove */ | |||
35 | #include "iwl-debug.h" | 35 | #include "iwl-debug.h" |
36 | #include "iwl-eeprom.h" | 36 | #include "iwl-eeprom.h" |
37 | #include "iwl-core.h" | 37 | #include "iwl-core.h" |
38 | #include "iwl-rfkill.h" | ||
38 | 39 | ||
39 | #include "iwl-4965.h" /* FIXME: remove */ | 40 | #include "iwl-4965.h" /* FIXME: remove */ |
40 | 41 | ||
@@ -257,12 +258,15 @@ int iwlcore_low_level_notify(struct iwl_priv *priv, | |||
257 | { | 258 | { |
258 | switch (notify) { | 259 | switch (notify) { |
259 | case IWLCORE_INIT_EVT: | 260 | case IWLCORE_INIT_EVT: |
261 | iwl_rfkill_init(priv); | ||
260 | break; | 262 | break; |
261 | case IWLCORE_START_EVT: | 263 | case IWLCORE_START_EVT: |
262 | break; | 264 | break; |
263 | case IWLCORE_STOP_EVT: | 265 | case IWLCORE_STOP_EVT: |
264 | break; | 266 | break; |
265 | case IWLCORE_REMOVE_EVT: | 267 | case IWLCORE_REMOVE_EVT: |
268 | iwl_rfkill_unregister(priv); | ||
269 | iwl_rfkill_free(priv); | ||
266 | break; | 270 | break; |
267 | } | 271 | } |
268 | 272 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4dfa05948d73..5efafe1a1d86 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -91,6 +91,7 @@ struct iwl_lib_ops { | |||
91 | int (*init_drv)(struct iwl_priv *priv); | 91 | int (*init_drv)(struct iwl_priv *priv); |
92 | /* eeprom operations (as defined in iwl-eeprom.h) */ | 92 | /* eeprom operations (as defined in iwl-eeprom.h) */ |
93 | struct iwl_eeprom_ops eeprom_ops; | 93 | struct iwl_eeprom_ops eeprom_ops; |
94 | void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio); | ||
94 | }; | 95 | }; |
95 | 96 | ||
96 | struct iwl_ops { | 97 | struct iwl_ops { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c new file mode 100644 index 000000000000..66abf52e8987 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c | |||
@@ -0,0 +1,174 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * Portions of this file are derived from the ipw3945 project, as well | ||
6 | * as portions of the ieee80211 subsystem header files. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution in the | ||
22 | * file called LICENSE. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * James P. Ketrenos <ipw2100-admin@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/version.h> | ||
31 | #include <linux/init.h> | ||
32 | |||
33 | #include <net/mac80211.h> | ||
34 | |||
35 | #include "iwl-eeprom.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-4965.h" | ||
38 | #include "iwl-helpers.h" | ||
39 | |||
40 | |||
41 | static inline int iwl_is_rfkill(struct iwl_priv *priv) | ||
42 | { | ||
43 | return test_bit(STATUS_RF_KILL_HW, &priv->status) || | ||
44 | test_bit(STATUS_RF_KILL_SW, &priv->status); | ||
45 | } | ||
46 | |||
47 | |||
48 | /* software rf-kill from user */ | ||
49 | static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | ||
50 | { | ||
51 | struct iwl_priv *priv = data; | ||
52 | int err = 0; | ||
53 | |||
54 | if (!priv->rfkill_mngr.rfkill) | ||
55 | return 0; | ||
56 | |||
57 | IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state); | ||
58 | mutex_lock(&priv->mutex); | ||
59 | |||
60 | switch (state) { | ||
61 | case RFKILL_STATE_ON: | ||
62 | priv->cfg->ops->lib->radio_kill_sw(priv, 0); | ||
63 | /* if HW rf-kill is set dont allow ON state */ | ||
64 | if (iwl_is_rfkill(priv)) | ||
65 | err = -EBUSY; | ||
66 | break; | ||
67 | case RFKILL_STATE_OFF: | ||
68 | priv->cfg->ops->lib->radio_kill_sw(priv, 1); | ||
69 | if (!iwl_is_rfkill(priv)) | ||
70 | err = -EBUSY; | ||
71 | break; | ||
72 | } | ||
73 | mutex_unlock(&priv->mutex); | ||
74 | |||
75 | return err; | ||
76 | } | ||
77 | |||
78 | int iwl_rfkill_init(struct iwl_priv *priv) | ||
79 | { | ||
80 | struct device *device = wiphy_dev(priv->hw->wiphy); | ||
81 | int ret = 0; | ||
82 | |||
83 | BUG_ON(device == NULL); | ||
84 | |||
85 | priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); | ||
86 | if (!priv->rfkill_mngr.rfkill) { | ||
87 | ret = -ENOMEM; | ||
88 | goto error; | ||
89 | } | ||
90 | |||
91 | priv->rfkill_mngr.rfkill->name = priv->cfg->name; | ||
92 | priv->rfkill_mngr.rfkill->data = priv; | ||
93 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | ||
94 | priv->rfkill_mngr.rfkill->toggle_radio = iwl_rfkill_soft_rf_kill; | ||
95 | priv->rfkill_mngr.rfkill->user_claim_unsupported = 1; | ||
96 | |||
97 | priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; | ||
98 | priv->rfkill_mngr.rfkill->dev.class->resume = NULL; | ||
99 | |||
100 | priv->rfkill_mngr.input_dev = input_allocate_device(); | ||
101 | if (!priv->rfkill_mngr.input_dev) { | ||
102 | ret = -ENOMEM; | ||
103 | goto freed_rfkill; | ||
104 | } | ||
105 | |||
106 | priv->rfkill_mngr.input_dev->name = priv->cfg->name; | ||
107 | priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy); | ||
108 | priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST; | ||
109 | priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor; | ||
110 | priv->rfkill_mngr.input_dev->dev.parent = device; | ||
111 | priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY); | ||
112 | set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit); | ||
113 | |||
114 | ret = rfkill_register(priv->rfkill_mngr.rfkill); | ||
115 | if (ret) | ||
116 | goto free_input_dev; | ||
117 | |||
118 | ret = input_register_device(priv->rfkill_mngr.input_dev); | ||
119 | if (ret) | ||
120 | goto unregister_rfkill; | ||
121 | |||
122 | return ret; | ||
123 | |||
124 | unregister_rfkill: | ||
125 | rfkill_unregister(priv->rfkill_mngr.rfkill); | ||
126 | |||
127 | free_input_dev: | ||
128 | input_free_device(priv->rfkill_mngr.input_dev); | ||
129 | priv->rfkill_mngr.input_dev = NULL; | ||
130 | |||
131 | freed_rfkill: | ||
132 | rfkill_free(priv->rfkill_mngr.rfkill); | ||
133 | priv->rfkill_mngr.rfkill = NULL; | ||
134 | |||
135 | error: | ||
136 | return ret; | ||
137 | } | ||
138 | EXPORT_SYMBOL(iwl_rfkill_init); | ||
139 | |||
140 | void iwl_rfkill_unregister(struct iwl_priv *priv) | ||
141 | { | ||
142 | |||
143 | if (priv->rfkill_mngr.input_dev) | ||
144 | input_unregister_device(priv->rfkill_mngr.input_dev); | ||
145 | |||
146 | if (priv->rfkill_mngr.rfkill) | ||
147 | rfkill_unregister(priv->rfkill_mngr.rfkill); | ||
148 | } | ||
149 | EXPORT_SYMBOL(iwl_rfkill_unregister); | ||
150 | |||
151 | |||
152 | void iwl_rfkill_free(struct iwl_priv *priv) | ||
153 | { | ||
154 | if (priv->rfkill_mngr.input_dev) | ||
155 | input_free_device(priv->rfkill_mngr.input_dev); | ||
156 | |||
157 | if (priv->rfkill_mngr.rfkill) | ||
158 | rfkill_free(priv->rfkill_mngr.rfkill); | ||
159 | } | ||
160 | EXPORT_SYMBOL(iwl_rfkill_free); | ||
161 | |||
162 | /* set rf-kill to the right state. */ | ||
163 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv) | ||
164 | { | ||
165 | |||
166 | if (!priv->rfkill_mngr.rfkill) | ||
167 | return; | ||
168 | |||
169 | if (!iwl_is_rfkill(priv)) | ||
170 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | ||
171 | else | ||
172 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; | ||
173 | } | ||
174 | EXPORT_SYMBOL(iwl_rfkill_set_hw_state); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h new file mode 100644 index 000000000000..a5cbc5ab45d9 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * Portions of this file are derived from the ipw3945 project, as well | ||
6 | * as portions of the ieee80211 subsystem header files. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution in the | ||
22 | * file called LICENSE. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * James P. Ketrenos <ipw2100-admin@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | #ifndef __iwl_rf_kill_h__ | ||
29 | #define __iwl_rf_kill_h__ | ||
30 | |||
31 | struct iwl_priv; | ||
32 | |||
33 | #include <linux/rfkill.h> | ||
34 | #include <linux/input.h> | ||
35 | |||
36 | |||
37 | #ifdef CONFIG_IWLCORE_RFKILL | ||
38 | struct iwl_rfkill_mngr { | ||
39 | struct rfkill *rfkill; | ||
40 | struct input_dev *input_dev; | ||
41 | }; | ||
42 | |||
43 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv); | ||
44 | void iwl_rfkill_free(struct iwl_priv *priv); | ||
45 | void iwl_rfkill_unregister(struct iwl_priv *priv); | ||
46 | int iwl_rfkill_init(struct iwl_priv *priv); | ||
47 | #else | ||
48 | static inline void iwl_rfkill_set_hw_state(struct iwl_priv *priv) {} | ||
49 | static inline void iwl_rfkill_free(struct iwl_priv *priv) {} | ||
50 | static inline void iwl_rfkill_unregister(struct iwl_priv *priv) {} | ||
51 | static inline int iwl_rfkill_init(struct iwl_priv *priv) { return 0; } | ||
52 | #endif | ||
53 | |||
54 | |||
55 | |||
56 | #endif /* __iwl_rf_kill_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 5261b6179a86..7f56565b4002 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -2607,7 +2607,7 @@ static void iwl4965_set_rate(struct iwl_priv *priv) | |||
2607 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | 2607 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; |
2608 | } | 2608 | } |
2609 | 2609 | ||
2610 | static void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) | 2610 | void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) |
2611 | { | 2611 | { |
2612 | unsigned long flags; | 2612 | unsigned long flags; |
2613 | 2613 | ||
@@ -2625,8 +2625,16 @@ static void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) | |||
2625 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, | 2625 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, |
2626 | CSR_UCODE_SW_BIT_RFKILL); | 2626 | CSR_UCODE_SW_BIT_RFKILL); |
2627 | spin_unlock_irqrestore(&priv->lock, flags); | 2627 | spin_unlock_irqrestore(&priv->lock, flags); |
2628 | iwl4965_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0); | 2628 | /* call the host command only if no hw rf-kill set */ |
2629 | if (!test_bit(STATUS_RF_KILL_HW, &priv->status)) | ||
2630 | iwl4965_send_card_state(priv, | ||
2631 | CARD_STATE_CMD_DISABLE, | ||
2632 | 0); | ||
2629 | set_bit(STATUS_RF_KILL_SW, &priv->status); | 2633 | set_bit(STATUS_RF_KILL_SW, &priv->status); |
2634 | |||
2635 | /* make sure mac80211 stop sending Tx frame */ | ||
2636 | if (priv->mac80211_registered) | ||
2637 | ieee80211_stop_queues(priv->hw); | ||
2630 | } | 2638 | } |
2631 | return; | 2639 | return; |
2632 | } | 2640 | } |
@@ -5852,6 +5860,7 @@ static int __iwl4965_up(struct iwl_priv *priv) | |||
5852 | if (test_bit(STATUS_RF_KILL_SW, &priv->status)) { | 5860 | if (test_bit(STATUS_RF_KILL_SW, &priv->status)) { |
5853 | IWL_WARNING("Radio disabled by SW RF kill (module " | 5861 | IWL_WARNING("Radio disabled by SW RF kill (module " |
5854 | "parameter)\n"); | 5862 | "parameter)\n"); |
5863 | iwl_rfkill_set_hw_state(priv); | ||
5855 | return -ENODEV; | 5864 | return -ENODEV; |
5856 | } | 5865 | } |
5857 | 5866 | ||
@@ -5867,11 +5876,13 @@ static int __iwl4965_up(struct iwl_priv *priv) | |||
5867 | else { | 5876 | else { |
5868 | set_bit(STATUS_RF_KILL_HW, &priv->status); | 5877 | set_bit(STATUS_RF_KILL_HW, &priv->status); |
5869 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { | 5878 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { |
5879 | iwl_rfkill_set_hw_state(priv); | ||
5870 | IWL_WARNING("Radio disabled by HW RF Kill switch\n"); | 5880 | IWL_WARNING("Radio disabled by HW RF Kill switch\n"); |
5871 | return -ENODEV; | 5881 | return -ENODEV; |
5872 | } | 5882 | } |
5873 | } | 5883 | } |
5874 | 5884 | ||
5885 | iwl_rfkill_set_hw_state(priv); | ||
5875 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | 5886 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); |
5876 | 5887 | ||
5877 | rc = iwl4965_hw_nic_init(priv); | 5888 | rc = iwl4965_hw_nic_init(priv); |
@@ -5985,6 +5996,9 @@ static void iwl4965_bg_rf_kill(struct work_struct *work) | |||
5985 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) | 5996 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) |
5986 | queue_work(priv->workqueue, &priv->restart); | 5997 | queue_work(priv->workqueue, &priv->restart); |
5987 | } else { | 5998 | } else { |
5999 | /* make sure mac80211 stop sending Tx frame */ | ||
6000 | if (priv->mac80211_registered) | ||
6001 | ieee80211_stop_queues(priv->hw); | ||
5988 | 6002 | ||
5989 | if (!test_bit(STATUS_RF_KILL_HW, &priv->status)) | 6003 | if (!test_bit(STATUS_RF_KILL_HW, &priv->status)) |
5990 | IWL_DEBUG_RF_KILL("Can not turn radio back on - " | 6004 | IWL_DEBUG_RF_KILL("Can not turn radio back on - " |
@@ -5994,6 +6008,8 @@ static void iwl4965_bg_rf_kill(struct work_struct *work) | |||
5994 | "Kill switch must be turned off for " | 6008 | "Kill switch must be turned off for " |
5995 | "wireless networking to work.\n"); | 6009 | "wireless networking to work.\n"); |
5996 | } | 6010 | } |
6011 | iwl_rfkill_set_hw_state(priv); | ||
6012 | |||
5997 | mutex_unlock(&priv->mutex); | 6013 | mutex_unlock(&priv->mutex); |
5998 | } | 6014 | } |
5999 | 6015 | ||
@@ -6674,7 +6690,8 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co | |||
6674 | } | 6690 | } |
6675 | #endif | 6691 | #endif |
6676 | 6692 | ||
6677 | iwl4965_radio_kill_sw(priv, !conf->radio_enabled); | 6693 | if (priv->cfg->ops->lib->radio_kill_sw) |
6694 | priv->cfg->ops->lib->radio_kill_sw(priv, !conf->radio_enabled); | ||
6678 | 6695 | ||
6679 | if (!conf->radio_enabled) { | 6696 | if (!conf->radio_enabled) { |
6680 | IWL_DEBUG_MAC80211("leave - radio disabled\n"); | 6697 | IWL_DEBUG_MAC80211("leave - radio disabled\n"); |
@@ -7449,36 +7466,6 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, | |||
7449 | 7466 | ||
7450 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 7467 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
7451 | 7468 | ||
7452 | static ssize_t show_rf_kill(struct device *d, | ||
7453 | struct device_attribute *attr, char *buf) | ||
7454 | { | ||
7455 | /* | ||
7456 | * 0 - RF kill not enabled | ||
7457 | * 1 - SW based RF kill active (sysfs) | ||
7458 | * 2 - HW based RF kill active | ||
7459 | * 3 - Both HW and SW based RF kill active | ||
7460 | */ | ||
7461 | struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; | ||
7462 | int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) | | ||
7463 | (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0); | ||
7464 | |||
7465 | return sprintf(buf, "%i\n", val); | ||
7466 | } | ||
7467 | |||
7468 | static ssize_t store_rf_kill(struct device *d, | ||
7469 | struct device_attribute *attr, | ||
7470 | const char *buf, size_t count) | ||
7471 | { | ||
7472 | struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; | ||
7473 | |||
7474 | mutex_lock(&priv->mutex); | ||
7475 | iwl4965_radio_kill_sw(priv, buf[0] == '1'); | ||
7476 | mutex_unlock(&priv->mutex); | ||
7477 | |||
7478 | return count; | ||
7479 | } | ||
7480 | |||
7481 | static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); | ||
7482 | 7469 | ||
7483 | static ssize_t show_temperature(struct device *d, | 7470 | static ssize_t show_temperature(struct device *d, |
7484 | struct device_attribute *attr, char *buf) | 7471 | struct device_attribute *attr, char *buf) |
@@ -7964,7 +7951,6 @@ static struct attribute *iwl4965_sysfs_entries[] = { | |||
7964 | #endif | 7951 | #endif |
7965 | &dev_attr_power_level.attr, | 7952 | &dev_attr_power_level.attr, |
7966 | &dev_attr_retry_rate.attr, | 7953 | &dev_attr_retry_rate.attr, |
7967 | &dev_attr_rf_kill.attr, | ||
7968 | &dev_attr_rs_window.attr, | 7954 | &dev_attr_rs_window.attr, |
7969 | &dev_attr_statistics.attr, | 7955 | &dev_attr_statistics.attr, |
7970 | &dev_attr_status.attr, | 7956 | &dev_attr_status.attr, |