diff mbox series

[RFC,v6,07/11] leds: trigger: netdev: use mutex instead of spinlocks

Message ID 20220503151633.18760-8-ansuelsmth@gmail.com
State Superseded
Headers show
Series Adds support for PHY LEDs with offload triggers | expand

Commit Message

Christian Marangi May 3, 2022, 3:16 p.m. UTC
Some LEDs may require to sleep to apply their hardware rules. Convert to
mutex lock to fix warning for sleeping unser spinlock softirq.

Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
 drivers/leds/trigger/ledtrig-netdev.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

Comments

Andrew Lunn May 5, 2022, 1:10 a.m. UTC | #1
> @@ -400,7 +400,7 @@ static int netdev_trig_notify(struct notifier_block *nb,
>  
>  	cancel_delayed_work_sync(&trigger_data->work);
>  
> -	spin_lock_bh(&trigger_data->lock);
> +	mutex_lock(&trigger_data->lock);

I'm not sure you can convert a spin_lock_bh() in a mutex_lock().

Did you check this? What context is the notifier called in?

    Andrew
Christian Marangi May 5, 2022, 1:29 p.m. UTC | #2
On Thu, May 05, 2022 at 03:10:21AM +0200, Andrew Lunn wrote:
> > @@ -400,7 +400,7 @@ static int netdev_trig_notify(struct notifier_block *nb,
> >  
> >  	cancel_delayed_work_sync(&trigger_data->work);
> >  
> > -	spin_lock_bh(&trigger_data->lock);
> > +	mutex_lock(&trigger_data->lock);
> 
> I'm not sure you can convert a spin_lock_bh() in a mutex_lock().
> 
> Did you check this? What context is the notifier called in?
> 
>     Andrew

I had to do this because qca8k use completion to set the value and that
can sleep... Mhhh any idea how to handle this?
Andrew Lunn May 5, 2022, 2:21 p.m. UTC | #3
On Thu, May 05, 2022 at 03:29:09PM +0200, Ansuel Smith wrote:
> On Thu, May 05, 2022 at 03:10:21AM +0200, Andrew Lunn wrote:
> > > @@ -400,7 +400,7 @@ static int netdev_trig_notify(struct notifier_block *nb,
> > >  
> > >  	cancel_delayed_work_sync(&trigger_data->work);
> > >  
> > > -	spin_lock_bh(&trigger_data->lock);
> > > +	mutex_lock(&trigger_data->lock);
> > 
> > I'm not sure you can convert a spin_lock_bh() in a mutex_lock().
> > 
> > Did you check this? What context is the notifier called in?
> > 
> >     Andrew
> 
> I had to do this because qca8k use completion to set the value and that
> can sleep... Mhhh any idea how to handle this?

First step is to define what the lock is protecting. Once you know
that, you should be able to see what you can do without actually
holding the lock.

Do you need the lock when actually setting the LED?

Or is the lock protecting state information inside trigger_data?

Can you make a copy of what you need from trigger_data while holding
the lock, release it and then set the LED?

Maybe a nested mutex and a spin lock? The spin lock protecting
trigger_data, and the mutex protecting setting the LED?

	      Andrew
Christian Marangi May 5, 2022, 2:43 p.m. UTC | #4
On Thu, May 05, 2022 at 04:21:54PM +0200, Andrew Lunn wrote:
> On Thu, May 05, 2022 at 03:29:09PM +0200, Ansuel Smith wrote:
> > On Thu, May 05, 2022 at 03:10:21AM +0200, Andrew Lunn wrote:
> > > > @@ -400,7 +400,7 @@ static int netdev_trig_notify(struct notifier_block *nb,
> > > >  
> > > >  	cancel_delayed_work_sync(&trigger_data->work);
> > > >  
> > > > -	spin_lock_bh(&trigger_data->lock);
> > > > +	mutex_lock(&trigger_data->lock);
> > > 
> > > I'm not sure you can convert a spin_lock_bh() in a mutex_lock().
> > > 
> > > Did you check this? What context is the notifier called in?
> > > 
> > >     Andrew
> > 
> > I had to do this because qca8k use completion to set the value and that
> > can sleep... Mhhh any idea how to handle this?
> 
> First step is to define what the lock is protecting. Once you know
> that, you should be able to see what you can do without actually
> holding the lock.
>
diff mbox series

Patch

diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
index ed019cb5867c..a471e0cde836 100644
--- a/drivers/leds/trigger/ledtrig-netdev.c
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -20,7 +20,7 @@ 
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/timer.h>
 #include "../leds.h"
 
@@ -38,7 +38,7 @@ 
 
 struct led_netdev_data {
 	enum led_blink_modes blink_mode;
-	spinlock_t lock;
+	struct mutex lock;
 
 	struct delayed_work work;
 	struct notifier_block notifier;
@@ -183,9 +183,9 @@  static ssize_t device_name_show(struct device *dev,
 	struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
 	ssize_t len;
 
-	spin_lock_bh(&trigger_data->lock);
+	mutex_lock(&trigger_data->lock);
 	len = sprintf(buf, "%s\n", trigger_data->device_name);
-	spin_unlock_bh(&trigger_data->lock);
+	mutex_unlock(&trigger_data->lock);
 
 	return len;
 }
@@ -206,7 +206,7 @@  static ssize_t device_name_store(struct device *dev,
 
 	cancel_delayed_work_sync(&trigger_data->work);
 
-	spin_lock_bh(&trigger_data->lock);
+	mutex_lock(&trigger_data->lock);
 
 	if (trigger_data->net_dev) {
 		dev_put(trigger_data->net_dev);
@@ -231,7 +231,7 @@  static ssize_t device_name_store(struct device *dev,
 		trigger_data->net_dev = old_net;
 		memcpy(trigger_data->device_name, old_device_name, IFNAMSIZ);
 
-		spin_unlock_bh(&trigger_data->lock);
+		mutex_unlock(&trigger_data->lock);
 		return -EINVAL;
 	}
 
@@ -242,7 +242,7 @@  static ssize_t device_name_store(struct device *dev,
 	trigger_data->last_activity = 0;
 
 	set_baseline_state(trigger_data);
-	spin_unlock_bh(&trigger_data->lock);
+	mutex_unlock(&trigger_data->lock);
 
 	return size;
 }
@@ -400,7 +400,7 @@  static int netdev_trig_notify(struct notifier_block *nb,
 
 	cancel_delayed_work_sync(&trigger_data->work);
 
-	spin_lock_bh(&trigger_data->lock);
+	mutex_lock(&trigger_data->lock);
 
 	trigger_data->carrier_link_up = false;
 	switch (evt) {
@@ -423,7 +423,7 @@  static int netdev_trig_notify(struct notifier_block *nb,
 
 	set_baseline_state(trigger_data);
 
-	spin_unlock_bh(&trigger_data->lock);
+	mutex_unlock(&trigger_data->lock);
 
 	return NOTIFY_DONE;
 }
@@ -484,7 +484,7 @@  static int netdev_trig_activate(struct led_classdev *led_cdev)
 	if (!trigger_data)
 		return -ENOMEM;
 
-	spin_lock_init(&trigger_data->lock);
+	mutex_init(&trigger_data->lock);
 
 	trigger_data->notifier.notifier_call = netdev_trig_notify;
 	trigger_data->notifier.priority = 10;