aboutsummaryrefslogtreecommitdiffstats
path: root/net/rfkill
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2008-08-02 14:10:58 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-22 16:29:56 -0400
commit9961920199ec88d6b581d3e38502088935925c04 (patch)
tree38a20b8d4441b4b2a6e033bc9e7a7e6863e72397 /net/rfkill
parent02589f60510030a3c1496e7a8c511e4f674ef5ff (diff)
rfkill: add default global states (v2)
Add a second set of global states, "rfkill_default_states", to track the state that will be used when the first rfkill class of a given type is registered, and also to save "undo" information when rfkill_epo is called. Add a new exported function, rfkill_set_default(), which can be used by platform drivers to restore radio state saved by the platform across reboots or shutdown. Also, fix rfkill_epo to properly update rfkill_states, but still preserve a copy of the state so that we can undo the effect of rfkill_epo later if we want to. Add rfkill_restore_states() to restore rfkill_states from the copy. Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Acked-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/rfkill')
-rw-r--r--net/rfkill/rfkill-input.h1
-rw-r--r--net/rfkill/rfkill.c127
2 files changed, 116 insertions, 12 deletions
diff --git a/net/rfkill/rfkill-input.h b/net/rfkill/rfkill-input.h
index f63d05045685..bbfa646157c6 100644
--- a/net/rfkill/rfkill-input.h
+++ b/net/rfkill/rfkill-input.h
@@ -13,5 +13,6 @@
13 13
14void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state); 14void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state);
15void rfkill_epo(void); 15void rfkill_epo(void);
16void rfkill_restore_states(void);
16 17
17#endif /* __RFKILL_INPUT_H */ 18#endif /* __RFKILL_INPUT_H */
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 1f23de20a85e..b995fa32cf84 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -44,7 +44,13 @@ module_param_named(default_state, rfkill_default_state, uint, 0444);
44MODULE_PARM_DESC(default_state, 44MODULE_PARM_DESC(default_state,
45 "Default initial state for all radio types, 0 = radio off"); 45 "Default initial state for all radio types, 0 = radio off");
46 46
47static enum rfkill_state rfkill_states[RFKILL_TYPE_MAX]; 47struct rfkill_gsw_state {
48 enum rfkill_state current_state;
49 enum rfkill_state default_state;
50};
51
52static struct rfkill_gsw_state rfkill_global_states[RFKILL_TYPE_MAX];
53static unsigned long rfkill_states_lockdflt[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
48 54
49static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list); 55static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list);
50 56
@@ -213,22 +219,22 @@ static int rfkill_toggle_radio(struct rfkill *rfkill,
213} 219}
214 220
215/** 221/**
216 * rfkill_switch_all - Toggle state of all switches of given type 222 * __rfkill_switch_all - Toggle state of all switches of given type
217 * @type: type of interfaces to be affected 223 * @type: type of interfaces to be affected
218 * @state: the new state 224 * @state: the new state
219 * 225 *
220 * This function toggles the state of all switches of given type, 226 * This function toggles the state of all switches of given type,
221 * unless a specific switch is claimed by userspace (in which case, 227 * unless a specific switch is claimed by userspace (in which case,
222 * that switch is left alone) or suspended. 228 * that switch is left alone) or suspended.
229 *
230 * Caller must have acquired rfkill_mutex.
223 */ 231 */
224void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) 232static void __rfkill_switch_all(const enum rfkill_type type,
233 const enum rfkill_state state)
225{ 234{
226 struct rfkill *rfkill; 235 struct rfkill *rfkill;
227 236
228 mutex_lock(&rfkill_mutex); 237 rfkill_global_states[type].current_state = state;
229
230 rfkill_states[type] = state;
231
232 list_for_each_entry(rfkill, &rfkill_list, node) { 238 list_for_each_entry(rfkill, &rfkill_list, node) {
233 if ((!rfkill->user_claim) && (rfkill->type == type)) { 239 if ((!rfkill->user_claim) && (rfkill->type == type)) {
234 mutex_lock(&rfkill->mutex); 240 mutex_lock(&rfkill->mutex);
@@ -236,7 +242,20 @@ void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state)
236 mutex_unlock(&rfkill->mutex); 242 mutex_unlock(&rfkill->mutex);
237 } 243 }
238 } 244 }
245}
239 246
247/**
248 * rfkill_switch_all - Toggle state of all switches of given type
249 * @type: type of interfaces to be affected
250 * @state: the new state
251 *
252 * Acquires rfkill_mutex and calls __rfkill_switch_all(@type, @state).
253 * Please refer to __rfkill_switch_all() for details.
254 */
255void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state)
256{
257 mutex_lock(&rfkill_mutex);
258 __rfkill_switch_all(type, state);
240 mutex_unlock(&rfkill_mutex); 259 mutex_unlock(&rfkill_mutex);
241} 260}
242EXPORT_SYMBOL(rfkill_switch_all); 261EXPORT_SYMBOL(rfkill_switch_all);
@@ -246,10 +265,14 @@ EXPORT_SYMBOL(rfkill_switch_all);
246 * 265 *
247 * This kicks all non-suspended rfkill devices to RFKILL_STATE_SOFT_BLOCKED, 266 * This kicks all non-suspended rfkill devices to RFKILL_STATE_SOFT_BLOCKED,
248 * ignoring everything in its path but rfkill_mutex and rfkill->mutex. 267 * ignoring everything in its path but rfkill_mutex and rfkill->mutex.
268 *
269 * The global state before the EPO is saved and can be restored later
270 * using rfkill_restore_states().
249 */ 271 */
250void rfkill_epo(void) 272void rfkill_epo(void)
251{ 273{
252 struct rfkill *rfkill; 274 struct rfkill *rfkill;
275 int i;
253 276
254 mutex_lock(&rfkill_mutex); 277 mutex_lock(&rfkill_mutex);
255 list_for_each_entry(rfkill, &rfkill_list, node) { 278 list_for_each_entry(rfkill, &rfkill_list, node) {
@@ -257,11 +280,35 @@ void rfkill_epo(void)
257 rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); 280 rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1);
258 mutex_unlock(&rfkill->mutex); 281 mutex_unlock(&rfkill->mutex);
259 } 282 }
283 for (i = 0; i < RFKILL_TYPE_MAX; i++) {
284 rfkill_global_states[i].default_state =
285 rfkill_global_states[i].current_state;
286 rfkill_global_states[i].current_state =
287 RFKILL_STATE_SOFT_BLOCKED;
288 }
260 mutex_unlock(&rfkill_mutex); 289 mutex_unlock(&rfkill_mutex);
261} 290}
262EXPORT_SYMBOL_GPL(rfkill_epo); 291EXPORT_SYMBOL_GPL(rfkill_epo);
263 292
264/** 293/**
294 * rfkill_restore_states - restore global states
295 *
296 * Restore (and sync switches to) the global state from the
297 * states in rfkill_default_states. This can undo the effects of
298 * a call to rfkill_epo().
299 */
300void rfkill_restore_states(void)
301{
302 int i;
303
304 mutex_lock(&rfkill_mutex);
305 for (i = 0; i < RFKILL_TYPE_MAX; i++)
306 __rfkill_switch_all(i, rfkill_global_states[i].default_state);
307 mutex_unlock(&rfkill_mutex);
308}
309EXPORT_SYMBOL_GPL(rfkill_restore_states);
310
311/**
265 * rfkill_force_state - Force the internal rfkill radio state 312 * rfkill_force_state - Force the internal rfkill radio state
266 * @rfkill: pointer to the rfkill class to modify. 313 * @rfkill: pointer to the rfkill class to modify.
267 * @state: the current radio state the class should be forced to. 314 * @state: the current radio state the class should be forced to.
@@ -406,8 +453,8 @@ static ssize_t rfkill_claim_store(struct device *dev,
406 if (!claim) { 453 if (!claim) {
407 mutex_lock(&rfkill->mutex); 454 mutex_lock(&rfkill->mutex);
408 rfkill_toggle_radio(rfkill, 455 rfkill_toggle_radio(rfkill,
409 rfkill_states[rfkill->type], 456 rfkill_global_states[rfkill->type].current_state,
410 0); 457 0);
411 mutex_unlock(&rfkill->mutex); 458 mutex_unlock(&rfkill->mutex);
412 } 459 }
413 rfkill->user_claim = claim; 460 rfkill->user_claim = claim;
@@ -554,7 +601,16 @@ static int rfkill_add_switch(struct rfkill *rfkill)
554 if (error < 0) 601 if (error < 0)
555 goto unlock_out; 602 goto unlock_out;
556 603
557 rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type], 0); 604 if (!error) {
605 /* lock default after first use */
606 set_bit(rfkill->type, rfkill_states_lockdflt);
607 rfkill_global_states[rfkill->type].current_state =
608 rfkill_global_states[rfkill->type].default_state;
609 }
610
611 rfkill_toggle_radio(rfkill,
612 rfkill_global_states[rfkill->type].current_state,
613 0);
558 614
559 list_add_tail(&rfkill->node, &rfkill_list); 615 list_add_tail(&rfkill->node, &rfkill_list);
560 616
@@ -710,6 +766,53 @@ void rfkill_unregister(struct rfkill *rfkill)
710} 766}
711EXPORT_SYMBOL(rfkill_unregister); 767EXPORT_SYMBOL(rfkill_unregister);
712 768
769/**
770 * rfkill_set_default - set initial value for a switch type
771 * @type - the type of switch to set the default state of
772 * @state - the new default state for that group of switches
773 *
774 * Sets the initial state rfkill should use for a given type.
775 * The following initial states are allowed: RFKILL_STATE_SOFT_BLOCKED
776 * and RFKILL_STATE_UNBLOCKED.
777 *
778 * This function is meant to be used by platform drivers for platforms
779 * that can save switch state across power down/reboot.
780 *
781 * The default state for each switch type can be changed exactly once.
782 * After a switch of that type is registered, the default state cannot
783 * be changed anymore. This guards against multiple drivers it the
784 * same platform trying to set the initial switch default state, which
785 * is not allowed.
786 *
787 * Returns -EPERM if the state has already been set once or is in use,
788 * so drivers likely want to either ignore or at most printk(KERN_NOTICE)
789 * if this function returns -EPERM.
790 *
791 * Returns 0 if the new default state was set, or an error if it
792 * could not be set.
793 */
794int rfkill_set_default(enum rfkill_type type, enum rfkill_state state)
795{
796 int error;
797
798 if (type >= RFKILL_TYPE_MAX ||
799 (state != RFKILL_STATE_SOFT_BLOCKED &&
800 state != RFKILL_STATE_UNBLOCKED))
801 return -EINVAL;
802
803 mutex_lock(&rfkill_mutex);
804
805 if (!test_and_set_bit(type, rfkill_states_lockdflt)) {
806 rfkill_global_states[type].default_state = state;
807 error = 0;
808 } else
809 error = -EPERM;
810
811 mutex_unlock(&rfkill_mutex);
812 return error;
813}
814EXPORT_SYMBOL_GPL(rfkill_set_default);
815
713/* 816/*
714 * Rfkill module initialization/deinitialization. 817 * Rfkill module initialization/deinitialization.
715 */ 818 */
@@ -723,8 +826,8 @@ static int __init rfkill_init(void)
723 rfkill_default_state != RFKILL_STATE_UNBLOCKED) 826 rfkill_default_state != RFKILL_STATE_UNBLOCKED)
724 return -EINVAL; 827 return -EINVAL;
725 828
726 for (i = 0; i < ARRAY_SIZE(rfkill_states); i++) 829 for (i = 0; i < RFKILL_TYPE_MAX; i++)
727 rfkill_states[i] = rfkill_default_state; 830 rfkill_global_states[i].default_state = rfkill_default_state;
728 831
729 error = class_register(&rfkill_class); 832 error = class_register(&rfkill_class);
730 if (error) { 833 if (error) {