diff options
author | Adel Gadllah <adel.gadllah@gmail.com> | 2008-07-01 11:49:50 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-07-08 10:21:35 -0400 |
commit | 80fcc9e28cf3a209fbfb39a7bbddc313c59c7424 (patch) | |
tree | fe77fdd591652db82a87bff12d4b1528a1ecdfe4 /drivers | |
parent | ebd74487d4b7a48ab8513ecfe3d321346d7c602e (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/Kconfig | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rfkill.c | 57 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rfkill.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 117 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 8 |
8 files changed, 105 insertions, 111 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index b628a44057f7..82b66a3d3a5d 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -104,6 +104,7 @@ config IWL3945 | |||
104 | select IWLWIFI | 104 | select IWLWIFI |
105 | select MAC80211_LEDS if IWL3945_LEDS | 105 | select MAC80211_LEDS if IWL3945_LEDS |
106 | select LEDS_CLASS if IWL3945_LEDS | 106 | select LEDS_CLASS if IWL3945_LEDS |
107 | select RFKILL if IWL3945_RFKILL | ||
107 | ---help--- | 108 | ---help--- |
108 | Select to build the driver supporting the: | 109 | Select to build the driver supporting the: |
109 | 110 | ||
@@ -126,6 +127,10 @@ config IWL3945 | |||
126 | say M here and read <file:Documentation/kbuild/modules.txt>. The | 127 | say M here and read <file:Documentation/kbuild/modules.txt>. The |
127 | module will be called iwl3945.ko. | 128 | module will be called iwl3945.ko. |
128 | 129 | ||
130 | config IWL3945_RFKILL | ||
131 | bool "Enable RF kill support in iwl3945 drivers" | ||
132 | depends on IWL3945 | ||
133 | |||
129 | config IWL3945_SPECTRUM_MEASUREMENT | 134 | config IWL3945_SPECTRUM_MEASUREMENT |
130 | bool "Enable Spectrum Measurement in iwl3945 drivers" | 135 | bool "Enable Spectrum Measurement in iwl3945 drivers" |
131 | depends on IWL3945 | 136 | depends on IWL3945 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index a77497809d97..9c0a09eaca6f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -690,14 +690,9 @@ enum { | |||
690 | 690 | ||
691 | #endif | 691 | #endif |
692 | 692 | ||
693 | #ifdef CONFIG_IWLWIFI_RFKILL | 693 | #ifdef CONFIG_IWL3945_RFKILL |
694 | struct iwl3945_priv; | 694 | struct iwl3945_priv; |
695 | 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); | 696 | void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv); |
702 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv); | 697 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv); |
703 | int iwl3945_rfkill_init(struct iwl3945_priv *priv); | 698 | int iwl3945_rfkill_init(struct iwl3945_priv *priv); |
@@ -800,8 +795,8 @@ struct iwl3945_priv { | |||
800 | struct iwl3945_init_alive_resp card_alive_init; | 795 | struct iwl3945_init_alive_resp card_alive_init; |
801 | struct iwl3945_alive_resp card_alive; | 796 | struct iwl3945_alive_resp card_alive; |
802 | 797 | ||
803 | #ifdef CONFIG_IWLWIFI_RFKILL | 798 | #ifdef CONFIG_IWL3945_RFKILL |
804 | struct iwl3945_rfkill_mngr rfkill_mngr; | 799 | struct rfkill *rfkill; |
805 | #endif | 800 | #endif |
806 | 801 | ||
807 | #ifdef CONFIG_IWL3945_LEDS | 802 | #ifdef CONFIG_IWL3945_LEDS |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index eb4abe1ebbdb..dafd62c7dfd6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -356,10 +356,19 @@ static inline int iwl_is_init(struct iwl_priv *priv) | |||
356 | return test_bit(STATUS_INIT, &priv->status); | 356 | return test_bit(STATUS_INIT, &priv->status); |
357 | } | 357 | } |
358 | 358 | ||
359 | static inline int iwl_is_rfkill_sw(struct iwl_priv *priv) | ||
360 | { | ||
361 | return test_bit(STATUS_RF_KILL_SW, &priv->status); | ||
362 | } | ||
363 | |||
364 | static inline int iwl_is_rfkill_hw(struct iwl_priv *priv) | ||
365 | { | ||
366 | return test_bit(STATUS_RF_KILL_HW, &priv->status); | ||
367 | } | ||
368 | |||
359 | static inline int iwl_is_rfkill(struct iwl_priv *priv) | 369 | static inline int iwl_is_rfkill(struct iwl_priv *priv) |
360 | { | 370 | { |
361 | return test_bit(STATUS_RF_KILL_HW, &priv->status) || | 371 | return iwl_is_rfkill_hw(priv) || iwl_is_rfkill_sw(priv); |
362 | test_bit(STATUS_RF_KILL_SW, &priv->status); | ||
363 | } | 372 | } |
364 | 373 | ||
365 | static inline int iwl_is_ready_rf(struct iwl_priv *priv) | 374 | static inline int iwl_is_ready_rf(struct iwl_priv *priv) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d1289cfc213c..70e10ea35a51 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -929,7 +929,7 @@ struct iwl_priv { | |||
929 | struct iwl_init_alive_resp card_alive_init; | 929 | struct iwl_init_alive_resp card_alive_init; |
930 | struct iwl_alive_resp card_alive; | 930 | struct iwl_alive_resp card_alive; |
931 | #ifdef CONFIG_IWLWIFI_RFKILL | 931 | #ifdef CONFIG_IWLWIFI_RFKILL |
932 | struct iwl_rfkill_mngr rfkill_mngr; | 932 | struct rfkill *rfkill; |
933 | #endif | 933 | #endif |
934 | 934 | ||
935 | #ifdef CONFIG_IWLWIFI_LEDS | 935 | #ifdef CONFIG_IWLWIFI_LEDS |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index eebaf43f66b2..e5e5846e9f25 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c | |||
@@ -44,7 +44,7 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | |||
44 | struct iwl_priv *priv = data; | 44 | struct iwl_priv *priv = data; |
45 | int err = 0; | 45 | int err = 0; |
46 | 46 | ||
47 | if (!priv->rfkill_mngr.rfkill) | 47 | if (!priv->rfkill) |
48 | return 0; | 48 | return 0; |
49 | 49 | ||
50 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 50 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
@@ -55,20 +55,20 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | |||
55 | 55 | ||
56 | switch (state) { | 56 | switch (state) { |
57 | case RFKILL_STATE_UNBLOCKED: | 57 | case RFKILL_STATE_UNBLOCKED: |
58 | iwl_radio_kill_sw_enable_radio(priv); | 58 | if (iwl_is_rfkill_hw(priv)) { |
59 | /* if HW rf-kill is set dont allow ON state */ | ||
60 | if (iwl_is_rfkill(priv)) | ||
61 | err = -EBUSY; | 59 | err = -EBUSY; |
60 | goto out_unlock; | ||
61 | } | ||
62 | iwl_radio_kill_sw_enable_radio(priv); | ||
62 | break; | 63 | break; |
63 | case RFKILL_STATE_SOFT_BLOCKED: | 64 | case RFKILL_STATE_SOFT_BLOCKED: |
64 | iwl_radio_kill_sw_disable_radio(priv); | 65 | iwl_radio_kill_sw_disable_radio(priv); |
65 | if (!iwl_is_rfkill(priv)) | ||
66 | err = -EBUSY; | ||
67 | break; | 66 | break; |
68 | default: | 67 | default: |
69 | IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); | 68 | IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); |
70 | break; | 69 | break; |
71 | } | 70 | } |
71 | out_unlock: | ||
72 | mutex_unlock(&priv->mutex); | 72 | mutex_unlock(&priv->mutex); |
73 | 73 | ||
74 | return err; | 74 | return err; |
@@ -82,23 +82,23 @@ int iwl_rfkill_init(struct iwl_priv *priv) | |||
82 | BUG_ON(device == NULL); | 82 | BUG_ON(device == NULL); |
83 | 83 | ||
84 | IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); | 84 | IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); |
85 | priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); | 85 | priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); |
86 | if (!priv->rfkill_mngr.rfkill) { | 86 | if (!priv->rfkill) { |
87 | IWL_ERROR("Unable to allocate rfkill device.\n"); | 87 | IWL_ERROR("Unable to allocate rfkill device.\n"); |
88 | ret = -ENOMEM; | 88 | ret = -ENOMEM; |
89 | goto error; | 89 | goto error; |
90 | } | 90 | } |
91 | 91 | ||
92 | priv->rfkill_mngr.rfkill->name = priv->cfg->name; | 92 | priv->rfkill->name = priv->cfg->name; |
93 | priv->rfkill_mngr.rfkill->data = priv; | 93 | priv->rfkill->data = priv; |
94 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | 94 | priv->rfkill->state = RFKILL_STATE_UNBLOCKED; |
95 | priv->rfkill_mngr.rfkill->toggle_radio = iwl_rfkill_soft_rf_kill; | 95 | priv->rfkill->toggle_radio = iwl_rfkill_soft_rf_kill; |
96 | priv->rfkill_mngr.rfkill->user_claim_unsupported = 1; | 96 | priv->rfkill->user_claim_unsupported = 1; |
97 | 97 | ||
98 | priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; | 98 | priv->rfkill->dev.class->suspend = NULL; |
99 | priv->rfkill_mngr.rfkill->dev.class->resume = NULL; | 99 | priv->rfkill->dev.class->resume = NULL; |
100 | 100 | ||
101 | ret = rfkill_register(priv->rfkill_mngr.rfkill); | 101 | ret = rfkill_register(priv->rfkill); |
102 | if (ret) { | 102 | if (ret) { |
103 | IWL_ERROR("Unable to register rfkill: %d\n", ret); | 103 | IWL_ERROR("Unable to register rfkill: %d\n", ret); |
104 | goto free_rfkill; | 104 | goto free_rfkill; |
@@ -108,9 +108,9 @@ int iwl_rfkill_init(struct iwl_priv *priv) | |||
108 | return ret; | 108 | return ret; |
109 | 109 | ||
110 | free_rfkill: | 110 | free_rfkill: |
111 | if (priv->rfkill_mngr.rfkill != NULL) | 111 | if (priv->rfkill != NULL) |
112 | rfkill_free(priv->rfkill_mngr.rfkill); | 112 | rfkill_free(priv->rfkill); |
113 | priv->rfkill_mngr.rfkill = NULL; | 113 | priv->rfkill = NULL; |
114 | 114 | ||
115 | error: | 115 | error: |
116 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | 116 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); |
@@ -121,22 +121,27 @@ EXPORT_SYMBOL(iwl_rfkill_init); | |||
121 | void iwl_rfkill_unregister(struct iwl_priv *priv) | 121 | void iwl_rfkill_unregister(struct iwl_priv *priv) |
122 | { | 122 | { |
123 | 123 | ||
124 | if (priv->rfkill_mngr.rfkill) | 124 | if (priv->rfkill) |
125 | rfkill_unregister(priv->rfkill_mngr.rfkill); | 125 | rfkill_unregister(priv->rfkill); |
126 | 126 | ||
127 | priv->rfkill_mngr.rfkill = NULL; | 127 | priv->rfkill = NULL; |
128 | } | 128 | } |
129 | EXPORT_SYMBOL(iwl_rfkill_unregister); | 129 | EXPORT_SYMBOL(iwl_rfkill_unregister); |
130 | 130 | ||
131 | /* set rf-kill to the right state. */ | 131 | /* set rf-kill to the right state. */ |
132 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv) | 132 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv) |
133 | { | 133 | { |
134 | if (!priv->rfkill_mngr.rfkill) | 134 | if (!priv->rfkill) |
135 | return; | 135 | return; |
136 | 136 | ||
137 | if (!iwl_is_rfkill(priv)) | 137 | if (iwl_is_rfkill_hw(priv)) { |
138 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | 138 | rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); |
139 | return; | ||
140 | } | ||
141 | |||
142 | if (!iwl_is_rfkill_sw(priv)) | ||
143 | rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED); | ||
139 | else | 144 | else |
140 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; | 145 | rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); |
141 | } | 146 | } |
142 | EXPORT_SYMBOL(iwl_rfkill_set_hw_state); | 147 | 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 index 00692d2e9bd8..402fd4c781da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h | |||
@@ -33,9 +33,6 @@ struct iwl_priv; | |||
33 | #include <linux/rfkill.h> | 33 | #include <linux/rfkill.h> |
34 | 34 | ||
35 | #ifdef CONFIG_IWLWIFI_RFKILL | 35 | #ifdef CONFIG_IWLWIFI_RFKILL |
36 | struct iwl_rfkill_mngr { | ||
37 | struct rfkill *rfkill; | ||
38 | }; | ||
39 | 36 | ||
40 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv); | 37 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv); |
41 | void iwl_rfkill_unregister(struct iwl_priv *priv); | 38 | void iwl_rfkill_unregister(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index baa1abd5a14d..1a7d18fea89d 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -537,10 +537,20 @@ static inline int iwl3945_is_init(struct iwl3945_priv *priv) | |||
537 | return test_bit(STATUS_INIT, &priv->status); | 537 | return test_bit(STATUS_INIT, &priv->status); |
538 | } | 538 | } |
539 | 539 | ||
540 | static inline int iwl3945_is_rfkill_sw(struct iwl3945_priv *priv) | ||
541 | { | ||
542 | return test_bit(STATUS_RF_KILL_SW, &priv->status); | ||
543 | } | ||
544 | |||
545 | static inline int iwl3945_is_rfkill_hw(struct iwl3945_priv *priv) | ||
546 | { | ||
547 | return test_bit(STATUS_RF_KILL_HW, &priv->status); | ||
548 | } | ||
549 | |||
540 | static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv) | 550 | static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv) |
541 | { | 551 | { |
542 | return test_bit(STATUS_RF_KILL_HW, &priv->status) || | 552 | return iwl3945_is_rfkill_hw(priv) || |
543 | test_bit(STATUS_RF_KILL_SW, &priv->status); | 553 | iwl3945_is_rfkill_sw(priv); |
544 | } | 554 | } |
545 | 555 | ||
546 | static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) | 556 | static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) |
@@ -6013,12 +6023,11 @@ static int __iwl3945_up(struct iwl3945_priv *priv) | |||
6013 | else { | 6023 | else { |
6014 | set_bit(STATUS_RF_KILL_HW, &priv->status); | 6024 | set_bit(STATUS_RF_KILL_HW, &priv->status); |
6015 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { | 6025 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { |
6016 | iwl3945_rfkill_set_hw_state(priv); | ||
6017 | IWL_WARNING("Radio disabled by HW RF Kill switch\n"); | 6026 | IWL_WARNING("Radio disabled by HW RF Kill switch\n"); |
6018 | return -ENODEV; | 6027 | return -ENODEV; |
6019 | } | 6028 | } |
6020 | } | 6029 | } |
6021 | iwl3945_rfkill_set_hw_state(priv); | 6030 | |
6022 | iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); | 6031 | iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); |
6023 | 6032 | ||
6024 | rc = iwl3945_hw_nic_init(priv); | 6033 | rc = iwl3945_hw_nic_init(priv); |
@@ -6143,8 +6152,8 @@ static void iwl3945_bg_rf_kill(struct work_struct *work) | |||
6143 | "wireless networking to work.\n"); | 6152 | "wireless networking to work.\n"); |
6144 | } | 6153 | } |
6145 | 6154 | ||
6146 | iwl3945_rfkill_set_hw_state(priv); | ||
6147 | mutex_unlock(&priv->mutex); | 6155 | mutex_unlock(&priv->mutex); |
6156 | iwl3945_rfkill_set_hw_state(priv); | ||
6148 | } | 6157 | } |
6149 | 6158 | ||
6150 | static void iwl3945_bg_set_monitor(struct work_struct *work) | 6159 | static void iwl3945_bg_set_monitor(struct work_struct *work) |
@@ -6398,6 +6407,7 @@ static void iwl3945_bg_up(struct work_struct *data) | |||
6398 | mutex_lock(&priv->mutex); | 6407 | mutex_lock(&priv->mutex); |
6399 | __iwl3945_up(priv); | 6408 | __iwl3945_up(priv); |
6400 | mutex_unlock(&priv->mutex); | 6409 | mutex_unlock(&priv->mutex); |
6410 | iwl3945_rfkill_set_hw_state(priv); | ||
6401 | } | 6411 | } |
6402 | 6412 | ||
6403 | static void iwl3945_bg_restart(struct work_struct *data) | 6413 | static void iwl3945_bg_restart(struct work_struct *data) |
@@ -6618,6 +6628,8 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) | |||
6618 | 6628 | ||
6619 | mutex_unlock(&priv->mutex); | 6629 | mutex_unlock(&priv->mutex); |
6620 | 6630 | ||
6631 | iwl3945_rfkill_set_hw_state(priv); | ||
6632 | |||
6621 | if (ret) | 6633 | if (ret) |
6622 | goto out_release_irq; | 6634 | goto out_release_irq; |
6623 | 6635 | ||
@@ -8276,14 +8288,14 @@ static int iwl3945_pci_resume(struct pci_dev *pdev) | |||
8276 | #endif /* CONFIG_PM */ | 8288 | #endif /* CONFIG_PM */ |
8277 | 8289 | ||
8278 | /*************** RFKILL FUNCTIONS **********/ | 8290 | /*************** RFKILL FUNCTIONS **********/ |
8279 | #ifdef CONFIG_IWLWIFI_RFKILL | 8291 | #ifdef CONFIG_IWL3945_RFKILL |
8280 | /* software rf-kill from user */ | 8292 | /* software rf-kill from user */ |
8281 | static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | 8293 | static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) |
8282 | { | 8294 | { |
8283 | struct iwl3945_priv *priv = data; | 8295 | struct iwl3945_priv *priv = data; |
8284 | int err = 0; | 8296 | int err = 0; |
8285 | 8297 | ||
8286 | if (!priv->rfkill_mngr.rfkill) | 8298 | if (!priv->rfkill) |
8287 | return 0; | 8299 | return 0; |
8288 | 8300 | ||
8289 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 8301 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
@@ -8294,20 +8306,20 @@ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | |||
8294 | 8306 | ||
8295 | switch (state) { | 8307 | switch (state) { |
8296 | case RFKILL_STATE_UNBLOCKED: | 8308 | case RFKILL_STATE_UNBLOCKED: |
8297 | iwl3945_radio_kill_sw(priv, 0); | 8309 | if (iwl3945_is_rfkill_hw(priv)) { |
8298 | /* if HW rf-kill is set dont allow ON state */ | ||
8299 | if (iwl3945_is_rfkill(priv)) | ||
8300 | err = -EBUSY; | 8310 | err = -EBUSY; |
8311 | goto out_unlock; | ||
8312 | } | ||
8313 | iwl3945_radio_kill_sw(priv, 0); | ||
8301 | break; | 8314 | break; |
8302 | case RFKILL_STATE_SOFT_BLOCKED: | 8315 | case RFKILL_STATE_SOFT_BLOCKED: |
8303 | iwl3945_radio_kill_sw(priv, 1); | 8316 | iwl3945_radio_kill_sw(priv, 1); |
8304 | if (!iwl3945_is_rfkill(priv)) | ||
8305 | err = -EBUSY; | ||
8306 | break; | 8317 | break; |
8307 | default: | 8318 | default: |
8308 | IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); | 8319 | IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); |
8309 | break; | 8320 | break; |
8310 | } | 8321 | } |
8322 | out_unlock: | ||
8311 | mutex_unlock(&priv->mutex); | 8323 | mutex_unlock(&priv->mutex); |
8312 | 8324 | ||
8313 | return err; | 8325 | return err; |
@@ -8321,64 +8333,35 @@ int iwl3945_rfkill_init(struct iwl3945_priv *priv) | |||
8321 | BUG_ON(device == NULL); | 8333 | BUG_ON(device == NULL); |
8322 | 8334 | ||
8323 | IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); | 8335 | IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); |
8324 | priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); | 8336 | priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); |
8325 | if (!priv->rfkill_mngr.rfkill) { | 8337 | if (!priv->rfkill) { |
8326 | IWL_ERROR("Unable to allocate rfkill device.\n"); | 8338 | IWL_ERROR("Unable to allocate rfkill device.\n"); |
8327 | ret = -ENOMEM; | 8339 | ret = -ENOMEM; |
8328 | goto error; | 8340 | goto error; |
8329 | } | 8341 | } |
8330 | 8342 | ||
8331 | priv->rfkill_mngr.rfkill->name = priv->cfg->name; | 8343 | priv->rfkill->name = priv->cfg->name; |
8332 | priv->rfkill_mngr.rfkill->data = priv; | 8344 | priv->rfkill->data = priv; |
8333 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | 8345 | priv->rfkill->state = RFKILL_STATE_UNBLOCKED; |
8334 | priv->rfkill_mngr.rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill; | 8346 | priv->rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill; |
8335 | priv->rfkill_mngr.rfkill->user_claim_unsupported = 1; | 8347 | priv->rfkill->user_claim_unsupported = 1; |
8336 | |||
8337 | priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; | ||
8338 | priv->rfkill_mngr.rfkill->dev.class->resume = NULL; | ||
8339 | 8348 | ||
8340 | priv->rfkill_mngr.input_dev = input_allocate_device(); | 8349 | priv->rfkill->dev.class->suspend = NULL; |
8341 | if (!priv->rfkill_mngr.input_dev) { | 8350 | priv->rfkill->dev.class->resume = NULL; |
8342 | IWL_ERROR("Unable to allocate rfkill input device.\n"); | ||
8343 | ret = -ENOMEM; | ||
8344 | goto freed_rfkill; | ||
8345 | } | ||
8346 | 8351 | ||
8347 | priv->rfkill_mngr.input_dev->name = priv->cfg->name; | 8352 | ret = rfkill_register(priv->rfkill); |
8348 | priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy); | ||
8349 | priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST; | ||
8350 | priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor; | ||
8351 | priv->rfkill_mngr.input_dev->dev.parent = device; | ||
8352 | priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY); | ||
8353 | set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit); | ||
8354 | |||
8355 | ret = rfkill_register(priv->rfkill_mngr.rfkill); | ||
8356 | if (ret) { | 8353 | if (ret) { |
8357 | IWL_ERROR("Unable to register rfkill: %d\n", ret); | 8354 | IWL_ERROR("Unable to register rfkill: %d\n", ret); |
8358 | goto free_input_dev; | 8355 | goto freed_rfkill; |
8359 | } | ||
8360 | |||
8361 | ret = input_register_device(priv->rfkill_mngr.input_dev); | ||
8362 | if (ret) { | ||
8363 | IWL_ERROR("Unable to register rfkill input device: %d\n", ret); | ||
8364 | goto unregister_rfkill; | ||
8365 | } | 8356 | } |
8366 | 8357 | ||
8367 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | 8358 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); |
8368 | return ret; | 8359 | return ret; |
8369 | 8360 | ||
8370 | unregister_rfkill: | ||
8371 | rfkill_unregister(priv->rfkill_mngr.rfkill); | ||
8372 | priv->rfkill_mngr.rfkill = NULL; | ||
8373 | |||
8374 | free_input_dev: | ||
8375 | input_free_device(priv->rfkill_mngr.input_dev); | ||
8376 | priv->rfkill_mngr.input_dev = NULL; | ||
8377 | |||
8378 | freed_rfkill: | 8361 | freed_rfkill: |
8379 | if (priv->rfkill_mngr.rfkill != NULL) | 8362 | if (priv->rfkill != NULL) |
8380 | rfkill_free(priv->rfkill_mngr.rfkill); | 8363 | rfkill_free(priv->rfkill); |
8381 | priv->rfkill_mngr.rfkill = NULL; | 8364 | priv->rfkill = NULL; |
8382 | 8365 | ||
8383 | error: | 8366 | error: |
8384 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | 8367 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); |
@@ -8387,28 +8370,28 @@ error: | |||
8387 | 8370 | ||
8388 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) | 8371 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) |
8389 | { | 8372 | { |
8373 | if (priv->rfkill) | ||
8374 | rfkill_unregister(priv->rfkill); | ||
8390 | 8375 | ||
8391 | if (priv->rfkill_mngr.input_dev) | 8376 | priv->rfkill = NULL; |
8392 | input_unregister_device(priv->rfkill_mngr.input_dev); | ||
8393 | |||
8394 | if (priv->rfkill_mngr.rfkill) | ||
8395 | rfkill_unregister(priv->rfkill_mngr.rfkill); | ||
8396 | |||
8397 | priv->rfkill_mngr.input_dev = NULL; | ||
8398 | priv->rfkill_mngr.rfkill = NULL; | ||
8399 | } | 8377 | } |
8400 | 8378 | ||
8401 | /* set rf-kill to the right state. */ | 8379 | /* set rf-kill to the right state. */ |
8402 | void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) | 8380 | void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) |
8403 | { | 8381 | { |
8404 | 8382 | ||
8405 | if (!priv->rfkill_mngr.rfkill) | 8383 | if (!priv->rfkill) |
8384 | return; | ||
8385 | |||
8386 | if (iwl3945_is_rfkill_hw(priv)) { | ||
8387 | rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); | ||
8406 | return; | 8388 | return; |
8389 | } | ||
8407 | 8390 | ||
8408 | if (!iwl3945_is_rfkill(priv)) | 8391 | if (!iwl3945_is_rfkill_sw(priv)) |
8409 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | 8392 | rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED); |
8410 | else | 8393 | else |
8411 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; | 8394 | rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); |
8412 | } | 8395 | } |
8413 | #endif | 8396 | #endif |
8414 | 8397 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 60b7a6498fe8..7f65d9123b2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -2187,13 +2187,11 @@ static int __iwl4965_up(struct iwl_priv *priv) | |||
2187 | 2187 | ||
2188 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status) && | 2188 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status) && |
2189 | iwl_is_rfkill(priv)) { | 2189 | iwl_is_rfkill(priv)) { |
2190 | iwl_rfkill_set_hw_state(priv); | ||
2191 | IWL_WARNING("Radio disabled by %s RF Kill switch\n", | 2190 | IWL_WARNING("Radio disabled by %s RF Kill switch\n", |
2192 | test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW"); | 2191 | test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW"); |
2193 | return -ENODEV; | 2192 | return -ENODEV; |
2194 | } | 2193 | } |
2195 | 2194 | ||
2196 | iwl_rfkill_set_hw_state(priv); | ||
2197 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | 2195 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); |
2198 | 2196 | ||
2199 | ret = priv->cfg->ops->lib->alloc_shared_mem(priv); | 2197 | ret = priv->cfg->ops->lib->alloc_shared_mem(priv); |
@@ -2330,9 +2328,8 @@ static void iwl4965_bg_rf_kill(struct work_struct *work) | |||
2330 | "Kill switch must be turned off for " | 2328 | "Kill switch must be turned off for " |
2331 | "wireless networking to work.\n"); | 2329 | "wireless networking to work.\n"); |
2332 | } | 2330 | } |
2333 | iwl_rfkill_set_hw_state(priv); | ||
2334 | |||
2335 | mutex_unlock(&priv->mutex); | 2331 | mutex_unlock(&priv->mutex); |
2332 | iwl_rfkill_set_hw_state(priv); | ||
2336 | } | 2333 | } |
2337 | 2334 | ||
2338 | static void iwl4965_bg_set_monitor(struct work_struct *work) | 2335 | static void iwl4965_bg_set_monitor(struct work_struct *work) |
@@ -2390,6 +2387,7 @@ static void iwl4965_bg_up(struct work_struct *data) | |||
2390 | mutex_lock(&priv->mutex); | 2387 | mutex_lock(&priv->mutex); |
2391 | __iwl4965_up(priv); | 2388 | __iwl4965_up(priv); |
2392 | mutex_unlock(&priv->mutex); | 2389 | mutex_unlock(&priv->mutex); |
2390 | iwl_rfkill_set_hw_state(priv); | ||
2393 | } | 2391 | } |
2394 | 2392 | ||
2395 | static void iwl4965_bg_restart(struct work_struct *data) | 2393 | static void iwl4965_bg_restart(struct work_struct *data) |
@@ -2604,6 +2602,8 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw) | |||
2604 | 2602 | ||
2605 | mutex_unlock(&priv->mutex); | 2603 | mutex_unlock(&priv->mutex); |
2606 | 2604 | ||
2605 | iwl_rfkill_set_hw_state(priv); | ||
2606 | |||
2607 | if (ret) | 2607 | if (ret) |
2608 | goto out_release_irq; | 2608 | goto out_release_irq; |
2609 | 2609 | ||