lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <zwckkfd6mzzjxfpitojcmhokhjbtc4u3brf34pcu4phdlipf3z@uijstw7daze2>
Date: Thu, 3 Apr 2025 17:01:46 +0200
From: Uwe Kleine-König <ukleinek@...nel.org>
To: Christian Marangi <ansuelsmth@...il.com>
Cc: linux-kernel@...r.kernel.org, linux-pwm@...r.kernel.org, 
	Benjamin Larsson <benjamin.larsson@...exis.eu>, 
	AngeloGioacchino Del Regno <angelogioacchino.delregno@...labora.com>, Lorenzo Bianconi <lorenzo@...nel.org>
Subject: Re: [RESEND PATCH v11] pwm: airoha: Add support for EN7581 SoC

Hello,

On Thu, Apr 03, 2025 at 12:50:27PM +0200, Christian Marangi wrote:
> On Thu, Apr 03, 2025 at 11:58:48AM +0200, Uwe Kleine-König wrote:
> > > +	if (hwpwm >= AIROHA_PWM_NUM_GPIO)
> > > +		offset -= AIROHA_PWM_NUM_GPIO;
> > > +
> > > +	/* One FLASH_MAP register handles 8 pins */
> > > +	*shift = do_div(offset, AIROHA_PWM_PINS_PER_FLASH_MAP);
> > > +	*shift = AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(*shift);
> > > +
> > > +	if (offset < AIROHA_PWM_NUM_GPIO)
> > > +		*addr = AIROHA_PWM_REG_GPIO_FLASH_MAP(offset);
> > > +	else
> > > +		*addr = AIROHA_PWM_REG_SIPO_FLASH_MAP(offset);
> > 
> > A single if would be a bit more straight forward. Something like:
> > 
> > 	static void airoha_pwm_get_flash_map_addr_and_shift(unsigned int hwpwm,
> > 							    unsigned int *addr, unsigned int *shift)
> > 	{
> > 		u64 offset = hwpwm;
> > 	
> > 		if (hwpwm >= AIROHA_PWM_NUM_GPIO) {
> > 			unsigned sipohwpwm = hwpwm - AIROHA_PWM_NUM_GPIO;
> > 
> > 			*shift = AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(sipohwpwm % AIROHA_PWM_PINS_PER_FLASH_MAP)
> > 			*addr = AIROHA_PWM_REG_SIPO_FLASH_MAP(sipohwpwm);
> > 		} else {
> > 			*shift = AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(hwpwm % AIROHA_PWM_PINS_PER_FLASH_MAP)
> > 			*addr = AIROHA_PWM_REG_GPIO_FLASH_MAP(hwpwm);
> > 		}
> > 	}
> > 
> 
> I think you missed the do_div that do side effect on offset. Also that
> needs to be / AIROHA_PWM_PINS_PER_FLASH_MAP.

Ack. Luckily you got the idea anyhow. This double effect of do_div() is
easy to miss, so getting rid of them sounds sensible.

> > > +		if (duty_ns == bucket->duty_ns &&
> > > +		    period_ns == bucket->period_ns)
> > > +			return i;
> > 
> > If period_ns == 4010 and bucket->period_ns == 4000 you're not
> > considering *bucket even though it has the right period setting.
> > (period_ns is the requested period and not the expected period actually
> > implemented by HW, right?)
> > 
> 
> Doesn't that requires a different generator? The value we store in the
> bucket is the requested period yes.

No it doesn't. If I understood right the possible periods are: 4ms, 8ms,
..., so a request to do 4.01ms will be mapped to 4ms which allows to
share the generator.

> > > +				  AIROHA_PWM_GPIO_FLASH_EN << shift);
> > > +		return;
> > > +	}
> > > +
> > > +	regmap_update_bits(pc->regmap, addr,
> > > +			   AIROHA_PWM_GPIO_FLASH_SET_ID << shift,
> > > +			   FIELD_PREP(AIROHA_PWM_GPIO_FLASH_SET_ID, index) << shift);
> > 
> > Huh, I'd prefer:
> > 
> > 	regmap_update_bits(pc->regmap, addr,
> > 			   AIROHA_PWM_GPIO_FLASH_SET_ID(hwpwm % 8)
> > 			   FIELD_PREP(AIROHA_PWM_GPIO_FLASH_SET_ID(hwpwm % 8), index));
> > 
> > (That probably doesn't work out of the box because of the
> > __builtin_constant_p check on mask, so you might need a local
> > alternative to FIELD_PREP without that check.)
> 
> Honestly it's not worth to introduce custom FIELD_PREP for this. Yes the
> problem is that FIELD_PREP requires constant mask so hwpwm % 8 is
> problematic. An old implementation had stuff in define but resulted in
> very ugly and confusing define and macro. The shift and FIELD_PREP
> permits a much cleaner description in the define part at the cost of
> that additional << shift needed.
> 
> Hope you can understand why I think it's better to keep it this way.

OK, I can live with that.

> > > +	bucket = airoha_pwm_consume_generator(pc, duty_ns, period_ns,
> > > +					      hwpwm);
> > > +	if (bucket < 0)
> > > +		return -EBUSY;
> > > +
> > > +	/*
> > > +	 * For SIPO reinit is always needed to trigger the shift register chip
> > > +	 * and apply the new flash configuration.
> > 
> > I don't understand that sentence. What is the shift register chip? What
> > is a flash configuration?
> > 
> 
> The SoC can have attached a shift register chip to supports multiple LEDs.
> The handling of this chip and comunication is done internally to the SoC
> and it's exposed to register with these additional register.
> 
> When such channel are used with an assumed shift register, to apply the
> new configuration in airoha_pwm_config_flash_map(), the shift register
> chip needs to be reinit to actually refresh the chip internal register
> with the new "flash configuration" (aka the values for
> AIROHA_PWM_GPIO_FLASH_SET_ID)
> 
> Will add more comments to this to make it more clear.

Sounds good.

> > > +	state->enabled = FIELD_GET(AIROHA_PWM_GPIO_FLASH_EN, val >> shift);
> > > +	if (!state->enabled)
> > > +		return 0;
> > > +
> > > +	state->polarity = PWM_POLARITY_NORMAL;
> > > +
> > > +	bucket = FIELD_GET(AIROHA_PWM_GPIO_FLASH_SET_ID, val >> shift);
> > > +	state->period = pc->buckets[bucket].period_ns;
> > 
> > Does .period_ns hold the requested or the actual period? You should
> > return the latter.
> 
> Problem is that putting .period_ns here cause error in the PWM_DEBUG
> validations. This is caused by the conversion error of the various / and
> * done to convert tick to ns. Also on applying the configuration we
> already do all the validation to make sure the request value is the
> expected one.

Then there is a bug somewhere. I wouldn't completely rule out it's in
the PWM_DEBUG logic, but my bet is on your driver then.
 
> For the initial values, there is airoha_pwm_fill_bucket that read the
> current PWM values at boot and fill the buckets with the current values.
> 
> This is the compromise I found to handle both pre-configured bucket and
> also handle the division errors in the ns - tick conversion.
> 
> Hope this is acceptable, do you have hint on better handling this?

I'd wait for the next iteration of your patch and then take a deeper
look in the maths involved. It should be possible to make PWM_DEBUG
happy and still report the actual configuration.

Best regards
Uwe

Download attachment "signature.asc" of type "application/pgp-signature" (489 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ