diff options
Diffstat (limited to 'net/rfkill/rfkill.c')
-rw-r--r-- | net/rfkill/rfkill.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index fdf87d2ab25e..e348eab756f3 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c | |||
@@ -51,6 +51,7 @@ struct rfkill_gsw_state { | |||
51 | 51 | ||
52 | static struct rfkill_gsw_state rfkill_global_states[RFKILL_TYPE_MAX]; | 52 | static struct rfkill_gsw_state rfkill_global_states[RFKILL_TYPE_MAX]; |
53 | static unsigned long rfkill_states_lockdflt[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; | 53 | static unsigned long rfkill_states_lockdflt[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; |
54 | static bool rfkill_epo_lock_active; | ||
54 | 55 | ||
55 | static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list); | 56 | static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list); |
56 | 57 | ||
@@ -264,11 +265,14 @@ static void __rfkill_switch_all(const enum rfkill_type type, | |||
264 | * | 265 | * |
265 | * Acquires rfkill_global_mutex and calls __rfkill_switch_all(@type, @state). | 266 | * Acquires rfkill_global_mutex and calls __rfkill_switch_all(@type, @state). |
266 | * Please refer to __rfkill_switch_all() for details. | 267 | * Please refer to __rfkill_switch_all() for details. |
268 | * | ||
269 | * Does nothing if the EPO lock is active. | ||
267 | */ | 270 | */ |
268 | void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) | 271 | void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) |
269 | { | 272 | { |
270 | mutex_lock(&rfkill_global_mutex); | 273 | mutex_lock(&rfkill_global_mutex); |
271 | __rfkill_switch_all(type, state); | 274 | if (!rfkill_epo_lock_active) |
275 | __rfkill_switch_all(type, state); | ||
272 | mutex_unlock(&rfkill_global_mutex); | 276 | mutex_unlock(&rfkill_global_mutex); |
273 | } | 277 | } |
274 | EXPORT_SYMBOL(rfkill_switch_all); | 278 | EXPORT_SYMBOL(rfkill_switch_all); |
@@ -289,6 +293,7 @@ void rfkill_epo(void) | |||
289 | 293 | ||
290 | mutex_lock(&rfkill_global_mutex); | 294 | mutex_lock(&rfkill_global_mutex); |
291 | 295 | ||
296 | rfkill_epo_lock_active = true; | ||
292 | list_for_each_entry(rfkill, &rfkill_list, node) { | 297 | list_for_each_entry(rfkill, &rfkill_list, node) { |
293 | mutex_lock(&rfkill->mutex); | 298 | mutex_lock(&rfkill->mutex); |
294 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); | 299 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); |
@@ -317,6 +322,7 @@ void rfkill_restore_states(void) | |||
317 | 322 | ||
318 | mutex_lock(&rfkill_global_mutex); | 323 | mutex_lock(&rfkill_global_mutex); |
319 | 324 | ||
325 | rfkill_epo_lock_active = false; | ||
320 | for (i = 0; i < RFKILL_TYPE_MAX; i++) | 326 | for (i = 0; i < RFKILL_TYPE_MAX; i++) |
321 | __rfkill_switch_all(i, rfkill_global_states[i].default_state); | 327 | __rfkill_switch_all(i, rfkill_global_states[i].default_state); |
322 | mutex_unlock(&rfkill_global_mutex); | 328 | mutex_unlock(&rfkill_global_mutex); |
@@ -324,6 +330,35 @@ void rfkill_restore_states(void) | |||
324 | EXPORT_SYMBOL_GPL(rfkill_restore_states); | 330 | EXPORT_SYMBOL_GPL(rfkill_restore_states); |
325 | 331 | ||
326 | /** | 332 | /** |
333 | * rfkill_remove_epo_lock - unlock state changes | ||
334 | * | ||
335 | * Used by rfkill-input manually unlock state changes, when | ||
336 | * the EPO switch is deactivated. | ||
337 | */ | ||
338 | void rfkill_remove_epo_lock(void) | ||
339 | { | ||
340 | mutex_lock(&rfkill_global_mutex); | ||
341 | rfkill_epo_lock_active = false; | ||
342 | mutex_unlock(&rfkill_global_mutex); | ||
343 | } | ||
344 | EXPORT_SYMBOL_GPL(rfkill_remove_epo_lock); | ||
345 | |||
346 | /** | ||
347 | * rfkill_is_epo_lock_active - returns true EPO is active | ||
348 | * | ||
349 | * Returns 0 (false) if there is NOT an active EPO contidion, | ||
350 | * and 1 (true) if there is an active EPO contition, which | ||
351 | * locks all radios in one of the BLOCKED states. | ||
352 | * | ||
353 | * Can be called in atomic context. | ||
354 | */ | ||
355 | bool rfkill_is_epo_lock_active(void) | ||
356 | { | ||
357 | return rfkill_epo_lock_active; | ||
358 | } | ||
359 | EXPORT_SYMBOL_GPL(rfkill_is_epo_lock_active); | ||
360 | |||
361 | /** | ||
327 | * rfkill_get_global_state - returns global state for a type | 362 | * rfkill_get_global_state - returns global state for a type |
328 | * @type: the type to get the global state of | 363 | * @type: the type to get the global state of |
329 | * | 364 | * |
@@ -447,7 +482,12 @@ static ssize_t rfkill_state_store(struct device *dev, | |||
447 | error = mutex_lock_killable(&rfkill->mutex); | 482 | error = mutex_lock_killable(&rfkill->mutex); |
448 | if (error) | 483 | if (error) |
449 | return error; | 484 | return error; |
450 | error = rfkill_toggle_radio(rfkill, state, 0); | 485 | |
486 | if (!rfkill_epo_lock_active) | ||
487 | error = rfkill_toggle_radio(rfkill, state, 0); | ||
488 | else | ||
489 | error = -EPERM; | ||
490 | |||
451 | mutex_unlock(&rfkill->mutex); | 491 | mutex_unlock(&rfkill->mutex); |
452 | 492 | ||
453 | return error ? error : count; | 493 | return error ? error : count; |
@@ -491,7 +531,7 @@ static ssize_t rfkill_claim_store(struct device *dev, | |||
491 | return error; | 531 | return error; |
492 | 532 | ||
493 | if (rfkill->user_claim != claim) { | 533 | if (rfkill->user_claim != claim) { |
494 | if (!claim) { | 534 | if (!claim && !rfkill_epo_lock_active) { |
495 | mutex_lock(&rfkill->mutex); | 535 | mutex_lock(&rfkill->mutex); |
496 | rfkill_toggle_radio(rfkill, | 536 | rfkill_toggle_radio(rfkill, |
497 | rfkill_global_states[rfkill->type].current_state, | 537 | rfkill_global_states[rfkill->type].current_state, |