All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lee Jones <lee@kernel.org>
To: Runyu Xiao <runyu.xiao@seu.edu.cn>,
	Andreas Werner <andreas.werner@men.de>
Cc: Pavel Machek <pavel@kernel.org>,
	linux-leds@vger.kernel.org,
	Andreas Werner <andreas.werner@men.de>,
	Andrew Morton <akpm@linux-foundation.org>,
	Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com>,
	Bryan Wu <cooloney@gmail.com>,
	linux-kernel@vger.kernel.org, jianhao.xu@seu.edu.cn,
	stable@vger.kernel.org
Subject: Re: [PATCH 2/2] leds: menf21bmc: use brightness_set_blocking for sleepable callback
Date: Thu, 2 Jul 2026 11:45:10 +0100	[thread overview]
Message-ID: <20260702104510.GI2108533@google.com> (raw)
In-Reply-To: <20260615145756.1019184-3-runyu.xiao@seu.edu.cn>

Andreas, any thoughts?

On Mon, 15 Jun 2026, Runyu Xiao wrote:

> menf21bmc_led_set() serializes access with a mutex and performs I2C
> transfers, but the driver exposes it through brightness_set.  That
> mismatches the LED core callback contract for atomic callers.
> 
> This issue was found by our static analysis tool and then manually
> reviewed against the current tree.
> 
> A minimal Lockdep reproducer that keeps the original registration and
> call chain is enough to trigger the warning: menf21bmc_led_probe()
> still publishes menf21bmc_led_set() as brightness_set,
> led_trigger_event_atomic() invokes it under spin_lock_irqsave(), and
> the callback immediately tries mutex_lock(&led_lock) before reaching
> its I2C accesses.
> 
> Lockdep reports:
> 
>   BUG: sleeping function called from invalid context
>   __mutex_lock+0x4f/0xd20
>   menf21bmc_led_set+0x15/0x49 [vuln_msv]
>   [ BUG: Invalid wait context ]
>   ... (led_lock#2) ... at: menf21bmc_led_set+0x15/0x49 [vuln_msv]
> 
> Convert the driver to brightness_set_blocking and return the transport
> status to the LED core.
> 
> Fixes: 38433639af91 ("leds: leds-menf21bmc: Introduce MEN 14F021P00 BMC LED driver")
> Cc: stable@vger.kernel.org
> Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
> ---
> Notes:
>   - Validated with a grounded Lockdep PoC that preserves the
>     menf21bmc_led_probe() brightness_set registration and the
>     led_trigger_event_atomic() -> menf21bmc_led_set() ->
>     mutex_lock(&led_lock) path.
>   - checkpatch.pl --strict: clean.
>   - Not tested on MEN 14F021P00 BMC hardware.
> 
>  drivers/leds/leds-menf21bmc.c | 18 ++++++++++++------
>  1 file changed, 12 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/leds/leds-menf21bmc.c b/drivers/leds/leds-menf21bmc.c
> index 6b1b47160602..da476fe6ed2c 100644
> --- a/drivers/leds/leds-menf21bmc.c
> +++ b/drivers/leds/leds-menf21bmc.c
> @@ -49,28 +49,33 @@ static struct menf21bmc_led leds[] = {
>  
>  static DEFINE_MUTEX(led_lock);
>  
> -static void
> -menf21bmc_led_set(struct led_classdev *led_cdev, enum led_brightness value)
> +static int
> +menf21bmc_led_set_blocking(struct led_classdev *led_cdev,
> +			   enum led_brightness value)
>  {
>  	int led_val;
> +	int ret = 0;
>  	struct menf21bmc_led *led = container_of(led_cdev,
>  					struct menf21bmc_led, cdev);
>  
>  	mutex_lock(&led_lock);
>  	led_val = i2c_smbus_read_byte_data(led->i2c_client,
>  					   BMC_CMD_LED_GET_SET);
> -	if (led_val < 0)
> +	if (led_val < 0) {
> +		ret = led_val;
>  		goto err_out;
> +	}
>  
>  	if (value == LED_OFF)
>  		led_val &= ~led->led_bit;
>  	else
>  		led_val |= led->led_bit;
>  
> -	i2c_smbus_write_byte_data(led->i2c_client,
> -				  BMC_CMD_LED_GET_SET, led_val);
> +	ret = i2c_smbus_write_byte_data(led->i2c_client,
> +					BMC_CMD_LED_GET_SET, led_val);
>  err_out:
>  	mutex_unlock(&led_lock);
> +	return ret;
>  }
>  
>  static int menf21bmc_led_probe(struct platform_device *pdev)
> @@ -81,7 +86,8 @@ static int menf21bmc_led_probe(struct platform_device *pdev)
>  
>  	for (i = 0; i < ARRAY_SIZE(leds); i++) {
>  		leds[i].cdev.name = leds[i].name;
> -		leds[i].cdev.brightness_set = menf21bmc_led_set;
> +		leds[i].cdev.brightness_set_blocking =
> +			menf21bmc_led_set_blocking;
>  		leds[i].i2c_client = i2c_client;
>  		ret = devm_led_classdev_register(&pdev->dev, &leds[i].cdev);
>  		if (ret < 0) {
> -- 
> 2.34.1

-- 
Lee Jones

      reply	other threads:[~2026-07-02 10:45 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-15 14:57 [PATCH 0/2] leds: use brightness_set_blocking for sleepable callbacks Runyu Xiao
2026-06-15 14:57 ` [PATCH 1/2] leds: lm3530: use brightness_set_blocking for sleepable callback Runyu Xiao
2026-07-02 10:20   ` Lee Jones
2026-06-15 14:57 ` [PATCH 2/2] leds: menf21bmc: " Runyu Xiao
2026-07-02 10:45   ` 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=20260702104510.GI2108533@google.com \
    --to=lee@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=andreas.werner@men.de \
    --cc=cooloney@gmail.com \
    --cc=jianhao.xu@seu.edu.cn \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-leds@vger.kernel.org \
    --cc=pavel@kernel.org \
    --cc=runyu.xiao@seu.edu.cn \
    --cc=shreshthakumar.sahu@stericsson.com \
    --cc=stable@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.