aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-06-02 07:01:37 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-06-03 14:06:13 -0400
commit19d337dff95cbf76edd3ad95c0cee2732c3e1ec5 (patch)
tree33326eeb09cb9664cc8427a5dc7cd2b08b5a57c3 /drivers
parent0f6399c4c525b518644a9b09f8d6fb125a418c4d (diff)
rfkill: rewrite
This patch completely rewrites the rfkill core to address the following deficiencies: * all rfkill drivers need to implement polling where necessary rather than having one central implementation * updating the rfkill state cannot be done from arbitrary contexts, forcing drivers to use schedule_work and requiring lots of code * rfkill drivers need to keep track of soft/hard blocked internally -- the core should do this * the rfkill API has many unexpected quirks, for example being asymmetric wrt. alloc/free and register/unregister * rfkill can call back into a driver from within a function the driver called -- this is prone to deadlocks and generally should be avoided * rfkill-input pointlessly is a separate module * drivers need to #ifdef rfkill functions (unless they want to depend on or select RFKILL) -- rfkill should provide inlines that do nothing if it isn't compiled in * the rfkill structure is not opaque -- drivers need to initialise it correctly (lots of sanity checking code required) -- instead force drivers to pass the right variables to rfkill_alloc() * the documentation is hard to read because it always assumes the reader is completely clueless and contains way TOO MANY CAPS * the rfkill code needlessly uses a lot of locks and atomic operations in locked sections * fix LED trigger to actually change the LED when the radio state changes -- this wasn't done before Tested-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk> Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> [thinkpad] Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/usb/hso.c42
-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
-rw-r--r--drivers/platform/x86/Kconfig14
-rw-r--r--drivers/platform/x86/acer-wmi.c50
-rw-r--r--drivers/platform/x86/dell-laptop.c101
-rw-r--r--drivers/platform/x86/eeepc-laptop.c99
-rw-r--r--drivers/platform/x86/hp-wmi.c103
-rw-r--r--drivers/platform/x86/sony-laptop.c191
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c873
-rw-r--r--drivers/platform/x86/toshiba_acpi.c159
30 files changed, 904 insertions, 1281 deletions
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 837135f0390a..5ddd8c4f9019 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -2481,10 +2481,10 @@ static int add_net_device(struct hso_device *hso_dev)
2481 return 0; 2481 return 0;
2482} 2482}
2483 2483
2484static int hso_radio_toggle(void *data, enum rfkill_state state) 2484static int hso_rfkill_set_block(void *data, bool blocked)
2485{ 2485{
2486 struct hso_device *hso_dev = data; 2486 struct hso_device *hso_dev = data;
2487 int enabled = (state == RFKILL_STATE_UNBLOCKED); 2487 int enabled = !blocked;
2488 int rv; 2488 int rv;
2489 2489
2490 mutex_lock(&hso_dev->mutex); 2490 mutex_lock(&hso_dev->mutex);
@@ -2498,6 +2498,10 @@ static int hso_radio_toggle(void *data, enum rfkill_state state)
2498 return rv; 2498 return rv;
2499} 2499}
2500 2500
2501static const struct rfkill_ops hso_rfkill_ops = {
2502 .set_block = hso_rfkill_set_block,
2503};
2504
2501/* Creates and sets up everything for rfkill */ 2505/* Creates and sets up everything for rfkill */
2502static void hso_create_rfkill(struct hso_device *hso_dev, 2506static void hso_create_rfkill(struct hso_device *hso_dev,
2503 struct usb_interface *interface) 2507 struct usb_interface *interface)
@@ -2506,29 +2510,25 @@ static void hso_create_rfkill(struct hso_device *hso_dev,
2506 struct device *dev = &hso_net->net->dev; 2510 struct device *dev = &hso_net->net->dev;
2507 char *rfkn; 2511 char *rfkn;
2508 2512
2509 hso_net->rfkill = rfkill_allocate(&interface_to_usbdev(interface)->dev,
2510 RFKILL_TYPE_WWAN);
2511 if (!hso_net->rfkill) {
2512 dev_err(dev, "%s - Out of memory\n", __func__);
2513 return;
2514 }
2515 rfkn = kzalloc(20, GFP_KERNEL); 2513 rfkn = kzalloc(20, GFP_KERNEL);
2516 if (!rfkn) { 2514 if (!rfkn)
2517 rfkill_free(hso_net->rfkill);
2518 hso_net->rfkill = NULL;
2519 dev_err(dev, "%s - Out of memory\n", __func__); 2515 dev_err(dev, "%s - Out of memory\n", __func__);
2520 return; 2516
2521 }
2522 snprintf(rfkn, 20, "hso-%d", 2517 snprintf(rfkn, 20, "hso-%d",
2523 interface->altsetting->desc.bInterfaceNumber); 2518 interface->altsetting->desc.bInterfaceNumber);
2524 hso_net->rfkill->name = rfkn; 2519
2525 hso_net->rfkill->state = RFKILL_STATE_UNBLOCKED; 2520 hso_net->rfkill = rfkill_alloc(rfkn,
2526 hso_net->rfkill->data = hso_dev; 2521 &interface_to_usbdev(interface)->dev,
2527 hso_net->rfkill->toggle_radio = hso_radio_toggle; 2522 RFKILL_TYPE_WWAN,
2523 &hso_rfkill_ops, hso_dev);
2524 if (!hso_net->rfkill) {
2525 dev_err(dev, "%s - Out of memory\n", __func__);
2526 kfree(rfkn);
2527 return;
2528 }
2528 if (rfkill_register(hso_net->rfkill) < 0) { 2529 if (rfkill_register(hso_net->rfkill) < 0) {
2530 rfkill_destroy(hso_net->rfkill);
2529 kfree(rfkn); 2531 kfree(rfkn);
2530 hso_net->rfkill->name = NULL;
2531 rfkill_free(hso_net->rfkill);
2532 hso_net->rfkill = NULL; 2532 hso_net->rfkill = NULL;
2533 dev_err(dev, "%s - Failed to register rfkill\n", __func__); 2533 dev_err(dev, "%s - Failed to register rfkill\n", __func__);
2534 return; 2534 return;
@@ -3165,8 +3165,10 @@ static void hso_free_interface(struct usb_interface *interface)
3165 hso_stop_net_device(network_table[i]); 3165 hso_stop_net_device(network_table[i]);
3166 cancel_work_sync(&network_table[i]->async_put_intf); 3166 cancel_work_sync(&network_table[i]->async_put_intf);
3167 cancel_work_sync(&network_table[i]->async_get_intf); 3167 cancel_work_sync(&network_table[i]->async_get_intf);
3168 if (rfk) 3168 if (rfk) {
3169 rfkill_unregister(rfk); 3169 rfkill_unregister(rfk);
3170 rfkill_destroy(rfk);
3171 }
3170 hso_free_net_device(network_table[i]); 3172 hso_free_net_device(network_table[i]);
3171 } 3173 }
3172 } 3174 }
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}
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 284ebaca6e45..c682ac536415 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -21,7 +21,7 @@ config ACER_WMI
21 depends on NEW_LEDS 21 depends on NEW_LEDS
22 depends on BACKLIGHT_CLASS_DEVICE 22 depends on BACKLIGHT_CLASS_DEVICE
23 depends on SERIO_I8042 23 depends on SERIO_I8042
24 depends on RFKILL 24 depends on RFKILL || RFKILL = n
25 select ACPI_WMI 25 select ACPI_WMI
26 ---help--- 26 ---help---
27 This is a driver for newer Acer (and Wistron) laptops. It adds 27 This is a driver for newer Acer (and Wistron) laptops. It adds
@@ -60,7 +60,7 @@ config DELL_LAPTOP
60 depends on DCDBAS 60 depends on DCDBAS
61 depends on EXPERIMENTAL 61 depends on EXPERIMENTAL
62 depends on BACKLIGHT_CLASS_DEVICE 62 depends on BACKLIGHT_CLASS_DEVICE
63 depends on RFKILL 63 depends on RFKILL || RFKILL = n
64 depends on POWER_SUPPLY 64 depends on POWER_SUPPLY
65 default n 65 default n
66 ---help--- 66 ---help---
@@ -117,7 +117,7 @@ config HP_WMI
117 tristate "HP WMI extras" 117 tristate "HP WMI extras"
118 depends on ACPI_WMI 118 depends on ACPI_WMI
119 depends on INPUT 119 depends on INPUT
120 depends on RFKILL 120 depends on RFKILL || RFKILL = n
121 help 121 help
122 Say Y here if you want to support WMI-based hotkeys on HP laptops and 122 Say Y here if you want to support WMI-based hotkeys on HP laptops and
123 to read data from WMI such as docking or ambient light sensor state. 123 to read data from WMI such as docking or ambient light sensor state.
@@ -196,14 +196,13 @@ config THINKPAD_ACPI
196 tristate "ThinkPad ACPI Laptop Extras" 196 tristate "ThinkPad ACPI Laptop Extras"
197 depends on ACPI 197 depends on ACPI
198 depends on INPUT 198 depends on INPUT
199 depends on RFKILL || RFKILL = n
199 select BACKLIGHT_LCD_SUPPORT 200 select BACKLIGHT_LCD_SUPPORT
200 select BACKLIGHT_CLASS_DEVICE 201 select BACKLIGHT_CLASS_DEVICE
201 select HWMON 202 select HWMON
202 select NVRAM 203 select NVRAM
203 select NEW_LEDS 204 select NEW_LEDS
204 select LEDS_CLASS 205 select LEDS_CLASS
205 select NET
206 select RFKILL
207 ---help--- 206 ---help---
208 This is a driver for the IBM and Lenovo ThinkPad laptops. It adds 207 This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
209 support for Fn-Fx key combinations, Bluetooth control, video 208 support for Fn-Fx key combinations, Bluetooth control, video
@@ -338,9 +337,9 @@ config EEEPC_LAPTOP
338 depends on ACPI 337 depends on ACPI
339 depends on INPUT 338 depends on INPUT
340 depends on EXPERIMENTAL 339 depends on EXPERIMENTAL
340 depends on RFKILL || RFKILL = n
341 select BACKLIGHT_CLASS_DEVICE 341 select BACKLIGHT_CLASS_DEVICE
342 select HWMON 342 select HWMON
343 select RFKILL
344 ---help--- 343 ---help---
345 This driver supports the Fn-Fx keys on Eee PC laptops. 344 This driver supports the Fn-Fx keys on Eee PC laptops.
346 It also adds the ability to switch camera/wlan on/off. 345 It also adds the ability to switch camera/wlan on/off.
@@ -405,9 +404,8 @@ config ACPI_TOSHIBA
405 tristate "Toshiba Laptop Extras" 404 tristate "Toshiba Laptop Extras"
406 depends on ACPI 405 depends on ACPI
407 depends on INPUT 406 depends on INPUT
407 depends on RFKILL || RFKILL = n
408 select INPUT_POLLDEV 408 select INPUT_POLLDEV
409 select NET
410 select RFKILL
411 select BACKLIGHT_CLASS_DEVICE 409 select BACKLIGHT_CLASS_DEVICE
412 ---help--- 410 ---help---
413 This driver adds support for access to certain system settings 411 This driver adds support for access to certain system settings
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 62d02b3c998e..b618fa51db2d 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -958,58 +958,50 @@ static void acer_rfkill_update(struct work_struct *ignored)
958 958
959 status = get_u32(&state, ACER_CAP_WIRELESS); 959 status = get_u32(&state, ACER_CAP_WIRELESS);
960 if (ACPI_SUCCESS(status)) 960 if (ACPI_SUCCESS(status))
961 rfkill_force_state(wireless_rfkill, state ? 961 rfkill_set_sw_state(wireless_rfkill, !!state);
962 RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED);
963 962
964 if (has_cap(ACER_CAP_BLUETOOTH)) { 963 if (has_cap(ACER_CAP_BLUETOOTH)) {
965 status = get_u32(&state, ACER_CAP_BLUETOOTH); 964 status = get_u32(&state, ACER_CAP_BLUETOOTH);
966 if (ACPI_SUCCESS(status)) 965 if (ACPI_SUCCESS(status))
967 rfkill_force_state(bluetooth_rfkill, state ? 966 rfkill_set_sw_state(bluetooth_rfkill, !!state);
968 RFKILL_STATE_UNBLOCKED :
969 RFKILL_STATE_SOFT_BLOCKED);
970 } 967 }
971 968
972 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); 969 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
973} 970}
974 971
975static int acer_rfkill_set(void *data, enum rfkill_state state) 972static int acer_rfkill_set(void *data, bool blocked)
976{ 973{
977 acpi_status status; 974 acpi_status status;
978 u32 *cap = data; 975 u32 cap = (unsigned long)data;
979 status = set_u32((u32) (state == RFKILL_STATE_UNBLOCKED), *cap); 976 status = set_u32(!!blocked, cap);
980 if (ACPI_FAILURE(status)) 977 if (ACPI_FAILURE(status))
981 return -ENODEV; 978 return -ENODEV;
982 return 0; 979 return 0;
983} 980}
984 981
985static struct rfkill * acer_rfkill_register(struct device *dev, 982static const struct rfkill_ops acer_rfkill_ops = {
986enum rfkill_type type, char *name, u32 cap) 983 .set_block = acer_rfkill_set,
984};
985
986static struct rfkill *acer_rfkill_register(struct device *dev,
987 enum rfkill_type type,
988 char *name, u32 cap)
987{ 989{
988 int err; 990 int err;
989 u32 state; 991 u32 state;
990 u32 *data;
991 struct rfkill *rfkill_dev; 992 struct rfkill *rfkill_dev;
992 993
993 rfkill_dev = rfkill_allocate(dev, type); 994 rfkill_dev = rfkill_alloc(name, dev, type,
995 &acer_rfkill_ops,
996 (void *)(unsigned long)cap);
994 if (!rfkill_dev) 997 if (!rfkill_dev)
995 return ERR_PTR(-ENOMEM); 998 return ERR_PTR(-ENOMEM);
996 rfkill_dev->name = name;
997 get_u32(&state, cap); 999 get_u32(&state, cap);
998 rfkill_dev->state = state ? RFKILL_STATE_UNBLOCKED : 1000 rfkill_set_sw_state(rfkill_dev, !state);
999 RFKILL_STATE_SOFT_BLOCKED;
1000 data = kzalloc(sizeof(u32), GFP_KERNEL);
1001 if (!data) {
1002 rfkill_free(rfkill_dev);
1003 return ERR_PTR(-ENOMEM);
1004 }
1005 *data = cap;
1006 rfkill_dev->data = data;
1007 rfkill_dev->toggle_radio = acer_rfkill_set;
1008 1001
1009 err = rfkill_register(rfkill_dev); 1002 err = rfkill_register(rfkill_dev);
1010 if (err) { 1003 if (err) {
1011 kfree(rfkill_dev->data); 1004 rfkill_destroy(rfkill_dev);
1012 rfkill_free(rfkill_dev);
1013 return ERR_PTR(err); 1005 return ERR_PTR(err);
1014 } 1006 }
1015 return rfkill_dev; 1007 return rfkill_dev;
@@ -1027,8 +1019,8 @@ static int acer_rfkill_init(struct device *dev)
1027 RFKILL_TYPE_BLUETOOTH, "acer-bluetooth", 1019 RFKILL_TYPE_BLUETOOTH, "acer-bluetooth",
1028 ACER_CAP_BLUETOOTH); 1020 ACER_CAP_BLUETOOTH);
1029 if (IS_ERR(bluetooth_rfkill)) { 1021 if (IS_ERR(bluetooth_rfkill)) {
1030 kfree(wireless_rfkill->data);
1031 rfkill_unregister(wireless_rfkill); 1022 rfkill_unregister(wireless_rfkill);
1023 rfkill_destroy(wireless_rfkill);
1032 return PTR_ERR(bluetooth_rfkill); 1024 return PTR_ERR(bluetooth_rfkill);
1033 } 1025 }
1034 } 1026 }
@@ -1041,11 +1033,13 @@ static int acer_rfkill_init(struct device *dev)
1041static void acer_rfkill_exit(void) 1033static void acer_rfkill_exit(void)
1042{ 1034{
1043 cancel_delayed_work_sync(&acer_rfkill_work); 1035 cancel_delayed_work_sync(&acer_rfkill_work);
1044 kfree(wireless_rfkill->data); 1036
1045 rfkill_unregister(wireless_rfkill); 1037 rfkill_unregister(wireless_rfkill);
1038 rfkill_destroy(wireless_rfkill);
1039
1046 if (has_cap(ACER_CAP_BLUETOOTH)) { 1040 if (has_cap(ACER_CAP_BLUETOOTH)) {
1047 kfree(bluetooth_rfkill->data);
1048 rfkill_unregister(bluetooth_rfkill); 1041 rfkill_unregister(bluetooth_rfkill);
1042 rfkill_destroy(bluetooth_rfkill);
1049 } 1043 }
1050 return; 1044 return;
1051} 1045}
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index af9f43021172..2faf0e14f05a 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -174,10 +174,11 @@ dell_send_request(struct calling_interface_buffer *buffer, int class,
174 result[3]: NVRAM format version number 174 result[3]: NVRAM format version number
175*/ 175*/
176 176
177static int dell_rfkill_set(int radio, enum rfkill_state state) 177static int dell_rfkill_set(void *data, bool blocked)
178{ 178{
179 struct calling_interface_buffer buffer; 179 struct calling_interface_buffer buffer;
180 int disable = (state == RFKILL_STATE_UNBLOCKED) ? 0 : 1; 180 int disable = blocked ? 0 : 1;
181 unsigned long radio = (unsigned long)data;
181 182
182 memset(&buffer, 0, sizeof(struct calling_interface_buffer)); 183 memset(&buffer, 0, sizeof(struct calling_interface_buffer));
183 buffer.input[0] = (1 | (radio<<8) | (disable << 16)); 184 buffer.input[0] = (1 | (radio<<8) | (disable << 16));
@@ -186,56 +187,24 @@ static int dell_rfkill_set(int radio, enum rfkill_state state)
186 return 0; 187 return 0;
187} 188}
188 189
189static int dell_wifi_set(void *data, enum rfkill_state state) 190static void dell_rfkill_query(struct rfkill *rfkill, void *data)
190{
191 return dell_rfkill_set(1, state);
192}
193
194static int dell_bluetooth_set(void *data, enum rfkill_state state)
195{
196 return dell_rfkill_set(2, state);
197}
198
199static int dell_wwan_set(void *data, enum rfkill_state state)
200{
201 return dell_rfkill_set(3, state);
202}
203
204static int dell_rfkill_get(int bit, enum rfkill_state *state)
205{ 191{
206 struct calling_interface_buffer buffer; 192 struct calling_interface_buffer buffer;
207 int status; 193 int status;
208 int new_state = RFKILL_STATE_HARD_BLOCKED; 194 int bit = (unsigned long)data + 16;
209 195
210 memset(&buffer, 0, sizeof(struct calling_interface_buffer)); 196 memset(&buffer, 0, sizeof(struct calling_interface_buffer));
211 dell_send_request(&buffer, 17, 11); 197 dell_send_request(&buffer, 17, 11);
212 status = buffer.output[1]; 198 status = buffer.output[1];
213 199
214 if (status & (1<<16)) 200 if (status & BIT(bit))
215 new_state = RFKILL_STATE_SOFT_BLOCKED; 201 rfkill_set_hw_state(rfkill, !!(status & BIT(16)));
216
217 if (status & (1<<bit))
218 *state = new_state;
219 else
220 *state = RFKILL_STATE_UNBLOCKED;
221
222 return 0;
223}
224
225static int dell_wifi_get(void *data, enum rfkill_state *state)
226{
227 return dell_rfkill_get(17, state);
228}
229
230static int dell_bluetooth_get(void *data, enum rfkill_state *state)
231{
232 return dell_rfkill_get(18, state);
233} 202}
234 203
235static int dell_wwan_get(void *data, enum rfkill_state *state) 204static const struct rfkill_ops dell_rfkill_ops = {
236{ 205 .set_block = dell_rfkill_set,
237 return dell_rfkill_get(19, state); 206 .query = dell_rfkill_query,
238} 207};
239 208
240static int dell_setup_rfkill(void) 209static int dell_setup_rfkill(void)
241{ 210{
@@ -248,36 +217,37 @@ static int dell_setup_rfkill(void)
248 status = buffer.output[1]; 217 status = buffer.output[1];
249 218
250 if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { 219 if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
251 wifi_rfkill = rfkill_allocate(NULL, RFKILL_TYPE_WLAN); 220 wifi_rfkill = rfkill_alloc("dell-wifi", NULL, RFKILL_TYPE_WLAN,
252 if (!wifi_rfkill) 221 &dell_rfkill_ops, (void *) 1);
222 if (!wifi_rfkill) {
223 ret = -ENOMEM;
253 goto err_wifi; 224 goto err_wifi;
254 wifi_rfkill->name = "dell-wifi"; 225 }
255 wifi_rfkill->toggle_radio = dell_wifi_set;
256 wifi_rfkill->get_state = dell_wifi_get;
257 ret = rfkill_register(wifi_rfkill); 226 ret = rfkill_register(wifi_rfkill);
258 if (ret) 227 if (ret)
259 goto err_wifi; 228 goto err_wifi;
260 } 229 }
261 230
262 if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { 231 if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) {
263 bluetooth_rfkill = rfkill_allocate(NULL, RFKILL_TYPE_BLUETOOTH); 232 bluetooth_rfkill = rfkill_alloc("dell-bluetooth", NULL,
264 if (!bluetooth_rfkill) 233 RFKILL_TYPE_BLUETOOTH,
234 &dell_rfkill_ops, (void *) 2);
235 if (!bluetooth_rfkill) {
236 ret = -ENOMEM;
265 goto err_bluetooth; 237 goto err_bluetooth;
266 bluetooth_rfkill->name = "dell-bluetooth"; 238 }
267 bluetooth_rfkill->toggle_radio = dell_bluetooth_set;
268 bluetooth_rfkill->get_state = dell_bluetooth_get;
269 ret = rfkill_register(bluetooth_rfkill); 239 ret = rfkill_register(bluetooth_rfkill);
270 if (ret) 240 if (ret)
271 goto err_bluetooth; 241 goto err_bluetooth;
272 } 242 }
273 243
274 if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { 244 if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) {
275 wwan_rfkill = rfkill_allocate(NULL, RFKILL_TYPE_WWAN); 245 wwan_rfkill = rfkill_alloc("dell-wwan", NULL, RFKILL_TYPE_WWAN,
276 if (!wwan_rfkill) 246 &dell_rfkill_ops, (void *) 3);
247 if (!wwan_rfkill) {
248 ret = -ENOMEM;
277 goto err_wwan; 249 goto err_wwan;
278 wwan_rfkill->name = "dell-wwan"; 250 }
279 wwan_rfkill->toggle_radio = dell_wwan_set;
280 wwan_rfkill->get_state = dell_wwan_get;
281 ret = rfkill_register(wwan_rfkill); 251 ret = rfkill_register(wwan_rfkill);
282 if (ret) 252 if (ret)
283 goto err_wwan; 253 goto err_wwan;
@@ -285,22 +255,15 @@ static int dell_setup_rfkill(void)
285 255
286 return 0; 256 return 0;
287err_wwan: 257err_wwan:
288 if (wwan_rfkill) 258 rfkill_destroy(wwan_rfkill);
289 rfkill_free(wwan_rfkill); 259 if (bluetooth_rfkill)
290 if (bluetooth_rfkill) {
291 rfkill_unregister(bluetooth_rfkill); 260 rfkill_unregister(bluetooth_rfkill);
292 bluetooth_rfkill = NULL;
293 }
294err_bluetooth: 261err_bluetooth:
295 if (bluetooth_rfkill) 262 rfkill_destroy(bluetooth_rfkill);
296 rfkill_free(bluetooth_rfkill); 263 if (wifi_rfkill)
297 if (wifi_rfkill) {
298 rfkill_unregister(wifi_rfkill); 264 rfkill_unregister(wifi_rfkill);
299 wifi_rfkill = NULL;
300 }
301err_wifi: 265err_wifi:
302 if (wifi_rfkill) 266 rfkill_destroy(wifi_rfkill);
303 rfkill_free(wifi_rfkill);
304 267
305 return ret; 268 return ret;
306} 269}
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 353a898c3693..1208d0cedd15 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -299,39 +299,22 @@ static int update_bl_status(struct backlight_device *bd)
299 * Rfkill helpers 299 * Rfkill helpers
300 */ 300 */
301 301
302static int eeepc_wlan_rfkill_set(void *data, enum rfkill_state state) 302static bool eeepc_wlan_rfkill_blocked(void)
303{
304 if (state == RFKILL_STATE_SOFT_BLOCKED)
305 return set_acpi(CM_ASL_WLAN, 0);
306 else
307 return set_acpi(CM_ASL_WLAN, 1);
308}
309
310static int eeepc_wlan_rfkill_state(void *data, enum rfkill_state *state)
311{ 303{
312 if (get_acpi(CM_ASL_WLAN) == 1) 304 if (get_acpi(CM_ASL_WLAN) == 1)
313 *state = RFKILL_STATE_UNBLOCKED; 305 return false;
314 else 306 return true;
315 *state = RFKILL_STATE_SOFT_BLOCKED;
316 return 0;
317} 307}
318 308
319static int eeepc_bluetooth_rfkill_set(void *data, enum rfkill_state state) 309static int eeepc_rfkill_set(void *data, bool blocked)
320{ 310{
321 if (state == RFKILL_STATE_SOFT_BLOCKED) 311 unsigned long asl = (unsigned long)data;
322 return set_acpi(CM_ASL_BLUETOOTH, 0); 312 return set_acpi(asl, !blocked);
323 else
324 return set_acpi(CM_ASL_BLUETOOTH, 1);
325} 313}
326 314
327static int eeepc_bluetooth_rfkill_state(void *data, enum rfkill_state *state) 315static const struct rfkill_ops eeepc_rfkill_ops = {
328{ 316 .set_block = eeepc_rfkill_set,
329 if (get_acpi(CM_ASL_BLUETOOTH) == 1) 317};
330 *state = RFKILL_STATE_UNBLOCKED;
331 else
332 *state = RFKILL_STATE_SOFT_BLOCKED;
333 return 0;
334}
335 318
336/* 319/*
337 * Sys helpers 320 * Sys helpers
@@ -531,9 +514,9 @@ static int notify_brn(void)
531 514
532static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) 515static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
533{ 516{
534 enum rfkill_state state;
535 struct pci_dev *dev; 517 struct pci_dev *dev;
536 struct pci_bus *bus = pci_find_bus(0, 1); 518 struct pci_bus *bus = pci_find_bus(0, 1);
519 bool blocked;
537 520
538 if (event != ACPI_NOTIFY_BUS_CHECK) 521 if (event != ACPI_NOTIFY_BUS_CHECK)
539 return; 522 return;
@@ -543,9 +526,8 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
543 return; 526 return;
544 } 527 }
545 528
546 eeepc_wlan_rfkill_state(ehotk->eeepc_wlan_rfkill, &state); 529 blocked = eeepc_wlan_rfkill_blocked();
547 530 if (!blocked) {
548 if (state == RFKILL_STATE_UNBLOCKED) {
549 dev = pci_get_slot(bus, 0); 531 dev = pci_get_slot(bus, 0);
550 if (dev) { 532 if (dev) {
551 /* Device already present */ 533 /* Device already present */
@@ -566,7 +548,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
566 } 548 }
567 } 549 }
568 550
569 rfkill_force_state(ehotk->eeepc_wlan_rfkill, state); 551 rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked);
570} 552}
571 553
572static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) 554static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
@@ -684,26 +666,17 @@ static int eeepc_hotk_add(struct acpi_device *device)
684 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); 666 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
685 667
686 if (get_acpi(CM_ASL_WLAN) != -1) { 668 if (get_acpi(CM_ASL_WLAN) != -1) {
687 ehotk->eeepc_wlan_rfkill = rfkill_allocate(&device->dev, 669 ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan",
688 RFKILL_TYPE_WLAN); 670 &device->dev,
671 RFKILL_TYPE_WLAN,
672 &eeepc_rfkill_ops,
673 (void *)CM_ASL_WLAN);
689 674
690 if (!ehotk->eeepc_wlan_rfkill) 675 if (!ehotk->eeepc_wlan_rfkill)
691 goto wlan_fail; 676 goto wlan_fail;
692 677
693 ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; 678 rfkill_set_global_sw_state(RFKILL_TYPE_WLAN,
694 ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; 679 get_acpi(CM_ASL_WLAN) != 1);
695 ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state;
696 if (get_acpi(CM_ASL_WLAN) == 1) {
697 ehotk->eeepc_wlan_rfkill->state =
698 RFKILL_STATE_UNBLOCKED;
699 rfkill_set_default(RFKILL_TYPE_WLAN,
700 RFKILL_STATE_UNBLOCKED);
701 } else {
702 ehotk->eeepc_wlan_rfkill->state =
703 RFKILL_STATE_SOFT_BLOCKED;
704 rfkill_set_default(RFKILL_TYPE_WLAN,
705 RFKILL_STATE_SOFT_BLOCKED);
706 }
707 result = rfkill_register(ehotk->eeepc_wlan_rfkill); 680 result = rfkill_register(ehotk->eeepc_wlan_rfkill);
708 if (result) 681 if (result)
709 goto wlan_fail; 682 goto wlan_fail;
@@ -711,28 +684,17 @@ static int eeepc_hotk_add(struct acpi_device *device)
711 684
712 if (get_acpi(CM_ASL_BLUETOOTH) != -1) { 685 if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
713 ehotk->eeepc_bluetooth_rfkill = 686 ehotk->eeepc_bluetooth_rfkill =
714 rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); 687 rfkill_alloc("eeepc-bluetooth",
688 &device->dev,
689 RFKILL_TYPE_BLUETOOTH,
690 &eeepc_rfkill_ops,
691 (void *)CM_ASL_BLUETOOTH);
715 692
716 if (!ehotk->eeepc_bluetooth_rfkill) 693 if (!ehotk->eeepc_bluetooth_rfkill)
717 goto bluetooth_fail; 694 goto bluetooth_fail;
718 695
719 ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; 696 rfkill_set_global_sw_state(RFKILL_TYPE_BLUETOOTH,
720 ehotk->eeepc_bluetooth_rfkill->toggle_radio = 697 get_acpi(CM_ASL_BLUETOOTH) != 1);
721 eeepc_bluetooth_rfkill_set;
722 ehotk->eeepc_bluetooth_rfkill->get_state =
723 eeepc_bluetooth_rfkill_state;
724 if (get_acpi(CM_ASL_BLUETOOTH) == 1) {
725 ehotk->eeepc_bluetooth_rfkill->state =
726 RFKILL_STATE_UNBLOCKED;
727 rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
728 RFKILL_STATE_UNBLOCKED);
729 } else {
730 ehotk->eeepc_bluetooth_rfkill->state =
731 RFKILL_STATE_SOFT_BLOCKED;
732 rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
733 RFKILL_STATE_SOFT_BLOCKED);
734 }
735
736 result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); 698 result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
737 if (result) 699 if (result)
738 goto bluetooth_fail; 700 goto bluetooth_fail;
@@ -741,13 +703,10 @@ static int eeepc_hotk_add(struct acpi_device *device)
741 return 0; 703 return 0;
742 704
743 bluetooth_fail: 705 bluetooth_fail:
744 if (ehotk->eeepc_bluetooth_rfkill) 706 rfkill_destroy(ehotk->eeepc_bluetooth_rfkill);
745 rfkill_free(ehotk->eeepc_bluetooth_rfkill);
746 rfkill_unregister(ehotk->eeepc_wlan_rfkill); 707 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
747 ehotk->eeepc_wlan_rfkill = NULL;
748 wlan_fail: 708 wlan_fail:
749 if (ehotk->eeepc_wlan_rfkill) 709 rfkill_destroy(ehotk->eeepc_wlan_rfkill);
750 rfkill_free(ehotk->eeepc_wlan_rfkill);
751 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); 710 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
752 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); 711 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
753 ehotk_fail: 712 ehotk_fail:
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index fe171fad12cf..8d931145cbfa 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -154,58 +154,46 @@ static int hp_wmi_dock_state(void)
154 return hp_wmi_perform_query(HPWMI_DOCK_QUERY, 0, 0); 154 return hp_wmi_perform_query(HPWMI_DOCK_QUERY, 0, 0);
155} 155}
156 156
157static int hp_wmi_wifi_set(void *data, enum rfkill_state state) 157static int hp_wmi_set_block(void *data, bool blocked)
158{ 158{
159 if (state) 159 unsigned long b = (unsigned long) data;
160 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x101); 160 int query = BIT(b + 8) | ((!!blocked) << b);
161 else
162 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x100);
163}
164 161
165static int hp_wmi_bluetooth_set(void *data, enum rfkill_state state) 162 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query);
166{
167 if (state)
168 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x202);
169 else
170 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x200);
171} 163}
172 164
173static int hp_wmi_wwan_set(void *data, enum rfkill_state state) 165static const struct rfkill_ops hp_wmi_rfkill_ops = {
174{ 166 .set_block = hp_wmi_set_block,
175 if (state) 167};
176 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x404);
177 else
178 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x400);
179}
180 168
181static int hp_wmi_wifi_state(void) 169static bool hp_wmi_wifi_state(void)
182{ 170{
183 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 171 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
184 172
185 if (wireless & 0x100) 173 if (wireless & 0x100)
186 return RFKILL_STATE_UNBLOCKED; 174 return false;
187 else 175 else
188 return RFKILL_STATE_SOFT_BLOCKED; 176 return true;
189} 177}
190 178
191static int hp_wmi_bluetooth_state(void) 179static bool hp_wmi_bluetooth_state(void)
192{ 180{
193 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 181 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
194 182
195 if (wireless & 0x10000) 183 if (wireless & 0x10000)
196 return RFKILL_STATE_UNBLOCKED; 184 return false;
197 else 185 else
198 return RFKILL_STATE_SOFT_BLOCKED; 186 return true;
199} 187}
200 188
201static int hp_wmi_wwan_state(void) 189static bool hp_wmi_wwan_state(void)
202{ 190{
203 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 191 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
204 192
205 if (wireless & 0x1000000) 193 if (wireless & 0x1000000)
206 return RFKILL_STATE_UNBLOCKED; 194 return false;
207 else 195 else
208 return RFKILL_STATE_SOFT_BLOCKED; 196 return true;
209} 197}
210 198
211static ssize_t show_display(struct device *dev, struct device_attribute *attr, 199static ssize_t show_display(struct device *dev, struct device_attribute *attr,
@@ -347,14 +335,14 @@ static void hp_wmi_notify(u32 value, void *context)
347 } 335 }
348 } else if (eventcode == 0x5) { 336 } else if (eventcode == 0x5) {
349 if (wifi_rfkill) 337 if (wifi_rfkill)
350 rfkill_force_state(wifi_rfkill, 338 rfkill_set_sw_state(wifi_rfkill,
351 hp_wmi_wifi_state()); 339 hp_wmi_wifi_state());
352 if (bluetooth_rfkill) 340 if (bluetooth_rfkill)
353 rfkill_force_state(bluetooth_rfkill, 341 rfkill_set_sw_state(bluetooth_rfkill,
354 hp_wmi_bluetooth_state()); 342 hp_wmi_bluetooth_state());
355 if (wwan_rfkill) 343 if (wwan_rfkill)
356 rfkill_force_state(wwan_rfkill, 344 rfkill_set_sw_state(wwan_rfkill,
357 hp_wmi_wwan_state()); 345 hp_wmi_wwan_state());
358 } else 346 } else
359 printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", 347 printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
360 eventcode); 348 eventcode);
@@ -430,31 +418,34 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
430 goto add_sysfs_error; 418 goto add_sysfs_error;
431 419
432 if (wireless & 0x1) { 420 if (wireless & 0x1) {
433 wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN); 421 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
434 wifi_rfkill->name = "hp-wifi"; 422 RFKILL_TYPE_WLAN,
435 wifi_rfkill->state = hp_wmi_wifi_state(); 423 &hp_wmi_rfkill_ops,
436 wifi_rfkill->toggle_radio = hp_wmi_wifi_set; 424 (void *) 0);
425 rfkill_set_sw_state(wifi_rfkill, hp_wmi_wifi_state());
437 err = rfkill_register(wifi_rfkill); 426 err = rfkill_register(wifi_rfkill);
438 if (err) 427 if (err)
439 goto add_sysfs_error; 428 goto register_wifi_error;
440 } 429 }
441 430
442 if (wireless & 0x2) { 431 if (wireless & 0x2) {
443 bluetooth_rfkill = rfkill_allocate(&device->dev, 432 bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev,
444 RFKILL_TYPE_BLUETOOTH); 433 RFKILL_TYPE_BLUETOOTH,
445 bluetooth_rfkill->name = "hp-bluetooth"; 434 &hp_wmi_rfkill_ops,
446 bluetooth_rfkill->state = hp_wmi_bluetooth_state(); 435 (void *) 1);
447 bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set; 436 rfkill_set_sw_state(bluetooth_rfkill,
437 hp_wmi_bluetooth_state());
448 err = rfkill_register(bluetooth_rfkill); 438 err = rfkill_register(bluetooth_rfkill);
449 if (err) 439 if (err)
450 goto register_bluetooth_error; 440 goto register_bluetooth_error;
451 } 441 }
452 442
453 if (wireless & 0x4) { 443 if (wireless & 0x4) {
454 wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN); 444 wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev,
455 wwan_rfkill->name = "hp-wwan"; 445 RFKILL_TYPE_WWAN,
456 wwan_rfkill->state = hp_wmi_wwan_state(); 446 &hp_wmi_rfkill_ops,
457 wwan_rfkill->toggle_radio = hp_wmi_wwan_set; 447 (void *) 2);
448 rfkill_set_sw_state(wwan_rfkill, hp_wmi_wwan_state());
458 err = rfkill_register(wwan_rfkill); 449 err = rfkill_register(wwan_rfkill);
459 if (err) 450 if (err)
460 goto register_wwan_err; 451 goto register_wwan_err;
@@ -462,11 +453,15 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
462 453
463 return 0; 454 return 0;
464register_wwan_err: 455register_wwan_err:
456 rfkill_destroy(wwan_rfkill);
465 if (bluetooth_rfkill) 457 if (bluetooth_rfkill)
466 rfkill_unregister(bluetooth_rfkill); 458 rfkill_unregister(bluetooth_rfkill);
467register_bluetooth_error: 459register_bluetooth_error:
460 rfkill_destroy(bluetooth_rfkill);
468 if (wifi_rfkill) 461 if (wifi_rfkill)
469 rfkill_unregister(wifi_rfkill); 462 rfkill_unregister(wifi_rfkill);
463register_wifi_error:
464 rfkill_destroy(wifi_rfkill);
470add_sysfs_error: 465add_sysfs_error:
471 cleanup_sysfs(device); 466 cleanup_sysfs(device);
472 return err; 467 return err;
@@ -476,12 +471,18 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device)
476{ 471{
477 cleanup_sysfs(device); 472 cleanup_sysfs(device);
478 473
479 if (wifi_rfkill) 474 if (wifi_rfkill) {
480 rfkill_unregister(wifi_rfkill); 475 rfkill_unregister(wifi_rfkill);
481 if (bluetooth_rfkill) 476 rfkill_destroy(wifi_rfkill);
477 }
478 if (bluetooth_rfkill) {
482 rfkill_unregister(bluetooth_rfkill); 479 rfkill_unregister(bluetooth_rfkill);
483 if (wwan_rfkill) 480 rfkill_destroy(wifi_rfkill);
481 }
482 if (wwan_rfkill) {
484 rfkill_unregister(wwan_rfkill); 483 rfkill_unregister(wwan_rfkill);
484 rfkill_destroy(wwan_rfkill);
485 }
485 486
486 return 0; 487 return 0;
487} 488}
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index f1963b05175b..aec0b27fd774 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -128,11 +128,11 @@ enum sony_nc_rfkill {
128 SONY_BLUETOOTH, 128 SONY_BLUETOOTH,
129 SONY_WWAN, 129 SONY_WWAN,
130 SONY_WIMAX, 130 SONY_WIMAX,
131 SONY_RFKILL_MAX, 131 N_SONY_RFKILL,
132}; 132};
133 133
134static struct rfkill *sony_rfkill_devices[SONY_RFKILL_MAX]; 134static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
135static int sony_rfkill_address[SONY_RFKILL_MAX] = {0x300, 0x500, 0x700, 0x900}; 135static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
136static void sony_nc_rfkill_update(void); 136static void sony_nc_rfkill_update(void);
137 137
138/*********** Input Devices ***********/ 138/*********** Input Devices ***********/
@@ -1051,147 +1051,98 @@ static void sony_nc_rfkill_cleanup(void)
1051{ 1051{
1052 int i; 1052 int i;
1053 1053
1054 for (i = 0; i < SONY_RFKILL_MAX; i++) { 1054 for (i = 0; i < N_SONY_RFKILL; i++) {
1055 if (sony_rfkill_devices[i]) 1055 if (sony_rfkill_devices[i]) {
1056 rfkill_unregister(sony_rfkill_devices[i]); 1056 rfkill_unregister(sony_rfkill_devices[i]);
1057 rfkill_destroy(sony_rfkill_devices[i]);
1058 }
1057 } 1059 }
1058} 1060}
1059 1061
1060static int sony_nc_rfkill_get(void *data, enum rfkill_state *state) 1062static int sony_nc_rfkill_set(void *data, bool blocked)
1061{
1062 int result;
1063 int argument = sony_rfkill_address[(long) data];
1064
1065 sony_call_snc_handle(0x124, 0x200, &result);
1066 if (result & 0x1) {
1067 sony_call_snc_handle(0x124, argument, &result);
1068 if (result & 0xf)
1069 *state = RFKILL_STATE_UNBLOCKED;
1070 else
1071 *state = RFKILL_STATE_SOFT_BLOCKED;
1072 } else {
1073 *state = RFKILL_STATE_HARD_BLOCKED;
1074 }
1075
1076 return 0;
1077}
1078
1079static int sony_nc_rfkill_set(void *data, enum rfkill_state state)
1080{ 1063{
1081 int result; 1064 int result;
1082 int argument = sony_rfkill_address[(long) data] + 0x100; 1065 int argument = sony_rfkill_address[(long) data] + 0x100;
1083 1066
1084 if (state == RFKILL_STATE_UNBLOCKED) 1067 if (!blocked)
1085 argument |= 0xff0000; 1068 argument |= 0xff0000;
1086 1069
1087 return sony_call_snc_handle(0x124, argument, &result); 1070 return sony_call_snc_handle(0x124, argument, &result);
1088} 1071}
1089 1072
1090static int sony_nc_setup_wifi_rfkill(struct acpi_device *device) 1073static const struct rfkill_ops sony_rfkill_ops = {
1091{ 1074 .set_block = sony_nc_rfkill_set,
1092 int err = 0; 1075};
1093 struct rfkill *sony_wifi_rfkill;
1094
1095 sony_wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN);
1096 if (!sony_wifi_rfkill)
1097 return -1;
1098 sony_wifi_rfkill->name = "sony-wifi";
1099 sony_wifi_rfkill->toggle_radio = sony_nc_rfkill_set;
1100 sony_wifi_rfkill->get_state = sony_nc_rfkill_get;
1101 sony_wifi_rfkill->data = (void *)SONY_WIFI;
1102 err = rfkill_register(sony_wifi_rfkill);
1103 if (err)
1104 rfkill_free(sony_wifi_rfkill);
1105 else {
1106 sony_rfkill_devices[SONY_WIFI] = sony_wifi_rfkill;
1107 sony_nc_rfkill_set(sony_wifi_rfkill->data,
1108 RFKILL_STATE_UNBLOCKED);
1109 }
1110 return err;
1111}
1112 1076
1113static int sony_nc_setup_bluetooth_rfkill(struct acpi_device *device) 1077static int sony_nc_setup_rfkill(struct acpi_device *device,
1078 enum sony_nc_rfkill nc_type)
1114{ 1079{
1115 int err = 0; 1080 int err = 0;
1116 struct rfkill *sony_bluetooth_rfkill; 1081 struct rfkill *rfk;
1117 1082 enum rfkill_type type;
1118 sony_bluetooth_rfkill = rfkill_allocate(&device->dev, 1083 const char *name;
1119 RFKILL_TYPE_BLUETOOTH); 1084
1120 if (!sony_bluetooth_rfkill) 1085 switch (nc_type) {
1121 return -1; 1086 case SONY_WIFI:
1122 sony_bluetooth_rfkill->name = "sony-bluetooth"; 1087 type = RFKILL_TYPE_WLAN;
1123 sony_bluetooth_rfkill->toggle_radio = sony_nc_rfkill_set; 1088 name = "sony-wifi";
1124 sony_bluetooth_rfkill->get_state = sony_nc_rfkill_get; 1089 break;
1125 sony_bluetooth_rfkill->data = (void *)SONY_BLUETOOTH; 1090 case SONY_BLUETOOTH:
1126 err = rfkill_register(sony_bluetooth_rfkill); 1091 type = RFKILL_TYPE_BLUETOOTH;
1127 if (err) 1092 name = "sony-bluetooth";
1128 rfkill_free(sony_bluetooth_rfkill); 1093 break;
1129 else { 1094 case SONY_WWAN:
1130 sony_rfkill_devices[SONY_BLUETOOTH] = sony_bluetooth_rfkill; 1095 type = RFKILL_TYPE_WWAN;
1131 sony_nc_rfkill_set(sony_bluetooth_rfkill->data, 1096 name = "sony-wwan";
1132 RFKILL_STATE_UNBLOCKED); 1097 break;
1098 case SONY_WIMAX:
1099 type = RFKILL_TYPE_WIMAX;
1100 name = "sony-wimax";
1101 break;
1102 default:
1103 return -EINVAL;
1133 } 1104 }
1134 return err;
1135}
1136 1105
1137static int sony_nc_setup_wwan_rfkill(struct acpi_device *device) 1106 rfk = rfkill_alloc(name, &device->dev, type,
1138{ 1107 &sony_rfkill_ops, (void *)nc_type);
1139 int err = 0; 1108 if (!rfk)
1140 struct rfkill *sony_wwan_rfkill; 1109 return -ENOMEM;
1141 1110
1142 sony_wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN); 1111 err = rfkill_register(rfk);
1143 if (!sony_wwan_rfkill) 1112 if (err) {
1144 return -1; 1113 rfkill_destroy(rfk);
1145 sony_wwan_rfkill->name = "sony-wwan"; 1114 return err;
1146 sony_wwan_rfkill->toggle_radio = sony_nc_rfkill_set;
1147 sony_wwan_rfkill->get_state = sony_nc_rfkill_get;
1148 sony_wwan_rfkill->data = (void *)SONY_WWAN;
1149 err = rfkill_register(sony_wwan_rfkill);
1150 if (err)
1151 rfkill_free(sony_wwan_rfkill);
1152 else {
1153 sony_rfkill_devices[SONY_WWAN] = sony_wwan_rfkill;
1154 sony_nc_rfkill_set(sony_wwan_rfkill->data,
1155 RFKILL_STATE_UNBLOCKED);
1156 } 1115 }
1116 sony_rfkill_devices[nc_type] = rfk;
1117 sony_nc_rfkill_set((void *)nc_type, false);
1157 return err; 1118 return err;
1158} 1119}
1159 1120
1160static int sony_nc_setup_wimax_rfkill(struct acpi_device *device) 1121static void sony_nc_rfkill_update()
1161{ 1122{
1162 int err = 0; 1123 enum sony_nc_rfkill i;
1163 struct rfkill *sony_wimax_rfkill; 1124 int result;
1125 bool hwblock;
1164 1126
1165 sony_wimax_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX); 1127 sony_call_snc_handle(0x124, 0x200, &result);
1166 if (!sony_wimax_rfkill) 1128 hwblock = !(result & 0x1);
1167 return -1;
1168 sony_wimax_rfkill->name = "sony-wimax";
1169 sony_wimax_rfkill->toggle_radio = sony_nc_rfkill_set;
1170 sony_wimax_rfkill->get_state = sony_nc_rfkill_get;
1171 sony_wimax_rfkill->data = (void *)SONY_WIMAX;
1172 err = rfkill_register(sony_wimax_rfkill);
1173 if (err)
1174 rfkill_free(sony_wimax_rfkill);
1175 else {
1176 sony_rfkill_devices[SONY_WIMAX] = sony_wimax_rfkill;
1177 sony_nc_rfkill_set(sony_wimax_rfkill->data,
1178 RFKILL_STATE_UNBLOCKED);
1179 }
1180 return err;
1181}
1182 1129
1183static void sony_nc_rfkill_update() 1130 for (i = 0; i < N_SONY_RFKILL; i++) {
1184{ 1131 int argument = sony_rfkill_address[i];
1185 int i;
1186 enum rfkill_state state;
1187 1132
1188 for (i = 0; i < SONY_RFKILL_MAX; i++) { 1133 if (!sony_rfkill_devices[i])
1189 if (sony_rfkill_devices[i]) { 1134 continue;
1190 sony_rfkill_devices[i]-> 1135
1191 get_state(sony_rfkill_devices[i]->data, 1136 if (hwblock) {
1192 &state); 1137 if (rfkill_set_hw_state(sony_rfkill_devices[i], true))
1193 rfkill_force_state(sony_rfkill_devices[i], state); 1138 sony_nc_rfkill_set(sony_rfkill_devices[i],
1139 true);
1140 continue;
1194 } 1141 }
1142
1143 sony_call_snc_handle(0x124, argument, &result);
1144 rfkill_set_states(sony_rfkill_devices[i],
1145 !(result & 0xf), false);
1195 } 1146 }
1196} 1147}
1197 1148
@@ -1210,13 +1161,13 @@ static int sony_nc_rfkill_setup(struct acpi_device *device)
1210 } 1161 }
1211 1162
1212 if (result & 0x1) 1163 if (result & 0x1)
1213 sony_nc_setup_wifi_rfkill(device); 1164 sony_nc_setup_rfkill(device, SONY_WIFI);
1214 if (result & 0x2) 1165 if (result & 0x2)
1215 sony_nc_setup_bluetooth_rfkill(device); 1166 sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
1216 if (result & 0x1c) 1167 if (result & 0x1c)
1217 sony_nc_setup_wwan_rfkill(device); 1168 sony_nc_setup_rfkill(device, SONY_WWAN);
1218 if (result & 0x20) 1169 if (result & 0x20)
1219 sony_nc_setup_wimax_rfkill(device); 1170 sony_nc_setup_rfkill(device, SONY_WIMAX);
1220 1171
1221 return 0; 1172 return 0;
1222} 1173}
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 912be65b6261..cfcafa4e9473 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -166,13 +166,6 @@ enum {
166 166
167#define TPACPI_MAX_ACPI_ARGS 3 167#define TPACPI_MAX_ACPI_ARGS 3
168 168
169/* rfkill switches */
170enum {
171 TPACPI_RFK_BLUETOOTH_SW_ID = 0,
172 TPACPI_RFK_WWAN_SW_ID,
173 TPACPI_RFK_UWB_SW_ID,
174};
175
176/* printk headers */ 169/* printk headers */
177#define TPACPI_LOG TPACPI_FILE ": " 170#define TPACPI_LOG TPACPI_FILE ": "
178#define TPACPI_EMERG KERN_EMERG TPACPI_LOG 171#define TPACPI_EMERG KERN_EMERG TPACPI_LOG
@@ -1005,67 +998,237 @@ static int __init tpacpi_check_std_acpi_brightness_support(void)
1005 return 0; 998 return 0;
1006} 999}
1007 1000
1008static int __init tpacpi_new_rfkill(const unsigned int id, 1001static void printk_deprecated_attribute(const char * const what,
1009 struct rfkill **rfk, 1002 const char * const details)
1003{
1004 tpacpi_log_usertask("deprecated sysfs attribute");
1005 printk(TPACPI_WARN "WARNING: sysfs attribute %s is deprecated and "
1006 "will be removed. %s\n",
1007 what, details);
1008}
1009
1010/*************************************************************************
1011 * rfkill and radio control support helpers
1012 */
1013
1014/*
1015 * ThinkPad-ACPI firmware handling model:
1016 *
1017 * WLSW (master wireless switch) is event-driven, and is common to all
1018 * firmware-controlled radios. It cannot be controlled, just monitored,
1019 * as expected. It overrides all radio state in firmware
1020 *
1021 * The kernel, a masked-off hotkey, and WLSW can change the radio state
1022 * (TODO: verify how WLSW interacts with the returned radio state).
1023 *
1024 * The only time there are shadow radio state changes, is when
1025 * masked-off hotkeys are used.
1026 */
1027
1028/*
1029 * Internal driver API for radio state:
1030 *
1031 * int: < 0 = error, otherwise enum tpacpi_rfkill_state
1032 * bool: true means radio blocked (off)
1033 */
1034enum tpacpi_rfkill_state {
1035 TPACPI_RFK_RADIO_OFF = 0,
1036 TPACPI_RFK_RADIO_ON
1037};
1038
1039/* rfkill switches */
1040enum tpacpi_rfk_id {
1041 TPACPI_RFK_BLUETOOTH_SW_ID = 0,
1042 TPACPI_RFK_WWAN_SW_ID,
1043 TPACPI_RFK_UWB_SW_ID,
1044 TPACPI_RFK_SW_MAX
1045};
1046
1047static const char *tpacpi_rfkill_names[] = {
1048 [TPACPI_RFK_BLUETOOTH_SW_ID] = "bluetooth",
1049 [TPACPI_RFK_WWAN_SW_ID] = "wwan",
1050 [TPACPI_RFK_UWB_SW_ID] = "uwb",
1051 [TPACPI_RFK_SW_MAX] = NULL
1052};
1053
1054/* ThinkPad-ACPI rfkill subdriver */
1055struct tpacpi_rfk {
1056 struct rfkill *rfkill;
1057 enum tpacpi_rfk_id id;
1058 const struct tpacpi_rfk_ops *ops;
1059};
1060
1061struct tpacpi_rfk_ops {
1062 /* firmware interface */
1063 int (*get_status)(void);
1064 int (*set_status)(const enum tpacpi_rfkill_state);
1065};
1066
1067static struct tpacpi_rfk *tpacpi_rfkill_switches[TPACPI_RFK_SW_MAX];
1068
1069/* Query FW and update rfkill sw state for a given rfkill switch */
1070static int tpacpi_rfk_update_swstate(const struct tpacpi_rfk *tp_rfk)
1071{
1072 int status;
1073
1074 if (!tp_rfk)
1075 return -ENODEV;
1076
1077 status = (tp_rfk->ops->get_status)();
1078 if (status < 0)
1079 return status;
1080
1081 rfkill_set_sw_state(tp_rfk->rfkill,
1082 (status == TPACPI_RFK_RADIO_OFF));
1083
1084 return status;
1085}
1086
1087/* Query FW and update rfkill sw state for all rfkill switches */
1088static void tpacpi_rfk_update_swstate_all(void)
1089{
1090 unsigned int i;
1091
1092 for (i = 0; i < TPACPI_RFK_SW_MAX; i++)
1093 tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[i]);
1094}
1095
1096/*
1097 * Sync the HW-blocking state of all rfkill switches,
1098 * do notice it causes the rfkill core to schedule uevents
1099 */
1100static void tpacpi_rfk_update_hwblock_state(bool blocked)
1101{
1102 unsigned int i;
1103 struct tpacpi_rfk *tp_rfk;
1104
1105 for (i = 0; i < TPACPI_RFK_SW_MAX; i++) {
1106 tp_rfk = tpacpi_rfkill_switches[i];
1107 if (tp_rfk) {
1108 if (rfkill_set_hw_state(tp_rfk->rfkill,
1109 blocked)) {
1110 /* ignore -- we track sw block */
1111 }
1112 }
1113 }
1114}
1115
1116/* Call to get the WLSW state from the firmware */
1117static int hotkey_get_wlsw(void);
1118
1119/* Call to query WLSW state and update all rfkill switches */
1120static bool tpacpi_rfk_check_hwblock_state(void)
1121{
1122 int res = hotkey_get_wlsw();
1123 int hw_blocked;
1124
1125 /* When unknown or unsupported, we have to assume it is unblocked */
1126 if (res < 0)
1127 return false;
1128
1129 hw_blocked = (res == TPACPI_RFK_RADIO_OFF);
1130 tpacpi_rfk_update_hwblock_state(hw_blocked);
1131
1132 return hw_blocked;
1133}
1134
1135static int tpacpi_rfk_hook_set_block(void *data, bool blocked)
1136{
1137 struct tpacpi_rfk *tp_rfk = data;
1138 int res;
1139
1140 dbg_printk(TPACPI_DBG_RFKILL,
1141 "request to change radio state to %s\n",
1142 blocked ? "blocked" : "unblocked");
1143
1144 /* try to set radio state */
1145 res = (tp_rfk->ops->set_status)(blocked ?
1146 TPACPI_RFK_RADIO_OFF : TPACPI_RFK_RADIO_ON);
1147
1148 /* and update the rfkill core with whatever the FW really did */
1149 tpacpi_rfk_update_swstate(tp_rfk);
1150
1151 return (res < 0) ? res : 0;
1152}
1153
1154static const struct rfkill_ops tpacpi_rfk_rfkill_ops = {
1155 .set_block = tpacpi_rfk_hook_set_block,
1156};
1157
1158static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1159 const struct tpacpi_rfk_ops *tp_rfkops,
1010 const enum rfkill_type rfktype, 1160 const enum rfkill_type rfktype,
1011 const char *name, 1161 const char *name,
1012 const bool set_default, 1162 const bool set_default)
1013 int (*toggle_radio)(void *, enum rfkill_state),
1014 int (*get_state)(void *, enum rfkill_state *))
1015{ 1163{
1164 struct tpacpi_rfk *atp_rfk;
1016 int res; 1165 int res;
1017 enum rfkill_state initial_state = RFKILL_STATE_SOFT_BLOCKED; 1166 bool initial_sw_state = false;
1167 int initial_sw_status;
1018 1168
1019 res = get_state(NULL, &initial_state); 1169 BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]);
1020 if (res < 0) { 1170
1171 initial_sw_status = (tp_rfkops->get_status)();
1172 if (initial_sw_status < 0) {
1021 printk(TPACPI_ERR 1173 printk(TPACPI_ERR
1022 "failed to read initial state for %s, error %d; " 1174 "failed to read initial state for %s, error %d; "
1023 "will turn radio off\n", name, res); 1175 "will turn radio off\n", name, initial_sw_status);
1024 } else if (set_default) { 1176 } else {
1025 /* try to set the initial state as the default for the rfkill 1177 initial_sw_state = (initial_sw_status == TPACPI_RFK_RADIO_OFF);
1026 * type, since we ask the firmware to preserve it across S5 in 1178 if (set_default) {
1027 * NVRAM */ 1179 /* try to set the initial state as the default for the
1028 if (rfkill_set_default(rfktype, 1180 * rfkill type, since we ask the firmware to preserve
1029 (initial_state == RFKILL_STATE_UNBLOCKED) ? 1181 * it across S5 in NVRAM */
1030 RFKILL_STATE_UNBLOCKED : 1182 rfkill_set_global_sw_state(rfktype, initial_sw_state);
1031 RFKILL_STATE_SOFT_BLOCKED) == -EPERM) 1183 }
1032 vdbg_printk(TPACPI_DBG_RFKILL, 1184 }
1033 "Default state for %s cannot be changed\n", 1185
1034 name); 1186 atp_rfk = kzalloc(sizeof(struct tpacpi_rfk), GFP_KERNEL);
1035 } 1187 if (atp_rfk)
1036 1188 atp_rfk->rfkill = rfkill_alloc(name,
1037 *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype); 1189 &tpacpi_pdev->dev,
1038 if (!*rfk) { 1190 rfktype,
1191 &tpacpi_rfk_rfkill_ops,
1192 atp_rfk);
1193 if (!atp_rfk || !atp_rfk->rfkill) {
1039 printk(TPACPI_ERR 1194 printk(TPACPI_ERR
1040 "failed to allocate memory for rfkill class\n"); 1195 "failed to allocate memory for rfkill class\n");
1196 kfree(atp_rfk);
1041 return -ENOMEM; 1197 return -ENOMEM;
1042 } 1198 }
1043 1199
1044 (*rfk)->name = name; 1200 atp_rfk->id = id;
1045 (*rfk)->get_state = get_state; 1201 atp_rfk->ops = tp_rfkops;
1046 (*rfk)->toggle_radio = toggle_radio; 1202
1047 (*rfk)->state = initial_state; 1203 rfkill_set_states(atp_rfk->rfkill, initial_sw_state,
1204 tpacpi_rfk_check_hwblock_state());
1048 1205
1049 res = rfkill_register(*rfk); 1206 res = rfkill_register(atp_rfk->rfkill);
1050 if (res < 0) { 1207 if (res < 0) {
1051 printk(TPACPI_ERR 1208 printk(TPACPI_ERR
1052 "failed to register %s rfkill switch: %d\n", 1209 "failed to register %s rfkill switch: %d\n",
1053 name, res); 1210 name, res);
1054 rfkill_free(*rfk); 1211 rfkill_destroy(atp_rfk->rfkill);
1055 *rfk = NULL; 1212 kfree(atp_rfk);
1056 return res; 1213 return res;
1057 } 1214 }
1058 1215
1216 tpacpi_rfkill_switches[id] = atp_rfk;
1059 return 0; 1217 return 0;
1060} 1218}
1061 1219
1062static void printk_deprecated_attribute(const char * const what, 1220static void tpacpi_destroy_rfkill(const enum tpacpi_rfk_id id)
1063 const char * const details)
1064{ 1221{
1065 tpacpi_log_usertask("deprecated sysfs attribute"); 1222 struct tpacpi_rfk *tp_rfk;
1066 printk(TPACPI_WARN "WARNING: sysfs attribute %s is deprecated and " 1223
1067 "will be removed. %s\n", 1224 BUG_ON(id >= TPACPI_RFK_SW_MAX);
1068 what, details); 1225
1226 tp_rfk = tpacpi_rfkill_switches[id];
1227 if (tp_rfk) {
1228 rfkill_unregister(tp_rfk->rfkill);
1229 tpacpi_rfkill_switches[id] = NULL;
1230 kfree(tp_rfk);
1231 }
1069} 1232}
1070 1233
1071static void printk_deprecated_rfkill_attribute(const char * const what) 1234static void printk_deprecated_rfkill_attribute(const char * const what)
@@ -1074,6 +1237,112 @@ static void printk_deprecated_rfkill_attribute(const char * const what)
1074 "Please switch to generic rfkill before year 2010"); 1237 "Please switch to generic rfkill before year 2010");
1075} 1238}
1076 1239
1240/* sysfs <radio> enable ------------------------------------------------ */
1241static ssize_t tpacpi_rfk_sysfs_enable_show(const enum tpacpi_rfk_id id,
1242 struct device_attribute *attr,
1243 char *buf)
1244{
1245 int status;
1246
1247 printk_deprecated_rfkill_attribute(attr->attr.name);
1248
1249 /* This is in the ABI... */
1250 if (tpacpi_rfk_check_hwblock_state()) {
1251 status = TPACPI_RFK_RADIO_OFF;
1252 } else {
1253 status = tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[id]);
1254 if (status < 0)
1255 return status;
1256 }
1257
1258 return snprintf(buf, PAGE_SIZE, "%d\n",
1259 (status == TPACPI_RFK_RADIO_ON) ? 1 : 0);
1260}
1261
1262static ssize_t tpacpi_rfk_sysfs_enable_store(const enum tpacpi_rfk_id id,
1263 struct device_attribute *attr,
1264 const char *buf, size_t count)
1265{
1266 unsigned long t;
1267 int res;
1268
1269 printk_deprecated_rfkill_attribute(attr->attr.name);
1270
1271 if (parse_strtoul(buf, 1, &t))
1272 return -EINVAL;
1273
1274 tpacpi_disclose_usertask(attr->attr.name, "set to %ld\n", t);
1275
1276 /* This is in the ABI... */
1277 if (tpacpi_rfk_check_hwblock_state() && !!t)
1278 return -EPERM;
1279
1280 res = tpacpi_rfkill_switches[id]->ops->set_status((!!t) ?
1281 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF);
1282 tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[id]);
1283
1284 return (res < 0) ? res : count;
1285}
1286
1287/* procfs -------------------------------------------------------------- */
1288static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p)
1289{
1290 int len = 0;
1291
1292 if (id >= TPACPI_RFK_SW_MAX)
1293 len += sprintf(p + len, "status:\t\tnot supported\n");
1294 else {
1295 int status;
1296
1297 /* This is in the ABI... */
1298 if (tpacpi_rfk_check_hwblock_state()) {
1299 status = TPACPI_RFK_RADIO_OFF;
1300 } else {
1301 status = tpacpi_rfk_update_swstate(
1302 tpacpi_rfkill_switches[id]);
1303 if (status < 0)
1304 return status;
1305 }
1306
1307 len += sprintf(p + len, "status:\t\t%s\n",
1308 (status == TPACPI_RFK_RADIO_ON) ?
1309 "enabled" : "disabled");
1310 len += sprintf(p + len, "commands:\tenable, disable\n");
1311 }
1312
1313 return len;
1314}
1315
1316static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf)
1317{
1318 char *cmd;
1319 int status = -1;
1320 int res = 0;
1321
1322 if (id >= TPACPI_RFK_SW_MAX)
1323 return -ENODEV;
1324
1325 while ((cmd = next_cmd(&buf))) {
1326 if (strlencmp(cmd, "enable") == 0)
1327 status = TPACPI_RFK_RADIO_ON;
1328 else if (strlencmp(cmd, "disable") == 0)
1329 status = TPACPI_RFK_RADIO_OFF;
1330 else
1331 return -EINVAL;
1332 }
1333
1334 if (status != -1) {
1335 tpacpi_disclose_usertask("procfs", "attempt to %s %s\n",
1336 (status == TPACPI_RFK_RADIO_ON) ?
1337 "enable" : "disable",
1338 tpacpi_rfkill_names[id]);
1339 res = (tpacpi_rfkill_switches[id]->ops->set_status)(status);
1340 tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[id]);
1341 }
1342
1343 return res;
1344}
1345
1077/************************************************************************* 1346/*************************************************************************
1078 * thinkpad-acpi driver attributes 1347 * thinkpad-acpi driver attributes
1079 */ 1348 */
@@ -1127,8 +1396,6 @@ static DRIVER_ATTR(version, S_IRUGO,
1127 1396
1128#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 1397#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
1129 1398
1130static void tpacpi_send_radiosw_update(void);
1131
1132/* wlsw_emulstate ------------------------------------------------------ */ 1399/* wlsw_emulstate ------------------------------------------------------ */
1133static ssize_t tpacpi_driver_wlsw_emulstate_show(struct device_driver *drv, 1400static ssize_t tpacpi_driver_wlsw_emulstate_show(struct device_driver *drv,
1134 char *buf) 1401 char *buf)
@@ -1144,11 +1411,10 @@ static ssize_t tpacpi_driver_wlsw_emulstate_store(struct device_driver *drv,
1144 if (parse_strtoul(buf, 1, &t)) 1411 if (parse_strtoul(buf, 1, &t))
1145 return -EINVAL; 1412 return -EINVAL;
1146 1413
1147 if (tpacpi_wlsw_emulstate != t) { 1414 if (tpacpi_wlsw_emulstate != !!t) {
1148 tpacpi_wlsw_emulstate = !!t;
1149 tpacpi_send_radiosw_update();
1150 } else
1151 tpacpi_wlsw_emulstate = !!t; 1415 tpacpi_wlsw_emulstate = !!t;
1416 tpacpi_rfk_update_hwblock_state(!t); /* negative logic */
1417 }
1152 1418
1153 return count; 1419 return count;
1154} 1420}
@@ -1463,17 +1729,23 @@ static struct attribute_set *hotkey_dev_attributes;
1463/* HKEY.MHKG() return bits */ 1729/* HKEY.MHKG() return bits */
1464#define TP_HOTKEY_TABLET_MASK (1 << 3) 1730#define TP_HOTKEY_TABLET_MASK (1 << 3)
1465 1731
1466static int hotkey_get_wlsw(int *status) 1732static int hotkey_get_wlsw(void)
1467{ 1733{
1734 int status;
1735
1736 if (!tp_features.hotkey_wlsw)
1737 return -ENODEV;
1738
1468#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 1739#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
1469 if (dbg_wlswemul) { 1740 if (dbg_wlswemul)
1470 *status = !!tpacpi_wlsw_emulstate; 1741 return (tpacpi_wlsw_emulstate) ?
1471 return 0; 1742 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
1472 }
1473#endif 1743#endif
1474 if (!acpi_evalf(hkey_handle, status, "WLSW", "d")) 1744
1745 if (!acpi_evalf(hkey_handle, &status, "WLSW", "d"))
1475 return -EIO; 1746 return -EIO;
1476 return 0; 1747
1748 return (status) ? TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
1477} 1749}
1478 1750
1479static int hotkey_get_tablet_mode(int *status) 1751static int hotkey_get_tablet_mode(int *status)
@@ -2107,12 +2379,16 @@ static ssize_t hotkey_radio_sw_show(struct device *dev,
2107 struct device_attribute *attr, 2379 struct device_attribute *attr,
2108 char *buf) 2380 char *buf)
2109{ 2381{
2110 int res, s; 2382 int res;
2111 res = hotkey_get_wlsw(&s); 2383 res = hotkey_get_wlsw();
2112 if (res < 0) 2384 if (res < 0)
2113 return res; 2385 return res;
2114 2386
2115 return snprintf(buf, PAGE_SIZE, "%d\n", !!s); 2387 /* Opportunistic update */
2388 tpacpi_rfk_update_hwblock_state((res == TPACPI_RFK_RADIO_OFF));
2389
2390 return snprintf(buf, PAGE_SIZE, "%d\n",
2391 (res == TPACPI_RFK_RADIO_OFF) ? 0 : 1);
2116} 2392}
2117 2393
2118static struct device_attribute dev_attr_hotkey_radio_sw = 2394static struct device_attribute dev_attr_hotkey_radio_sw =
@@ -2223,30 +2499,52 @@ static struct attribute *hotkey_mask_attributes[] __initdata = {
2223 &dev_attr_hotkey_wakeup_hotunplug_complete.attr, 2499 &dev_attr_hotkey_wakeup_hotunplug_complete.attr,
2224}; 2500};
2225 2501
2226static void bluetooth_update_rfk(void); 2502/*
2227static void wan_update_rfk(void); 2503 * Sync both the hw and sw blocking state of all switches
2228static void uwb_update_rfk(void); 2504 */
2229static void tpacpi_send_radiosw_update(void) 2505static void tpacpi_send_radiosw_update(void)
2230{ 2506{
2231 int wlsw; 2507 int wlsw;
2232 2508
2233 /* Sync these BEFORE sending any rfkill events */ 2509 /*
2234 if (tp_features.bluetooth) 2510 * We must sync all rfkill controllers *before* issuing any
2235 bluetooth_update_rfk(); 2511 * rfkill input events, or we will race the rfkill core input
2236 if (tp_features.wan) 2512 * handler.
2237 wan_update_rfk(); 2513 *
2238 if (tp_features.uwb) 2514 * tpacpi_inputdev_send_mutex works as a syncronization point
2239 uwb_update_rfk(); 2515 * for the above.
2516 *
2517 * We optimize to avoid numerous calls to hotkey_get_wlsw.
2518 */
2240 2519
2241 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) { 2520 wlsw = hotkey_get_wlsw();
2521
2522 /* Sync hw blocking state first if it is hw-blocked */
2523 if (wlsw == TPACPI_RFK_RADIO_OFF)
2524 tpacpi_rfk_update_hwblock_state(true);
2525
2526 /* Sync sw blocking state */
2527 tpacpi_rfk_update_swstate_all();
2528
2529 /* Sync hw blocking state last if it is hw-unblocked */
2530 if (wlsw == TPACPI_RFK_RADIO_ON)
2531 tpacpi_rfk_update_hwblock_state(false);
2532
2533 /* Issue rfkill input event for WLSW switch */
2534 if (!(wlsw < 0)) {
2242 mutex_lock(&tpacpi_inputdev_send_mutex); 2535 mutex_lock(&tpacpi_inputdev_send_mutex);
2243 2536
2244 input_report_switch(tpacpi_inputdev, 2537 input_report_switch(tpacpi_inputdev,
2245 SW_RFKILL_ALL, !!wlsw); 2538 SW_RFKILL_ALL, (wlsw > 0));
2246 input_sync(tpacpi_inputdev); 2539 input_sync(tpacpi_inputdev);
2247 2540
2248 mutex_unlock(&tpacpi_inputdev_send_mutex); 2541 mutex_unlock(&tpacpi_inputdev_send_mutex);
2249 } 2542 }
2543
2544 /*
2545 * this can be unconditional, as we will poll state again
2546 * if userspace uses the notify to read data
2547 */
2250 hotkey_radio_sw_notify_change(); 2548 hotkey_radio_sw_notify_change();
2251} 2549}
2252 2550
@@ -3056,8 +3354,6 @@ enum {
3056 3354
3057#define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw" 3355#define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw"
3058 3356
3059static struct rfkill *tpacpi_bluetooth_rfkill;
3060
3061static void bluetooth_suspend(pm_message_t state) 3357static void bluetooth_suspend(pm_message_t state)
3062{ 3358{
3063 /* Try to make sure radio will resume powered off */ 3359 /* Try to make sure radio will resume powered off */
@@ -3067,83 +3363,47 @@ static void bluetooth_suspend(pm_message_t state)
3067 "bluetooth power down on resume request failed\n"); 3363 "bluetooth power down on resume request failed\n");
3068} 3364}
3069 3365
3070static int bluetooth_get_radiosw(void) 3366static int bluetooth_get_status(void)
3071{ 3367{
3072 int status; 3368 int status;
3073 3369
3074 if (!tp_features.bluetooth)
3075 return -ENODEV;
3076
3077 /* WLSW overrides bluetooth in firmware/hardware, reflect that */
3078 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
3079 return RFKILL_STATE_HARD_BLOCKED;
3080
3081#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3370#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3082 if (dbg_bluetoothemul) 3371 if (dbg_bluetoothemul)
3083 return (tpacpi_bluetooth_emulstate) ? 3372 return (tpacpi_bluetooth_emulstate) ?
3084 RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; 3373 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
3085#endif 3374#endif
3086 3375
3087 if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) 3376 if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
3088 return -EIO; 3377 return -EIO;
3089 3378
3090 return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0) ? 3379 return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0) ?
3091 RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; 3380 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
3092} 3381}
3093 3382
3094static void bluetooth_update_rfk(void) 3383static int bluetooth_set_status(enum tpacpi_rfkill_state state)
3095{ 3384{
3096 int status; 3385 int status;
3097 3386
3098 if (!tpacpi_bluetooth_rfkill)
3099 return;
3100
3101 status = bluetooth_get_radiosw();
3102 if (status < 0)
3103 return;
3104 rfkill_force_state(tpacpi_bluetooth_rfkill, status);
3105
3106 vdbg_printk(TPACPI_DBG_RFKILL, 3387 vdbg_printk(TPACPI_DBG_RFKILL,
3107 "forced rfkill state to %d\n", 3388 "will attempt to %s bluetooth\n",
3108 status); 3389 (state == TPACPI_RFK_RADIO_ON) ? "enable" : "disable");
3109}
3110
3111static int bluetooth_set_radiosw(int radio_on, int update_rfk)
3112{
3113 int status;
3114
3115 if (!tp_features.bluetooth)
3116 return -ENODEV;
3117
3118 /* WLSW overrides bluetooth in firmware/hardware, but there is no
3119 * reason to risk weird behaviour. */
3120 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status
3121 && radio_on)
3122 return -EPERM;
3123
3124 vdbg_printk(TPACPI_DBG_RFKILL,
3125 "will %s bluetooth\n", radio_on ? "enable" : "disable");
3126 3390
3127#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3391#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3128 if (dbg_bluetoothemul) { 3392 if (dbg_bluetoothemul) {
3129 tpacpi_bluetooth_emulstate = !!radio_on; 3393 tpacpi_bluetooth_emulstate = (state == TPACPI_RFK_RADIO_ON);
3130 if (update_rfk)
3131 bluetooth_update_rfk();
3132 return 0; 3394 return 0;
3133 } 3395 }
3134#endif 3396#endif
3135 3397
3136 /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */ 3398 /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
3137 if (radio_on) 3399 if (state == TPACPI_RFK_RADIO_ON)
3138 status = TP_ACPI_BLUETOOTH_RADIOSSW; 3400 status = TP_ACPI_BLUETOOTH_RADIOSSW;
3139 else 3401 else
3140 status = 0; 3402 status = 0;
3403
3141 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) 3404 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
3142 return -EIO; 3405 return -EIO;
3143 3406
3144 if (update_rfk)
3145 bluetooth_update_rfk();
3146
3147 return 0; 3407 return 0;
3148} 3408}
3149 3409
@@ -3152,35 +3412,16 @@ static ssize_t bluetooth_enable_show(struct device *dev,
3152 struct device_attribute *attr, 3412 struct device_attribute *attr,
3153 char *buf) 3413 char *buf)
3154{ 3414{
3155 int status; 3415 return tpacpi_rfk_sysfs_enable_show(TPACPI_RFK_BLUETOOTH_SW_ID,
3156 3416 attr, buf);
3157 printk_deprecated_rfkill_attribute("bluetooth_enable");
3158
3159 status = bluetooth_get_radiosw();
3160 if (status < 0)
3161 return status;
3162
3163 return snprintf(buf, PAGE_SIZE, "%d\n",
3164 (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0);
3165} 3417}
3166 3418
3167static ssize_t bluetooth_enable_store(struct device *dev, 3419static ssize_t bluetooth_enable_store(struct device *dev,
3168 struct device_attribute *attr, 3420 struct device_attribute *attr,
3169 const char *buf, size_t count) 3421 const char *buf, size_t count)
3170{ 3422{
3171 unsigned long t; 3423 return tpacpi_rfk_sysfs_enable_store(TPACPI_RFK_BLUETOOTH_SW_ID,
3172 int res; 3424 attr, buf, count);
3173
3174 printk_deprecated_rfkill_attribute("bluetooth_enable");
3175
3176 if (parse_strtoul(buf, 1, &t))
3177 return -EINVAL;
3178
3179 tpacpi_disclose_usertask("bluetooth_enable", "set to %ld\n", t);
3180
3181 res = bluetooth_set_radiosw(t, 1);
3182
3183 return (res) ? res : count;
3184} 3425}
3185 3426
3186static struct device_attribute dev_attr_bluetooth_enable = 3427static struct device_attribute dev_attr_bluetooth_enable =
@@ -3198,23 +3439,10 @@ static const struct attribute_group bluetooth_attr_group = {
3198 .attrs = bluetooth_attributes, 3439 .attrs = bluetooth_attributes,
3199}; 3440};
3200 3441
3201static int tpacpi_bluetooth_rfk_get(void *data, enum rfkill_state *state) 3442static const struct tpacpi_rfk_ops bluetooth_tprfk_ops = {
3202{ 3443 .get_status = bluetooth_get_status,
3203 int bts = bluetooth_get_radiosw(); 3444 .set_status = bluetooth_set_status,
3204 3445};
3205 if (bts < 0)
3206 return bts;
3207
3208 *state = bts;
3209 return 0;
3210}
3211
3212static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state)
3213{
3214 dbg_printk(TPACPI_DBG_RFKILL,
3215 "request to change radio state to %d\n", state);
3216 return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
3217}
3218 3446
3219static void bluetooth_shutdown(void) 3447static void bluetooth_shutdown(void)
3220{ 3448{
@@ -3230,13 +3458,12 @@ static void bluetooth_shutdown(void)
3230 3458
3231static void bluetooth_exit(void) 3459static void bluetooth_exit(void)
3232{ 3460{
3233 bluetooth_shutdown();
3234
3235 if (tpacpi_bluetooth_rfkill)
3236 rfkill_unregister(tpacpi_bluetooth_rfkill);
3237
3238 sysfs_remove_group(&tpacpi_pdev->dev.kobj, 3461 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
3239 &bluetooth_attr_group); 3462 &bluetooth_attr_group);
3463
3464 tpacpi_destroy_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID);
3465
3466 bluetooth_shutdown();
3240} 3467}
3241 3468
3242static int __init bluetooth_init(struct ibm_init_struct *iibm) 3469static int __init bluetooth_init(struct ibm_init_struct *iibm)
@@ -3277,20 +3504,18 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
3277 if (!tp_features.bluetooth) 3504 if (!tp_features.bluetooth)
3278 return 1; 3505 return 1;
3279 3506
3280 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
3281 &bluetooth_attr_group);
3282 if (res)
3283 return res;
3284
3285 res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID, 3507 res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID,
3286 &tpacpi_bluetooth_rfkill, 3508 &bluetooth_tprfk_ops,
3287 RFKILL_TYPE_BLUETOOTH, 3509 RFKILL_TYPE_BLUETOOTH,
3288 TPACPI_RFK_BLUETOOTH_SW_NAME, 3510 TPACPI_RFK_BLUETOOTH_SW_NAME,
3289 true, 3511 true);
3290 tpacpi_bluetooth_rfk_set, 3512 if (res)
3291 tpacpi_bluetooth_rfk_get); 3513 return res;
3514
3515 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
3516 &bluetooth_attr_group);
3292 if (res) { 3517 if (res) {
3293 bluetooth_exit(); 3518 tpacpi_destroy_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID);
3294 return res; 3519 return res;
3295 } 3520 }
3296 3521
@@ -3300,46 +3525,12 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
3300/* procfs -------------------------------------------------------------- */ 3525/* procfs -------------------------------------------------------------- */
3301static int bluetooth_read(char *p) 3526static int bluetooth_read(char *p)
3302{ 3527{
3303 int len = 0; 3528 return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, p);
3304 int status = bluetooth_get_radiosw();
3305
3306 if (!tp_features.bluetooth)
3307 len += sprintf(p + len, "status:\t\tnot supported\n");
3308 else {
3309 len += sprintf(p + len, "status:\t\t%s\n",
3310 (status == RFKILL_STATE_UNBLOCKED) ?
3311 "enabled" : "disabled");
3312 len += sprintf(p + len, "commands:\tenable, disable\n");
3313 }
3314
3315 return len;
3316} 3529}
3317 3530
3318static int bluetooth_write(char *buf) 3531static int bluetooth_write(char *buf)
3319{ 3532{
3320 char *cmd; 3533 return tpacpi_rfk_procfs_write(TPACPI_RFK_BLUETOOTH_SW_ID, buf);
3321 int state = -1;
3322
3323 if (!tp_features.bluetooth)
3324 return -ENODEV;
3325
3326 while ((cmd = next_cmd(&buf))) {
3327 if (strlencmp(cmd, "enable") == 0) {
3328 state = 1;
3329 } else if (strlencmp(cmd, "disable") == 0) {
3330 state = 0;
3331 } else
3332 return -EINVAL;
3333 }
3334
3335 if (state != -1) {
3336 tpacpi_disclose_usertask("procfs bluetooth",
3337 "attempt to %s\n",
3338 state ? "enable" : "disable");
3339 bluetooth_set_radiosw(state, 1);
3340 }
3341
3342 return 0;
3343} 3534}
3344 3535
3345static struct ibm_struct bluetooth_driver_data = { 3536static struct ibm_struct bluetooth_driver_data = {
@@ -3365,8 +3556,6 @@ enum {
3365 3556
3366#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw" 3557#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw"
3367 3558
3368static struct rfkill *tpacpi_wan_rfkill;
3369
3370static void wan_suspend(pm_message_t state) 3559static void wan_suspend(pm_message_t state)
3371{ 3560{
3372 /* Try to make sure radio will resume powered off */ 3561 /* Try to make sure radio will resume powered off */
@@ -3376,83 +3565,47 @@ static void wan_suspend(pm_message_t state)
3376 "WWAN power down on resume request failed\n"); 3565 "WWAN power down on resume request failed\n");
3377} 3566}
3378 3567
3379static int wan_get_radiosw(void) 3568static int wan_get_status(void)
3380{ 3569{
3381 int status; 3570 int status;
3382 3571
3383 if (!tp_features.wan)
3384 return -ENODEV;
3385
3386 /* WLSW overrides WWAN in firmware/hardware, reflect that */
3387 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
3388 return RFKILL_STATE_HARD_BLOCKED;
3389
3390#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3572#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3391 if (dbg_wwanemul) 3573 if (dbg_wwanemul)
3392 return (tpacpi_wwan_emulstate) ? 3574 return (tpacpi_wwan_emulstate) ?
3393 RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; 3575 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
3394#endif 3576#endif
3395 3577
3396 if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) 3578 if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
3397 return -EIO; 3579 return -EIO;
3398 3580
3399 return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0) ? 3581 return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0) ?
3400 RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; 3582 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
3401}
3402
3403static void wan_update_rfk(void)
3404{
3405 int status;
3406
3407 if (!tpacpi_wan_rfkill)
3408 return;
3409
3410 status = wan_get_radiosw();
3411 if (status < 0)
3412 return;
3413 rfkill_force_state(tpacpi_wan_rfkill, status);
3414
3415 vdbg_printk(TPACPI_DBG_RFKILL,
3416 "forced rfkill state to %d\n",
3417 status);
3418} 3583}
3419 3584
3420static int wan_set_radiosw(int radio_on, int update_rfk) 3585static int wan_set_status(enum tpacpi_rfkill_state state)
3421{ 3586{
3422 int status; 3587 int status;
3423 3588
3424 if (!tp_features.wan)
3425 return -ENODEV;
3426
3427 /* WLSW overrides bluetooth in firmware/hardware, but there is no
3428 * reason to risk weird behaviour. */
3429 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status
3430 && radio_on)
3431 return -EPERM;
3432
3433 vdbg_printk(TPACPI_DBG_RFKILL, 3589 vdbg_printk(TPACPI_DBG_RFKILL,
3434 "will %s WWAN\n", radio_on ? "enable" : "disable"); 3590 "will attempt to %s wwan\n",
3591 (state == TPACPI_RFK_RADIO_ON) ? "enable" : "disable");
3435 3592
3436#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3593#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3437 if (dbg_wwanemul) { 3594 if (dbg_wwanemul) {
3438 tpacpi_wwan_emulstate = !!radio_on; 3595 tpacpi_wwan_emulstate = (state == TPACPI_RFK_RADIO_ON);
3439 if (update_rfk)
3440 wan_update_rfk();
3441 return 0; 3596 return 0;
3442 } 3597 }
3443#endif 3598#endif
3444 3599
3445 /* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */ 3600 /* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */
3446 if (radio_on) 3601 if (state == TPACPI_RFK_RADIO_ON)
3447 status = TP_ACPI_WANCARD_RADIOSSW; 3602 status = TP_ACPI_WANCARD_RADIOSSW;
3448 else 3603 else
3449 status = 0; 3604 status = 0;
3605
3450 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) 3606 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
3451 return -EIO; 3607 return -EIO;
3452 3608
3453 if (update_rfk)
3454 wan_update_rfk();
3455
3456 return 0; 3609 return 0;
3457} 3610}
3458 3611
@@ -3461,35 +3614,16 @@ static ssize_t wan_enable_show(struct device *dev,
3461 struct device_attribute *attr, 3614 struct device_attribute *attr,
3462 char *buf) 3615 char *buf)
3463{ 3616{
3464 int status; 3617 return tpacpi_rfk_sysfs_enable_show(TPACPI_RFK_WWAN_SW_ID,
3465 3618 attr, buf);
3466 printk_deprecated_rfkill_attribute("wwan_enable");
3467
3468 status = wan_get_radiosw();
3469 if (status < 0)
3470 return status;
3471
3472 return snprintf(buf, PAGE_SIZE, "%d\n",
3473 (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0);
3474} 3619}
3475 3620
3476static ssize_t wan_enable_store(struct device *dev, 3621static ssize_t wan_enable_store(struct device *dev,
3477 struct device_attribute *attr, 3622 struct device_attribute *attr,
3478 const char *buf, size_t count) 3623 const char *buf, size_t count)
3479{ 3624{
3480 unsigned long t; 3625 return tpacpi_rfk_sysfs_enable_store(TPACPI_RFK_WWAN_SW_ID,
3481 int res; 3626 attr, buf, count);
3482
3483 printk_deprecated_rfkill_attribute("wwan_enable");
3484
3485 if (parse_strtoul(buf, 1, &t))
3486 return -EINVAL;
3487
3488 tpacpi_disclose_usertask("wwan_enable", "set to %ld\n", t);
3489
3490 res = wan_set_radiosw(t, 1);
3491
3492 return (res) ? res : count;
3493} 3627}
3494 3628
3495static struct device_attribute dev_attr_wan_enable = 3629static struct device_attribute dev_attr_wan_enable =
@@ -3507,23 +3641,10 @@ static const struct attribute_group wan_attr_group = {
3507 .attrs = wan_attributes, 3641 .attrs = wan_attributes,
3508}; 3642};
3509 3643
3510static int tpacpi_wan_rfk_get(void *data, enum rfkill_state *state) 3644static const struct tpacpi_rfk_ops wan_tprfk_ops = {
3511{ 3645 .get_status = wan_get_status,
3512 int wans = wan_get_radiosw(); 3646 .set_status = wan_set_status,
3513 3647};
3514 if (wans < 0)
3515 return wans;
3516
3517 *state = wans;
3518 return 0;
3519}
3520
3521static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state)
3522{
3523 dbg_printk(TPACPI_DBG_RFKILL,
3524 "request to change radio state to %d\n", state);
3525 return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
3526}
3527 3648
3528static void wan_shutdown(void) 3649static void wan_shutdown(void)
3529{ 3650{
@@ -3539,13 +3660,12 @@ static void wan_shutdown(void)
3539 3660
3540static void wan_exit(void) 3661static void wan_exit(void)
3541{ 3662{
3542 wan_shutdown();
3543
3544 if (tpacpi_wan_rfkill)
3545 rfkill_unregister(tpacpi_wan_rfkill);
3546
3547 sysfs_remove_group(&tpacpi_pdev->dev.kobj, 3663 sysfs_remove_group(&tpacpi_pdev->dev.kobj,
3548 &wan_attr_group); 3664 &wan_attr_group);
3665
3666 tpacpi_destroy_rfkill(TPACPI_RFK_WWAN_SW_ID);
3667
3668 wan_shutdown();
3549} 3669}
3550 3670
3551static int __init wan_init(struct ibm_init_struct *iibm) 3671static int __init wan_init(struct ibm_init_struct *iibm)
@@ -3584,20 +3704,19 @@ static int __init wan_init(struct ibm_init_struct *iibm)
3584 if (!tp_features.wan) 3704 if (!tp_features.wan)
3585 return 1; 3705 return 1;
3586 3706
3587 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
3588 &wan_attr_group);
3589 if (res)
3590 return res;
3591
3592 res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID, 3707 res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID,
3593 &tpacpi_wan_rfkill, 3708 &wan_tprfk_ops,
3594 RFKILL_TYPE_WWAN, 3709 RFKILL_TYPE_WWAN,
3595 TPACPI_RFK_WWAN_SW_NAME, 3710 TPACPI_RFK_WWAN_SW_NAME,
3596 true, 3711 true);
3597 tpacpi_wan_rfk_set, 3712 if (res)
3598 tpacpi_wan_rfk_get); 3713 return res;
3714
3715 res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
3716 &wan_attr_group);
3717
3599 if (res) { 3718 if (res) {
3600 wan_exit(); 3719 tpacpi_destroy_rfkill(TPACPI_RFK_WWAN_SW_ID);
3601 return res; 3720 return res;
3602 } 3721 }
3603 3722
@@ -3607,48 +3726,12 @@ static int __init wan_init(struct ibm_init_struct *iibm)
3607/* procfs -------------------------------------------------------------- */ 3726/* procfs -------------------------------------------------------------- */
3608static int wan_read(char *p) 3727static int wan_read(char *p)
3609{ 3728{
3610 int len = 0; 3729 return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, p);
3611 int status = wan_get_radiosw();
3612
3613 tpacpi_disclose_usertask("procfs wan", "read");
3614
3615 if (!tp_features.wan)
3616 len += sprintf(p + len, "status:\t\tnot supported\n");
3617 else {
3618 len += sprintf(p + len, "status:\t\t%s\n",
3619 (status == RFKILL_STATE_UNBLOCKED) ?
3620 "enabled" : "disabled");
3621 len += sprintf(p + len, "commands:\tenable, disable\n");
3622 }
3623
3624 return len;
3625} 3730}
3626 3731
3627static int wan_write(char *buf) 3732static int wan_write(char *buf)
3628{ 3733{
3629 char *cmd; 3734 return tpacpi_rfk_procfs_write(TPACPI_RFK_WWAN_SW_ID, buf);
3630 int state = -1;
3631
3632 if (!tp_features.wan)
3633 return -ENODEV;
3634
3635 while ((cmd = next_cmd(&buf))) {
3636 if (strlencmp(cmd, "enable") == 0) {
3637 state = 1;
3638 } else if (strlencmp(cmd, "disable") == 0) {
3639 state = 0;
3640 } else
3641 return -EINVAL;
3642 }
3643
3644 if (state != -1) {
3645 tpacpi_disclose_usertask("procfs wan",
3646 "attempt to %s\n",
3647 state ? "enable" : "disable");
3648 wan_set_radiosw(state, 1);
3649 }
3650
3651 return 0;
3652} 3735}
3653 3736
3654static struct ibm_struct wan_driver_data = { 3737static struct ibm_struct wan_driver_data = {
@@ -3672,108 +3755,59 @@ enum {
3672 3755
3673#define TPACPI_RFK_UWB_SW_NAME "tpacpi_uwb_sw" 3756#define TPACPI_RFK_UWB_SW_NAME "tpacpi_uwb_sw"
3674 3757
3675static struct rfkill *tpacpi_uwb_rfkill; 3758static int uwb_get_status(void)
3676
3677static int uwb_get_radiosw(void)
3678{ 3759{
3679 int status; 3760 int status;
3680 3761
3681 if (!tp_features.uwb)
3682 return -ENODEV;
3683
3684 /* WLSW overrides UWB in firmware/hardware, reflect that */
3685 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
3686 return RFKILL_STATE_HARD_BLOCKED;
3687
3688#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3762#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3689 if (dbg_uwbemul) 3763 if (dbg_uwbemul)
3690 return (tpacpi_uwb_emulstate) ? 3764 return (tpacpi_uwb_emulstate) ?
3691 RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; 3765 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
3692#endif 3766#endif
3693 3767
3694 if (!acpi_evalf(hkey_handle, &status, "GUWB", "d")) 3768 if (!acpi_evalf(hkey_handle, &status, "GUWB", "d"))
3695 return -EIO; 3769 return -EIO;
3696 3770
3697 return ((status & TP_ACPI_UWB_RADIOSSW) != 0) ? 3771 return ((status & TP_ACPI_UWB_RADIOSSW) != 0) ?
3698 RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; 3772 TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
3699} 3773}
3700 3774
3701static void uwb_update_rfk(void) 3775static int uwb_set_status(enum tpacpi_rfkill_state state)
3702{ 3776{
3703 int status; 3777 int status;
3704 3778
3705 if (!tpacpi_uwb_rfkill)
3706 return;
3707
3708 status = uwb_get_radiosw();
3709 if (status < 0)
3710 return;
3711 rfkill_force_state(tpacpi_uwb_rfkill, status);
3712
3713 vdbg_printk(TPACPI_DBG_RFKILL, 3779 vdbg_printk(TPACPI_DBG_RFKILL,
3714 "forced rfkill state to %d\n", 3780 "will attempt to %s UWB\n",
3715 status); 3781 (state == TPACPI_RFK_RADIO_ON) ? "enable" : "disable");
3716}
3717
3718static int uwb_set_radiosw(int radio_on, int update_rfk)
3719{
3720 int status;
3721
3722 if (!tp_features.uwb)
3723 return -ENODEV;
3724
3725 /* WLSW overrides UWB in firmware/hardware, but there is no
3726 * reason to risk weird behaviour. */
3727 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status
3728 && radio_on)
3729 return -EPERM;
3730
3731 vdbg_printk(TPACPI_DBG_RFKILL,
3732 "will %s UWB\n", radio_on ? "enable" : "disable");
3733 3782
3734#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3783#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3735 if (dbg_uwbemul) { 3784 if (dbg_uwbemul) {
3736 tpacpi_uwb_emulstate = !!radio_on; 3785 tpacpi_uwb_emulstate = (state == TPACPI_RFK_RADIO_ON);
3737 if (update_rfk)
3738 uwb_update_rfk();
3739 return 0; 3786 return 0;
3740 } 3787 }
3741#endif 3788#endif
3742 3789
3743 status = (radio_on) ? TP_ACPI_UWB_RADIOSSW : 0; 3790 if (state == TPACPI_RFK_RADIO_ON)
3791 status = TP_ACPI_UWB_RADIOSSW;
3792 else
3793 status = 0;
3794
3744 if (!acpi_evalf(hkey_handle, NULL, "SUWB", "vd", status)) 3795 if (!acpi_evalf(hkey_handle, NULL, "SUWB", "vd", status))
3745 return -EIO; 3796 return -EIO;
3746 3797
3747 if (update_rfk)
3748 uwb_update_rfk();
3749
3750 return 0; 3798 return 0;
3751} 3799}
3752 3800
3753/* --------------------------------------------------------------------- */ 3801/* --------------------------------------------------------------------- */
3754 3802
3755static int tpacpi_uwb_rfk_get(void *data, enum rfkill_state *state) 3803static const struct tpacpi_rfk_ops uwb_tprfk_ops = {
3756{ 3804 .get_status = uwb_get_status,
3757 int uwbs = uwb_get_radiosw(); 3805 .set_status = uwb_set_status,
3758 3806};
3759 if (uwbs < 0)
3760 return uwbs;
3761
3762 *state = uwbs;
3763 return 0;
3764}
3765
3766static int tpacpi_uwb_rfk_set(void *data, enum rfkill_state state)
3767{
3768 dbg_printk(TPACPI_DBG_RFKILL,
3769 "request to change radio state to %d\n", state);
3770 return uwb_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
3771}
3772 3807
3773static void uwb_exit(void) 3808static void uwb_exit(void)
3774{ 3809{
3775 if (tpacpi_uwb_rfkill) 3810 tpacpi_destroy_rfkill(TPACPI_RFK_UWB_SW_ID);
3776 rfkill_unregister(tpacpi_uwb_rfkill);
3777} 3811}
3778 3812
3779static int __init uwb_init(struct ibm_init_struct *iibm) 3813static int __init uwb_init(struct ibm_init_struct *iibm)
@@ -3813,13 +3847,10 @@ static int __init uwb_init(struct ibm_init_struct *iibm)
3813 return 1; 3847 return 1;
3814 3848
3815 res = tpacpi_new_rfkill(TPACPI_RFK_UWB_SW_ID, 3849 res = tpacpi_new_rfkill(TPACPI_RFK_UWB_SW_ID,
3816 &tpacpi_uwb_rfkill, 3850 &uwb_tprfk_ops,
3817 RFKILL_TYPE_UWB, 3851 RFKILL_TYPE_UWB,
3818 TPACPI_RFK_UWB_SW_NAME, 3852 TPACPI_RFK_UWB_SW_NAME,
3819 false, 3853 false);
3820 tpacpi_uwb_rfk_set,
3821 tpacpi_uwb_rfk_get);
3822
3823 return res; 3854 return res;
3824} 3855}
3825 3856
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 4345089f5171..81d31ea507d1 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -45,7 +45,6 @@
45#include <linux/backlight.h> 45#include <linux/backlight.h>
46#include <linux/platform_device.h> 46#include <linux/platform_device.h>
47#include <linux/rfkill.h> 47#include <linux/rfkill.h>
48#include <linux/input-polldev.h>
49 48
50#include <asm/uaccess.h> 49#include <asm/uaccess.h>
51 50
@@ -250,21 +249,15 @@ static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result)
250 249
251struct toshiba_acpi_dev { 250struct toshiba_acpi_dev {
252 struct platform_device *p_dev; 251 struct platform_device *p_dev;
253 struct rfkill *rfk_dev; 252 struct rfkill *bt_rfk;
254 struct input_polled_dev *poll_dev;
255 253
256 const char *bt_name; 254 const char *bt_name;
257 const char *rfk_name;
258
259 bool last_rfk_state;
260 255
261 struct mutex mutex; 256 struct mutex mutex;
262}; 257};
263 258
264static struct toshiba_acpi_dev toshiba_acpi = { 259static struct toshiba_acpi_dev toshiba_acpi = {
265 .bt_name = "Toshiba Bluetooth", 260 .bt_name = "Toshiba Bluetooth",
266 .rfk_name = "Toshiba RFKill Switch",
267 .last_rfk_state = false,
268}; 261};
269 262
270/* Bluetooth rfkill handlers */ 263/* Bluetooth rfkill handlers */
@@ -283,21 +276,6 @@ static u32 hci_get_bt_present(bool *present)
283 return hci_result; 276 return hci_result;
284} 277}
285 278
286static u32 hci_get_bt_on(bool *on)
287{
288 u32 hci_result;
289 u32 value, value2;
290
291 value = 0;
292 value2 = 0x0001;
293 hci_read2(HCI_WIRELESS, &value, &value2, &hci_result);
294 if (hci_result == HCI_SUCCESS)
295 *on = (value & HCI_WIRELESS_BT_POWER) &&
296 (value & HCI_WIRELESS_BT_ATTACH);
297
298 return hci_result;
299}
300
301static u32 hci_get_radio_state(bool *radio_state) 279static u32 hci_get_radio_state(bool *radio_state)
302{ 280{
303 u32 hci_result; 281 u32 hci_result;
@@ -311,70 +289,67 @@ static u32 hci_get_radio_state(bool *radio_state)
311 return hci_result; 289 return hci_result;
312} 290}
313 291
314static int bt_rfkill_toggle_radio(void *data, enum rfkill_state state) 292static int bt_rfkill_set_block(void *data, bool blocked)
315{ 293{
294 struct toshiba_acpi_dev *dev = data;
316 u32 result1, result2; 295 u32 result1, result2;
317 u32 value; 296 u32 value;
297 int err;
318 bool radio_state; 298 bool radio_state;
319 struct toshiba_acpi_dev *dev = data;
320 299
321 value = (state == RFKILL_STATE_UNBLOCKED); 300 value = (blocked == false);
322 301
323 if (hci_get_radio_state(&radio_state) != HCI_SUCCESS) 302 mutex_lock(&dev->mutex);
324 return -EFAULT; 303 if (hci_get_radio_state(&radio_state) != HCI_SUCCESS) {
304 err = -EBUSY;
305 goto out;
306 }
325 307
326 switch (state) { 308 if (!radio_state) {
327 case RFKILL_STATE_UNBLOCKED: 309 err = 0;
328 if (!radio_state) 310 goto out;
329 return -EPERM;
330 break;
331 case RFKILL_STATE_SOFT_BLOCKED:
332 break;
333 default:
334 return -EINVAL;
335 } 311 }
336 312
337 mutex_lock(&dev->mutex);
338 hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1); 313 hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1);
339 hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2); 314 hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2);
340 mutex_unlock(&dev->mutex);
341 315
342 if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS) 316 if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS)
343 return -EFAULT; 317 err = -EBUSY;
344 318 else
345 return 0; 319 err = 0;
320 out:
321 mutex_unlock(&dev->mutex);
322 return err;
346} 323}
347 324
348static void bt_poll_rfkill(struct input_polled_dev *poll_dev) 325static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
349{ 326{
350 bool state_changed;
351 bool new_rfk_state; 327 bool new_rfk_state;
352 bool value; 328 bool value;
353 u32 hci_result; 329 u32 hci_result;
354 struct toshiba_acpi_dev *dev = poll_dev->private; 330 struct toshiba_acpi_dev *dev = data;
331
332 mutex_lock(&dev->mutex);
355 333
356 hci_result = hci_get_radio_state(&value); 334 hci_result = hci_get_radio_state(&value);
357 if (hci_result != HCI_SUCCESS) 335 if (hci_result != HCI_SUCCESS) {
358 return; /* Can't do anything useful */ 336 /* Can't do anything useful */
337 mutex_unlock(&dev->mutex);
338 }
359 339
360 new_rfk_state = value; 340 new_rfk_state = value;
361 341
362 mutex_lock(&dev->mutex);
363 state_changed = new_rfk_state != dev->last_rfk_state;
364 dev->last_rfk_state = new_rfk_state;
365 mutex_unlock(&dev->mutex); 342 mutex_unlock(&dev->mutex);
366 343
367 if (unlikely(state_changed)) { 344 if (rfkill_set_hw_state(rfkill, !new_rfk_state))
368 rfkill_force_state(dev->rfk_dev, 345 bt_rfkill_set_block(data, true);
369 new_rfk_state ?
370 RFKILL_STATE_SOFT_BLOCKED :
371 RFKILL_STATE_HARD_BLOCKED);
372 input_report_switch(poll_dev->input, SW_RFKILL_ALL,
373 new_rfk_state);
374 input_sync(poll_dev->input);
375 }
376} 346}
377 347
348static const struct rfkill_ops toshiba_rfk_ops = {
349 .set_block = bt_rfkill_set_block,
350 .poll = bt_rfkill_poll,
351};
352
378static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; 353static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
379static struct backlight_device *toshiba_backlight_device; 354static struct backlight_device *toshiba_backlight_device;
380static int force_fan; 355static int force_fan;
@@ -702,14 +677,11 @@ static struct backlight_ops toshiba_backlight_data = {
702 677
703static void toshiba_acpi_exit(void) 678static void toshiba_acpi_exit(void)
704{ 679{
705 if (toshiba_acpi.poll_dev) { 680 if (toshiba_acpi.bt_rfk) {
706 input_unregister_polled_device(toshiba_acpi.poll_dev); 681 rfkill_unregister(toshiba_acpi.bt_rfk);
707 input_free_polled_device(toshiba_acpi.poll_dev); 682 rfkill_destroy(toshiba_acpi.bt_rfk);
708 } 683 }
709 684
710 if (toshiba_acpi.rfk_dev)
711 rfkill_unregister(toshiba_acpi.rfk_dev);
712
713 if (toshiba_backlight_device) 685 if (toshiba_backlight_device)
714 backlight_device_unregister(toshiba_backlight_device); 686 backlight_device_unregister(toshiba_backlight_device);
715 687
@@ -728,8 +700,6 @@ static int __init toshiba_acpi_init(void)
728 acpi_status status = AE_OK; 700 acpi_status status = AE_OK;
729 u32 hci_result; 701 u32 hci_result;
730 bool bt_present; 702 bool bt_present;
731 bool bt_on;
732 bool radio_on;
733 int ret = 0; 703 int ret = 0;
734 704
735 if (acpi_disabled) 705 if (acpi_disabled)
@@ -793,60 +763,21 @@ static int __init toshiba_acpi_init(void)
793 763
794 /* Register rfkill switch for Bluetooth */ 764 /* Register rfkill switch for Bluetooth */
795 if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) { 765 if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) {
796 toshiba_acpi.rfk_dev = rfkill_allocate(&toshiba_acpi.p_dev->dev, 766 toshiba_acpi.bt_rfk = rfkill_alloc(toshiba_acpi.bt_name,
797 RFKILL_TYPE_BLUETOOTH); 767 &toshiba_acpi.p_dev->dev,
798 if (!toshiba_acpi.rfk_dev) { 768 RFKILL_TYPE_BLUETOOTH,
769 &toshiba_rfk_ops,
770 &toshiba_acpi);
771 if (!toshiba_acpi.bt_rfk) {
799 printk(MY_ERR "unable to allocate rfkill device\n"); 772 printk(MY_ERR "unable to allocate rfkill device\n");
800 toshiba_acpi_exit(); 773 toshiba_acpi_exit();
801 return -ENOMEM; 774 return -ENOMEM;
802 } 775 }
803 776
804 toshiba_acpi.rfk_dev->name = toshiba_acpi.bt_name; 777 ret = rfkill_register(toshiba_acpi.bt_rfk);
805 toshiba_acpi.rfk_dev->toggle_radio = bt_rfkill_toggle_radio;
806 toshiba_acpi.rfk_dev->data = &toshiba_acpi;
807
808 if (hci_get_bt_on(&bt_on) == HCI_SUCCESS && bt_on) {
809 toshiba_acpi.rfk_dev->state = RFKILL_STATE_UNBLOCKED;
810 } else if (hci_get_radio_state(&radio_on) == HCI_SUCCESS &&
811 radio_on) {
812 toshiba_acpi.rfk_dev->state = RFKILL_STATE_SOFT_BLOCKED;
813 } else {
814 toshiba_acpi.rfk_dev->state = RFKILL_STATE_HARD_BLOCKED;
815 }
816
817 ret = rfkill_register(toshiba_acpi.rfk_dev);
818 if (ret) { 778 if (ret) {
819 printk(MY_ERR "unable to register rfkill device\n"); 779 printk(MY_ERR "unable to register rfkill device\n");
820 toshiba_acpi_exit(); 780 rfkill_destroy(toshiba_acpi.bt_rfk);
821 return -ENOMEM;
822 }
823
824 /* Register input device for kill switch */
825 toshiba_acpi.poll_dev = input_allocate_polled_device();
826 if (!toshiba_acpi.poll_dev) {
827 printk(MY_ERR
828 "unable to allocate kill-switch input device\n");
829 toshiba_acpi_exit();
830 return -ENOMEM;
831 }
832 toshiba_acpi.poll_dev->private = &toshiba_acpi;
833 toshiba_acpi.poll_dev->poll = bt_poll_rfkill;
834 toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */
835
836 toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name;
837 toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST;
838 /* Toshiba USB ID */
839 toshiba_acpi.poll_dev->input->id.vendor = 0x0930;
840 set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit);
841 set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit);
842 input_report_switch(toshiba_acpi.poll_dev->input,
843 SW_RFKILL_ALL, TRUE);
844 input_sync(toshiba_acpi.poll_dev->input);
845
846 ret = input_register_polled_device(toshiba_acpi.poll_dev);
847 if (ret) {
848 printk(MY_ERR
849 "unable to register kill-switch input device\n");
850 toshiba_acpi_exit(); 781 toshiba_acpi_exit();
851 return ret; 782 return ret;
852 } 783 }