Devicetree
 help / color / mirror / Atom feed
From: Lee Jones <lee@kernel.org>
To: sashiko-reviews@lists.linux.dev
Cc: Paul Sajna <sajattack@postmarketos.org>,
	linux-leds@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org,
	devicetree@vger.kernel.org
Subject: Re: [PATCH RFC 3/3] leds: aw2013: Add AW2027 support and rename to aw20xx
Date: Wed, 9 Sep 2026 17:02:27 +0100	[thread overview]
Message-ID: <20260909160227.GE2133376@google.com> (raw)
In-Reply-To: <20260908000128.B92201F00A3A@smtp.kernel.org>

On Tue, 08 Sep 2026, sashiko-bot@kernel.org wrote:

> Thank you for your contribution! Sashiko AI review found 8 potential issue(s) to consider:
> 
> New issues:
> - [High] Missing NULL check for the result of `device_get_match_data()`, which leads to a kernel oops during manual sysfs driver binding.
> - [Medium] The return value from `regmap_update_bits()` for configuring the global IMAX register is ignored and overwritten.
> - [Medium] Incorrect default current configuration for AW2027 assigns a global register enum to a local scale, leading to 0mA output.
> - [Low] The inline function `aw20xx_microamp_to_imax` lacks the `static` keyword, creating a non-static inline definition that causes linker errors or compiler warnings.
> - [Low] Struct initialization uses a non-constant expression at file scope, causing a hard compiler error.

Please review, explain or fix the Sashiko review(s).

If this is a set, this request includes the other patches too.

> Pre-existing issues:
> - [High] Self-deadlock in `aw20xx_probe()` due to holding `chip->mutex` during LED registration.
> - [High] Late assignment of `chip->num_leds` breaks initialization during probe and causes unbalanced regulator disables.
> - [Low] Failure to use dev_err_probe() for regulator requests violates LED subsystem guidelines.
> --
> 
> commit 66ff1fb4c5655ece202f9cdb3c5a3a75b313c787
> Author: Paul Sajna <sajattack@postmarketos.org>
> Subject: leds: aw2013: Add AW2027 support and rename to aw20xx
> 
> This commit adds support for the AW2027 LED driver by renaming the existing
> AW2013 driver to aw20xx and abstracting chip-specific features. It introduces
> a common chipdef structure to handle differences in maximum current, current
> mixing levels, and initialization registers.
> 
> > diff --git a/drivers/leds/leds-aw20xx.c b/drivers/leds/leds-aw20xx.c
> > index 216755d6010fe..635965b712d48 100644
> > --- a/drivers/leds/leds-aw20xx.c
> > +++ b/drivers/leds/leds-aw20xx.c
> 
> [ ... ]
> 
> > +/* finds the closest current step to the given microamp
> > + * given the max current and number of levels
> > + */
> > +inline u32 aw20xx_microamp_to_imax(u32 microamp, const struct aw20xx_chipdef *cdef)
> > +{
> > +	return min_t(u32, ((microamp * (cdef->current_levels - 1))
> > +			  + (cdef->current_max / 2)) / cdef->current_max,
> > +		     cdef->current_levels - 1);
> > +}
> 
> [Severity: Low]
> Does this inline function need the static keyword? When compiling with C99/C11
> standards, an inline function without static might require an external
> definition, which could lead to build failures or linker errors.
> 
> [ ... ]
> 
> > +static const struct aw20xx_chipdef aw2013_chipdef = {
> > +	.chip_id = AW2013_RSTR_CHIP_ID,
> > +	.regmap_cfg = aw2013_regmap_config,
> > +	.default_imax = 0b01, // 5mA
> > +	.gcr2_imax = false,
> > +	.current_levels = 4,
> > +	.current_max = 15000,
> > +};
> > +
> > +static const struct aw20xx_chipdef aw2027_chipdef = {
> > +	.chip_id = AW2027_RSTR_CHIP_ID,
> > +	.regmap_cfg = aw2027_regmap_config,
> 
> [Severity: Low]
> Does this cause a compiler error due to non-constant initialization? Using
> the global variable aw2013_regmap_config to initialize this struct by value
> at file scope is not a constant expression in standard C. The same applies
> below for aw2027_regmap_config.
> 
> > +	.default_imax = AW2027_IMAX_15MA,
> 
> [Severity: Medium]
> Does this assign a global register enum to a property used for the LCFG local
> current step? AW2027_IMAX_15MA expands to 0. Writing 0 to the 16-level local
> current scale (AW20XX_LCFG_CUR_MASK) configures the LED for 0mA instead of
> 15mA if the led-max-microamp devicetree property is missing.
> 
> [ ... ]
> 
> > +	if (chip->cdef->gcr2_imax) {
> > +		/* AW2027 supports 4-step global imax, and also a 16-step control for limiting
> > +		 * individual current per LED. This doesn't map to the single value the
> > +		 * devicetree provides super well, so set global imax  to maximum, and
> > +		 * local imax to whatever gets us closest to the value in the devicetree
> > +		 */
> >  		ret = regmap_update_bits(chip->regmap,
> > -					 AW2013_LCFG(chip->leds[i].num),
> > -					 AW2013_LCFG_IMAX_MASK,
> > -					 chip->leds[i].imax);
> > -		if (ret) {
> > -			dev_err(&chip->client->dev,
> > -				"Failed to set maximum current for led %d: %d\n",
> > -				chip->leds[i].num, ret);
> > -			return ret;
> > +				AW20XX_GCR2,
> > +				AW20XX_IMAX_MASK,
> > +				AW2027_IMAX_30MA);
> > +
> > +		for (i = 0; i < chip->num_leds; i++) {
> > +			ret = regmap_update_bits(chip->regmap,
> 
> [Severity: Medium]
> Is the return value for the global IMAX register update intentionally ignored?
> The ret variable is immediately overwritten by the loop, meaning any hardware
> I2C errors during AW20XX_GCR2 configuration will not be caught.
> 
> [ ... ]
> 
> > -		led->cdev.brightness_set_blocking = aw2013_brightness_set;
> > -		led->cdev.blink_set = aw2013_blink_set;
> > +		led->cdev.brightness_set_blocking = aw20xx_brightness_set;
> > +		led->cdev.blink_set = aw20xx_blink_set;
> >  
> >  		ret = devm_led_classdev_register_ext(&chip->client->dev,
> >  						     &led->cdev, &init_data);
> 
> [Severity: High]
> This is a pre-existing issue, but does assigning chip->num_leds after
> registering the LED class devices cause initialization problems?
> Looking at aw20xx_probe_dt(), chip->num_leds is set to i after the loop
> completes. However, devm_led_classdev_register_ext() executes default triggers
> synchronously, which call aw20xx_brightness_set(). If num_leds is still 0,
> aw20xx_chip_in_use() silently returns false, skipping chip enablement and
> causing unbalanced regulator disables while probe is still running.
> 
> [ ... ]
> 
> >  static int aw20xx_probe(struct i2c_client *client)
> >  {
> > -	struct aw2013 *chip;
> > +	struct aw20xx *chip;
> > +	const struct aw20xx_chipdef *cdef;
> >  	int ret;
> >  	unsigned int chipid;
> >  
> > +	cdef = device_get_match_data(&client->dev);
> > +
> 
> [Severity: High]
> Does this need a NULL check? If a user with privileges manually binds the
> driver to an I2C device via sysfs, device_get_match_data() will return NULL,
> causing a kernel oops when it is later dereferenced.
> 
> [ ... ]
> 
> >  	mutex_lock(&chip->mutex);
> >  
> >  	chip->client = client;
> > +	chip->cdef = cdef;
> >  	i2c_set_clientdata(client, chip);
> >  
> > -	chip->regmap = devm_regmap_init_i2c(client, &aw2013_regmap_config);
> > +	chip->regmap = devm_regmap_init_i2c(client, &chip->cdef->regmap_cfg);
> 
> [Severity: High]
> This is a pre-existing issue, but does holding chip->mutex here cause a
> self-deadlock during probe? Later in the probe path, aw20xx_probe_dt() calls
> devm_led_classdev_register_ext(). If a default trigger is configured, it
> synchronously calls aw20xx_brightness_set() which attempts to acquire the
> same chip->mutex lock.
> 
> [ ... ]
> 
> >  	}
> >  
> >  	ret = regulator_bulk_enable(ARRAY_SIZE(chip->regulators),
> > -				    chip->regulators);
> > +					chip->regulators);
> >  	if (ret) {
> 
> [Severity: Low]
> This is a pre-existing issue, but does the regulator request code earlier
> in aw20xx_probe() violate the LED subsystem guidelines? It uses manual
> ret != -EPROBE_DEFER checks and dev_err() instead of dev_err_probe(), which
> is required to correctly handle deferred probes and clean up the kernel log.
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/20260907-aw2013-aw20xx-rename-v1-0-c9a7df12a701@postmarketos.org?part=3
> 

-- 
Lee Jones

      reply	other threads:[~2026-09-09 16:02 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-07 23:47 [PATCH RFC 0/3] leds: aw2013: Rename aw2013 to aw20xx and add AW2027 support Paul Sajna
2026-09-07 23:47 ` [PATCH RFC 1/3] dt-bindings: leds: aw2013: Add aw2027 compatible and rename to aw20xx Paul Sajna
2026-09-07 23:52   ` sashiko-bot
2026-09-08 18:03   ` Conor Dooley
2026-09-07 23:47 ` [PATCH RFC 2/3] leds: aw2013: Rename " Paul Sajna
2026-09-07 23:57   ` sashiko-bot
2026-09-07 23:47 ` [PATCH RFC 3/3] leds: aw2013: Add AW2027 support and rename " Paul Sajna
2026-09-08  0:01   ` sashiko-bot
2026-09-09 16:02     ` Lee Jones [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260909160227.GE2133376@google.com \
    --to=lee@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-leds@vger.kernel.org \
    --cc=robh@kernel.org \
    --cc=sajattack@postmarketos.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox