diff options
-rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 8 | ||||
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 14 | ||||
-rw-r--r-- | include/linux/rfkill.h | 32 | ||||
-rw-r--r-- | net/rfkill/core.c | 40 |
4 files changed, 63 insertions, 31 deletions
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 03bf522bd7ab..01682eca4360 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
@@ -675,8 +675,8 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
675 | if (!ehotk->eeepc_wlan_rfkill) | 675 | if (!ehotk->eeepc_wlan_rfkill) |
676 | goto wlan_fail; | 676 | goto wlan_fail; |
677 | 677 | ||
678 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, | 678 | rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill, |
679 | get_acpi(CM_ASL_WLAN) != 1); | 679 | get_acpi(CM_ASL_WLAN) != 1); |
680 | result = rfkill_register(ehotk->eeepc_wlan_rfkill); | 680 | result = rfkill_register(ehotk->eeepc_wlan_rfkill); |
681 | if (result) | 681 | if (result) |
682 | goto wlan_fail; | 682 | goto wlan_fail; |
@@ -693,8 +693,8 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
693 | if (!ehotk->eeepc_bluetooth_rfkill) | 693 | if (!ehotk->eeepc_bluetooth_rfkill) |
694 | goto bluetooth_fail; | 694 | goto bluetooth_fail; |
695 | 695 | ||
696 | rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill, | 696 | rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill, |
697 | get_acpi(CM_ASL_BLUETOOTH) != 1); | 697 | get_acpi(CM_ASL_BLUETOOTH) != 1); |
698 | result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); | 698 | result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); |
699 | if (result) | 699 | if (result) |
700 | goto bluetooth_fail; | 700 | goto bluetooth_fail; |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 86e958539f46..40d64c03278c 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -1163,8 +1163,8 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id, | |||
1163 | { | 1163 | { |
1164 | struct tpacpi_rfk *atp_rfk; | 1164 | struct tpacpi_rfk *atp_rfk; |
1165 | int res; | 1165 | int res; |
1166 | bool initial_sw_state = false; | 1166 | bool sw_state = false; |
1167 | int initial_sw_status; | 1167 | int sw_status; |
1168 | 1168 | ||
1169 | BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]); | 1169 | BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]); |
1170 | 1170 | ||
@@ -1185,17 +1185,17 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id, | |||
1185 | atp_rfk->id = id; | 1185 | atp_rfk->id = id; |
1186 | atp_rfk->ops = tp_rfkops; | 1186 | atp_rfk->ops = tp_rfkops; |
1187 | 1187 | ||
1188 | initial_sw_status = (tp_rfkops->get_status)(); | 1188 | sw_status = (tp_rfkops->get_status)(); |
1189 | if (initial_sw_status < 0) { | 1189 | if (sw_status < 0) { |
1190 | printk(TPACPI_ERR | 1190 | printk(TPACPI_ERR |
1191 | "failed to read initial state for %s, error %d\n", | 1191 | "failed to read initial state for %s, error %d\n", |
1192 | name, initial_sw_status); | 1192 | name, sw_status); |
1193 | } else { | 1193 | } else { |
1194 | initial_sw_state = (initial_sw_status == TPACPI_RFK_RADIO_OFF); | 1194 | sw_state = (sw_status == TPACPI_RFK_RADIO_OFF); |
1195 | if (set_default) { | 1195 | if (set_default) { |
1196 | /* try to keep the initial state, since we ask the | 1196 | /* try to keep the initial state, since we ask the |
1197 | * firmware to preserve it across S5 in NVRAM */ | 1197 | * firmware to preserve it across S5 in NVRAM */ |
1198 | rfkill_set_sw_state(atp_rfk->rfkill, initial_sw_state); | 1198 | rfkill_init_sw_state(atp_rfk->rfkill, sw_state); |
1199 | } | 1199 | } |
1200 | } | 1200 | } |
1201 | rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state()); | 1201 | rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state()); |
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index 16e39c7a67fc..dcac724340d8 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h | |||
@@ -160,8 +160,9 @@ struct rfkill * __must_check rfkill_alloc(const char *name, | |||
160 | * the rfkill structure. Before calling this function the driver needs | 160 | * the rfkill structure. Before calling this function the driver needs |
161 | * to be ready to service method calls from rfkill. | 161 | * to be ready to service method calls from rfkill. |
162 | * | 162 | * |
163 | * If the software blocked state is not set before registration, | 163 | * If rfkill_init_sw_state() is not called before registration, |
164 | * set_block will be called to initialize it to a default value. | 164 | * set_block() will be called to initialize the software blocked state |
165 | * to a default value. | ||
165 | * | 166 | * |
166 | * If the hardware blocked state is not set before registration, | 167 | * If the hardware blocked state is not set before registration, |
167 | * it is assumed to be unblocked. | 168 | * it is assumed to be unblocked. |
@@ -234,9 +235,11 @@ bool __must_check rfkill_set_hw_state(struct rfkill *rfkill, bool blocked); | |||
234 | * rfkill drivers that get events when the soft-blocked state changes | 235 | * rfkill drivers that get events when the soft-blocked state changes |
235 | * (yes, some platforms directly act on input but allow changing again) | 236 | * (yes, some platforms directly act on input but allow changing again) |
236 | * use this function to notify the rfkill core (and through that also | 237 | * use this function to notify the rfkill core (and through that also |
237 | * userspace) of the current state. It is not necessary to notify on | 238 | * userspace) of the current state. |
238 | * resume; since hibernation can always change the soft-blocked state, | 239 | * |
239 | * the rfkill core will unconditionally restore the previous state. | 240 | * Drivers should also call this function after resume if the state has |
241 | * been changed by the user. This only makes sense for "persistent" | ||
242 | * devices (see rfkill_init_sw_state()). | ||
240 | * | 243 | * |
241 | * This function can be called in any context, even from within rfkill | 244 | * This function can be called in any context, even from within rfkill |
242 | * callbacks. | 245 | * callbacks. |
@@ -247,6 +250,21 @@ bool __must_check rfkill_set_hw_state(struct rfkill *rfkill, bool blocked); | |||
247 | bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked); | 250 | bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked); |
248 | 251 | ||
249 | /** | 252 | /** |
253 | * rfkill_init_sw_state - Initialize persistent software block state | ||
254 | * @rfkill: pointer to the rfkill class to modify. | ||
255 | * @state: the current software block state to set | ||
256 | * | ||
257 | * rfkill drivers that preserve their software block state over power off | ||
258 | * use this function to notify the rfkill core (and through that also | ||
259 | * userspace) of their initial state. It should only be used before | ||
260 | * registration. | ||
261 | * | ||
262 | * In addition, it marks the device as "persistent". Persistent devices | ||
263 | * are expected to preserve preserve their own state when suspended. | ||
264 | */ | ||
265 | void rfkill_init_sw_state(struct rfkill *rfkill, bool blocked); | ||
266 | |||
267 | /** | ||
250 | * rfkill_set_states - Set the internal rfkill block states | 268 | * rfkill_set_states - Set the internal rfkill block states |
251 | * @rfkill: pointer to the rfkill class to modify. | 269 | * @rfkill: pointer to the rfkill class to modify. |
252 | * @sw: the current software block state to set | 270 | * @sw: the current software block state to set |
@@ -307,6 +325,10 @@ static inline bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked) | |||
307 | return blocked; | 325 | return blocked; |
308 | } | 326 | } |
309 | 327 | ||
328 | static inline void rfkill_init_sw_state(struct rfkill *rfkill, bool blocked) | ||
329 | { | ||
330 | } | ||
331 | |||
310 | static inline void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) | 332 | static inline void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) |
311 | { | 333 | { |
312 | } | 334 | } |
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 868d79f8ac1d..dcf8df7c573c 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -56,7 +56,6 @@ struct rfkill { | |||
56 | u32 idx; | 56 | u32 idx; |
57 | 57 | ||
58 | bool registered; | 58 | bool registered; |
59 | bool suspended; | ||
60 | bool persistent; | 59 | bool persistent; |
61 | 60 | ||
62 | const struct rfkill_ops *ops; | 61 | const struct rfkill_ops *ops; |
@@ -224,7 +223,7 @@ static void rfkill_send_events(struct rfkill *rfkill, enum rfkill_operation op) | |||
224 | 223 | ||
225 | static void rfkill_event(struct rfkill *rfkill) | 224 | static void rfkill_event(struct rfkill *rfkill) |
226 | { | 225 | { |
227 | if (!rfkill->registered || rfkill->suspended) | 226 | if (!rfkill->registered) |
228 | return; | 227 | return; |
229 | 228 | ||
230 | kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE); | 229 | kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE); |
@@ -508,19 +507,32 @@ bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked) | |||
508 | blocked = blocked || hwblock; | 507 | blocked = blocked || hwblock; |
509 | spin_unlock_irqrestore(&rfkill->lock, flags); | 508 | spin_unlock_irqrestore(&rfkill->lock, flags); |
510 | 509 | ||
511 | if (!rfkill->registered) { | 510 | if (!rfkill->registered) |
512 | rfkill->persistent = true; | 511 | return blocked; |
513 | } else { | ||
514 | if (prev != blocked && !hwblock) | ||
515 | schedule_work(&rfkill->uevent_work); | ||
516 | 512 | ||
517 | rfkill_led_trigger_event(rfkill); | 513 | if (prev != blocked && !hwblock) |
518 | } | 514 | schedule_work(&rfkill->uevent_work); |
515 | |||
516 | rfkill_led_trigger_event(rfkill); | ||
519 | 517 | ||
520 | return blocked; | 518 | return blocked; |
521 | } | 519 | } |
522 | EXPORT_SYMBOL(rfkill_set_sw_state); | 520 | EXPORT_SYMBOL(rfkill_set_sw_state); |
523 | 521 | ||
522 | void rfkill_init_sw_state(struct rfkill *rfkill, bool blocked) | ||
523 | { | ||
524 | unsigned long flags; | ||
525 | |||
526 | BUG_ON(!rfkill); | ||
527 | BUG_ON(rfkill->registered); | ||
528 | |||
529 | spin_lock_irqsave(&rfkill->lock, flags); | ||
530 | __rfkill_set_sw_state(rfkill, blocked); | ||
531 | rfkill->persistent = true; | ||
532 | spin_unlock_irqrestore(&rfkill->lock, flags); | ||
533 | } | ||
534 | EXPORT_SYMBOL(rfkill_init_sw_state); | ||
535 | |||
524 | void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) | 536 | void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) |
525 | { | 537 | { |
526 | unsigned long flags; | 538 | unsigned long flags; |
@@ -718,8 +730,6 @@ static int rfkill_suspend(struct device *dev, pm_message_t state) | |||
718 | 730 | ||
719 | rfkill_pause_polling(rfkill); | 731 | rfkill_pause_polling(rfkill); |
720 | 732 | ||
721 | rfkill->suspended = true; | ||
722 | |||
723 | return 0; | 733 | return 0; |
724 | } | 734 | } |
725 | 735 | ||
@@ -728,10 +738,10 @@ static int rfkill_resume(struct device *dev) | |||
728 | struct rfkill *rfkill = to_rfkill(dev); | 738 | struct rfkill *rfkill = to_rfkill(dev); |
729 | bool cur; | 739 | bool cur; |
730 | 740 | ||
731 | cur = !!(rfkill->state & RFKILL_BLOCK_SW); | 741 | if (!rfkill->persistent) { |
732 | rfkill_set_block(rfkill, cur); | 742 | cur = !!(rfkill->state & RFKILL_BLOCK_SW); |
733 | 743 | rfkill_set_block(rfkill, cur); | |
734 | rfkill->suspended = false; | 744 | } |
735 | 745 | ||
736 | rfkill_resume_polling(rfkill); | 746 | rfkill_resume_polling(rfkill); |
737 | 747 | ||