diff mbox series

[v1,080/101] pwm: lpss: Store parent device in driver data

Message ID 20230808171931.944154-81-u.kleine-koenig@pengutronix.de
State Superseded
Headers show
Series pwm: Fix lifetime issues for pwm_chips | expand

Commit Message

Uwe Kleine-König Aug. 8, 2023, 5:19 p.m. UTC
struct pwm_chip::dev is about to change. To not have to touch this
driver in the same commit as struct pwm_chip::dev, store a pointer to
the parent device in driver data.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-lpss.c | 16 +++++++++-------
 drivers/pwm/pwm-lpss.h |  1 +
 2 files changed, 10 insertions(+), 7 deletions(-)

Comments

Andy Shevchenko Aug. 8, 2023, 5:49 p.m. UTC | #1
On Tue, Aug 08, 2023 at 07:19:10PM +0200, Uwe Kleine-König wrote:
> struct pwm_chip::dev is about to change. To not have to touch this
> driver in the same commit as struct pwm_chip::dev, store a pointer to
> the parent device in driver data.

I'm not against this change, so
Acked-by: Andy Shevchenko <andy@kernel.org>
bu see some comments below.

I think ideally pwm_chip should be an opaque to the driver
(or something near to it). OTOH it may be I understood that
wrong.

...

>  	if (state->enabled) {
>  		if (!pwm_is_enabled(pwm)) {
> -			pm_runtime_get_sync(chip->dev);
> +			pm_runtime_get_sync(lpwm->parent);
>  			ret = pwm_lpss_prepare_enable(lpwm, pwm, state);
>  			if (ret)
> -				pm_runtime_put(chip->dev);
> +				pm_runtime_put(lpwm->parent);
>  		} else {
>  			ret = pwm_lpss_prepare_enable(lpwm, pwm, state);
>  		}
>  	} else if (pwm_is_enabled(pwm)) {
>  		pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE);
> -		pm_runtime_put(chip->dev);
> +		pm_runtime_put(lpwm->parent);
>  	}

I'm wondering why PM runtime calls can't be part of PWM core?
We may cleanup a lot of code with it, no?

...

> -	pm_runtime_get_sync(chip->dev);
> +	pm_runtime_get_sync(lpwm->parent);


> -	pm_runtime_put(chip->dev);
> +	pm_runtime_put(lpwm->parent);

Ditto.

...

>  struct pwm_lpss_chip {
> +	struct device *parent;

Have you checked IIO approach with the public and private members
(under private the opaque pointer is meant)? Maybe something of that
can be applied to PWM code as well, dunno.

>  	void __iomem *regs;
>  	const struct pwm_lpss_boardinfo *info;
>  };
Uwe Kleine-König Aug. 9, 2023, 6:10 a.m. UTC | #2
Hello Andy,

On Tue, Aug 08, 2023 at 08:49:53PM +0300, Andy Shevchenko wrote:
> On Tue, Aug 08, 2023 at 07:19:10PM +0200, Uwe Kleine-König wrote:
> > struct pwm_chip::dev is about to change. To not have to touch this
> > driver in the same commit as struct pwm_chip::dev, store a pointer to
> > the parent device in driver data.
> 
> I'm not against this change, so
> Acked-by: Andy Shevchenko <andy@kernel.org>
> bu see some comments below.
> 
> I think ideally pwm_chip should be an opaque to the driver
> (or something near to it). OTOH it may be I understood that
> wrong.

What would be the benefit of making it opaque? True, the drivers only
use .ops which could be added to devm_pwmchip_alloc() as a parameter to
drop the need to assign .ops, but the benefit of hiding the details
isn't clear to me.

> >  	if (state->enabled) {
> >  		if (!pwm_is_enabled(pwm)) {
> > -			pm_runtime_get_sync(chip->dev);
> > +			pm_runtime_get_sync(lpwm->parent);
> >  			ret = pwm_lpss_prepare_enable(lpwm, pwm, state);
> >  			if (ret)
> > -				pm_runtime_put(chip->dev);
> > +				pm_runtime_put(lpwm->parent);
> >  		} else {
> >  			ret = pwm_lpss_prepare_enable(lpwm, pwm, state);
> >  		}
> >  	} else if (pwm_is_enabled(pwm)) {
> >  		pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE);
> > -		pm_runtime_put(chip->dev);
> > +		pm_runtime_put(lpwm->parent);
> >  	}
> 
> I'm wondering why PM runtime calls can't be part of PWM core?
> We may cleanup a lot of code with it, no?

Yes, I wondered about that one during the conversion, too. One thing at
a time. (There are also a few drivers using SET_SYSTEM_SLEEP_PM_OPS /
SET_RUNTIME_PM_OPS which could be converted to moderner variants.)

> > -	pm_runtime_get_sync(chip->dev);
> > +	pm_runtime_get_sync(lpwm->parent);
> 
> 
> > -	pm_runtime_put(chip->dev);
> > +	pm_runtime_put(lpwm->parent);
> 
> Ditto.
> 
> ...
> 
> >  struct pwm_lpss_chip {
> > +	struct device *parent;
> 
> Have you checked IIO approach with the public and private members
> (under private the opaque pointer is meant)? Maybe something of that
> can be applied to PWM code as well, dunno.

Not sure I see what you mean. I guess it's about iio_device_alloc() and
how the size calculations are done there? I didn't do any measurements
if aligning the priv data helps. ISTR that for net the aligning is done
because some drivers do DMA to/from their priv data area. That's not the
case for PWMs. So I kept that simple. I'm open to address that, but
unless there is an obvious reason that doesn't involve extensive runtime
testing, I'd postpone that for a later time and concentrate on getting
the groundwork for my character device plans done.

Thanks for your feedback
Uwe
diff mbox series

Patch

diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
index 13087203d05a..105b06f1a6bc 100644
--- a/drivers/pwm/pwm-lpss.c
+++ b/drivers/pwm/pwm-lpss.c
@@ -106,15 +106,16 @@  static int pwm_lpss_wait_for_update(struct pwm_device *pwm)
 	 */
 	err = readl_poll_timeout(addr, val, !(val & PWM_SW_UPDATE), 40, ms);
 	if (err)
-		dev_err(pwm->chip->dev, "PWM_SW_UPDATE was not cleared\n");
+		dev_err(lpwm->parent, "PWM_SW_UPDATE was not cleared\n");
 
 	return err;
 }
 
 static inline int pwm_lpss_is_updating(struct pwm_device *pwm)
 {
+	struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip);
 	if (pwm_lpss_read(pwm) & PWM_SW_UPDATE) {
-		dev_err(pwm->chip->dev, "PWM_SW_UPDATE is still set, skipping update\n");
+		dev_err(lpwm->parent, "PWM_SW_UPDATE is still set, skipping update\n");
 		return -EBUSY;
 	}
 
@@ -190,16 +191,16 @@  static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 
 	if (state->enabled) {
 		if (!pwm_is_enabled(pwm)) {
-			pm_runtime_get_sync(chip->dev);
+			pm_runtime_get_sync(lpwm->parent);
 			ret = pwm_lpss_prepare_enable(lpwm, pwm, state);
 			if (ret)
-				pm_runtime_put(chip->dev);
+				pm_runtime_put(lpwm->parent);
 		} else {
 			ret = pwm_lpss_prepare_enable(lpwm, pwm, state);
 		}
 	} else if (pwm_is_enabled(pwm)) {
 		pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE);
-		pm_runtime_put(chip->dev);
+		pm_runtime_put(lpwm->parent);
 	}
 
 	return ret;
@@ -213,7 +214,7 @@  static int pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
 	unsigned long long base_unit, freq, on_time_div;
 	u32 ctrl;
 
-	pm_runtime_get_sync(chip->dev);
+	pm_runtime_get_sync(lpwm->parent);
 
 	base_unit_range = BIT(lpwm->info->base_unit_bits);
 
@@ -235,7 +236,7 @@  static int pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
 	state->polarity = PWM_POLARITY_NORMAL;
 	state->enabled = !!(ctrl & PWM_ENABLE);
 
-	pm_runtime_put(chip->dev);
+	pm_runtime_put(lpwm->parent);
 
 	return 0;
 }
@@ -262,6 +263,7 @@  struct pwm_chip *devm_pwm_lpss_probe(struct device *dev, void __iomem *base,
 		return ERR_PTR(-ENOMEM);
 	lpwm = to_lpwm(chip);
 
+	lpwm->parent = dev;
 	lpwm->regs = base;
 	lpwm->info = info;
 
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
index b5267ab5193b..5ccc607c6811 100644
--- a/drivers/pwm/pwm-lpss.h
+++ b/drivers/pwm/pwm-lpss.h
@@ -18,6 +18,7 @@ 
 #define LPSS_MAX_PWMS			4
 
 struct pwm_lpss_chip {
+	struct device *parent;
 	void __iomem *regs;
 	const struct pwm_lpss_boardinfo *info;
 };