diff options
Diffstat (limited to 'net/rfkill/rfkill.c')
-rw-r--r-- | net/rfkill/rfkill.c | 62 |
1 files changed, 39 insertions, 23 deletions
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index 7a560b785097..c6f2f388cb72 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c | |||
@@ -130,7 +130,6 @@ static void update_rfkill_state(struct rfkill *rfkill) | |||
130 | 130 | ||
131 | /** | 131 | /** |
132 | * rfkill_toggle_radio - wrapper for toggle_radio hook | 132 | * rfkill_toggle_radio - wrapper for toggle_radio hook |
133 | * | ||
134 | * @rfkill: the rfkill struct to use | 133 | * @rfkill: the rfkill struct to use |
135 | * @force: calls toggle_radio even if cache says it is not needed, | 134 | * @force: calls toggle_radio even if cache says it is not needed, |
136 | * and also makes sure notifications of the state will be | 135 | * and also makes sure notifications of the state will be |
@@ -141,8 +140,8 @@ static void update_rfkill_state(struct rfkill *rfkill) | |||
141 | * calls and handling all the red tape such as issuing notifications | 140 | * calls and handling all the red tape such as issuing notifications |
142 | * if the call is successful. | 141 | * if the call is successful. |
143 | * | 142 | * |
144 | * Note that @force cannot override a (possibly cached) state of | 143 | * Note that the @force parameter cannot override a (possibly cached) |
145 | * RFKILL_STATE_HARD_BLOCKED. Any device making use of | 144 | * state of RFKILL_STATE_HARD_BLOCKED. Any device making use of |
146 | * RFKILL_STATE_HARD_BLOCKED implements either get_state() or | 145 | * RFKILL_STATE_HARD_BLOCKED implements either get_state() or |
147 | * rfkill_force_state(), so the cache either is bypassed or valid. | 146 | * rfkill_force_state(), so the cache either is bypassed or valid. |
148 | * | 147 | * |
@@ -150,7 +149,7 @@ static void update_rfkill_state(struct rfkill *rfkill) | |||
150 | * even if the radio is in RFKILL_STATE_HARD_BLOCKED state, so as to | 149 | * even if the radio is in RFKILL_STATE_HARD_BLOCKED state, so as to |
151 | * give the driver a hint that it should double-BLOCK the transmitter. | 150 | * give the driver a hint that it should double-BLOCK the transmitter. |
152 | * | 151 | * |
153 | * Caller must have aquired rfkill_mutex. | 152 | * Caller must have acquired rfkill->mutex. |
154 | */ | 153 | */ |
155 | static int rfkill_toggle_radio(struct rfkill *rfkill, | 154 | static int rfkill_toggle_radio(struct rfkill *rfkill, |
156 | enum rfkill_state state, | 155 | enum rfkill_state state, |
@@ -200,12 +199,12 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, | |||
200 | 199 | ||
201 | /** | 200 | /** |
202 | * rfkill_switch_all - Toggle state of all switches of given type | 201 | * rfkill_switch_all - Toggle state of all switches of given type |
203 | * @type: type of interfaces to be affeceted | 202 | * @type: type of interfaces to be affected |
204 | * @state: the new state | 203 | * @state: the new state |
205 | * | 204 | * |
206 | * This function toggles state of all switches of given type unless | 205 | * This function toggles the state of all switches of given type, |
207 | * a specific switch is claimed by userspace in which case it is | 206 | * unless a specific switch is claimed by userspace (in which case, |
208 | * left alone. | 207 | * that switch is left alone). |
209 | */ | 208 | */ |
210 | void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) | 209 | void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) |
211 | { | 210 | { |
@@ -216,8 +215,11 @@ void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) | |||
216 | rfkill_states[type] = state; | 215 | rfkill_states[type] = state; |
217 | 216 | ||
218 | list_for_each_entry(rfkill, &rfkill_list, node) { | 217 | list_for_each_entry(rfkill, &rfkill_list, node) { |
219 | if ((!rfkill->user_claim) && (rfkill->type == type)) | 218 | if ((!rfkill->user_claim) && (rfkill->type == type)) { |
219 | mutex_lock(&rfkill->mutex); | ||
220 | rfkill_toggle_radio(rfkill, state, 0); | 220 | rfkill_toggle_radio(rfkill, state, 0); |
221 | mutex_unlock(&rfkill->mutex); | ||
222 | } | ||
221 | } | 223 | } |
222 | 224 | ||
223 | mutex_unlock(&rfkill_mutex); | 225 | mutex_unlock(&rfkill_mutex); |
@@ -228,7 +230,7 @@ EXPORT_SYMBOL(rfkill_switch_all); | |||
228 | * rfkill_epo - emergency power off all transmitters | 230 | * rfkill_epo - emergency power off all transmitters |
229 | * | 231 | * |
230 | * This kicks all rfkill devices to RFKILL_STATE_SOFT_BLOCKED, ignoring | 232 | * This kicks all rfkill devices to RFKILL_STATE_SOFT_BLOCKED, ignoring |
231 | * everything in its path but rfkill_mutex. | 233 | * everything in its path but rfkill_mutex and rfkill->mutex. |
232 | */ | 234 | */ |
233 | void rfkill_epo(void) | 235 | void rfkill_epo(void) |
234 | { | 236 | { |
@@ -236,7 +238,9 @@ void rfkill_epo(void) | |||
236 | 238 | ||
237 | mutex_lock(&rfkill_mutex); | 239 | mutex_lock(&rfkill_mutex); |
238 | list_for_each_entry(rfkill, &rfkill_list, node) { | 240 | list_for_each_entry(rfkill, &rfkill_list, node) { |
241 | mutex_lock(&rfkill->mutex); | ||
239 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); | 242 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); |
243 | mutex_unlock(&rfkill->mutex); | ||
240 | } | 244 | } |
241 | mutex_unlock(&rfkill_mutex); | 245 | mutex_unlock(&rfkill_mutex); |
242 | } | 246 | } |
@@ -252,7 +256,12 @@ EXPORT_SYMBOL_GPL(rfkill_epo); | |||
252 | * a notification by the firmware/hardware of the current *real* | 256 | * a notification by the firmware/hardware of the current *real* |
253 | * state of the radio rfkill switch. | 257 | * state of the radio rfkill switch. |
254 | * | 258 | * |
255 | * It may not be called from an atomic context. | 259 | * Devices which are subject to external changes on their rfkill |
260 | * state (such as those caused by a hardware rfkill line) MUST | ||
261 | * have their driver arrange to call rfkill_force_state() as soon | ||
262 | * as possible after such a change. | ||
263 | * | ||
264 | * This function may not be called from an atomic context. | ||
256 | */ | 265 | */ |
257 | int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state) | 266 | int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state) |
258 | { | 267 | { |
@@ -367,6 +376,9 @@ static ssize_t rfkill_claim_store(struct device *dev, | |||
367 | if (!capable(CAP_NET_ADMIN)) | 376 | if (!capable(CAP_NET_ADMIN)) |
368 | return -EPERM; | 377 | return -EPERM; |
369 | 378 | ||
379 | if (rfkill->user_claim_unsupported) | ||
380 | return -EOPNOTSUPP; | ||
381 | |||
370 | /* | 382 | /* |
371 | * Take the global lock to make sure the kernel is not in | 383 | * Take the global lock to make sure the kernel is not in |
372 | * the middle of rfkill_switch_all | 384 | * the middle of rfkill_switch_all |
@@ -375,19 +387,17 @@ static ssize_t rfkill_claim_store(struct device *dev, | |||
375 | if (error) | 387 | if (error) |
376 | return error; | 388 | return error; |
377 | 389 | ||
378 | if (rfkill->user_claim_unsupported) { | ||
379 | error = -EOPNOTSUPP; | ||
380 | goto out_unlock; | ||
381 | } | ||
382 | if (rfkill->user_claim != claim) { | 390 | if (rfkill->user_claim != claim) { |
383 | if (!claim) | 391 | if (!claim) { |
392 | mutex_lock(&rfkill->mutex); | ||
384 | rfkill_toggle_radio(rfkill, | 393 | rfkill_toggle_radio(rfkill, |
385 | rfkill_states[rfkill->type], | 394 | rfkill_states[rfkill->type], |
386 | 0); | 395 | 0); |
396 | mutex_unlock(&rfkill->mutex); | ||
397 | } | ||
387 | rfkill->user_claim = claim; | 398 | rfkill->user_claim = claim; |
388 | } | 399 | } |
389 | 400 | ||
390 | out_unlock: | ||
391 | mutex_unlock(&rfkill_mutex); | 401 | mutex_unlock(&rfkill_mutex); |
392 | 402 | ||
393 | return error ? error : count; | 403 | return error ? error : count; |
@@ -516,8 +526,11 @@ static void rfkill_remove_switch(struct rfkill *rfkill) | |||
516 | { | 526 | { |
517 | mutex_lock(&rfkill_mutex); | 527 | mutex_lock(&rfkill_mutex); |
518 | list_del_init(&rfkill->node); | 528 | list_del_init(&rfkill->node); |
519 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); | ||
520 | mutex_unlock(&rfkill_mutex); | 529 | mutex_unlock(&rfkill_mutex); |
530 | |||
531 | mutex_lock(&rfkill->mutex); | ||
532 | rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); | ||
533 | mutex_unlock(&rfkill->mutex); | ||
521 | } | 534 | } |
522 | 535 | ||
523 | /** | 536 | /** |
@@ -526,9 +539,10 @@ static void rfkill_remove_switch(struct rfkill *rfkill) | |||
526 | * @type: type of the switch (RFKILL_TYPE_*) | 539 | * @type: type of the switch (RFKILL_TYPE_*) |
527 | * | 540 | * |
528 | * This function should be called by the network driver when it needs | 541 | * This function should be called by the network driver when it needs |
529 | * rfkill structure. Once the structure is allocated the driver shoud | 542 | * rfkill structure. Once the structure is allocated the driver should |
530 | * finish its initialization by setting name, private data, enable_radio | 543 | * finish its initialization by setting the name, private data, enable_radio |
531 | * and disable_radio methods and then register it with rfkill_register(). | 544 | * and disable_radio methods and then register it with rfkill_register(). |
545 | * | ||
532 | * NOTE: If registration fails the structure shoudl be freed by calling | 546 | * NOTE: If registration fails the structure shoudl be freed by calling |
533 | * rfkill_free() otherwise rfkill_unregister() should be used. | 547 | * rfkill_free() otherwise rfkill_unregister() should be used. |
534 | */ | 548 | */ |
@@ -560,7 +574,7 @@ EXPORT_SYMBOL(rfkill_allocate); | |||
560 | * rfkill_free - Mark rfkill structure for deletion | 574 | * rfkill_free - Mark rfkill structure for deletion |
561 | * @rfkill: rfkill structure to be destroyed | 575 | * @rfkill: rfkill structure to be destroyed |
562 | * | 576 | * |
563 | * Decrements reference count of rfkill structure so it is destroyed. | 577 | * Decrements reference count of the rfkill structure so it is destroyed. |
564 | * Note that rfkill_free() should _not_ be called after rfkill_unregister(). | 578 | * Note that rfkill_free() should _not_ be called after rfkill_unregister(). |
565 | */ | 579 | */ |
566 | void rfkill_free(struct rfkill *rfkill) | 580 | void rfkill_free(struct rfkill *rfkill) |
@@ -585,8 +599,10 @@ static void rfkill_led_trigger_register(struct rfkill *rfkill) | |||
585 | static void rfkill_led_trigger_unregister(struct rfkill *rfkill) | 599 | static void rfkill_led_trigger_unregister(struct rfkill *rfkill) |
586 | { | 600 | { |
587 | #ifdef CONFIG_RFKILL_LEDS | 601 | #ifdef CONFIG_RFKILL_LEDS |
588 | if (rfkill->led_trigger.name) | 602 | if (rfkill->led_trigger.name) { |
589 | led_trigger_unregister(&rfkill->led_trigger); | 603 | led_trigger_unregister(&rfkill->led_trigger); |
604 | rfkill->led_trigger.name = NULL; | ||
605 | } | ||
590 | #endif | 606 | #endif |
591 | } | 607 | } |
592 | 608 | ||
@@ -622,8 +638,8 @@ int rfkill_register(struct rfkill *rfkill) | |||
622 | 638 | ||
623 | error = device_add(dev); | 639 | error = device_add(dev); |
624 | if (error) { | 640 | if (error) { |
625 | rfkill_led_trigger_unregister(rfkill); | ||
626 | rfkill_remove_switch(rfkill); | 641 | rfkill_remove_switch(rfkill); |
642 | rfkill_led_trigger_unregister(rfkill); | ||
627 | return error; | 643 | return error; |
628 | } | 644 | } |
629 | 645 | ||