All of lore.kernel.org
 help / color / mirror / Atom feed
* fakelb: sleeping under a spinlock
@ 2015-07-21 13:52 Lennert Buytenhek
  2015-07-22 17:35 ` Alexander Aring
  0 siblings, 1 reply; 2+ messages in thread
From: Lennert Buytenhek @ 2015-07-21 13:52 UTC (permalink / raw)
  To: linux-wpan, Alexander Aring

Since commit 6fa2cffe8cf9 ("fakelb: move lock out of iteration"),
fakelb is taking a mutex while holding a spinlock.  The patch does
this:

> commit 6fa2cffe8cf937fc10be362a2dcac8a5965f618e
> Author: Alexander Aring <alex.aring@gmail.com>
> Date:   Sun May 17 21:45:04 2015 +0200
> 
>     fakelb: move lock out of iteration
>     
>     The list need to be protected while iteration which is need when other
>     list iterates at the same time over this list.
>     
>     Signed-off-by: Alexander Aring <alex.aring@gmail.com>
>     Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
> 
> diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c
> index c7e7d50..e1c0195 100644
> --- a/drivers/net/ieee802154/fakelb.c
> +++ b/drivers/net/ieee802154/fakelb.c
> @@ -193,9 +193,7 @@ err_reg:
>  
>  static void fakelb_del(struct fakelb_phy *phy)
>  {
> -	write_lock_bh(&fakelb_lock);
>  	list_del(&phy->list);
> -	write_unlock_bh(&fakelb_lock);
>  
>  	ieee802154_unregister_hw(phy->hw);
>  	ieee802154_free_hw(phy->hw);
> @@ -217,8 +215,10 @@ static int fakelb_probe(struct platform_device *pdev)
>  	return 0;
>  
>  err_slave:
> +	write_lock_bh(&fakelb_lock);
>  	list_for_each_entry_safe(phy, tmp, &fakelb_phys, list)
>  		fakelb_del(phy);
> +	write_unlock_bh(&fakelb_lock);
>  	return err;
>  }
>  
> @@ -226,9 +226,10 @@ static int fakelb_remove(struct platform_device *pdev)
>  {
>  	struct fakelb_phy *phy, *temp;
>  
> +	write_lock_bh(&fakelb_lock);
>  	list_for_each_entry_safe(phy, temp, &fakelb_phys, list)
>  		fakelb_del(phy);
> -
> +	write_unlock_bh(&fakelb_lock);
>  	return 0;
>  }

Which causes all of fakelb_del() to run under a spinlock, including
the call to ieee802154_unregister_hw(), which takes a mutex and
flushes a workqueue.

The quick fix is probably to drop the lock for each fakelb_del(phy)
call, i.e. to do something along the lines of:

	write_lock_bh(&fakelb_lock);
	while (!list_empty(&fakelb_phys)) {
		phy = list_first_entry(&fakelb_phys, struct fakelb_phy, list);

		write_unlock_bh(&fakelb_lock);
		fakelb_del(phy);
		write_lock_bh(&fakelb_lock);
	}
	write_unlock_bh(&fakelb_lock);

I also wonder if the locking here can be converted to RCU or something
like that, as the writer side locking happens very very infrequently.

Any thoughts?

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-07-22 17:35 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-21 13:52 fakelb: sleeping under a spinlock Lennert Buytenhek
2015-07-22 17:35 ` Alexander Aring

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.