Skip to content

Commit 0267b5d

Browse files
ukleinekgregkh
authored andcommitted
pwm: Ensure callbacks exist before calling them
commit da6b353 upstream. If one of the waveform functions is called for a chip that only supports .apply(), we want that an error code is returned and not a NULL pointer exception. Fixes: 6c5126c ("pwm: Provide new consumer API functions for waveforms") Cc: stable@vger.kernel.org Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com> Tested-by: Trevor Gamblin <tgamblin@baylibre.com> Link: https://lore.kernel.org/r/20250123172709.391349-2-u.kleine-koenig@baylibre.com Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 4657683 commit 0267b5d

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
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

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)