All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephen Boyd <sboyd@codeaurora.org>
To: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Cc: Mike Turquette <mturquette@linaro.org>,
	Javier Martinez Canillas <javier.martinez@collabora.co.uk>,
	Russell King <linux@arm.linux.org.uk>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 8/8] clk: Add floor and ceiling constraints to clock rates
Date: Fri, 10 Oct 2014 16:55:41 -0700	[thread overview]
Message-ID: <20141010235541.GH5493@codeaurora.org> (raw)
In-Reply-To: <1412866903-6970-9-git-send-email-tomeu.vizoso@collabora.com>

On 10/09, Tomeu Vizoso wrote:
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 4db918a..97cf1a3 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1629,18 +1609,27 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
>  	/* prevent racing with updates to the clock topology */
>  	clk_prepare_lock();
>  
> +	hlist_for_each_entry(clk_user, &clk->per_user_clks, child_node) {
> +		rate = max(rate, clk_user->floor_constraint);
> +	}
> +
> +	hlist_for_each_entry(clk_user, &clk->per_user_clks, child_node) {
> +		if (clk_user->ceiling_constraint > 0)
> +			rate = min(rate, clk_user->ceiling_constraint);
> +	}
> +
>  	/* bail early if nothing to do */
> -	if (rate == clk_get_rate(clk))
> +	if (rate == clk_core_get_rate(clk))

Can we use the nolock variant here? As an aside, this is going to
make my per-clock locking series complicated. I'm not even sure
how the two series will work together. In the per-clock locking
series I was hoping we could check if rate == current rate
without holding any locks. Otherwise we get into a recursive lock
situation. Need to think more about that one.

>  		goto out;
>  
> -	if ((clk->core->flags & CLK_SET_RATE_GATE) &&
> -	    clk->core->prepare_count) {
> +	if ((clk->flags & CLK_SET_RATE_GATE) &&
> +	    clk->prepare_count) {
>  		ret = -EBUSY;
>  		goto out;
>  	}
>  
>  	/* calculate new rates and get the topmost changed clock */
> -	top = clk_calc_new_rates(clk->core, rate);
> +	top = clk_calc_new_rates(clk, rate);
>  	if (!top) {
>  		ret = -EINVAL;
>  		goto out;
> @@ -1664,8 +1653,69 @@ out:
[...]
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	return clk_core_set_rate(clk->core, rate);
> +}
>  EXPORT_SYMBOL_GPL(clk_set_rate);
>  

What about clk_round_rate()? That needs to tell us what the rate
will be if we call clk_set_rate() with whatever value is passed
here. I would expect that the rate aggregation logic would be
somewhere in that codepath but I don't see it.


> +int clk_set_floor_rate(struct clk *clk, unsigned long rate)

We need some documentation for these new functions. I see we have
them in the header, maybe we can copy that here.

> +{
> +	int ret;
> +
> +	clk_prepare_lock();
> +
> +	clk->floor_constraint = rate;

No check for ceiling being less than floor?

> +	ret = clk_set_rate(clk, clk_get_rate(clk));
> +
> +	clk_prepare_unlock();
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_floor_rate);
> +
> +int clk_set_ceiling_rate(struct clk *clk, unsigned long rate)
> +{
> +	int ret;
> +
> +	clk_prepare_lock();

We don't need to grab the lock this early right? Presumably the
caller is doing any required locking so they don't call different
clk APIs for the same clk pointer at the same time. So we should
be able to grab this lock after checking for this error
condition.

> +
> +	WARN(rate > 0 && rate < clk->floor_constraint,
> +	     "clk %s dev %s con %s: new ceiling %lu lower than existing floor %lu\n",
> +	     clk->core->name, clk->dev_id, clk->con_id, rate,
> +	     clk->floor_constraint);
> +
> +	clk->ceiling_constraint = rate;
> +	ret = clk_set_rate(clk, clk_get_rate(clk));

Why not just pass 0 as the second argument? The same comment
applies in the floor function.

> +
> +	clk_prepare_unlock();
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_ceiling_rate);
> +
>  static struct clk_core *clk_core_get_parent(struct clk_core *clk)
>  {
>  	struct clk_core *parent;
> @@ -2143,6 +2195,12 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
>  }
>  EXPORT_SYMBOL_GPL(__clk_register);
>  
> +static void __clk_free_clk(struct clk *clk_user)
> +{
> +	hlist_del(&clk_user->child_node);
> +	kfree(clk_user);

We need to re-evaluate the rate when a user is removed, right?

This leads to another question though. What does it means for a
per-user clock to be disabled and change it's floor or ceiling?
Should that count in the aggregation logic?

So far we haven't required drivers to explicitly call
clk_set_rate() with 0 so they can "drop" their rate request
because there isn't any other user and disabling the clock is
pretty much the same. With multiple users it looks like we're
going to require them to set the floor or ceiling to 0 or INT_MAX
if they want to remove their request. Alternatively we could
track the prepare/unprepare state of the per-user clock and drop
the constraint when that instance is unprepared (or reapply it
when prepared). It's pretty much a semantic difference, but one
benefit would be that we don't have to make two (or three?) calls
to the clock framework if we want to drop the rate constraints
and disable the clock.

> +}
> +
>  /**
>   * clk_register - allocate a new clock, register it and return an opaque cookie
>   * @dev: device that is registering this clock
> diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
> index 1cdb727..025aca2 100644
> --- a/include/linux/clk-private.h
> +++ b/include/linux/clk-private.h
> @@ -50,6 +50,7 @@ struct clk_core {
>  	struct hlist_head	children;
>  	struct hlist_node	child_node;
>  	struct hlist_node	debug_node;
> +	struct hlist_head	per_user_clks;

Can we just call it 'clks'?

>  	unsigned int		notifier_count;
>  #ifdef CONFIG_DEBUG_FS
>  	struct dentry		*dentry;
> @@ -61,6 +62,10 @@ struct clk {
>  	struct clk_core	*core;
>  	const char *dev_id;
>  	const char *con_id;
> +
> +	unsigned long	floor_constraint;
> +	unsigned long	ceiling_constraint;
> +	struct hlist_node child_node;
>  };
>  

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

  reply	other threads:[~2014-10-10 23:55 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-09 15:01 [PATCH v3 0/8] Per-user clock constraints Tomeu Vizoso
2014-10-09 15:01 ` Tomeu Vizoso
2014-10-09 15:01 ` [PATCH v3 1/8] MIPS: Alchemy: Remove direct access to prepare_count field of struct clk Tomeu Vizoso
2014-10-09 20:45   ` Stephen Boyd
2014-10-09 15:01 ` [PATCH v3 2/8] clk: Remove unused function __clk_get_prepare_count Tomeu Vizoso
2014-10-09 15:01 ` [PATCH v3 3/8] clk: Don't try to use a struct clk* after it could have been freed Tomeu Vizoso
2014-10-09 20:27   ` Stephen Boyd
2014-10-09 15:01 ` [PATCH v3 4/8] clk: Don't expose __clk_get_accuracy Tomeu Vizoso
2014-10-09 15:01 ` [PATCH v3 5/8] clk: change clk_debugfs_add_file to take a struct clk_hw Tomeu Vizoso
2014-10-09 15:01 ` [PATCH v3 6/8] clk: Change clk_ops->determine_rate to return a clk_hw as the best parent Tomeu Vizoso
2014-10-09 15:01   ` Tomeu Vizoso
2014-10-09 20:44   ` Stephen Boyd
2014-10-09 20:44     ` Stephen Boyd
2014-10-09 15:01 ` [PATCH v3 7/8] clk: Make clk API return per-user struct clk instances Tomeu Vizoso
2014-10-09 15:01   ` Tomeu Vizoso
2014-10-09 23:22   ` Stephen Boyd
2014-10-09 23:22     ` Stephen Boyd
2014-10-09 23:42     ` Kodiak Furr
2014-10-09 23:42       ` Kodiak Furr
2014-10-09 23:42       ` Kodiak Furr
2014-10-13 14:23     ` Tomeu Vizoso
2014-10-13 14:23       ` Tomeu Vizoso
2014-10-09 15:01 ` [PATCH v3 8/8] clk: Add floor and ceiling constraints to clock rates Tomeu Vizoso
2014-10-10 23:55   ` Stephen Boyd [this message]
2014-10-14 13:27     ` Tomeu Vizoso
2014-10-24  0:54       ` Stephen Boyd

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20141010235541.GH5493@codeaurora.org \
    --to=sboyd@codeaurora.org \
    --cc=javier.martinez@collabora.co.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@arm.linux.org.uk \
    --cc=mturquette@linaro.org \
    --cc=tomeu.vizoso@collabora.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.