aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h7
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c115
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c15
-rw-r--r--drivers/net/wireless/b43/Kconfig2
-rw-r--r--drivers/net/wireless/b43/leds.c2
-rw-r--r--drivers/net/wireless/b43/main.c4
-rw-r--r--drivers/net/wireless/b43/phy_a.c4
-rw-r--r--drivers/net/wireless/b43/phy_common.c17
-rw-r--r--drivers/net/wireless/b43/phy_common.h4
-rw-r--r--drivers/net/wireless/b43/phy_g.c4
-rw-r--r--drivers/net/wireless/b43/phy_lp.c2
-rw-r--r--drivers/net/wireless/b43/phy_n.c2
-rw-r--r--drivers/net/wireless/b43/rfkill.c123
-rw-r--r--drivers/net/wireless/b43/rfkill.h5
-rw-r--r--drivers/net/wireless/b43legacy/Kconfig2
-rw-r--r--drivers/net/wireless/b43legacy/leds.c3
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.c123
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.h6
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rfkill.c69
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rfkill.c39
21 files changed, 173 insertions, 380 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 796a3adffea0..515880aa2116 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -460,12 +460,9 @@ struct ath_led {
460 bool registered; 460 bool registered;
461}; 461};
462 462
463/* Rfkill */
464#define ATH_RFKILL_POLL_INTERVAL 2000 /* msecs */
465
466struct ath_rfkill { 463struct ath_rfkill {
467 struct rfkill *rfkill; 464 struct rfkill *rfkill;
468 struct delayed_work rfkill_poll; 465 struct rfkill_ops ops;
469 char rfkill_name[32]; 466 char rfkill_name[32];
470}; 467};
471 468
@@ -509,8 +506,6 @@ struct ath_rfkill {
509#define SC_OP_RXFLUSH BIT(7) 506#define SC_OP_RXFLUSH BIT(7)
510#define SC_OP_LED_ASSOCIATED BIT(8) 507#define SC_OP_LED_ASSOCIATED BIT(8)
511#define SC_OP_RFKILL_REGISTERED BIT(9) 508#define SC_OP_RFKILL_REGISTERED BIT(9)
512#define SC_OP_RFKILL_SW_BLOCKED BIT(10)
513#define SC_OP_RFKILL_HW_BLOCKED BIT(11)
514#define SC_OP_WAIT_FOR_BEACON BIT(12) 509#define SC_OP_WAIT_FOR_BEACON BIT(12)
515#define SC_OP_LED_ON BIT(13) 510#define SC_OP_LED_ON BIT(13)
516#define SC_OP_SCANNING BIT(14) 511#define SC_OP_SCANNING BIT(14)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 61da08a1648c..f7baa406918b 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1192,120 +1192,69 @@ static bool ath_is_rfkill_set(struct ath_softc *sc)
1192 ah->rfkill_polarity; 1192 ah->rfkill_polarity;
1193} 1193}
1194 1194
1195/* h/w rfkill poll function */ 1195/* s/w rfkill handlers */
1196static void ath_rfkill_poll(struct work_struct *work) 1196static int ath_rfkill_set_block(void *data, bool blocked)
1197{ 1197{
1198 struct ath_softc *sc = container_of(work, struct ath_softc, 1198 struct ath_softc *sc = data;
1199 rf_kill.rfkill_poll.work);
1200 bool radio_on;
1201
1202 if (sc->sc_flags & SC_OP_INVALID)
1203 return;
1204
1205 radio_on = !ath_is_rfkill_set(sc);
1206
1207 /*
1208 * enable/disable radio only when there is a
1209 * state change in RF switch
1210 */
1211 if (radio_on == !!(sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED)) {
1212 enum rfkill_state state;
1213
1214 if (sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED) {
1215 state = radio_on ? RFKILL_STATE_SOFT_BLOCKED
1216 : RFKILL_STATE_HARD_BLOCKED;
1217 } else if (radio_on) {
1218 ath_radio_enable(sc);
1219 state = RFKILL_STATE_UNBLOCKED;
1220 } else {
1221 ath_radio_disable(sc);
1222 state = RFKILL_STATE_HARD_BLOCKED;
1223 }
1224
1225 if (state == RFKILL_STATE_HARD_BLOCKED)
1226 sc->sc_flags |= SC_OP_RFKILL_HW_BLOCKED;
1227 else
1228 sc->sc_flags &= ~SC_OP_RFKILL_HW_BLOCKED;
1229 1199
1230 rfkill_force_state(sc->rf_kill.rfkill, state); 1200 if (blocked)
1231 } 1201 ath_radio_disable(sc);
1202 else
1203 ath_radio_enable(sc);
1232 1204
1233 queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll, 1205 return 0;
1234 msecs_to_jiffies(ATH_RFKILL_POLL_INTERVAL));
1235} 1206}
1236 1207
1237/* s/w rfkill handler */ 1208static void ath_rfkill_poll_state(struct rfkill *rfkill, void *data)
1238static int ath_sw_toggle_radio(void *data, enum rfkill_state state)
1239{ 1209{
1240 struct ath_softc *sc = data; 1210 struct ath_softc *sc = data;
1211 bool blocked = !!ath_is_rfkill_set(sc);
1241 1212
1242 switch (state) { 1213 if (rfkill_set_hw_state(rfkill, blocked))
1243 case RFKILL_STATE_SOFT_BLOCKED: 1214 ath_radio_disable(sc);
1244 if (!(sc->sc_flags & (SC_OP_RFKILL_HW_BLOCKED | 1215 else
1245 SC_OP_RFKILL_SW_BLOCKED))) 1216 ath_radio_enable(sc);
1246 ath_radio_disable(sc);
1247 sc->sc_flags |= SC_OP_RFKILL_SW_BLOCKED;
1248 return 0;
1249 case RFKILL_STATE_UNBLOCKED:
1250 if ((sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED)) {
1251 sc->sc_flags &= ~SC_OP_RFKILL_SW_BLOCKED;
1252 if (sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED) {
1253 DPRINTF(sc, ATH_DBG_FATAL, "Can't turn on the"
1254 "radio as it is disabled by h/w\n");
1255 return -EPERM;
1256 }
1257 ath_radio_enable(sc);
1258 }
1259 return 0;
1260 default:
1261 return -EINVAL;
1262 }
1263} 1217}
1264 1218
1265/* Init s/w rfkill */ 1219/* Init s/w rfkill */
1266static int ath_init_sw_rfkill(struct ath_softc *sc) 1220static int ath_init_sw_rfkill(struct ath_softc *sc)
1267{ 1221{
1268 sc->rf_kill.rfkill = rfkill_allocate(wiphy_dev(sc->hw->wiphy), 1222 sc->rf_kill.ops.set_block = ath_rfkill_set_block;
1269 RFKILL_TYPE_WLAN); 1223 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
1224 sc->rf_kill.ops.poll = ath_rfkill_poll_state;
1225
1226 snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name),
1227 "ath9k-%s::rfkill", wiphy_name(sc->hw->wiphy));
1228
1229 sc->rf_kill.rfkill = rfkill_alloc(sc->rf_kill.rfkill_name,
1230 wiphy_dev(sc->hw->wiphy),
1231 RFKILL_TYPE_WLAN,
1232 &sc->rf_kill.ops, sc);
1270 if (!sc->rf_kill.rfkill) { 1233 if (!sc->rf_kill.rfkill) {
1271 DPRINTF(sc, ATH_DBG_FATAL, "Failed to allocate rfkill\n"); 1234 DPRINTF(sc, ATH_DBG_FATAL, "Failed to allocate rfkill\n");
1272 return -ENOMEM; 1235 return -ENOMEM;
1273 } 1236 }
1274 1237
1275 snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name),
1276 "ath9k-%s::rfkill", wiphy_name(sc->hw->wiphy));
1277 sc->rf_kill.rfkill->name = sc->rf_kill.rfkill_name;
1278 sc->rf_kill.rfkill->data = sc;
1279 sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio;
1280 sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED;
1281
1282 return 0; 1238 return 0;
1283} 1239}
1284 1240
1285/* Deinitialize rfkill */ 1241/* Deinitialize rfkill */
1286static void ath_deinit_rfkill(struct ath_softc *sc) 1242static void ath_deinit_rfkill(struct ath_softc *sc)
1287{ 1243{
1288 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
1289 cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
1290
1291 if (sc->sc_flags & SC_OP_RFKILL_REGISTERED) { 1244 if (sc->sc_flags & SC_OP_RFKILL_REGISTERED) {
1292 rfkill_unregister(sc->rf_kill.rfkill); 1245 rfkill_unregister(sc->rf_kill.rfkill);
1246 rfkill_destroy(sc->rf_kill.rfkill);
1293 sc->sc_flags &= ~SC_OP_RFKILL_REGISTERED; 1247 sc->sc_flags &= ~SC_OP_RFKILL_REGISTERED;
1294 sc->rf_kill.rfkill = NULL;
1295 } 1248 }
1296} 1249}
1297 1250
1298static int ath_start_rfkill_poll(struct ath_softc *sc) 1251static int ath_start_rfkill_poll(struct ath_softc *sc)
1299{ 1252{
1300 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
1301 queue_delayed_work(sc->hw->workqueue,
1302 &sc->rf_kill.rfkill_poll, 0);
1303
1304 if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) { 1253 if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) {
1305 if (rfkill_register(sc->rf_kill.rfkill)) { 1254 if (rfkill_register(sc->rf_kill.rfkill)) {
1306 DPRINTF(sc, ATH_DBG_FATAL, 1255 DPRINTF(sc, ATH_DBG_FATAL,
1307 "Unable to register rfkill\n"); 1256 "Unable to register rfkill\n");
1308 rfkill_free(sc->rf_kill.rfkill); 1257 rfkill_destroy(sc->rf_kill.rfkill);
1309 1258
1310 /* Deinitialize the device */ 1259 /* Deinitialize the device */
1311 ath_cleanup(sc); 1260 ath_cleanup(sc);
@@ -1678,10 +1627,6 @@ int ath_attach(u16 devid, struct ath_softc *sc)
1678 goto error_attach; 1627 goto error_attach;
1679 1628
1680#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) 1629#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
1681 /* Initialze h/w Rfkill */
1682 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
1683 INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll);
1684
1685 /* Initialize s/w rfkill */ 1630 /* Initialize s/w rfkill */
1686 error = ath_init_sw_rfkill(sc); 1631 error = ath_init_sw_rfkill(sc);
1687 if (error) 1632 if (error)
@@ -2214,10 +2159,8 @@ static void ath9k_stop(struct ieee80211_hw *hw)
2214 } else 2159 } else
2215 sc->rx.rxlink = NULL; 2160 sc->rx.rxlink = NULL;
2216 2161
2217#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) 2162 rfkill_pause_polling(sc->rf_kill.rfkill);
2218 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) 2163
2219 cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
2220#endif
2221 /* disable HAL and put h/w to sleep */ 2164 /* disable HAL and put h/w to sleep */
2222 ath9k_hw_disable(sc->sc_ah); 2165 ath9k_hw_disable(sc->sc_ah);
2223 ath9k_hw_configpcipowersave(sc->sc_ah, 1); 2166 ath9k_hw_configpcipowersave(sc->sc_ah, 1);
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 168411d322a2..ccdf20a2e9be 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -227,11 +227,6 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
227 227
228 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); 228 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
229 229
230#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
231 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
232 cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
233#endif
234
235 pci_save_state(pdev); 230 pci_save_state(pdev);
236 pci_disable_device(pdev); 231 pci_disable_device(pdev);
237 pci_set_power_state(pdev, PCI_D3hot); 232 pci_set_power_state(pdev, PCI_D3hot);
@@ -256,16 +251,6 @@ static int ath_pci_resume(struct pci_dev *pdev)
256 AR_GPIO_OUTPUT_MUX_AS_OUTPUT); 251 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
257 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); 252 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
258 253
259#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
260 /*
261 * check the h/w rfkill state on resume
262 * and start the rfkill poll timer
263 */
264 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
265 queue_delayed_work(sc->hw->workqueue,
266 &sc->rf_kill.rfkill_poll, 0);
267#endif
268
269 return 0; 254 return 0;
270} 255}
271 256
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 21572e40b79d..07a99e3faf94 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -102,7 +102,7 @@ config B43_LEDS
102# if it's possible. 102# if it's possible.
103config B43_RFKILL 103config B43_RFKILL
104 bool 104 bool
105 depends on B43 && (RFKILL = y || RFKILL = B43) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43) 105 depends on B43 && (RFKILL = y || RFKILL = B43)
106 default y 106 default y
107 107
108# This config option automatically enables b43 HW-RNG support, 108# This config option automatically enables b43 HW-RNG support,
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
index 76f4c7bad8b8..9a498d3fc653 100644
--- a/drivers/net/wireless/b43/leds.c
+++ b/drivers/net/wireless/b43/leds.c
@@ -87,7 +87,7 @@ static void b43_led_brightness_set(struct led_classdev *led_dev,
87} 87}
88 88
89static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, 89static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
90 const char *name, char *default_trigger, 90 const char *name, const char *default_trigger,
91 u8 led_index, bool activelow) 91 u8 led_index, bool activelow)
92{ 92{
93 int err; 93 int err;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index cb4a8712946a..1d3e40095ada 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3470,7 +3470,7 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
3470 3470
3471 if (!!conf->radio_enabled != phy->radio_on) { 3471 if (!!conf->radio_enabled != phy->radio_on) {
3472 if (conf->radio_enabled) { 3472 if (conf->radio_enabled) {
3473 b43_software_rfkill(dev, RFKILL_STATE_UNBLOCKED); 3473 b43_software_rfkill(dev, false);
3474 b43info(dev->wl, "Radio turned on by software\n"); 3474 b43info(dev->wl, "Radio turned on by software\n");
3475 if (!dev->radio_hw_enable) { 3475 if (!dev->radio_hw_enable) {
3476 b43info(dev->wl, "The hardware RF-kill button " 3476 b43info(dev->wl, "The hardware RF-kill button "
@@ -3478,7 +3478,7 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
3478 "Press the button to turn it on.\n"); 3478 "Press the button to turn it on.\n");
3479 } 3479 }
3480 } else { 3480 } else {
3481 b43_software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED); 3481 b43_software_rfkill(dev, true);
3482 b43info(dev->wl, "Radio turned off by software\n"); 3482 b43info(dev->wl, "Radio turned off by software\n");
3483 } 3483 }
3484 } 3484 }
diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c
index c836c077d51d..816e028a2620 100644
--- a/drivers/net/wireless/b43/phy_a.c
+++ b/drivers/net/wireless/b43/phy_a.c
@@ -480,11 +480,11 @@ static bool b43_aphy_op_supports_hwpctl(struct b43_wldev *dev)
480} 480}
481 481
482static void b43_aphy_op_software_rfkill(struct b43_wldev *dev, 482static void b43_aphy_op_software_rfkill(struct b43_wldev *dev,
483 enum rfkill_state state) 483 bool blocked)
484{ 484{
485 struct b43_phy *phy = &dev->phy; 485 struct b43_phy *phy = &dev->phy;
486 486
487 if (state == RFKILL_STATE_UNBLOCKED) { 487 if (!blocked) {
488 if (phy->radio_on) 488 if (phy->radio_on)
489 return; 489 return;
490 b43_radio_write16(dev, 0x0004, 0x00C0); 490 b43_radio_write16(dev, 0x0004, 0x00C0);
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index e176b6e0d9cf..6d241622210e 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -84,7 +84,7 @@ int b43_phy_init(struct b43_wldev *dev)
84 84
85 phy->channel = ops->get_default_chan(dev); 85 phy->channel = ops->get_default_chan(dev);
86 86
87 ops->software_rfkill(dev, RFKILL_STATE_UNBLOCKED); 87 ops->software_rfkill(dev, false);
88 err = ops->init(dev); 88 err = ops->init(dev);
89 if (err) { 89 if (err) {
90 b43err(dev->wl, "PHY init failed\n"); 90 b43err(dev->wl, "PHY init failed\n");
@@ -104,7 +104,7 @@ err_phy_exit:
104 if (ops->exit) 104 if (ops->exit)
105 ops->exit(dev); 105 ops->exit(dev);
106err_block_rf: 106err_block_rf:
107 ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED); 107 ops->software_rfkill(dev, true);
108 108
109 return err; 109 return err;
110} 110}
@@ -113,7 +113,7 @@ void b43_phy_exit(struct b43_wldev *dev)
113{ 113{
114 const struct b43_phy_operations *ops = dev->phy.ops; 114 const struct b43_phy_operations *ops = dev->phy.ops;
115 115
116 ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED); 116 ops->software_rfkill(dev, true);
117 if (ops->exit) 117 if (ops->exit)
118 ops->exit(dev); 118 ops->exit(dev);
119} 119}
@@ -295,18 +295,13 @@ err_restore_cookie:
295 return err; 295 return err;
296} 296}
297 297
298void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state) 298void b43_software_rfkill(struct b43_wldev *dev, bool blocked)
299{ 299{
300 struct b43_phy *phy = &dev->phy; 300 struct b43_phy *phy = &dev->phy;
301 301
302 if (state == RFKILL_STATE_HARD_BLOCKED) {
303 /* We cannot hardware-block the device */
304 state = RFKILL_STATE_SOFT_BLOCKED;
305 }
306
307 b43_mac_suspend(dev); 302 b43_mac_suspend(dev);
308 phy->ops->software_rfkill(dev, state); 303 phy->ops->software_rfkill(dev, blocked);
309 phy->radio_on = (state == RFKILL_STATE_UNBLOCKED); 304 phy->radio_on = !blocked;
310 b43_mac_enable(dev); 305 b43_mac_enable(dev);
311} 306}
312 307
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index b2d99101947b..f4c2d79cbc89 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -159,7 +159,7 @@ struct b43_phy_operations {
159 159
160 /* Radio */ 160 /* Radio */
161 bool (*supports_hwpctl)(struct b43_wldev *dev); 161 bool (*supports_hwpctl)(struct b43_wldev *dev);
162 void (*software_rfkill)(struct b43_wldev *dev, enum rfkill_state state); 162 void (*software_rfkill)(struct b43_wldev *dev, bool blocked);
163 void (*switch_analog)(struct b43_wldev *dev, bool on); 163 void (*switch_analog)(struct b43_wldev *dev, bool on);
164 int (*switch_channel)(struct b43_wldev *dev, unsigned int new_channel); 164 int (*switch_channel)(struct b43_wldev *dev, unsigned int new_channel);
165 unsigned int (*get_default_chan)(struct b43_wldev *dev); 165 unsigned int (*get_default_chan)(struct b43_wldev *dev);
@@ -364,7 +364,7 @@ int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel);
364/** 364/**
365 * b43_software_rfkill - Turn the radio ON or OFF in software. 365 * b43_software_rfkill - Turn the radio ON or OFF in software.
366 */ 366 */
367void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state); 367void b43_software_rfkill(struct b43_wldev *dev, bool blocked);
368 368
369/** 369/**
370 * b43_phy_txpower_check - Check TX power output. 370 * b43_phy_txpower_check - Check TX power output.
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c
index e7b98f013b0f..5300232449f6 100644
--- a/drivers/net/wireless/b43/phy_g.c
+++ b/drivers/net/wireless/b43/phy_g.c
@@ -2592,7 +2592,7 @@ static bool b43_gphy_op_supports_hwpctl(struct b43_wldev *dev)
2592} 2592}
2593 2593
2594static void b43_gphy_op_software_rfkill(struct b43_wldev *dev, 2594static void b43_gphy_op_software_rfkill(struct b43_wldev *dev,
2595 enum rfkill_state state) 2595 bool blocked)
2596{ 2596{
2597 struct b43_phy *phy = &dev->phy; 2597 struct b43_phy *phy = &dev->phy;
2598 struct b43_phy_g *gphy = phy->g; 2598 struct b43_phy_g *gphy = phy->g;
@@ -2600,7 +2600,7 @@ static void b43_gphy_op_software_rfkill(struct b43_wldev *dev,
2600 2600
2601 might_sleep(); 2601 might_sleep();
2602 2602
2603 if (state == RFKILL_STATE_UNBLOCKED) { 2603 if (!blocked) {
2604 /* Turn radio ON */ 2604 /* Turn radio ON */
2605 if (phy->radio_on) 2605 if (phy->radio_on)
2606 return; 2606 return;
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 58e319d6b1ed..ea0d3a3a6a64 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -488,7 +488,7 @@ static void b43_lpphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
488} 488}
489 489
490static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev, 490static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
491 enum rfkill_state state) 491 bool blocked)
492{ 492{
493 //TODO 493 //TODO
494} 494}
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 8bcfda5f3f07..be7b5604947b 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -579,7 +579,7 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
579} 579}
580 580
581static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, 581static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
582 enum rfkill_state state) 582 bool blocked)
583{//TODO 583{//TODO
584} 584}
585 585
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index 9e1d00bc24d3..96047843cd56 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -45,12 +45,11 @@ static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
45} 45}
46 46
47/* The poll callback for the hardware button. */ 47/* The poll callback for the hardware button. */
48static void b43_rfkill_poll(struct input_polled_dev *poll_dev) 48static void b43_rfkill_poll(struct rfkill *rfkill, void *data)
49{ 49{
50 struct b43_wldev *dev = poll_dev->private; 50 struct b43_wldev *dev = data;
51 struct b43_wl *wl = dev->wl; 51 struct b43_wl *wl = dev->wl;
52 bool enabled; 52 bool enabled;
53 bool report_change = 0;
54 53
55 mutex_lock(&wl->mutex); 54 mutex_lock(&wl->mutex);
56 if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) { 55 if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) {
@@ -60,68 +59,55 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
60 enabled = b43_is_hw_radio_enabled(dev); 59 enabled = b43_is_hw_radio_enabled(dev);
61 if (unlikely(enabled != dev->radio_hw_enable)) { 60 if (unlikely(enabled != dev->radio_hw_enable)) {
62 dev->radio_hw_enable = enabled; 61 dev->radio_hw_enable = enabled;
63 report_change = 1;
64 b43info(wl, "Radio hardware status changed to %s\n", 62 b43info(wl, "Radio hardware status changed to %s\n",
65 enabled ? "ENABLED" : "DISABLED"); 63 enabled ? "ENABLED" : "DISABLED");
64 enabled = !rfkill_set_hw_state(rfkill, !enabled);
65 if (enabled != dev->phy.radio_on)
66 b43_software_rfkill(dev, !enabled);
66 } 67 }
67 mutex_unlock(&wl->mutex); 68 mutex_unlock(&wl->mutex);
68
69 /* send the radio switch event to the system - note both a key press
70 * and a release are required */
71 if (unlikely(report_change)) {
72 input_report_key(poll_dev->input, KEY_WLAN, 1);
73 input_report_key(poll_dev->input, KEY_WLAN, 0);
74 }
75} 69}
76 70
77/* Called when the RFKILL toggled in software. */ 71/* Called when the RFKILL toggled in software. */
78static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) 72static int b43_rfkill_soft_set(void *data, bool blocked)
79{ 73{
80 struct b43_wldev *dev = data; 74 struct b43_wldev *dev = data;
81 struct b43_wl *wl = dev->wl; 75 struct b43_wl *wl = dev->wl;
82 int err = -EBUSY; 76 int err = -EINVAL;
83 77
84 if (!wl->rfkill.registered) 78 if (WARN_ON(!wl->rfkill.registered))
85 return 0; 79 return -EINVAL;
86 80
87 mutex_lock(&wl->mutex); 81 mutex_lock(&wl->mutex);
82
88 if (b43_status(dev) < B43_STAT_INITIALIZED) 83 if (b43_status(dev) < B43_STAT_INITIALIZED)
89 goto out_unlock; 84 goto out_unlock;
85
86 if (!dev->radio_hw_enable)
87 goto out_unlock;
88
89 if (!blocked != dev->phy.radio_on)
90 b43_software_rfkill(dev, blocked);
90 err = 0; 91 err = 0;
91 switch (state) {
92 case RFKILL_STATE_UNBLOCKED:
93 if (!dev->radio_hw_enable) {
94 /* No luck. We can't toggle the hardware RF-kill
95 * button from software. */
96 err = -EBUSY;
97 goto out_unlock;
98 }
99 if (!dev->phy.radio_on)
100 b43_software_rfkill(dev, state);
101 break;
102 case RFKILL_STATE_SOFT_BLOCKED:
103 if (dev->phy.radio_on)
104 b43_software_rfkill(dev, state);
105 break;
106 default:
107 b43warn(wl, "Received unexpected rfkill state %d.\n", state);
108 break;
109 }
110out_unlock: 92out_unlock:
111 mutex_unlock(&wl->mutex); 93 mutex_unlock(&wl->mutex);
112
113 return err; 94 return err;
114} 95}
115 96
116char *b43_rfkill_led_name(struct b43_wldev *dev) 97const char *b43_rfkill_led_name(struct b43_wldev *dev)
117{ 98{
118 struct b43_rfkill *rfk = &(dev->wl->rfkill); 99 struct b43_rfkill *rfk = &(dev->wl->rfkill);
119 100
120 if (!rfk->registered) 101 if (!rfk->registered)
121 return NULL; 102 return NULL;
122 return rfkill_get_led_name(rfk->rfkill); 103 return rfkill_get_led_trigger_name(rfk->rfkill);
123} 104}
124 105
106static const struct rfkill_ops b43_rfkill_ops = {
107 .set_block = b43_rfkill_soft_set,
108 .poll = b43_rfkill_poll,
109};
110
125void b43_rfkill_init(struct b43_wldev *dev) 111void b43_rfkill_init(struct b43_wldev *dev)
126{ 112{
127 struct b43_wl *wl = dev->wl; 113 struct b43_wl *wl = dev->wl;
@@ -130,65 +116,26 @@ void b43_rfkill_init(struct b43_wldev *dev)
130 116
131 rfk->registered = 0; 117 rfk->registered = 0;
132 118
133 rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
134 if (!rfk->rfkill)
135 goto out_error;
136 snprintf(rfk->name, sizeof(rfk->name), 119 snprintf(rfk->name, sizeof(rfk->name),
137 "b43-%s", wiphy_name(wl->hw->wiphy)); 120 "b43-%s", wiphy_name(wl->hw->wiphy));
138 rfk->rfkill->name = rfk->name;
139 rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
140 rfk->rfkill->data = dev;
141 rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle;
142
143 rfk->poll_dev = input_allocate_polled_device();
144 if (!rfk->poll_dev) {
145 rfkill_free(rfk->rfkill);
146 goto err_freed_rfk;
147 }
148
149 rfk->poll_dev->private = dev;
150 rfk->poll_dev->poll = b43_rfkill_poll;
151 rfk->poll_dev->poll_interval = 1000; /* msecs */
152 121
153 rfk->poll_dev->input->name = rfk->name; 122 rfk->rfkill = rfkill_alloc(rfk->name,
154 rfk->poll_dev->input->id.bustype = BUS_HOST; 123 dev->dev->dev,
155 rfk->poll_dev->input->id.vendor = dev->dev->bus->boardinfo.vendor; 124 RFKILL_TYPE_WLAN,
156 rfk->poll_dev->input->evbit[0] = BIT(EV_KEY); 125 &b43_rfkill_ops, dev);
157 set_bit(KEY_WLAN, rfk->poll_dev->input->keybit); 126 if (!rfk->rfkill)
127 goto out_error;
158 128
159 err = rfkill_register(rfk->rfkill); 129 err = rfkill_register(rfk->rfkill);
160 if (err) 130 if (err)
161 goto err_free_polldev; 131 goto err_free;
162
163#ifdef CONFIG_RFKILL_INPUT_MODULE
164 /* B43 RF-kill isn't useful without the rfkill-input subsystem.
165 * Try to load the module. */
166 err = request_module("rfkill-input");
167 if (err)
168 b43warn(wl, "Failed to load the rfkill-input module. "
169 "The built-in radio LED will not work.\n");
170#endif /* CONFIG_RFKILL_INPUT */
171
172#if !defined(CONFIG_RFKILL_INPUT) && !defined(CONFIG_RFKILL_INPUT_MODULE)
173 b43warn(wl, "The rfkill-input subsystem is not available. "
174 "The built-in radio LED will not work.\n");
175#endif
176
177 err = input_register_polled_device(rfk->poll_dev);
178 if (err)
179 goto err_unreg_rfk;
180 132
181 rfk->registered = 1; 133 rfk->registered = 1;
182 134
183 return; 135 return;
184err_unreg_rfk: 136 err_free:
185 rfkill_unregister(rfk->rfkill); 137 rfkill_destroy(rfk->rfkill);
186err_free_polldev: 138 out_error:
187 input_free_polled_device(rfk->poll_dev);
188 rfk->poll_dev = NULL;
189err_freed_rfk:
190 rfk->rfkill = NULL;
191out_error:
192 rfk->registered = 0; 139 rfk->registered = 0;
193 b43warn(wl, "RF-kill button init failed\n"); 140 b43warn(wl, "RF-kill button init failed\n");
194} 141}
@@ -201,9 +148,7 @@ void b43_rfkill_exit(struct b43_wldev *dev)
201 return; 148 return;
202 rfk->registered = 0; 149 rfk->registered = 0;
203 150
204 input_unregister_polled_device(rfk->poll_dev);
205 rfkill_unregister(rfk->rfkill); 151 rfkill_unregister(rfk->rfkill);
206 input_free_polled_device(rfk->poll_dev); 152 rfkill_destroy(rfk->rfkill);
207 rfk->poll_dev = NULL;
208 rfk->rfkill = NULL; 153 rfk->rfkill = NULL;
209} 154}
diff --git a/drivers/net/wireless/b43/rfkill.h b/drivers/net/wireless/b43/rfkill.h
index adacf936d815..da497e01bbb1 100644
--- a/drivers/net/wireless/b43/rfkill.h
+++ b/drivers/net/wireless/b43/rfkill.h
@@ -7,14 +7,11 @@ struct b43_wldev;
7#ifdef CONFIG_B43_RFKILL 7#ifdef CONFIG_B43_RFKILL
8 8
9#include <linux/rfkill.h> 9#include <linux/rfkill.h>
10#include <linux/input-polldev.h>
11 10
12 11
13struct b43_rfkill { 12struct b43_rfkill {
14 /* The RFKILL subsystem data structure */ 13 /* The RFKILL subsystem data structure */
15 struct rfkill *rfkill; 14 struct rfkill *rfkill;
16 /* The poll device for the RFKILL input button */
17 struct input_polled_dev *poll_dev;
18 /* Did initialization succeed? Used for freeing. */ 15 /* Did initialization succeed? Used for freeing. */
19 bool registered; 16 bool registered;
20 /* The unique name of this rfkill switch */ 17 /* The unique name of this rfkill switch */
@@ -26,7 +23,7 @@ struct b43_rfkill {
26void b43_rfkill_init(struct b43_wldev *dev); 23void b43_rfkill_init(struct b43_wldev *dev);
27void b43_rfkill_exit(struct b43_wldev *dev); 24void b43_rfkill_exit(struct b43_wldev *dev);
28 25
29char * b43_rfkill_led_name(struct b43_wldev *dev); 26const char *b43_rfkill_led_name(struct b43_wldev *dev);
30 27
31 28
32#else /* CONFIG_B43_RFKILL */ 29#else /* CONFIG_B43_RFKILL */
diff --git a/drivers/net/wireless/b43legacy/Kconfig b/drivers/net/wireless/b43legacy/Kconfig
index d4f628a74bbd..6893f439df70 100644
--- a/drivers/net/wireless/b43legacy/Kconfig
+++ b/drivers/net/wireless/b43legacy/Kconfig
@@ -47,7 +47,7 @@ config B43LEGACY_LEDS
47# if it's possible. 47# if it's possible.
48config B43LEGACY_RFKILL 48config B43LEGACY_RFKILL
49 bool 49 bool
50 depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43LEGACY) 50 depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY)
51 default y 51 default y
52 52
53# This config option automatically enables b43 HW-RNG support, 53# This config option automatically enables b43 HW-RNG support,
diff --git a/drivers/net/wireless/b43legacy/leds.c b/drivers/net/wireless/b43legacy/leds.c
index 3ea55b18c700..538d3117594b 100644
--- a/drivers/net/wireless/b43legacy/leds.c
+++ b/drivers/net/wireless/b43legacy/leds.c
@@ -86,7 +86,8 @@ static void b43legacy_led_brightness_set(struct led_classdev *led_dev,
86 86
87static int b43legacy_register_led(struct b43legacy_wldev *dev, 87static int b43legacy_register_led(struct b43legacy_wldev *dev,
88 struct b43legacy_led *led, 88 struct b43legacy_led *led,
89 const char *name, char *default_trigger, 89 const char *name,
90 const char *default_trigger,
90 u8 led_index, bool activelow) 91 u8 led_index, bool activelow)
91{ 92{
92 int err; 93 int err;
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
index 4b0c7d27a51f..c6230a64505a 100644
--- a/drivers/net/wireless/b43legacy/rfkill.c
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -45,12 +45,11 @@ static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
45} 45}
46 46
47/* The poll callback for the hardware button. */ 47/* The poll callback for the hardware button. */
48static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev) 48static void b43legacy_rfkill_poll(struct rfkill *rfkill, void *data)
49{ 49{
50 struct b43legacy_wldev *dev = poll_dev->private; 50 struct b43legacy_wldev *dev = data;
51 struct b43legacy_wl *wl = dev->wl; 51 struct b43legacy_wl *wl = dev->wl;
52 bool enabled; 52 bool enabled;
53 bool report_change = 0;
54 53
55 mutex_lock(&wl->mutex); 54 mutex_lock(&wl->mutex);
56 if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) { 55 if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) {
@@ -60,71 +59,64 @@ static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev)
60 enabled = b43legacy_is_hw_radio_enabled(dev); 59 enabled = b43legacy_is_hw_radio_enabled(dev);
61 if (unlikely(enabled != dev->radio_hw_enable)) { 60 if (unlikely(enabled != dev->radio_hw_enable)) {
62 dev->radio_hw_enable = enabled; 61 dev->radio_hw_enable = enabled;
63 report_change = 1;
64 b43legacyinfo(wl, "Radio hardware status changed to %s\n", 62 b43legacyinfo(wl, "Radio hardware status changed to %s\n",
65 enabled ? "ENABLED" : "DISABLED"); 63 enabled ? "ENABLED" : "DISABLED");
64 enabled = !rfkill_set_hw_state(rfkill, !enabled);
65 if (enabled != dev->phy.radio_on) {
66 if (enabled)
67 b43legacy_radio_turn_on(dev);
68 else
69 b43legacy_radio_turn_off(dev, 0);
70 }
66 } 71 }
67 mutex_unlock(&wl->mutex); 72 mutex_unlock(&wl->mutex);
68
69 /* send the radio switch event to the system - note both a key press
70 * and a release are required */
71 if (unlikely(report_change)) {
72 input_report_key(poll_dev->input, KEY_WLAN, 1);
73 input_report_key(poll_dev->input, KEY_WLAN, 0);
74 }
75} 73}
76 74
77/* Called when the RFKILL toggled in software. 75/* Called when the RFKILL toggled in software.
78 * This is called without locking. */ 76 * This is called without locking. */
79static int b43legacy_rfkill_soft_toggle(void *data, enum rfkill_state state) 77static int b43legacy_rfkill_soft_set(void *data, bool blocked)
80{ 78{
81 struct b43legacy_wldev *dev = data; 79 struct b43legacy_wldev *dev = data;
82 struct b43legacy_wl *wl = dev->wl; 80 struct b43legacy_wl *wl = dev->wl;
83 int err = -EBUSY; 81 int ret = -EINVAL;
84 82
85 if (!wl->rfkill.registered) 83 if (!wl->rfkill.registered)
86 return 0; 84 return -EINVAL;
87 85
88 mutex_lock(&wl->mutex); 86 mutex_lock(&wl->mutex);
89 if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) 87 if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
90 goto out_unlock; 88 goto out_unlock;
91 err = 0; 89
92 switch (state) { 90 if (!dev->radio_hw_enable)
93 case RFKILL_STATE_UNBLOCKED: 91 goto out_unlock;
94 if (!dev->radio_hw_enable) { 92
95 /* No luck. We can't toggle the hardware RF-kill 93 if (!blocked != dev->phy.radio_on) {
96 * button from software. */ 94 if (!blocked)
97 err = -EBUSY;
98 goto out_unlock;
99 }
100 if (!dev->phy.radio_on)
101 b43legacy_radio_turn_on(dev); 95 b43legacy_radio_turn_on(dev);
102 break; 96 else
103 case RFKILL_STATE_SOFT_BLOCKED:
104 if (dev->phy.radio_on)
105 b43legacy_radio_turn_off(dev, 0); 97 b43legacy_radio_turn_off(dev, 0);
106 break;
107 default:
108 b43legacywarn(wl, "Received unexpected rfkill state %d.\n",
109 state);
110 break;
111 } 98 }
99 ret = 0;
112 100
113out_unlock: 101out_unlock:
114 mutex_unlock(&wl->mutex); 102 mutex_unlock(&wl->mutex);
115 103 return ret;
116 return err;
117} 104}
118 105
119char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev) 106const char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
120{ 107{
121 struct b43legacy_rfkill *rfk = &(dev->wl->rfkill); 108 struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
122 109
123 if (!rfk->registered) 110 if (!rfk->registered)
124 return NULL; 111 return NULL;
125 return rfkill_get_led_name(rfk->rfkill); 112 return rfkill_get_led_trigger_name(rfk->rfkill);
126} 113}
127 114
115static const struct rfkill_ops b43legacy_rfkill_ops = {
116 .set_block = b43legacy_rfkill_soft_set,
117 .poll = b43legacy_rfkill_poll,
118};
119
128void b43legacy_rfkill_init(struct b43legacy_wldev *dev) 120void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
129{ 121{
130 struct b43legacy_wl *wl = dev->wl; 122 struct b43legacy_wl *wl = dev->wl;
@@ -133,60 +125,25 @@ void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
133 125
134 rfk->registered = 0; 126 rfk->registered = 0;
135 127
136 rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
137 if (!rfk->rfkill)
138 goto out_error;
139 snprintf(rfk->name, sizeof(rfk->name), 128 snprintf(rfk->name, sizeof(rfk->name),
140 "b43legacy-%s", wiphy_name(wl->hw->wiphy)); 129 "b43legacy-%s", wiphy_name(wl->hw->wiphy));
141 rfk->rfkill->name = rfk->name; 130 rfk->rfkill = rfkill_alloc(rfk->name,
142 rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; 131 dev->dev->dev,
143 rfk->rfkill->data = dev; 132 RFKILL_TYPE_WLAN,
144 rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle; 133 &b43legacy_rfkill_ops, dev);
145 134 if (!rfk->rfkill)
146 rfk->poll_dev = input_allocate_polled_device(); 135 goto out_error;
147 if (!rfk->poll_dev) {
148 rfkill_free(rfk->rfkill);
149 goto err_freed_rfk;
150 }
151
152 rfk->poll_dev->private = dev;
153 rfk->poll_dev->poll = b43legacy_rfkill_poll;
154 rfk->poll_dev->poll_interval = 1000; /* msecs */
155
156 rfk->poll_dev->input->name = rfk->name;
157 rfk->poll_dev->input->id.bustype = BUS_HOST;
158 rfk->poll_dev->input->id.vendor = dev->dev->bus->boardinfo.vendor;
159 rfk->poll_dev->input->evbit[0] = BIT(EV_KEY);
160 set_bit(KEY_WLAN, rfk->poll_dev->input->keybit);
161 136
162 err = rfkill_register(rfk->rfkill); 137 err = rfkill_register(rfk->rfkill);
163 if (err) 138 if (err)
164 goto err_free_polldev; 139 goto err_free;
165
166#ifdef CONFIG_RFKILL_INPUT_MODULE
167 /* B43legacy RF-kill isn't useful without the rfkill-input subsystem.
168 * Try to load the module. */
169 err = request_module("rfkill-input");
170 if (err)
171 b43legacywarn(wl, "Failed to load the rfkill-input module."
172 "The built-in radio LED will not work.\n");
173#endif /* CONFIG_RFKILL_INPUT */
174
175 err = input_register_polled_device(rfk->poll_dev);
176 if (err)
177 goto err_unreg_rfk;
178 140
179 rfk->registered = 1; 141 rfk->registered = 1;
180 142
181 return; 143 return;
182err_unreg_rfk: 144 err_free:
183 rfkill_unregister(rfk->rfkill); 145 rfkill_destroy(rfk->rfkill);
184err_free_polldev: 146 out_error:
185 input_free_polled_device(rfk->poll_dev);
186 rfk->poll_dev = NULL;
187err_freed_rfk:
188 rfk->rfkill = NULL;
189out_error:
190 rfk->registered = 0; 147 rfk->registered = 0;
191 b43legacywarn(wl, "RF-kill button init failed\n"); 148 b43legacywarn(wl, "RF-kill button init failed\n");
192} 149}
@@ -199,10 +156,8 @@ void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
199 return; 156 return;
200 rfk->registered = 0; 157 rfk->registered = 0;
201 158
202 input_unregister_polled_device(rfk->poll_dev);
203 rfkill_unregister(rfk->rfkill); 159 rfkill_unregister(rfk->rfkill);
204 input_free_polled_device(rfk->poll_dev); 160 rfkill_destroy(rfk->rfkill);
205 rfk->poll_dev = NULL;
206 rfk->rfkill = NULL; 161 rfk->rfkill = NULL;
207} 162}
208 163
diff --git a/drivers/net/wireless/b43legacy/rfkill.h b/drivers/net/wireless/b43legacy/rfkill.h
index 11150a8032f0..adffc503a6a1 100644
--- a/drivers/net/wireless/b43legacy/rfkill.h
+++ b/drivers/net/wireless/b43legacy/rfkill.h
@@ -6,16 +6,12 @@ struct b43legacy_wldev;
6#ifdef CONFIG_B43LEGACY_RFKILL 6#ifdef CONFIG_B43LEGACY_RFKILL
7 7
8#include <linux/rfkill.h> 8#include <linux/rfkill.h>
9#include <linux/workqueue.h>
10#include <linux/input-polldev.h>
11 9
12 10
13 11
14struct b43legacy_rfkill { 12struct b43legacy_rfkill {
15 /* The RFKILL subsystem data structure */ 13 /* The RFKILL subsystem data structure */
16 struct rfkill *rfkill; 14 struct rfkill *rfkill;
17 /* The poll device for the RFKILL input button */
18 struct input_polled_dev *poll_dev;
19 /* Did initialization succeed? Used for freeing. */ 15 /* Did initialization succeed? Used for freeing. */
20 bool registered; 16 bool registered;
21 /* The unique name of this rfkill switch */ 17 /* The unique name of this rfkill switch */
@@ -27,7 +23,7 @@ struct b43legacy_rfkill {
27void b43legacy_rfkill_init(struct b43legacy_wldev *dev); 23void b43legacy_rfkill_init(struct b43legacy_wldev *dev);
28void b43legacy_rfkill_exit(struct b43legacy_wldev *dev); 24void b43legacy_rfkill_exit(struct b43legacy_wldev *dev);
29 25
30char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev); 26const char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev);
31 27
32 28
33#else /* CONFIG_B43LEGACY_RFKILL */ 29#else /* CONFIG_B43LEGACY_RFKILL */
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 8304f6406a17..6fe259fcfb8f 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -5,15 +5,14 @@ config IWLWIFI
5 select FW_LOADER 5 select FW_LOADER
6 select MAC80211_LEDS if IWLWIFI_LEDS 6 select MAC80211_LEDS if IWLWIFI_LEDS
7 select LEDS_CLASS if IWLWIFI_LEDS 7 select LEDS_CLASS if IWLWIFI_LEDS
8 select RFKILL if IWLWIFI_RFKILL
9 8
10config IWLWIFI_LEDS 9config IWLWIFI_LEDS
11 bool "Enable LED support in iwlagn and iwl3945 drivers" 10 bool "Enable LED support in iwlagn and iwl3945 drivers"
12 depends on IWLWIFI 11 depends on IWLWIFI
13 12
14config IWLWIFI_RFKILL 13config IWLWIFI_RFKILL
15 bool "Enable RF kill support in iwlagn and iwl3945 drivers" 14 def_bool y
16 depends on IWLWIFI 15 depends on IWLWIFI && RFKILL
17 16
18config IWLWIFI_SPECTRUM_MEASUREMENT 17config IWLWIFI_SPECTRUM_MEASUREMENT
19 bool "Enable Spectrum Measurement in iwlagn driver" 18 bool "Enable Spectrum Measurement in iwlagn driver"
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
index 65605ad44e4b..13149936fd26 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
@@ -36,42 +36,37 @@
36#include "iwl-core.h" 36#include "iwl-core.h"
37 37
38/* software rf-kill from user */ 38/* software rf-kill from user */
39static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) 39static int iwl_rfkill_soft_rf_kill(void *data, bool blocked)
40{ 40{
41 struct iwl_priv *priv = data; 41 struct iwl_priv *priv = data;
42 int err = 0;
43 42
44 if (!priv->rfkill) 43 if (!priv->rfkill)
45 return 0; 44 return -EINVAL;
46 45
47 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 46 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
48 return 0; 47 return 0;
49 48
50 IWL_DEBUG_RF_KILL(priv, "we received soft RFKILL set to state %d\n", state); 49 IWL_DEBUG_RF_KILL(priv, "received soft RFKILL: block=%d\n", blocked);
50
51 mutex_lock(&priv->mutex); 51 mutex_lock(&priv->mutex);
52 52
53 switch (state) { 53 if (iwl_is_rfkill_hw(priv))
54 case RFKILL_STATE_UNBLOCKED: 54 goto out_unlock;
55 if (iwl_is_rfkill_hw(priv)) { 55
56 err = -EBUSY; 56 if (!blocked)
57 goto out_unlock;
58 }
59 iwl_radio_kill_sw_enable_radio(priv); 57 iwl_radio_kill_sw_enable_radio(priv);
60 break; 58 else
61 case RFKILL_STATE_SOFT_BLOCKED:
62 iwl_radio_kill_sw_disable_radio(priv); 59 iwl_radio_kill_sw_disable_radio(priv);
63 break; 60
64 default:
65 IWL_WARN(priv, "we received unexpected RFKILL state %d\n",
66 state);
67 break;
68 }
69out_unlock: 61out_unlock:
70 mutex_unlock(&priv->mutex); 62 mutex_unlock(&priv->mutex);
71 63 return 0;
72 return err;
73} 64}
74 65
66static const struct rfkill_ops iwl_rfkill_ops = {
67 .set_block = iwl_rfkill_soft_rf_kill,
68};
69
75int iwl_rfkill_init(struct iwl_priv *priv) 70int iwl_rfkill_init(struct iwl_priv *priv)
76{ 71{
77 struct device *device = wiphy_dev(priv->hw->wiphy); 72 struct device *device = wiphy_dev(priv->hw->wiphy);
@@ -80,21 +75,16 @@ int iwl_rfkill_init(struct iwl_priv *priv)
80 BUG_ON(device == NULL); 75 BUG_ON(device == NULL);
81 76
82 IWL_DEBUG_RF_KILL(priv, "Initializing RFKILL.\n"); 77 IWL_DEBUG_RF_KILL(priv, "Initializing RFKILL.\n");
83 priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); 78 priv->rfkill = rfkill_alloc(priv->cfg->name,
79 device,
80 RFKILL_TYPE_WLAN,
81 &iwl_rfkill_ops, priv);
84 if (!priv->rfkill) { 82 if (!priv->rfkill) {
85 IWL_ERR(priv, "Unable to allocate RFKILL device.\n"); 83 IWL_ERR(priv, "Unable to allocate RFKILL device.\n");
86 ret = -ENOMEM; 84 ret = -ENOMEM;
87 goto error; 85 goto error;
88 } 86 }
89 87
90 priv->rfkill->name = priv->cfg->name;
91 priv->rfkill->data = priv;
92 priv->rfkill->state = RFKILL_STATE_UNBLOCKED;
93 priv->rfkill->toggle_radio = iwl_rfkill_soft_rf_kill;
94
95 priv->rfkill->dev.class->suspend = NULL;
96 priv->rfkill->dev.class->resume = NULL;
97
98 ret = rfkill_register(priv->rfkill); 88 ret = rfkill_register(priv->rfkill);
99 if (ret) { 89 if (ret) {
100 IWL_ERR(priv, "Unable to register RFKILL: %d\n", ret); 90 IWL_ERR(priv, "Unable to register RFKILL: %d\n", ret);
@@ -102,11 +92,10 @@ int iwl_rfkill_init(struct iwl_priv *priv)
102 } 92 }
103 93
104 IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n"); 94 IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n");
105 return ret; 95 return 0;
106 96
107free_rfkill: 97free_rfkill:
108 if (priv->rfkill != NULL) 98 rfkill_destroy(priv->rfkill);
109 rfkill_free(priv->rfkill);
110 priv->rfkill = NULL; 99 priv->rfkill = NULL;
111 100
112error: 101error:
@@ -118,8 +107,10 @@ EXPORT_SYMBOL(iwl_rfkill_init);
118void iwl_rfkill_unregister(struct iwl_priv *priv) 107void iwl_rfkill_unregister(struct iwl_priv *priv)
119{ 108{
120 109
121 if (priv->rfkill) 110 if (priv->rfkill) {
122 rfkill_unregister(priv->rfkill); 111 rfkill_unregister(priv->rfkill);
112 rfkill_destroy(priv->rfkill);
113 }
123 114
124 priv->rfkill = NULL; 115 priv->rfkill = NULL;
125} 116}
@@ -131,14 +122,10 @@ void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
131 if (!priv->rfkill) 122 if (!priv->rfkill)
132 return; 123 return;
133 124
134 if (iwl_is_rfkill_hw(priv)) { 125 if (rfkill_set_hw_state(priv->rfkill,
135 rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); 126 !!iwl_is_rfkill_hw(priv)))
136 return; 127 iwl_radio_kill_sw_disable_radio(priv);
137 }
138
139 if (!iwl_is_rfkill_sw(priv))
140 rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
141 else 128 else
142 rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); 129 iwl_radio_kill_sw_enable_radio(priv);
143} 130}
144EXPORT_SYMBOL(iwl_rfkill_set_hw_state); 131EXPORT_SYMBOL(iwl_rfkill_set_hw_state);
diff --git a/drivers/net/wireless/iwmc3200wifi/rfkill.c b/drivers/net/wireless/iwmc3200wifi/rfkill.c
index 4ca8b495f82d..8ee2c3c09a02 100644
--- a/drivers/net/wireless/iwmc3200wifi/rfkill.c
+++ b/drivers/net/wireless/iwmc3200wifi/rfkill.c
@@ -25,47 +25,42 @@
25 25
26#include "iwm.h" 26#include "iwm.h"
27 27
28static int iwm_rfkill_soft_toggle(void *data, enum rfkill_state state) 28static int iwm_rfkill_set_block(void *data, bool blocked)
29{ 29{
30 struct iwm_priv *iwm = data; 30 struct iwm_priv *iwm = data;
31 31
32 switch (state) { 32 if (!blocked) {
33 case RFKILL_STATE_UNBLOCKED:
34 if (test_bit(IWM_RADIO_RFKILL_HW, &iwm->radio)) 33 if (test_bit(IWM_RADIO_RFKILL_HW, &iwm->radio))
35 return -EBUSY; 34 return -EBUSY;
36 35
37 if (test_and_clear_bit(IWM_RADIO_RFKILL_SW, &iwm->radio) && 36 if (test_and_clear_bit(IWM_RADIO_RFKILL_SW, &iwm->radio) &&
38 (iwm_to_ndev(iwm)->flags & IFF_UP)) 37 (iwm_to_ndev(iwm)->flags & IFF_UP))
39 iwm_up(iwm); 38 return iwm_up(iwm);
40 39 } else {
41 break;
42 case RFKILL_STATE_SOFT_BLOCKED:
43 if (!test_and_set_bit(IWM_RADIO_RFKILL_SW, &iwm->radio)) 40 if (!test_and_set_bit(IWM_RADIO_RFKILL_SW, &iwm->radio))
44 iwm_down(iwm); 41 return iwm_down(iwm);
45
46 break;
47 default:
48 break;
49 } 42 }
50 43
51 return 0; 44 return 0;
52} 45}
53 46
47static const struct rfkill_ops iwm_rfkill_ops = {
48 .set_block = iwm_rfkill_set_block,
49};
50
54int iwm_rfkill_init(struct iwm_priv *iwm) 51int iwm_rfkill_init(struct iwm_priv *iwm)
55{ 52{
56 int ret; 53 int ret;
57 54
58 iwm->rfkill = rfkill_allocate(iwm_to_dev(iwm), RFKILL_TYPE_WLAN); 55 iwm->rfkill = rfkill_alloc(KBUILD_MODNAME,
56 iwm_to_dev(iwm),
57 RFKILL_TYPE_WLAN,
58 &iwm_rfkill_ops, iwm);
59 if (!iwm->rfkill) { 59 if (!iwm->rfkill) {
60 IWM_ERR(iwm, "Unable to allocate rfkill device\n"); 60 IWM_ERR(iwm, "Unable to allocate rfkill device\n");
61 return -ENOMEM; 61 return -ENOMEM;
62 } 62 }
63 63
64 iwm->rfkill->name = KBUILD_MODNAME;
65 iwm->rfkill->data = iwm;
66 iwm->rfkill->state = RFKILL_STATE_UNBLOCKED;
67 iwm->rfkill->toggle_radio = iwm_rfkill_soft_toggle;
68
69 ret = rfkill_register(iwm->rfkill); 64 ret = rfkill_register(iwm->rfkill);
70 if (ret) { 65 if (ret) {
71 IWM_ERR(iwm, "Failed to register rfkill device\n"); 66 IWM_ERR(iwm, "Failed to register rfkill device\n");
@@ -74,15 +69,15 @@ int iwm_rfkill_init(struct iwm_priv *iwm)
74 69
75 return 0; 70 return 0;
76 fail: 71 fail:
77 rfkill_free(iwm->rfkill); 72 rfkill_destroy(iwm->rfkill);
78 return ret; 73 return ret;
79} 74}
80 75
81void iwm_rfkill_exit(struct iwm_priv *iwm) 76void iwm_rfkill_exit(struct iwm_priv *iwm)
82{ 77{
83 if (iwm->rfkill) 78 if (iwm->rfkill) {
84 rfkill_unregister(iwm->rfkill); 79 rfkill_unregister(iwm->rfkill);
85 80 rfkill_destroy(iwm->rfkill);
86 rfkill_free(iwm->rfkill); 81 }
87 iwm->rfkill = NULL; 82 iwm->rfkill = NULL;
88} 83}