pwm: Ensure pwm_apply_state() doesn't modify the state argument
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Sat, 24 Aug 2019 15:37:07 +0000 (17:37 +0200)
committerThierry Reding <thierry.reding@gmail.com>
Sat, 21 Sep 2019 01:25:10 +0000 (03:25 +0200)
It is surprising for a PWM consumer when the variable holding the
requested state is modified by pwm_apply_state(). Consider for example a
driver doing:

        #define PERIOD 5000000
        #define DUTY_LITTLE 10
        ...
        struct pwm_state state = {
                .period = PERIOD,
                .duty_cycle = DUTY_LITTLE,
                .polarity = PWM_POLARITY_NORMAL,
                .enabled = true,
        };

        pwm_apply_state(mypwm, &state);
        ...
        state.duty_cycle = PERIOD / 2;
        pwm_apply_state(mypwm, &state);

For sure the second call to pwm_apply_state() should still have
state.period = PERIOD and not something the hardware driver chose for a
reason that doesn't necessarily apply to the second call.

So declare the state argument as a pointer to a const type and adapt all
drivers' .apply callbacks.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
22 files changed:
drivers/gpio/gpio-mvebu.c
drivers/pwm/core.c
drivers/pwm/pwm-atmel-hlcdc.c
drivers/pwm/pwm-atmel.c
drivers/pwm/pwm-bcm-iproc.c
drivers/pwm/pwm-cros-ec.c
drivers/pwm/pwm-fsl-ftm.c
drivers/pwm/pwm-hibvt.c
drivers/pwm/pwm-imx-tpm.c
drivers/pwm/pwm-imx27.c
drivers/pwm/pwm-jz4740.c
drivers/pwm/pwm-lpss.c
drivers/pwm/pwm-meson.c
drivers/pwm/pwm-rcar.c
drivers/pwm/pwm-rockchip.c
drivers/pwm/pwm-sifive.c
drivers/pwm/pwm-sprd.c
drivers/pwm/pwm-stm32-lp.c
drivers/pwm/pwm-stm32.c
drivers/pwm/pwm-sun4i.c
drivers/pwm/pwm-zx.c
include/linux/pwm.h

index 869d47f895996efe4e73c78bc8e7dfe38df3668b..6c06876943412bc974999e247d6ffcd91301a7a3 100644 (file)
@@ -694,7 +694,7 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
 }
 
 static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                          struct pwm_state *state)
+                          const struct pwm_state *state)
 {
        struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
        struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
index 449ba161877d099948a241b87b1e4f738d8dc2f5..6ad51aa60c03dd1cf8afd00410a53a459f4d0a35 100644 (file)
@@ -448,11 +448,9 @@ EXPORT_SYMBOL_GPL(pwm_free);
 /**
  * pwm_apply_state() - atomically apply a new state to a PWM device
  * @pwm: PWM device
- * @state: new state to apply. This can be adjusted by the PWM driver
- *        if the requested config is not achievable, for example,
- *        ->duty_cycle and ->period might be approximated.
+ * @state: new state to apply
  */
-int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state)
+int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
 {
        struct pwm_chip *chip;
        int err;
index d13a83f430ace7a5ca1010285bdd24018fa65214..dcbc0489dfd401c5aad3032bafb8057748c7d4dc 100644 (file)
@@ -39,7 +39,7 @@ static inline struct atmel_hlcdc_pwm *to_atmel_hlcdc_pwm(struct pwm_chip *chip)
 }
 
 static int atmel_hlcdc_pwm_apply(struct pwm_chip *c, struct pwm_device *pwm,
-                                struct pwm_state *state)
+                                const struct pwm_state *state)
 {
        struct atmel_hlcdc_pwm *chip = to_atmel_hlcdc_pwm(c);
        struct atmel_hlcdc *hlcdc = chip->hlcdc;
index e5e1eaf372fa7a6e96912ad27ebae9b38bce0bcd..53bc7b9b35818ce79359971a635fd17dc622c1ed 100644 (file)
@@ -209,7 +209,7 @@ static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm,
 }
 
 static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                          struct pwm_state *state)
+                          const struct pwm_state *state)
 {
        struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
        struct pwm_state cstate;
index d961a8207b1cbe660cfb6f38d21b7383f1834847..56c38cfae92ca9285d69e6bd6596cd80d95fcae7 100644 (file)
@@ -115,7 +115,7 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
 }
 
 static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                           struct pwm_state *state)
+                           const struct pwm_state *state)
 {
        unsigned long prescale = IPROC_PWM_PRESCALE_MIN;
        struct iproc_pwmc *ip = to_iproc_pwmc(chip);
index 98f6ac6cf6ab4f9fcda159ae51e5017c519ed042..db5faa79c33f96e84e835ee1b28325a2ea525440 100644 (file)
@@ -93,7 +93,7 @@ static int cros_ec_pwm_get_duty(struct cros_ec_device *ec, u8 index)
 }
 
 static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                            struct pwm_state *state)
+                            const struct pwm_state *state)
 {
        struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
        int duty_cycle;
index 3c9738617cebcb6becdd8ab8ca486c3863e64937..59272a92047933b3c87b12f392ab3e9fa04d40bc 100644 (file)
@@ -227,7 +227,7 @@ static bool fsl_pwm_is_other_pwm_enabled(struct fsl_pwm_chip *fpc,
 
 static int fsl_pwm_apply_config(struct fsl_pwm_chip *fpc,
                                struct pwm_device *pwm,
-                               struct pwm_state *newstate)
+                               const struct pwm_state *newstate)
 {
        unsigned int duty;
        u32 reg_polarity;
@@ -298,7 +298,7 @@ static int fsl_pwm_apply_config(struct fsl_pwm_chip *fpc,
 }
 
 static int fsl_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                        struct pwm_state *newstate)
+                        const struct pwm_state *newstate)
 {
        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
        struct pwm_state *oldstate = &pwm->state;
index 753bd58111e4658258d448ad0df9671f79efc126..ad205fdad3722d46193c3a6a5099cd2878cf127a 100644 (file)
@@ -149,7 +149,7 @@ static void hibvt_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
 }
 
 static int hibvt_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                               struct pwm_state *state)
+                          const struct pwm_state *state)
 {
        struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip);
 
index e8385c1cf34280dce0f280a66a1058ff53e1e15b..9145f61606497cb0aa90aafd9e903c26e83a1374 100644 (file)
@@ -89,7 +89,7 @@ to_imx_tpm_pwm_chip(struct pwm_chip *chip)
 static int pwm_imx_tpm_round_state(struct pwm_chip *chip,
                                   struct imx_tpm_pwm_param *p,
                                   struct pwm_state *real_state,
-                                  struct pwm_state *state)
+                                  const struct pwm_state *state)
 {
        struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip);
        u32 rate, prescale, period_count, clock_unit;
@@ -289,7 +289,7 @@ static int pwm_imx_tpm_apply_hw(struct pwm_chip *chip,
 
 static int pwm_imx_tpm_apply(struct pwm_chip *chip,
                             struct pwm_device *pwm,
-                            struct pwm_state *state)
+                            const struct pwm_state *state)
 {
        struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip);
        struct imx_tpm_pwm_param param;
index 91c23cbbc1677c4789b9459fc6ae3db5c8a1fc82..ae11d8577f1866030173c8e47d513d12da590aae 100644 (file)
@@ -209,7 +209,7 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
 }
 
 static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                          struct pwm_state *state)
+                          const struct pwm_state *state)
 {
        unsigned long period_cycles, duty_cycles, prescale;
        struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
index 9d444d012f929eab15d9d3fadaa65cf1f989c4e8..9d78cc21cb12793bca321c6e941d607930e362cd 100644 (file)
@@ -88,7 +88,7 @@ static void jz4740_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 }
 
 static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                           struct pwm_state *state)
+                           const struct pwm_state *state)
 {
        struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip);
        unsigned long long tmp;
index 4098a4601691b048b3304f33814ba3d59ebfc6b4..75bbfe5f3bc2975479b1a27ade8eca58bab05455 100644 (file)
@@ -122,7 +122,7 @@ static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond)
 }
 
 static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                         struct pwm_state *state)
+                         const struct pwm_state *state)
 {
        struct pwm_lpss_chip *lpwm = to_lpwm(chip);
        int ret;
index 3cbff5cbb789a5646a51ec0f91717d2d39578ca6..6245bbdb6e6c1fab35dcff18c605bb5f24f38848 100644 (file)
@@ -159,7 +159,7 @@ static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 }
 
 static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
-                         struct pwm_state *state)
+                         const struct pwm_state *state)
 {
        struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
        unsigned int duty, period, pre_div, cnt, duty_cnt;
@@ -265,7 +265,7 @@ static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm)
 }
 
 static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                          struct pwm_state *state)
+                          const struct pwm_state *state)
 {
        struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
        struct meson_pwm *meson = to_meson_pwm(chip);
index c8cd43f91efcd4de11ef45f1278a6574fe67e9e7..852eb2347954d128669a176b0f6ca4fd6a48b84a 100644 (file)
@@ -158,7 +158,7 @@ static void rcar_pwm_disable(struct rcar_pwm_chip *rp)
 }
 
 static int rcar_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                         struct pwm_state *state)
+                         const struct pwm_state *state)
 {
        struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip);
        struct pwm_state cur_state;
index 83c7627868d810f21b738effd28f976458162f06..73352e6fbccbf4040f1d2b866443f4dc4d75387f 100644 (file)
@@ -99,7 +99,7 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip,
 }
 
 static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-                              struct pwm_state *state)
+                              const struct pwm_state *state)
 {
        struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
        unsigned long period, duty;
@@ -183,7 +183,7 @@ static int rockchip_pwm_enable(struct pwm_chip *chip,
 }
 
 static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                             struct pwm_state *state)
+                             const struct pwm_state *state)
 {
        struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
        struct pwm_state curstate;
index bb4f02ce4f94712e8e15851b07abfcded8a9f552..cc63f9baa481942f03e8a8228ce0b312ae15be25 100644 (file)
@@ -147,7 +147,7 @@ static int pwm_sifive_enable(struct pwm_chip *chip, bool enable)
 }
 
 static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                           struct pwm_state *state)
+                           const struct pwm_state *state)
 {
        struct pwm_sifive_ddata *ddata = pwm_sifive_chip_to_ddata(chip);
        struct pwm_state cur_state;
index 68c2d9f0411b05b7c3c8449ec0accabd32da11db..be23942274231a26c5aa07cf46608c0572febf5e 100644 (file)
@@ -156,7 +156,7 @@ static int sprd_pwm_config(struct sprd_pwm_chip *spc, struct pwm_device *pwm,
 }
 
 static int sprd_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                         struct pwm_state *state)
+                         const struct pwm_state *state)
 {
        struct sprd_pwm_chip *spc =
                container_of(chip, struct sprd_pwm_chip, chip);
index 2211a642066dbad0fe2288c6ebbfb56d19968c23..21cb260dc2c0dddfd3e2e764a6789c1db5dee791 100644 (file)
@@ -32,7 +32,7 @@ static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)
 #define STM32_LPTIM_MAX_PRESCALER      128
 
 static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                             struct pwm_state *state)
+                             const struct pwm_state *state)
 {
        struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);
        unsigned long long prd, div, dty;
index 740e2dec8313aa2f28b45276f1e56c738b972be0..359b08596d9e3262c00196412c5ce14df6661658 100644 (file)
@@ -440,7 +440,7 @@ static void stm32_pwm_disable(struct stm32_pwm *priv, int ch)
 }
 
 static int stm32_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                          struct pwm_state *state)
+                          const struct pwm_state *state)
 {
        bool enabled;
        struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
@@ -468,7 +468,7 @@ static int stm32_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 }
 
 static int stm32_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm,
-                                 struct pwm_state *state)
+                                 const struct pwm_state *state)
 {
        struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
        int ret;
index 39007a7c0d835efcfea85a1c760673e2433caa10..6f5840a1a82dc1909aad7e6d61632aea8a7b8271 100644 (file)
@@ -145,7 +145,7 @@ static void sun4i_pwm_get_state(struct pwm_chip *chip,
 }
 
 static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm,
-                              struct pwm_state *state,
+                              const struct pwm_state *state,
                               u32 *dty, u32 *prd, unsigned int *prsclr)
 {
        u64 clk_rate, div = 0;
@@ -196,7 +196,7 @@ static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm,
 }
 
 static int sun4i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                          struct pwm_state *state)
+                          const struct pwm_state *state)
 {
        struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip);
        struct pwm_state cstate;
index e24f4be35316e2218595f02753df11978affbc9d..e2c21cc34a96aadc968b8df8c9de296e1de45cc9 100644 (file)
@@ -148,7 +148,7 @@ static int zx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 }
 
 static int zx_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-                       struct pwm_state *state)
+                       const struct pwm_state *state)
 {
        struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip);
        struct pwm_state cstate;
index 24632a7a7d11ccf55d43e52993d44e72e3604c16..b2c9c460947d13ec3a724fab9fd36bf0f7a77b98 100644 (file)
@@ -262,7 +262,7 @@ struct pwm_ops {
        int (*capture)(struct pwm_chip *chip, struct pwm_device *pwm,
                       struct pwm_capture *result, unsigned long timeout);
        int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm,
-                    struct pwm_state *state);
+                    const struct pwm_state *state);
        void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm,
                          struct pwm_state *state);
        struct module *owner;
@@ -316,7 +316,7 @@ struct pwm_capture {
 /* PWM user APIs */
 struct pwm_device *pwm_request(int pwm_id, const char *label);
 void pwm_free(struct pwm_device *pwm);
-int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state);
+int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state);
 int pwm_adjust_config(struct pwm_device *pwm);
 
 /**