diff mbox series

pwm: soften potential loss of precision in compat code

Message ID 20210308092322.24502-1-u.kleine-koenig@pengutronix.de
State Superseded
Headers show
Series pwm: soften potential loss of precision in compat code | expand

Commit Message

Uwe Kleine-König March 8, 2021, 9:23 a.m. UTC
The legacy callback .config() only uses int for period and duty_cycle
while the corresponding values in struct pwm_state are u64. To prevent
that a value bigger than INT_MAX is discarded to a very small value,
explicitly check for big values and pass INT_MAX instead of discarding.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/core.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

Comments

Guru Das Srinagesh March 11, 2021, 9:06 p.m. UTC | #1
On Mon, Mar 08, 2021 at 10:23:22AM +0100, Uwe Kleine-König wrote:
>  		if (state->period != pwm->state.period ||
>  		    state->duty_cycle != pwm->state.duty_cycle) {
> +			int duty_cycle, period;
> +
> +			if (state->period < INT_MAX)
> +				period = state->period;
> +			else
> +				period = INT_MAX;

Using a MIN() macro here might improve readability:
	period = MIN(state->period, INT_MAX);
> +
> +			if (state->duty_cycle < INT_MAX)
> +				duty_cycle = state->duty_cycle;
> +			else
> +				duty_cycle = INT_MAX;

Same here.

> +
>  			err = chip->ops->config(pwm->chip, pwm,
> -						state->duty_cycle,
> -						state->period);
> +						duty_cycle, period);
>  			if (err)
>  				return err;
>  
> -- 
> 2.30.1
>
Uwe Kleine-König March 12, 2021, 7:12 a.m. UTC | #2
On Thu, Mar 11, 2021 at 01:06:39PM -0800, Guru Das Srinagesh wrote:
> On Mon, Mar 08, 2021 at 10:23:22AM +0100, Uwe Kleine-König wrote:
> >  		if (state->period != pwm->state.period ||
> >  		    state->duty_cycle != pwm->state.duty_cycle) {
> > +			int duty_cycle, period;
> > +
> > +			if (state->period < INT_MAX)
> > +				period = state->period;
> > +			else
> > +				period = INT_MAX;
> 
> Using a MIN() macro here might improve readability:
> 	period = MIN(state->period, INT_MAX);

Which MIN macro. There are 17 defined in the kernel and none of them in
a header that could be sensibly included by this code.

There are some helpers in <linux/minmax.h> which would result in:

	period = min_t(u64, state->period, INT_MAX)

or

	period = min(state->period, (u64)INT_MAX);

. I don't feel strong here, my initial variant needs more vertical space
but might be a tad easier to understand. In retrospect I'd say that
adding a comment would be more imporant than how to actually calculate
the value, something like:

	/*
	 * The legacy callbacks use only (signed!) int for period and
	 * duty_cycle compared to u64 in struct pwm_state. So clamp the
	 * values to INT_MAX.
	 */

Sounds sensible?

Best regards
Uwe
Guru Das Srinagesh March 15, 2021, 1:53 a.m. UTC | #3
On Fri, Mar 12, 2021 at 08:12:33AM +0100, Uwe Kleine-König wrote:
> On Thu, Mar 11, 2021 at 01:06:39PM -0800, Guru Das Srinagesh wrote:
> > On Mon, Mar 08, 2021 at 10:23:22AM +0100, Uwe Kleine-König wrote:
> > >  		if (state->period != pwm->state.period ||
> > >  		    state->duty_cycle != pwm->state.duty_cycle) {
> > > +			int duty_cycle, period;
> > > +
> > > +			if (state->period < INT_MAX)
> > > +				period = state->period;
> > > +			else
> > > +				period = INT_MAX;
> > 
> > Using a MIN() macro here might improve readability:
> > 	period = MIN(state->period, INT_MAX);
> 
> Which MIN macro. There are 17 defined in the kernel and none of them in
> a header that could be sensibly included by this code.
> 
> There are some helpers in <linux/minmax.h> which would result in:
> 
> 	period = min_t(u64, state->period, INT_MAX)
> 
> or
> 
> 	period = min(state->period, (u64)INT_MAX);
> 
> . I don't feel strong here, my initial variant needs more vertical space
> but might be a tad easier to understand. In retrospect I'd say that
> adding a comment would be more imporant than how to actually calculate
> the value, something like:
> 
> 	/*
> 	 * The legacy callbacks use only (signed!) int for period and
> 	 * duty_cycle compared to u64 in struct pwm_state. So clamp the
> 	 * values to INT_MAX.
> 	 */
> 
> Sounds sensible?

Yes, I agree.

Guru Das.
diff mbox series

Patch

diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index c4d5c0667137..4058d3c86a45 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -599,9 +599,20 @@  int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
 
 		if (state->period != pwm->state.period ||
 		    state->duty_cycle != pwm->state.duty_cycle) {
+			int duty_cycle, period;
+
+			if (state->period < INT_MAX)
+				period = state->period;
+			else
+				period = INT_MAX;
+
+			if (state->duty_cycle < INT_MAX)
+				duty_cycle = state->duty_cycle;
+			else
+				duty_cycle = INT_MAX;
+
 			err = chip->ops->config(pwm->chip, pwm,
-						state->duty_cycle,
-						state->period);
+						duty_cycle, period);
 			if (err)
 				return err;