diff mbox series

[RFC] pwm: keembay: Fix build failure with -Os

Message ID 20201116090804.206286-1-u.kleine-koenig@pengutronix.de (mailing list archive)
State New, archived
Headers show
Series [RFC] pwm: keembay: Fix build failure with -Os | expand

Commit Message

Uwe Kleine-König Nov. 16, 2020, 9:08 a.m. UTC
The driver used this construct:

	#define KMB_PWM_LEADIN_MASK             GENMASK(30, 0)

	static inline void keembay_pwm_update_bits(struct keembay_pwm *priv, u32 mask,
						   u32 val, u32 offset)
	{
		u32 buff = readl(priv->base + offset);

		buff = u32_replace_bits(buff, val, mask);
		writel(buff, priv->base + offset);
	}

	...
	keembay_pwm_update_bits(priv, KMB_PWM_LEADIN_MASK, 0,
					KMB_PWM_LEADIN_OFFSET(pwm->hwpwm));

With CONFIG_CC_OPTIMIZE_FOR_SIZE the compiler (here: gcc 10.2.0) this
triggers:

	In file included from /home/uwe/gsrc/linux/drivers/pwm/pwm-keembay.c:16:
	In function ‘field_multiplier’,
	    inlined from ‘keembay_pwm_update_bits’ at /home/uwe/gsrc/linux/include/linux/bitfield.h:124:17:
	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to ‘__bad_mask’ declared with attribute error: bad bitfield mask
	  119 |   __bad_mask();
	      |   ^~~~~~~~~~~~
	In function ‘field_multiplier’,
	    inlined from ‘keembay_pwm_update_bits’ at /home/uwe/gsrc/linux/include/linux/bitfield.h:154:1:
	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to ‘__bad_mask’ declared with attribute error: bad bitfield mask
	  119 |   __bad_mask();
	      |   ^~~~~~~~~~~~

The compiler doesn't seem to be able to notice that with field being
0x3ffffff the expression

	if ((field | (field - 1)) & ((field | (field - 1)) + 1))
		__bad_mask();

can be optimized away.

So use __always_inline and document the problem in a comment to fix
this.

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
Hello,

I'm not sure this is the right fix. Maybe the bitfield stuff can be
changed somehow to make this problem go away, too?

Best regards
Uwe

 drivers/pwm/pwm-keembay.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

Comments

Ayyathurai, Vijayakannan Nov. 17, 2020, 5:29 p.m. UTC | #1
Hi Uwe,

> From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> Sent: Monday, 16 November, 2020 5:08 PM
> Subject: [PATCH RFC] pwm: keembay: Fix build failure with -Os
> 
> The driver used this construct:
> 
> 	#define KMB_PWM_LEADIN_MASK             GENMASK(30, 0)
> 
> 	static inline void keembay_pwm_update_bits(struct keembay_pwm
> *priv, u32 mask,
> 						   u32 val, u32 offset)
> 	{
> 		u32 buff = readl(priv->base + offset);
> 
> 		buff = u32_replace_bits(buff, val, mask);
> 		writel(buff, priv->base + offset);
> 	}
> 
> 	...
> 	keembay_pwm_update_bits(priv, KMB_PWM_LEADIN_MASK, 0,
> 					KMB_PWM_LEADIN_OFFSET(pwm-
> >hwpwm));
> 
> With CONFIG_CC_OPTIMIZE_FOR_SIZE the compiler (here: gcc 10.2.0) this
> triggers:
> 
> 	In file included from /home/uwe/gsrc/linux/drivers/pwm/pwm-
> keembay.c:16:
> 	In function ‘field_multiplier’,
> 	    inlined from ‘keembay_pwm_update_bits’ at
> /home/uwe/gsrc/linux/include/linux/bitfield.h:124:17:
> 	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to
> ‘__bad_mask’ declared with attribute error: bad bitfield mask
> 	  119 |   __bad_mask();
> 	      |   ^~~~~~~~~~~~
> 	In function ‘field_multiplier’,
> 	    inlined from ‘keembay_pwm_update_bits’ at
> /home/uwe/gsrc/linux/include/linux/bitfield.h:154:1:
> 	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to
> ‘__bad_mask’ declared with attribute error: bad bitfield mask
> 	  119 |   __bad_mask();
> 	      |   ^~~~~~~~~~~~
> 
> The compiler doesn't seem to be able to notice that with field being
> 0x3ffffff the expression
> 
> 	if ((field | (field - 1)) & ((field | (field - 1)) + 1))
> 		__bad_mask();
> 
> can be optimized away.
> 
> So use __always_inline and document the problem in a comment to fix
> this.
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

Thank you for spending time in resolving this build failure.

I shall prepare and share the next version of patch with your approach.
 
> ---
> Hello,
> 
> I'm not sure this is the right fix. Maybe the bitfield stuff can be
> changed somehow to make this problem go away, too?
> 
> Best regards
> Uwe
> 
>  drivers/pwm/pwm-keembay.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pwm/pwm-keembay.c b/drivers/pwm/pwm-keembay.c
> index 2b6dd070daa4..cdfdef66ff8e 100644
> --- a/drivers/pwm/pwm-keembay.c
> +++ b/drivers/pwm/pwm-keembay.c
> @@ -63,7 +63,12 @@ static int keembay_clk_enable(struct device *dev,
> struct clk *clk)
>  	return devm_add_action_or_reset(dev, keembay_clk_unprepare, clk);
>  }
> 
> -static inline void keembay_pwm_update_bits(struct keembay_pwm *priv, u32
> mask,
> +/*
> + * With gcc 10, CONFIG_CC_OPTIMIZE_FOR_SIZE and only "inline" instead of
> + * "__always_inline" this fails to compile because the compiler doesn't notice
> + * for all valid masks (e.g. KMB_PWM_LEADIN_MASK) that they are ok.
> + */
> +static __always_inline void keembay_pwm_update_bits(struct
> keembay_pwm *priv, u32 mask,
>  					   u32 val, u32 offset)
>  {
>  	u32 buff = readl(priv->base + offset);
> --
> 2.28.0

Thanks,
Vijay
Uwe Kleine-König Nov. 18, 2020, 9:48 a.m. UTC | #2
On Tue, Nov 17, 2020 at 05:29:01PM +0000, Ayyathurai, Vijayakannan wrote:
> Hi Uwe,
> 
> > From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> > Sent: Monday, 16 November, 2020 5:08 PM
> > Subject: [PATCH RFC] pwm: keembay: Fix build failure with -Os
> > 
> > The driver used this construct:
> > 
> > 	#define KMB_PWM_LEADIN_MASK             GENMASK(30, 0)
> > 
> > 	static inline void keembay_pwm_update_bits(struct keembay_pwm
> > *priv, u32 mask,
> > 						   u32 val, u32 offset)
> > 	{
> > 		u32 buff = readl(priv->base + offset);
> > 
> > 		buff = u32_replace_bits(buff, val, mask);
> > 		writel(buff, priv->base + offset);
> > 	}
> > 
> > 	...
> > 	keembay_pwm_update_bits(priv, KMB_PWM_LEADIN_MASK, 0,
> > 					KMB_PWM_LEADIN_OFFSET(pwm-
> > >hwpwm));
> > 
> > With CONFIG_CC_OPTIMIZE_FOR_SIZE the compiler (here: gcc 10.2.0) this
> > triggers:
> > 
> > 	In file included from /home/uwe/gsrc/linux/drivers/pwm/pwm-
> > keembay.c:16:
> > 	In function ‘field_multiplier’,
> > 	    inlined from ‘keembay_pwm_update_bits’ at
> > /home/uwe/gsrc/linux/include/linux/bitfield.h:124:17:
> > 	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to
> > ‘__bad_mask’ declared with attribute error: bad bitfield mask
> > 	  119 |   __bad_mask();
> > 	      |   ^~~~~~~~~~~~
> > 	In function ‘field_multiplier’,
> > 	    inlined from ‘keembay_pwm_update_bits’ at
> > /home/uwe/gsrc/linux/include/linux/bitfield.h:154:1:
> > 	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to
> > ‘__bad_mask’ declared with attribute error: bad bitfield mask
> > 	  119 |   __bad_mask();
> > 	      |   ^~~~~~~~~~~~
> > 
> > The compiler doesn't seem to be able to notice that with field being
> > 0x3ffffff the expression
> > 
> > 	if ((field | (field - 1)) & ((field | (field - 1)) + 1))
> > 		__bad_mask();
> > 
> > can be optimized away.
> > 
> > So use __always_inline and document the problem in a comment to fix
> > this.
> > 
> > Reported-by: kernel test robot <lkp@intel.com>
> > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> 
> Thank you for spending time in resolving this build failure.
> 
> I shall prepare and share the next version of patch with your approach.

I don't understand this last sentence. IMHO there is currently nothing
you have to do for this problem. You can send an Ack however if you want
to.

Best regards
Uwe
Uwe Kleine-König Nov. 18, 2020, 10:06 a.m. UTC | #3
[Cc: += linux-pwm which I forgot for the initial submission]

Hello,

On Mon, Nov 16, 2020 at 10:08:04AM +0100, Uwe Kleine-König wrote:
> The driver used this construct:
> 
> 	#define KMB_PWM_LEADIN_MASK             GENMASK(30, 0)
> 
> 	static inline void keembay_pwm_update_bits(struct keembay_pwm *priv, u32 mask,
> 						   u32 val, u32 offset)
> 	{
> 		u32 buff = readl(priv->base + offset);
> 
> 		buff = u32_replace_bits(buff, val, mask);
> 		writel(buff, priv->base + offset);
> 	}
> 
> 	...
> 	keembay_pwm_update_bits(priv, KMB_PWM_LEADIN_MASK, 0,
> 					KMB_PWM_LEADIN_OFFSET(pwm->hwpwm));
> 
> With CONFIG_CC_OPTIMIZE_FOR_SIZE the compiler (here: gcc 10.2.0) this
> triggers:
> 
> 	In file included from /home/uwe/gsrc/linux/drivers/pwm/pwm-keembay.c:16:
> 	In function ‘field_multiplier’,
> 	    inlined from ‘keembay_pwm_update_bits’ at /home/uwe/gsrc/linux/include/linux/bitfield.h:124:17:
> 	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to ‘__bad_mask’ declared with attribute error: bad bitfield mask
> 	  119 |   __bad_mask();
> 	      |   ^~~~~~~~~~~~
> 	In function ‘field_multiplier’,
> 	    inlined from ‘keembay_pwm_update_bits’ at /home/uwe/gsrc/linux/include/linux/bitfield.h:154:1:
> 	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to ‘__bad_mask’ declared with attribute error: bad bitfield mask
> 	  119 |   __bad_mask();
> 	      |   ^~~~~~~~~~~~
> 
> The compiler doesn't seem to be able to notice that with field being
> 0x3ffffff the expression
> 
> 	if ((field | (field - 1)) & ((field | (field - 1)) + 1))
> 		__bad_mask();
> 
> can be optimized away.
> 
> So use __always_inline and document the problem in a comment to fix
> this.
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
> Hello,
> 
> I'm not sure this is the right fix. Maybe the bitfield stuff can be
> changed somehow to make this problem go away, too?

Note, this patch

Fixes: cdbea243f419 ("pwm: Add PWM driver for Intel Keem Bay")

so this isn't critical for v5.10.

@thierry: If this is ok for you and Vijayakannan, you can squash this
into the original commit.

Best regards
Uwe
Ayyathurai, Vijayakannan Nov. 18, 2020, 5:41 p.m. UTC | #4
Hi Thierry,

> From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> Subject: Re: [PATCH RFC] pwm: keembay: Fix build failure with -Os
> 
> [Cc: += linux-pwm which I forgot for the initial submission]
> 
> Hello,
> 
> On Mon, Nov 16, 2020 at 10:08:04AM +0100, Uwe Kleine-König wrote:
> > The driver used this construct:
> >
> > 	#define KMB_PWM_LEADIN_MASK             GENMASK(30, 0)
> >
> > 	static inline void keembay_pwm_update_bits(struct keembay_pwm
> *priv, u32 mask,
> > 						   u32 val, u32 offset)
> > 	{
> > 		u32 buff = readl(priv->base + offset);
> >
> > 		buff = u32_replace_bits(buff, val, mask);
> > 		writel(buff, priv->base + offset);
> > 	}
> >
> > 	...
> > 	keembay_pwm_update_bits(priv, KMB_PWM_LEADIN_MASK, 0,
> > 					KMB_PWM_LEADIN_OFFSET(pwm-
> >hwpwm));
> >
> > With CONFIG_CC_OPTIMIZE_FOR_SIZE the compiler (here: gcc 10.2.0) this
> > triggers:
> >
> > 	In file included from /home/uwe/gsrc/linux/drivers/pwm/pwm-
> keembay.c:16:
> > 	In function ‘field_multiplier’,
> > 	    inlined from ‘keembay_pwm_update_bits’ at
> /home/uwe/gsrc/linux/include/linux/bitfield.h:124:17:
> > 	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to
> ‘__bad_mask’ declared with attribute error: bad bitfield mask
> > 	  119 |   __bad_mask();
> > 	      |   ^~~~~~~~~~~~
> > 	In function ‘field_multiplier’,
> > 	    inlined from ‘keembay_pwm_update_bits’ at
> /home/uwe/gsrc/linux/include/linux/bitfield.h:154:1:
> > 	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to
> ‘__bad_mask’ declared with attribute error: bad bitfield mask
> > 	  119 |   __bad_mask();
> > 	      |   ^~~~~~~~~~~~
> >
> > The compiler doesn't seem to be able to notice that with field being
> > 0x3ffffff the expression
> >
> > 	if ((field | (field - 1)) & ((field | (field - 1)) + 1))
> > 		__bad_mask();
> >
> > can be optimized away.
> >
> > So use __always_inline and document the problem in a comment to fix
> > this.
> >
> > Reported-by: kernel test robot <lkp@intel.com>
> > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> > ---
> > Hello,
> >
> > I'm not sure this is the right fix. Maybe the bitfield stuff can be
> > changed somehow to make this problem go away, too?
> 
> Note, this patch
> 
> Fixes: cdbea243f419 ("pwm: Add PWM driver for Intel Keem Bay")
> 
> so this isn't critical for v5.10.
> 
> @thierry: If this is ok for you and Vijayakannan, you can squash this
> into the original commit.
> 

I am ok with Uwe approach.
I have compiled the change and tested in Keembay board as well.

> Best regards
> Uwe
> 
> --
> Pengutronix e.K.                           | Uwe Kleine-König            |
> Industrial Linux Solutions                 | https://www.pengutronix.de/ |

Thanks,
Vijay
Thierry Reding Nov. 18, 2020, 6 p.m. UTC | #5
On Mon, Nov 16, 2020 at 10:08:04AM +0100, Uwe Kleine-König wrote:
> The driver used this construct:
> 
> 	#define KMB_PWM_LEADIN_MASK             GENMASK(30, 0)
> 
> 	static inline void keembay_pwm_update_bits(struct keembay_pwm *priv, u32 mask,
> 						   u32 val, u32 offset)
> 	{
> 		u32 buff = readl(priv->base + offset);
> 
> 		buff = u32_replace_bits(buff, val, mask);
> 		writel(buff, priv->base + offset);
> 	}
> 
> 	...
> 	keembay_pwm_update_bits(priv, KMB_PWM_LEADIN_MASK, 0,
> 					KMB_PWM_LEADIN_OFFSET(pwm->hwpwm));
> 
> With CONFIG_CC_OPTIMIZE_FOR_SIZE the compiler (here: gcc 10.2.0) this
> triggers:
> 
> 	In file included from /home/uwe/gsrc/linux/drivers/pwm/pwm-keembay.c:16:
> 	In function ‘field_multiplier’,
> 	    inlined from ‘keembay_pwm_update_bits’ at /home/uwe/gsrc/linux/include/linux/bitfield.h:124:17:
> 	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to ‘__bad_mask’ declared with attribute error: bad bitfield mask
> 	  119 |   __bad_mask();
> 	      |   ^~~~~~~~~~~~
> 	In function ‘field_multiplier’,
> 	    inlined from ‘keembay_pwm_update_bits’ at /home/uwe/gsrc/linux/include/linux/bitfield.h:154:1:
> 	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to ‘__bad_mask’ declared with attribute error: bad bitfield mask
> 	  119 |   __bad_mask();
> 	      |   ^~~~~~~~~~~~
> 
> The compiler doesn't seem to be able to notice that with field being
> 0x3ffffff the expression
> 
> 	if ((field | (field - 1)) & ((field | (field - 1)) + 1))
> 		__bad_mask();
> 
> can be optimized away.
> 
> So use __always_inline and document the problem in a comment to fix
> this.
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
> Hello,
> 
> I'm not sure this is the right fix. Maybe the bitfield stuff can be
> changed somehow to make this problem go away, too?
> 
> Best regards
> Uwe
> 
>  drivers/pwm/pwm-keembay.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)

Applied, thanks.

Thierry
Thierry Reding Nov. 18, 2020, 6:01 p.m. UTC | #6
On Wed, Nov 18, 2020 at 05:41:57PM +0000, Ayyathurai, Vijayakannan wrote:
> Hi Thierry,
> 
> > From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> > Subject: Re: [PATCH RFC] pwm: keembay: Fix build failure with -Os
> > 
> > [Cc: += linux-pwm which I forgot for the initial submission]
> > 
> > Hello,
> > 
> > On Mon, Nov 16, 2020 at 10:08:04AM +0100, Uwe Kleine-König wrote:
> > > The driver used this construct:
> > >
> > > 	#define KMB_PWM_LEADIN_MASK             GENMASK(30, 0)
> > >
> > > 	static inline void keembay_pwm_update_bits(struct keembay_pwm
> > *priv, u32 mask,
> > > 						   u32 val, u32 offset)
> > > 	{
> > > 		u32 buff = readl(priv->base + offset);
> > >
> > > 		buff = u32_replace_bits(buff, val, mask);
> > > 		writel(buff, priv->base + offset);
> > > 	}
> > >
> > > 	...
> > > 	keembay_pwm_update_bits(priv, KMB_PWM_LEADIN_MASK, 0,
> > > 					KMB_PWM_LEADIN_OFFSET(pwm-
> > >hwpwm));
> > >
> > > With CONFIG_CC_OPTIMIZE_FOR_SIZE the compiler (here: gcc 10.2.0) this
> > > triggers:
> > >
> > > 	In file included from /home/uwe/gsrc/linux/drivers/pwm/pwm-
> > keembay.c:16:
> > > 	In function ‘field_multiplier’,
> > > 	    inlined from ‘keembay_pwm_update_bits’ at
> > /home/uwe/gsrc/linux/include/linux/bitfield.h:124:17:
> > > 	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to
> > ‘__bad_mask’ declared with attribute error: bad bitfield mask
> > > 	  119 |   __bad_mask();
> > > 	      |   ^~~~~~~~~~~~
> > > 	In function ‘field_multiplier’,
> > > 	    inlined from ‘keembay_pwm_update_bits’ at
> > /home/uwe/gsrc/linux/include/linux/bitfield.h:154:1:
> > > 	/home/uwe/gsrc/linux/include/linux/bitfield.h:119:3: error: call to
> > ‘__bad_mask’ declared with attribute error: bad bitfield mask
> > > 	  119 |   __bad_mask();
> > > 	      |   ^~~~~~~~~~~~
> > >
> > > The compiler doesn't seem to be able to notice that with field being
> > > 0x3ffffff the expression
> > >
> > > 	if ((field | (field - 1)) & ((field | (field - 1)) + 1))
> > > 		__bad_mask();
> > >
> > > can be optimized away.
> > >
> > > So use __always_inline and document the problem in a comment to fix
> > > this.
> > >
> > > Reported-by: kernel test robot <lkp@intel.com>
> > > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> > > ---
> > > Hello,
> > >
> > > I'm not sure this is the right fix. Maybe the bitfield stuff can be
> > > changed somehow to make this problem go away, too?
> > 
> > Note, this patch
> > 
> > Fixes: cdbea243f419 ("pwm: Add PWM driver for Intel Keem Bay")
> > 
> > so this isn't critical for v5.10.
> > 
> > @thierry: If this is ok for you and Vijayakannan, you can squash this
> > into the original commit.
> > 
> 
> I am ok with Uwe approach.
> I have compiled the change and tested in Keembay board as well.

I'll take that as a Tested-by. Next time, if you go through the trouble
of testing a patch, make sure to reply with a:

Tested-by: Your Name <your@email.com>

So that patchwork can pick that up and credit you for it.

Thierry
diff mbox series

Patch

diff --git a/drivers/pwm/pwm-keembay.c b/drivers/pwm/pwm-keembay.c
index 2b6dd070daa4..cdfdef66ff8e 100644
--- a/drivers/pwm/pwm-keembay.c
+++ b/drivers/pwm/pwm-keembay.c
@@ -63,7 +63,12 @@  static int keembay_clk_enable(struct device *dev, struct clk *clk)
 	return devm_add_action_or_reset(dev, keembay_clk_unprepare, clk);
 }
 
-static inline void keembay_pwm_update_bits(struct keembay_pwm *priv, u32 mask,
+/*
+ * With gcc 10, CONFIG_CC_OPTIMIZE_FOR_SIZE and only "inline" instead of
+ * "__always_inline" this fails to compile because the compiler doesn't notice
+ * for all valid masks (e.g. KMB_PWM_LEADIN_MASK) that they are ok.
+ */
+static __always_inline void keembay_pwm_update_bits(struct keembay_pwm *priv, u32 mask,
 					   u32 val, u32 offset)
 {
 	u32 buff = readl(priv->base + offset);