pwm: Restore initial state if a legacy callback fails
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Thu, 1 Jul 2021 07:29:27 +0000 (09:29 +0200)
committerThierry Reding <thierry.reding@gmail.com>
Wed, 17 Nov 2021 16:10:42 +0000 (17:10 +0100)
It is not entirely accurate to go back to the initial state after e.g.
.enable() failed, as .config() still modified the hardware, but this same
inconsistency exists for drivers that implement .apply().

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
drivers/pwm/core.c

index dedf38a81bf91dc12442614e1bd3268718550fd6..57b8cedfec3ff7c7a0d535ebd88d937fe951973f 100644 (file)
@@ -526,10 +526,8 @@ static int pwm_apply_legacy(struct pwm_chip *chip, struct pwm_device *pwm,
                            const struct pwm_state *state)
 {
        int err;
+       struct pwm_state initial_state = pwm->state;
 
-       /*
-        * FIXME: restore the initial state in case of error.
-        */
        if (state->polarity != pwm->state.polarity) {
                if (!chip->ops->set_polarity)
                        return -EINVAL;
@@ -550,7 +548,7 @@ static int pwm_apply_legacy(struct pwm_chip *chip, struct pwm_device *pwm,
 
                err = chip->ops->set_polarity(chip, pwm, state->polarity);
                if (err)
-                       return err;
+                       goto rollback;
 
                pwm->state.polarity = state->polarity;
        }
@@ -573,7 +571,7 @@ static int pwm_apply_legacy(struct pwm_chip *chip, struct pwm_device *pwm,
                                state->duty_cycle,
                                state->period);
        if (err)
-               return err;
+               goto rollback;
 
        pwm->state.period = state->period;
        pwm->state.duty_cycle = state->duty_cycle;
@@ -581,10 +579,14 @@ static int pwm_apply_legacy(struct pwm_chip *chip, struct pwm_device *pwm,
        if (!pwm->state.enabled) {
                err = chip->ops->enable(chip, pwm);
                if (err)
-                       return err;
+                       goto rollback;
        }
 
        return 0;
+
+rollback:
+       pwm->state = initial_state;
+       return err;
 }
 
 /**