diff options
Diffstat (limited to 'net/rfkill/core.c')
-rw-r--r-- | net/rfkill/core.c | 93 |
1 files changed, 35 insertions, 58 deletions
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 11b7314723df..4e68ab439d5d 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -57,6 +57,7 @@ struct rfkill { | |||
57 | 57 | ||
58 | bool registered; | 58 | bool registered; |
59 | bool suspended; | 59 | bool suspended; |
60 | bool persistent; | ||
60 | 61 | ||
61 | const struct rfkill_ops *ops; | 62 | const struct rfkill_ops *ops; |
62 | void *data; | 63 | void *data; |
@@ -116,11 +117,9 @@ MODULE_PARM_DESC(default_state, | |||
116 | "Default initial state for all radio types, 0 = radio off"); | 117 | "Default initial state for all radio types, 0 = radio off"); |
117 | 118 | ||
118 | static struct { | 119 | static struct { |
119 | bool cur, def; | 120 | bool cur, sav; |
120 | } rfkill_global_states[NUM_RFKILL_TYPES]; | 121 | } rfkill_global_states[NUM_RFKILL_TYPES]; |
121 | 122 | ||
122 | static unsigned long rfkill_states_default_locked; | ||
123 | |||
124 | static bool rfkill_epo_lock_active; | 123 | static bool rfkill_epo_lock_active; |
125 | 124 | ||
126 | 125 | ||
@@ -392,7 +391,7 @@ void rfkill_epo(void) | |||
392 | rfkill_set_block(rfkill, true); | 391 | rfkill_set_block(rfkill, true); |
393 | 392 | ||
394 | for (i = 0; i < NUM_RFKILL_TYPES; i++) { | 393 | for (i = 0; i < NUM_RFKILL_TYPES; i++) { |
395 | rfkill_global_states[i].def = rfkill_global_states[i].cur; | 394 | rfkill_global_states[i].sav = rfkill_global_states[i].cur; |
396 | rfkill_global_states[i].cur = true; | 395 | rfkill_global_states[i].cur = true; |
397 | } | 396 | } |
398 | 397 | ||
@@ -417,7 +416,7 @@ void rfkill_restore_states(void) | |||
417 | 416 | ||
418 | rfkill_epo_lock_active = false; | 417 | rfkill_epo_lock_active = false; |
419 | for (i = 0; i < NUM_RFKILL_TYPES; i++) | 418 | for (i = 0; i < NUM_RFKILL_TYPES; i++) |
420 | __rfkill_switch_all(i, rfkill_global_states[i].def); | 419 | __rfkill_switch_all(i, rfkill_global_states[i].sav); |
421 | mutex_unlock(&rfkill_global_mutex); | 420 | mutex_unlock(&rfkill_global_mutex); |
422 | } | 421 | } |
423 | 422 | ||
@@ -464,29 +463,6 @@ bool rfkill_get_global_sw_state(const enum rfkill_type type) | |||
464 | } | 463 | } |
465 | #endif | 464 | #endif |
466 | 465 | ||
467 | void rfkill_set_global_sw_state(const enum rfkill_type type, bool blocked) | ||
468 | { | ||
469 | BUG_ON(type == RFKILL_TYPE_ALL); | ||
470 | |||
471 | mutex_lock(&rfkill_global_mutex); | ||
472 | |||
473 | /* don't allow unblock when epo */ | ||
474 | if (rfkill_epo_lock_active && !blocked) | ||
475 | goto out; | ||
476 | |||
477 | /* too late */ | ||
478 | if (rfkill_states_default_locked & BIT(type)) | ||
479 | goto out; | ||
480 | |||
481 | rfkill_states_default_locked |= BIT(type); | ||
482 | |||
483 | rfkill_global_states[type].cur = blocked; | ||
484 | rfkill_global_states[type].def = blocked; | ||
485 | out: | ||
486 | mutex_unlock(&rfkill_global_mutex); | ||
487 | } | ||
488 | EXPORT_SYMBOL(rfkill_set_global_sw_state); | ||
489 | |||
490 | 466 | ||
491 | bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked) | 467 | bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked) |
492 | { | 468 | { |
@@ -532,13 +508,14 @@ bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked) | |||
532 | blocked = blocked || hwblock; | 508 | blocked = blocked || hwblock; |
533 | spin_unlock_irqrestore(&rfkill->lock, flags); | 509 | spin_unlock_irqrestore(&rfkill->lock, flags); |
534 | 510 | ||
535 | if (!rfkill->registered) | 511 | if (!rfkill->registered) { |
536 | return blocked; | 512 | rfkill->persistent = true; |
537 | 513 | } else { | |
538 | if (prev != blocked && !hwblock) | 514 | if (prev != blocked && !hwblock) |
539 | schedule_work(&rfkill->uevent_work); | 515 | schedule_work(&rfkill->uevent_work); |
540 | 516 | ||
541 | rfkill_led_trigger_event(rfkill); | 517 | rfkill_led_trigger_event(rfkill); |
518 | } | ||
542 | 519 | ||
543 | return blocked; | 520 | return blocked; |
544 | } | 521 | } |
@@ -563,13 +540,14 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) | |||
563 | 540 | ||
564 | spin_unlock_irqrestore(&rfkill->lock, flags); | 541 | spin_unlock_irqrestore(&rfkill->lock, flags); |
565 | 542 | ||
566 | if (!rfkill->registered) | 543 | if (!rfkill->registered) { |
567 | return; | 544 | rfkill->persistent = true; |
568 | 545 | } else { | |
569 | if (swprev != sw || hwprev != hw) | 546 | if (swprev != sw || hwprev != hw) |
570 | schedule_work(&rfkill->uevent_work); | 547 | schedule_work(&rfkill->uevent_work); |
571 | 548 | ||
572 | rfkill_led_trigger_event(rfkill); | 549 | rfkill_led_trigger_event(rfkill); |
550 | } | ||
573 | } | 551 | } |
574 | EXPORT_SYMBOL(rfkill_set_states); | 552 | EXPORT_SYMBOL(rfkill_set_states); |
575 | 553 | ||
@@ -750,15 +728,11 @@ static int rfkill_resume(struct device *dev) | |||
750 | struct rfkill *rfkill = to_rfkill(dev); | 728 | struct rfkill *rfkill = to_rfkill(dev); |
751 | bool cur; | 729 | bool cur; |
752 | 730 | ||
753 | mutex_lock(&rfkill_global_mutex); | 731 | cur = !!(rfkill->state & RFKILL_BLOCK_SW); |
754 | cur = rfkill_global_states[rfkill->type].cur; | ||
755 | rfkill_set_block(rfkill, cur); | 732 | rfkill_set_block(rfkill, cur); |
756 | mutex_unlock(&rfkill_global_mutex); | ||
757 | 733 | ||
758 | rfkill->suspended = false; | 734 | rfkill->suspended = false; |
759 | 735 | ||
760 | schedule_work(&rfkill->uevent_work); | ||
761 | |||
762 | rfkill_resume_polling(rfkill); | 736 | rfkill_resume_polling(rfkill); |
763 | 737 | ||
764 | return 0; | 738 | return 0; |
@@ -888,15 +862,6 @@ int __must_check rfkill_register(struct rfkill *rfkill) | |||
888 | dev_set_name(dev, "rfkill%lu", rfkill_no); | 862 | dev_set_name(dev, "rfkill%lu", rfkill_no); |
889 | rfkill_no++; | 863 | rfkill_no++; |
890 | 864 | ||
891 | if (!(rfkill_states_default_locked & BIT(rfkill->type))) { | ||
892 | /* first of its kind */ | ||
893 | BUILD_BUG_ON(NUM_RFKILL_TYPES > | ||
894 | sizeof(rfkill_states_default_locked) * 8); | ||
895 | rfkill_states_default_locked |= BIT(rfkill->type); | ||
896 | rfkill_global_states[rfkill->type].cur = | ||
897 | rfkill_global_states[rfkill->type].def; | ||
898 | } | ||
899 | |||
900 | list_add_tail(&rfkill->node, &rfkill_list); | 865 | list_add_tail(&rfkill->node, &rfkill_list); |
901 | 866 | ||
902 | error = device_add(dev); | 867 | error = device_add(dev); |
@@ -916,7 +881,17 @@ int __must_check rfkill_register(struct rfkill *rfkill) | |||
916 | if (rfkill->ops->poll) | 881 | if (rfkill->ops->poll) |
917 | schedule_delayed_work(&rfkill->poll_work, | 882 | schedule_delayed_work(&rfkill->poll_work, |
918 | round_jiffies_relative(POLL_INTERVAL)); | 883 | round_jiffies_relative(POLL_INTERVAL)); |
919 | schedule_work(&rfkill->sync_work); | 884 | |
885 | if (!rfkill->persistent || rfkill_epo_lock_active) { | ||
886 | schedule_work(&rfkill->sync_work); | ||
887 | } else { | ||
888 | #ifdef CONFIG_RFKILL_INPUT | ||
889 | bool soft_blocked = !!(rfkill->state & RFKILL_BLOCK_SW); | ||
890 | |||
891 | if (!atomic_read(&rfkill_input_disabled)) | ||
892 | __rfkill_switch_all(rfkill->type, soft_blocked); | ||
893 | #endif | ||
894 | } | ||
920 | 895 | ||
921 | rfkill_send_events(rfkill, RFKILL_OP_ADD); | 896 | rfkill_send_events(rfkill, RFKILL_OP_ADD); |
922 | 897 | ||
@@ -1134,7 +1109,8 @@ static int rfkill_fop_release(struct inode *inode, struct file *file) | |||
1134 | 1109 | ||
1135 | #ifdef CONFIG_RFKILL_INPUT | 1110 | #ifdef CONFIG_RFKILL_INPUT |
1136 | if (data->input_handler) | 1111 | if (data->input_handler) |
1137 | atomic_dec(&rfkill_input_disabled); | 1112 | if (atomic_dec_return(&rfkill_input_disabled) == 0) |
1113 | printk(KERN_DEBUG "rfkill: input handler enabled\n"); | ||
1138 | #endif | 1114 | #endif |
1139 | 1115 | ||
1140 | kfree(data); | 1116 | kfree(data); |
@@ -1157,7 +1133,8 @@ static long rfkill_fop_ioctl(struct file *file, unsigned int cmd, | |||
1157 | mutex_lock(&data->mtx); | 1133 | mutex_lock(&data->mtx); |
1158 | 1134 | ||
1159 | if (!data->input_handler) { | 1135 | if (!data->input_handler) { |
1160 | atomic_inc(&rfkill_input_disabled); | 1136 | if (atomic_inc_return(&rfkill_input_disabled) == 1) |
1137 | printk(KERN_DEBUG "rfkill: input handler disabled\n"); | ||
1161 | data->input_handler = true; | 1138 | data->input_handler = true; |
1162 | } | 1139 | } |
1163 | 1140 | ||
@@ -1191,7 +1168,7 @@ static int __init rfkill_init(void) | |||
1191 | int i; | 1168 | int i; |
1192 | 1169 | ||
1193 | for (i = 0; i < NUM_RFKILL_TYPES; i++) | 1170 | for (i = 0; i < NUM_RFKILL_TYPES; i++) |
1194 | rfkill_global_states[i].def = !rfkill_default_state; | 1171 | rfkill_global_states[i].cur = !rfkill_default_state; |
1195 | 1172 | ||
1196 | error = class_register(&rfkill_class); | 1173 | error = class_register(&rfkill_class); |
1197 | if (error) | 1174 | if (error) |