Locking in the clk API

Russell King - ARM Linux linux at arm.linux.org.uk
Tue Jan 11 05:47:09 EST 2011


On Tue, Jan 11, 2011 at 11:39:29AM +0100, Uwe Kleine-König wrote:
> A quick look into Digi's BSP (digiEL-5.0) shows they implemented
> something I suggested earlier here:
> 
> 	static int clk_enable_haslocknchange(struct clk *clk)
> 	{
> 		int ret = 0;
> 
> 		assert_spin_locked(&clk_lock);
> 		BUG_ON(!test_bit(CLK_FLAG_CHANGESTATE, &clk->flags));
> 
> 		if (clk->usage++ == 0) {
> 			if (clk->parent) {
> 				ret = clk_enable_haslock(clk->parent);
> 				if (ret)
> 					goto err_enable_parent;
> 			}
> 
> 			spin_unlock(&clk_lock);
> 
> 			if (clk->endisable)
> 				ret = clk->endisable(clk, 1);
> 
> 			spin_lock(&clk_lock);
> 
> 			if (ret) {
> 				clk_disable_parent_haslock(clk);
> 	err_enable_parent:
> 				clk->usage = 0;
> 			}
> 		}
> 
> 		return ret;
> 	}
> 
> 	static int clk_enable_haslock(struct clk *clk)
> 	{
> 		int ret;
> 		assert_spin_locked(&clk_lock);
> 		if (__test_and_set_bit(CLK_FLAG_CHANGESTATE, &clk->flags))
> 			return -EBUSY;
> 
> 		ret = clk_enable_haslocknchange(clk);
> 
> 		clear_bit(CLK_FLAG_CHANGESTATE, &clk->flags);
> 
> 		return ret;
> 	}
> 
> 	int clk_enable(struct clk *clk)
> 	{
> 		...
> 		spin_lock_irqsave(&clk_lock, flags);
> 		ret = clk_enable_haslock(clk);
> 		spin_unlock_irqrestore(&clk_lock, flags);
> 		return ret;
> 	}
> 
> 
> I think the idea is nice.  At least it allows with a single lock to
> implement both, sleeping and atomic clks without the need to mark the
> atomicity in a global flag.

It doesn't.  clk_enable() here can still end up trying to sleep when
it's called from IRQ context - the code doesn't solve that.  All it
means is that the intermediate code doesn't care whether clk->endisable
ends up sleeping or not.

What it does do is return -EBUSY if there are two concurrent attempts
to enable the same clock.  How many drivers today deal sanely with
such an error from clk_enable(), and how many would just fail their
probe() call on such an occurance?



More information about the linux-arm-kernel mailing list