Re: [PATCH 09/19] clk: divider: check validity of flags when a table is provided

Benoît Monin
2025-09-25T11:55:31Z

On Saturday, 20 September 2025 at 07:24:36 CEST, Stephen Boyd wrote:
> Quoting Benoît Monin (2025-09-03 05:47:16)
> > If any of the flag CLK_DIVIDER_ONE_BASED, CLK_DIVIDER_POWER_OF_TWO,
> > CLK_DIVIDER_MAX_AT_ZERO or CLK_DIVIDER_EVEN_INTEGERS is set, the divider
> > table will be ignored in _get_div and _get_val. This can lead to subtle
> > bug when a clock is registered with some flags and an optional table,
> > with the clock rate and register value being computed with the wrong
> > type of conversion.
> >
> > Prevent this by refusing to register a divider with both the flag and
> > the table set.
> >
> > Signed-off-by: Benoît Monin <benoit.monin@bootlin.com>
> > ---
> > drivers/clk/clk-divider.c | 7 +++++++
> > 1 file changed, 7 insertions(+)
> >
> > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> > index 8e8f87024e76625f348f1d66c15a7a938fa0c4db..b4861d519bac2121dd015d094c94a5fee2480148 100644
> > --- a/drivers/clk/clk-divider.c
> > +++ b/drivers/clk/clk-divider.c
> > @@ -561,6 +561,13 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev,
> > return ERR_PTR(-EINVAL);
> > }
> > }
>
> Nitpick: Prefer a newline here.
>
> > + if (table && (clk_divider_flags & (CLK_DIVIDER_ONE_BASED |
> > + CLK_DIVIDER_POWER_OF_TWO |
> > + CLK_DIVIDER_MAX_AT_ZERO |
> > + CLK_DIVIDER_EVEN_INTEGERS))) {
> > + pr_warn("divider table and flags incompatible\n");
>
> This pr_warn() (and the one above this one) are not very helpful because
> we don't know which clk is the problem. We also don't know if this is
> going to cause boot failures for devices out there that have this flag
> set and a table. Were all drivers audited?
>
> I wonder if we can check this condition at compile time with some sort
> of test on the clk_divider_flags expression to see if it is a compile
> time constant along with the table pointer being a compile time constant
> as well that isn't NULL?
>
I did check all the in-kernel callers and none got this wrong, passing
either the flag or the table, as I ended up doing in clk-eyeq. I'll see if
I can come up with a compile time check otherwise maybe just a note in
clk-provider.h where struct clk_divider is documented could be enough.

> > + return ERR_PTR(-EINVAL);
> > + }
>

Best regards,
--
Benoît Monin, Bootlin
Embedded Linux and Kernel engineering