aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/toshiba_acpi.c
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/x86/toshiba_acpi.c
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/x86/toshiba_acpi.c')
-rw-r--r--drivers/platform/x86/toshiba_acpi.c159
1 files changed, 45 insertions, 114 deletions
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 }