lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 03 Jul 2023 09:17:43 +0200
From:   Frank Oltmanns <frank@...manns.dev>
To:     Frank Oltmanns <frank@...manns.dev>
Cc:     Maxime Ripard <maxime@...no.tech>,
        Michael Turquette <mturquette@...libre.com>,
        Stephen Boyd <sboyd@...nel.org>, Chen-Yu Tsai <wens@...e.org>,
        Jernej Skrabec <jernej.skrabec@...il.com>,
        Samuel Holland <samuel@...lland.org>,
        Andre Przywara <andre.przywara@....com>,
        Roman Beranek <me@...y.cz>, linux-clk@...r.kernel.org,
        linux-arm-kernel@...ts.infradead.org, linux-sunxi@...ts.linux.dev,
        linux-kernel@...r.kernel.org
Subject: Re: [PATCH v3 5/8] clk: sunxi-ng: nkm: Support finding closest rate


On 2023-07-02 at 19:55:24 +0200, Frank Oltmanns <frank@...manns.dev> wrote:
> When finding the best rate for a NKM clock, consider rates that are
> higher than the requested rate, if the CCU_FEATURE_CLOSEST_RATE flag is
> set.
>
> Accommodate ccu_mux_helper_determine_rate to this change.
>
> Signed-off-by: Frank Oltmanns <frank@...manns.dev>
> ---
>  drivers/clk/sunxi-ng/ccu_mux.c | 23 +++++++++++++++-----
>  drivers/clk/sunxi-ng/ccu_nkm.c | 48 +++++++++++++++++++++++++++++++-----------
>  2 files changed, 54 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
> index 1d557e323169..8594d6a4addd 100644
> --- a/drivers/clk/sunxi-ng/ccu_mux.c
> +++ b/drivers/clk/sunxi-ng/ccu_mux.c
> @@ -113,7 +113,7 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common,
>  	}
>
>  	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
> -		unsigned long tmp_rate, parent_rate;
> +		unsigned long tmp_rate, parent_rate, best_diff = ULONG_MAX;
>  		struct clk_hw *parent;
>
>  		parent = clk_hw_get_parent_by_index(hw, i);
> @@ -139,10 +139,23 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common,
>  			goto out;
>  		}
>
> -		if ((req->rate - tmp_rate) < (req->rate - best_rate)) {
> -			best_rate = tmp_rate;
> -			best_parent_rate = parent_rate;
> -			best_parent = parent;
> +		if (common->features & CCU_FEATURE_CLOSEST_RATE) {
> +			unsigned long tmp_diff = req->rate > tmp_rate ?
> +						 req->rate - tmp_rate :
> +						 tmp_rate - req->rate;
> +
> +			if (tmp_diff < best_diff) {
> +				best_rate = tmp_rate;
> +				best_parent_rate = parent_rate;
> +				best_parent = parent;
> +				best_diff = tmp_diff;
> +			}
> +		} else {
> +			if ((req->rate - tmp_rate) < (req->rate - best_rate)) {
> +				best_rate = tmp_rate;
> +				best_parent_rate = parent_rate;
> +				best_parent = parent;
> +			}
>  		}
>  	}
>
> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
> index d83843e69c25..36d9e987e4d8 100644
> --- a/drivers/clk/sunxi-ng/ccu_nkm.c
> +++ b/drivers/clk/sunxi-ng/ccu_nkm.c
> @@ -18,9 +18,11 @@ struct _ccu_nkm {
>  };
>
>  static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, unsigned long rate,
> -						       struct _ccu_nkm *nkm, struct clk_hw *phw)
> +						       struct _ccu_nkm *nkm, struct clk_hw *phw,
> +						       unsigned long features)
>  {
> -	unsigned long best_rate = 0, best_parent_rate = *parent, tmp_parent = *parent;
> +	unsigned long best_rate = 0, best_parent_rate = 0, tmp_parent = *parent;
> +	unsigned long best_diff = ULONG_MAX;
>  	unsigned long best_n = 0, best_k = 0, best_m = 0;
>  	unsigned long _n, _k, _m;
>
> @@ -28,16 +30,26 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, un
>  		for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
>  			for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
>  				unsigned long tmp_rate;
> +				unsigned long tmp_diff;
>
>  				tmp_parent = clk_hw_round_rate(phw, rate * _m / (_n * _k));
>
>  				tmp_rate = tmp_parent * _n * _k / _m;
> -				if (tmp_rate > rate)
> -					continue;
>
> -				if ((rate - tmp_rate) < (rate - best_rate)) {
> +				if (features & CCU_FEATURE_CLOSEST_RATE) {
> +					tmp_diff = rate > tmp_rate ?
> +						   rate - tmp_rate :
> +						   tmp_rate - rate;
> +				} else {
> +					if (tmp_rate > rate)
> +						continue;
> +					tmp_diff = rate - tmp_diff;

Sorry, this should of course be tmp_diff = rate - tmp_rate. I'll fix
that in v4. Also I'll do tests on my phone where
CCU_FEATURE_CLOSEST_RATE is not set (i.e., without PATCH 8), so see if
it replicates the old behaviour. I'll also look into adding kunit tests,
so that this doesn't happen again. I'm not sure if this is feasible, but
I'll ask here for advise, if/when I encounter obstacles.

Best regards,
  Frank

> +				}
> +
> +				if (tmp_diff < best_diff) {
>  					best_rate = tmp_rate;
>  					best_parent_rate = tmp_parent;
> +					best_diff = tmp_diff;
>  					best_n = _n;
>  					best_k = _k;
>  					best_m = _m;
> @@ -56,9 +68,10 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(unsigned long *parent, un
>  }
>
>  static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate,
> -				       struct _ccu_nkm *nkm)
> +				       struct _ccu_nkm *nkm, unsigned long features)
>  {
>  	unsigned long best_rate = 0;
> +	unsigned long best_diff = ULONG_MAX;
>  	unsigned long best_n = 0, best_k = 0, best_m = 0;
>  	unsigned long _n, _k, _m;
>
> @@ -66,13 +79,23 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate,
>  		for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
>  			for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
>  				unsigned long tmp_rate;
> +				unsigned long tmp_diff;
>
>  				tmp_rate = parent * _n * _k / _m;
>
> -				if (tmp_rate > rate)
> -					continue;
> -				if ((rate - tmp_rate) < (rate - best_rate)) {
> +				if (features & CCU_FEATURE_CLOSEST_RATE) {
> +					tmp_diff = rate > tmp_rate ?
> +						   rate - tmp_rate :
> +						   tmp_rate - rate;
> +				} else {
> +					if (tmp_rate > rate)
> +						continue;
> +					tmp_diff = rate - tmp_diff;
> +				}
> +
> +				if (tmp_diff < best_diff) {
>  					best_rate = tmp_rate;
> +					best_diff = tmp_diff;
>  					best_n = _n;
>  					best_k = _k;
>  					best_m = _m;
> @@ -164,9 +187,10 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
>  		rate *= nkm->fixed_post_div;
>
>  	if (!clk_hw_can_set_rate_parent(&nkm->common.hw))
> -		rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm);
> +		rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm, nkm->common.features);
>  	else
> -		rate = ccu_nkm_find_best_with_parent_adj(parent_rate, rate, &_nkm, parent_hw);
> +		rate = ccu_nkm_find_best_with_parent_adj(parent_rate, rate, &_nkm, parent_hw,
> +							 nkm->common.features);
>
>  	if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
>  		rate /= nkm->fixed_post_div;
> @@ -201,7 +225,7 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
>  	_nkm.min_m = 1;
>  	_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
>
> -	ccu_nkm_find_best(&parent_rate, rate, &_nkm);
> +	ccu_nkm_find_best(parent_rate, rate, &_nkm, nkm->common.features);
>
>  	spin_lock_irqsave(nkm->common.lock, flags);

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ