diff options
Diffstat (limited to 'net/rfkill/core.c')
| -rw-r--r-- | net/rfkill/core.c | 100 | 
1 files changed, 85 insertions, 15 deletions
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 884027f62783..2064c3a35ef8 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -176,6 +176,50 @@ static void rfkill_led_trigger_unregister(struct rfkill *rfkill)  {  	led_trigger_unregister(&rfkill->led_trigger);  } + +static struct led_trigger rfkill_any_led_trigger; +static struct work_struct rfkill_any_work; + +static void rfkill_any_led_trigger_worker(struct work_struct *work) +{ +	enum led_brightness brightness = LED_OFF; +	struct rfkill *rfkill; + +	mutex_lock(&rfkill_global_mutex); +	list_for_each_entry(rfkill, &rfkill_list, node) { +		if (!(rfkill->state & RFKILL_BLOCK_ANY)) { +			brightness = LED_FULL; +			break; +		} +	} +	mutex_unlock(&rfkill_global_mutex); + +	led_trigger_event(&rfkill_any_led_trigger, brightness); +} + +static void rfkill_any_led_trigger_event(void) +{ +	schedule_work(&rfkill_any_work); +} + +static void rfkill_any_led_trigger_activate(struct led_classdev *led_cdev) +{ +	rfkill_any_led_trigger_event(); +} + +static int rfkill_any_led_trigger_register(void) +{ +	INIT_WORK(&rfkill_any_work, rfkill_any_led_trigger_worker); +	rfkill_any_led_trigger.name = "rfkill-any"; +	rfkill_any_led_trigger.activate = rfkill_any_led_trigger_activate; +	return led_trigger_register(&rfkill_any_led_trigger); +} + +static void rfkill_any_led_trigger_unregister(void) +{ +	led_trigger_unregister(&rfkill_any_led_trigger); +	cancel_work_sync(&rfkill_any_work); +}  #else  static void rfkill_led_trigger_event(struct rfkill *rfkill)  { @@ -189,6 +233,19 @@ static inline int rfkill_led_trigger_register(struct rfkill *rfkill)  static inline void rfkill_led_trigger_unregister(struct rfkill *rfkill)  {  } + +static void rfkill_any_led_trigger_event(void) +{ +} + +static int rfkill_any_led_trigger_register(void) +{ +	return 0; +} + +static void rfkill_any_led_trigger_unregister(void) +{ +}  #endif /* CONFIG_RFKILL_LEDS */  static void rfkill_fill_event(struct rfkill_event *ev, struct rfkill *rfkill, @@ -297,6 +354,7 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked)  	spin_unlock_irqrestore(&rfkill->lock, flags);  	rfkill_led_trigger_event(rfkill); +	rfkill_any_led_trigger_event();  	if (prev != curr)  		rfkill_event(rfkill); @@ -477,11 +535,9 @@ bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked)  	spin_unlock_irqrestore(&rfkill->lock, flags);  	rfkill_led_trigger_event(rfkill); +	rfkill_any_led_trigger_event(); -	if (!rfkill->registered) -		return ret; - -	if (prev != blocked) +	if (rfkill->registered && prev != blocked)  		schedule_work(&rfkill->uevent_work);  	return ret; @@ -523,6 +579,7 @@ bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked)  		schedule_work(&rfkill->uevent_work);  	rfkill_led_trigger_event(rfkill); +	rfkill_any_led_trigger_event();  	return blocked;  } @@ -572,6 +629,7 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw)  			schedule_work(&rfkill->uevent_work);  		rfkill_led_trigger_event(rfkill); +		rfkill_any_led_trigger_event();  	}  }  EXPORT_SYMBOL(rfkill_set_states); @@ -988,6 +1046,7 @@ int __must_check rfkill_register(struct rfkill *rfkill)  #endif  	} +	rfkill_any_led_trigger_event();  	rfkill_send_events(rfkill, RFKILL_OP_ADD);  	mutex_unlock(&rfkill_global_mutex); @@ -1020,6 +1079,7 @@ void rfkill_unregister(struct rfkill *rfkill)  	mutex_lock(&rfkill_global_mutex);  	rfkill_send_events(rfkill, RFKILL_OP_DEL);  	list_del_init(&rfkill->node); +	rfkill_any_led_trigger_event();  	mutex_unlock(&rfkill_global_mutex);  	rfkill_led_trigger_unregister(rfkill); @@ -1266,24 +1326,33 @@ static int __init rfkill_init(void)  	error = class_register(&rfkill_class);  	if (error) -		goto out; +		goto error_class;  	error = misc_register(&rfkill_miscdev); -	if (error) { -		class_unregister(&rfkill_class); -		goto out; -	} +	if (error) +		goto error_misc; + +	error = rfkill_any_led_trigger_register(); +	if (error) +		goto error_led_trigger;  #ifdef CONFIG_RFKILL_INPUT  	error = rfkill_handler_init(); -	if (error) { -		misc_deregister(&rfkill_miscdev); -		class_unregister(&rfkill_class); -		goto out; -	} +	if (error) +		goto error_input;  #endif - out: +	return 0; + +#ifdef CONFIG_RFKILL_INPUT +error_input: +	rfkill_any_led_trigger_unregister(); +#endif +error_led_trigger: +	misc_deregister(&rfkill_miscdev); +error_misc: +	class_unregister(&rfkill_class); +error_class:  	return error;  }  subsys_initcall(rfkill_init); @@ -1293,6 +1362,7 @@ static void __exit rfkill_exit(void)  #ifdef CONFIG_RFKILL_INPUT  	rfkill_handler_exit();  #endif +	rfkill_any_led_trigger_unregister();  	misc_deregister(&rfkill_miscdev);  	class_unregister(&rfkill_class);  }  | 
