diff options
Diffstat (limited to 'drivers/leds/led-triggers.c')
| -rw-r--r-- | drivers/leds/led-triggers.c | 41 | 
1 files changed, 21 insertions, 20 deletions
| diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 4e7b78a84149..072491d3e17b 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -157,7 +157,6 @@ EXPORT_SYMBOL_GPL(led_trigger_read);  /* Caller must ensure led_cdev->trigger_lock held */  int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)  { -	unsigned long flags;  	char *event = NULL;  	char *envp[2];  	const char *name; @@ -171,10 +170,13 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)  	/* Remove any existing trigger */  	if (led_cdev->trigger) { -		write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); -		list_del(&led_cdev->trig_list); -		write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, -			flags); +		spin_lock(&led_cdev->trigger->leddev_list_lock); +		list_del_rcu(&led_cdev->trig_list); +		spin_unlock(&led_cdev->trigger->leddev_list_lock); + +		/* ensure it's no longer visible on the led_cdevs list */ +		synchronize_rcu(); +  		cancel_work_sync(&led_cdev->set_brightness_work);  		led_stop_software_blink(led_cdev);  		if (led_cdev->trigger->deactivate) @@ -186,9 +188,9 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)  		led_set_brightness(led_cdev, LED_OFF);  	}  	if (trig) { -		write_lock_irqsave(&trig->leddev_list_lock, flags); -		list_add_tail(&led_cdev->trig_list, &trig->led_cdevs); -		write_unlock_irqrestore(&trig->leddev_list_lock, flags); +		spin_lock(&trig->leddev_list_lock); +		list_add_tail_rcu(&led_cdev->trig_list, &trig->led_cdevs); +		spin_unlock(&trig->leddev_list_lock);  		led_cdev->trigger = trig;  		if (trig->activate) @@ -223,9 +225,10 @@ err_add_groups:  		trig->deactivate(led_cdev);  err_activate: -	write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); -	list_del(&led_cdev->trig_list); -	write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags); +	spin_lock(&led_cdev->trigger->leddev_list_lock); +	list_del_rcu(&led_cdev->trig_list); +	spin_unlock(&led_cdev->trigger->leddev_list_lock); +	synchronize_rcu();  	led_cdev->trigger = NULL;  	led_cdev->trigger_data = NULL;  	led_set_brightness(led_cdev, LED_OFF); @@ -285,7 +288,7 @@ int led_trigger_register(struct led_trigger *trig)  	struct led_classdev *led_cdev;  	struct led_trigger *_trig; -	rwlock_init(&trig->leddev_list_lock); +	spin_lock_init(&trig->leddev_list_lock);  	INIT_LIST_HEAD(&trig->led_cdevs);  	down_write(&triggers_list_lock); @@ -378,15 +381,14 @@ void led_trigger_event(struct led_trigger *trig,  			enum led_brightness brightness)  {  	struct led_classdev *led_cdev; -	unsigned long flags;  	if (!trig)  		return; -	read_lock_irqsave(&trig->leddev_list_lock, flags); -	list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) +	rcu_read_lock(); +	list_for_each_entry_rcu(led_cdev, &trig->led_cdevs, trig_list)  		led_set_brightness(led_cdev, brightness); -	read_unlock_irqrestore(&trig->leddev_list_lock, flags); +	rcu_read_unlock();  }  EXPORT_SYMBOL_GPL(led_trigger_event); @@ -397,20 +399,19 @@ static void led_trigger_blink_setup(struct led_trigger *trig,  			     int invert)  {  	struct led_classdev *led_cdev; -	unsigned long flags;  	if (!trig)  		return; -	read_lock_irqsave(&trig->leddev_list_lock, flags); -	list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) { +	rcu_read_lock(); +	list_for_each_entry_rcu(led_cdev, &trig->led_cdevs, trig_list) {  		if (oneshot)  			led_blink_set_oneshot(led_cdev, delay_on, delay_off,  					      invert);  		else  			led_blink_set(led_cdev, delay_on, delay_off);  	} -	read_unlock_irqrestore(&trig->leddev_list_lock, flags); +	rcu_read_unlock();  }  void led_trigger_blink(struct led_trigger *trig, | 
