• Mike Turquette's avatar
    clk: allow reentrant calls into the clk framework · 533ddeb1
    Mike Turquette authored
    Reentrancy into the clock framework is necessary for clock operations
    that result in nested calls to the clk api.  A common example is a clock
    that is prepared via an i2c transaction, such as a clock inside of a
    discrete audio chip or a power management IC.  The i2c subsystem itself
    will use the clk api resulting in a deadlock:
    
    clk_prepare(audio_clk)
    	i2c_transfer(..)
    		clk_prepare(i2c_controller_clk)
    
    The ability to reenter the clock framework prevents this deadlock.
    
    Other use cases exist such as allowing .set_rate callbacks to call
    clk_set_parent to achieve the best rate, or to save power in certain
    configurations.  Yet another example is performing pinctrl operations
    from a clk_ops callback.  Calls into the pinctrl subsystem may call
    clk_{un}prepare on an unrelated clock.  Allowing for nested calls to
    reenter the clock framework enables both of these use cases.
    
    Reentrancy is implemented by two global pointers that track the owner
    currently holding a global lock.  One pointer tracks the owner during
    sleepable, mutex-protected operations and the other one tracks the owner
    during non-interruptible, spinlock-protected operations.
    
    When the clk framework is entered we try to hold the global lock.  If it
    is held we compare the current task against the current owner; a match
    implies a nested call and we reenter.  If the values do not match then
    we block on the lock until it is released.
    Signed-off-by: default avatarMike Turquette <mturquette@linaro.org>
    Cc: Rajagopal Venkat <rajagopal.venkat@linaro.org>
    Cc: David Brown <davidb@codeaurora.org>
    Tested-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
    Reviewed-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Reviewed-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
    533ddeb1
clk.c 48.3 KB