Commit ae52f797 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pwm/for-6.3-rc6' of...

Merge tag 'pwm/for-6.3-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm

Pull pwm fixes from Thierry Reding:
 "These are some fixes to make sure the PWM state structure is always
  initialized to a known state.

  Prior to this it could happen in some situations that random data from
  the stack would leak into the data structure and cause subtle bugs"

* tag 'pwm/for-6.3-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm:
  pwm: Zero-initialize the pwm_state passed to driver's .get_state()
  pwm: meson: Explicitly set .polarity in .get_state()
  pwm: sprd: Explicitly set .polarity in .get_state()
  pwm: iqs620a: Explicitly set .polarity in .get_state()
  pwm: cros-ec: Explicitly set .polarity in .get_state()
  pwm: hibvt: Explicitly set .polarity in .get_state()
parents ac6c0433 1271a7b9
......@@ -115,7 +115,14 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label)
}
if (pwm->chip->ops->get_state) {
struct pwm_state state;
/*
* Zero-initialize state because most drivers are unaware of
* .usage_power. The other members of state are supposed to be
* set by lowlevel drivers. We still initialize the whole
* structure for simplicity even though this might paper over
* faulty implementations of .get_state().
*/
struct pwm_state state = { 0, };
err = pwm->chip->ops->get_state(pwm->chip, pwm, &state);
trace_pwm_get(pwm, &state, err);
......@@ -448,7 +455,7 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
{
struct pwm_state *last = &pwm->last;
struct pwm_chip *chip = pwm->chip;
struct pwm_state s1, s2;
struct pwm_state s1 = { 0 }, s2 = { 0 };
int err;
if (!IS_ENABLED(CONFIG_PWM_DEBUG))
......@@ -530,6 +537,7 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
return;
}
*last = (struct pwm_state){ 0 };
err = chip->ops->get_state(chip, pwm, last);
trace_pwm_get(pwm, last, err);
if (err)
......
......@@ -198,6 +198,7 @@ static int cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->enabled = (ret > 0);
state->period = EC_PWM_MAX_DUTY;
state->polarity = PWM_POLARITY_NORMAL;
/*
* Note that "disabled" and "duty cycle == 0" are treated the same. If
......
......@@ -146,6 +146,7 @@ static int hibvt_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
value = readl(base + PWM_CTRL_ADDR(pwm->hwpwm));
state->enabled = (PWM_ENABLE_MASK & value);
state->polarity = (PWM_POLARITY_MASK & value) ? PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL;
return 0;
}
......
......@@ -126,6 +126,7 @@ static int iqs620_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
mutex_unlock(&iqs620_pwm->lock);
state->period = IQS620_PWM_PERIOD_NS;
state->polarity = PWM_POLARITY_NORMAL;
return 0;
}
......
......@@ -162,6 +162,12 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
duty = state->duty_cycle;
period = state->period;
/*
* Note this is wrong. The result is an output wave that isn't really
* inverted and so is wrongly identified by .get_state as normal.
* Fixing this needs some care however as some machines might rely on
* this.
*/
if (state->polarity == PWM_POLARITY_INVERSED)
duty = period - duty;
......@@ -358,6 +364,8 @@ static int meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->duty_cycle = 0;
}
state->polarity = PWM_POLARITY_NORMAL;
return 0;
}
......
......@@ -109,6 +109,7 @@ static int sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
duty = val & SPRD_PWM_DUTY_MSK;
tmp = (prescale + 1) * NSEC_PER_SEC * duty;
state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, chn->clk_rate);
state->polarity = PWM_POLARITY_NORMAL;
/* Disable PWM clocks if the PWM channel is not in enable state. */
if (!state->enabled)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment