Skip to content

Commit 078eac2

Browse files
committed
Merge tag 'pwm/for-6.14-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux
Pull pwm fixes from Uwe Kleine-König: "Two fixes. Conor Dooley found and fixed a problem in the pwm-microchip-core driver that existed since the driver's birth in v6.5-rc1. It's about a corner case that only happens if two pwm devices of the same chip are set to the same long period. The other problem is about the new pwm API that currently is only supported by two hardware drivers. The fix prevents a NULL pointer exception if one of the new functions is called for a pwm device with a driver that only provides the old callbacks" * tag 'pwm/for-6.14-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux: pwm: Ensure callbacks exist before calling them pwm: microchip-core: fix incorrect comparison with max period
2 parents f28f489 + da6b353 commit 078eac2

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

drivers/pwm/core.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,9 @@ int pwm_round_waveform_might_sleep(struct pwm_device *pwm, struct pwm_waveform *
242242

243243
BUG_ON(WFHWSIZE < ops->sizeof_wfhw);
244244

245+
if (!pwmchip_supports_waveform(chip))
246+
return -EOPNOTSUPP;
247+
245248
if (!pwm_wf_valid(wf))
246249
return -EINVAL;
247250

@@ -294,6 +297,9 @@ int pwm_get_waveform_might_sleep(struct pwm_device *pwm, struct pwm_waveform *wf
294297

295298
BUG_ON(WFHWSIZE < ops->sizeof_wfhw);
296299

300+
if (!pwmchip_supports_waveform(chip) || !ops->read_waveform)
301+
return -EOPNOTSUPP;
302+
297303
guard(pwmchip)(chip);
298304

299305
if (!chip->operational)
@@ -320,6 +326,9 @@ static int __pwm_set_waveform(struct pwm_device *pwm,
320326

321327
BUG_ON(WFHWSIZE < ops->sizeof_wfhw);
322328

329+
if (!pwmchip_supports_waveform(chip))
330+
return -EOPNOTSUPP;
331+
323332
if (!pwm_wf_valid(wf))
324333
return -EINVAL;
325334

@@ -592,7 +601,7 @@ static int __pwm_apply(struct pwm_device *pwm, const struct pwm_state *state)
592601
state->usage_power == pwm->state.usage_power)
593602
return 0;
594603

595-
if (ops->write_waveform) {
604+
if (pwmchip_supports_waveform(chip)) {
596605
struct pwm_waveform wf;
597606
char wfhw[WFHWSIZE];
598607

@@ -746,7 +755,7 @@ int pwm_get_state_hw(struct pwm_device *pwm, struct pwm_state *state)
746755
if (!chip->operational)
747756
return -ENODEV;
748757

749-
if (ops->read_waveform) {
758+
if (pwmchip_supports_waveform(chip) && ops->read_waveform) {
750759
char wfhw[WFHWSIZE];
751760
struct pwm_waveform wf;
752761

drivers/pwm/pwm-microchip-core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ static int mchp_core_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *
327327
* mchp_core_pwm_calc_period().
328328
* The period is locked and we cannot change this, so we abort.
329329
*/
330-
if (hw_period_steps == MCHPCOREPWM_PERIOD_STEPS_MAX)
330+
if (hw_period_steps > MCHPCOREPWM_PERIOD_STEPS_MAX)
331331
return -EINVAL;
332332

333333
prescale = hw_prescale;

include/linux/pwm.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,23 @@ struct pwm_chip {
347347
struct pwm_device pwms[] __counted_by(npwm);
348348
};
349349

350+
/**
351+
* pwmchip_supports_waveform() - checks if the given chip supports waveform callbacks
352+
* @chip: The pwm_chip to test
353+
*
354+
* Returns true iff the pwm chip support the waveform functions like
355+
* pwm_set_waveform_might_sleep() and pwm_round_waveform_might_sleep()
356+
*/
357+
static inline bool pwmchip_supports_waveform(struct pwm_chip *chip)
358+
{
359+
/*
360+
* only check for .write_waveform(). If that is available,
361+
* .round_waveform_tohw() and .round_waveform_fromhw() asserted to be
362+
* available, too, in pwmchip_add().
363+
*/
364+
return chip->ops->write_waveform != NULL;
365+
}
366+
350367
static inline struct device *pwmchip_parent(const struct pwm_chip *chip)
351368
{
352369
return chip->dev.parent;

0 commit comments

Comments
 (0)