Commit ae52f797 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -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)
+1 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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;
}
+1 −0
Original line number Diff line number Diff line
@@ -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;
}
+8 −0
Original line number Diff line number Diff line
@@ -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;
}

Loading