Locking in the clk API

Nicolas Pitre nicolas.pitre at linaro.org
Fri Jan 21 16:53:44 EST 2011


On Fri, 21 Jan 2011, Dima Zavin wrote:

> On Thu, Jan 20, 2011 at 8:12 PM, Saravana Kannan <skannan at codeaurora.org> wrote:
> > On 01/20/2011 06:06 PM, Dima Zavin wrote:
> >> Here's a better one.
> >>
> >> Many devices use serial display panels sitting on either MDDI or MIPI
> >> links. The interface clocks need to be on, but they stay in low-power
> >> mode while the display is on. The display controller however does not
> >> need to be on since the serial panels typically have a local
> >> framebuffer that does the idle panel refresh on it's own. When a new
> >> frame comes in to be displayed, you need to clock on the display
> >> controller, DMA the data to the panel, and when it's done turn the
> >> controller off. The clk_enable may or may not happen at irq context,
> >> depending on whether or not you are starting the DMA from a
> >> vsync/tear-effect irq or simply from the screen_update() function. The
> >> clk_disable will most certainly happen from the DMA_DONE irq.
> >
> > Why do we need to turn on the clock in the IRQ? Why not defer it to a
> > workqueue (or whatever is the method of the day to defer work from an IRQ)?
> > The advantage of doing the clk_enable in the IRQ should be negligible
> > compared to the time it takes to do the DMA.
> 
> Because in an interactive system running at 60fps, you only have 16ms
> budget per frame. During the blanking interval when you receive the
> IRQ you need to immediately start the DMA. If you defer to a workqueue
> and schedule you are practically guaranteeing to never run at 60fps
> (more like 30 if you are consistently late, which you would with that
> kind of timing and even a mildly busy system).

And... is there really some advantage to turn the clock off in between 
frames when you're otherwise busy generating them anyway?

I think the fundamental problem with this clock API is that it tries to 
consolidate completely different usages behind the same set of 
interfaces, and that obviously fails.

Some people have clocks that are derived from slow-stabilizing PLLs and 
in that case you do want to use a sleeping API.  Obviously such clocks 
just can't be turned off and on between video frames while in interrupt 
context, hence for such clocks, the hypothetical clk_disable() call must 
do nothing.

So I think that the API must be augmented with more methods, such as:

clk_slow_enable():
  - may sleep
  - may be a no-op if the clk_fast_enable() is supported

clk_fast_enable():
  - may not sleep, used in atomic context
  - may be a no-op if controlling the clock takes time, in which case 
    clk_slow_enable() must have set the clock up entirely

... and similar for clk_slow_disable() and clk_fast_disable().

Then the driver must call clk_slow_enable() when in sleepable context, 
at worst after a successful probe, or better within the open method, or 
even better right before some processing request if possible.  The 
driver must also call clk_fast_enable() right before the hardware is 
kicked into motion.

Then, as soon as the IRQ from the hardware to indicate that the job is 
done is received, you call clk_fast_disable().  At that point you might 
awake a sleeping thread waiting for the resulting data.  In that thread, 
you then call clk_slow_disable() if possible, or from the driver's 
release() method otherwise.

So if you happen to have a fast-enabling clock, you make 
clk_slow_enable() a no op, and do everything in clk_fast_enable().  If 
your clock control sits on some I2C bus then you must do everything from 
clk_slow_enable() and make clk_fast_enable() a no op.  If you do have 
both a PLL and the ability to gate clock signals, then you just 
configure the PLL from clk_slow_enable() keeping the clock signal gated, 
and ungate it only from clk_fast_enable(), to gate it (and only 
gate it) with clk_fast_disable() so it can be quickly be ungated again 
with clk_fast_enable().

This way, the API has a chance of making drivers look generic, and the 
clock providers have more flexibility to hook into the API and optimize 
to the best they can do.

Of course that means that drivers must call both the slow and the fast 
methods eventually, each in their best place.  If a driver has no use 
for clk_fast_enable() then it should simply call it right after 
clk_slow_enable() returns (and a convenience macro could be provided for 
that case).


Nicolas



More information about the linux-arm-kernel mailing list