aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
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/platform
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/platform')
-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
8 files changed, 709 insertions, 881 deletions
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 }