Skip to content

Commit 9deba7b

Browse files
lumaggregkh
authored andcommitted
led: qcom-lpg: Fix sleeping in atomic
[ Upstream commit 3031993 ] lpg_brighness_set() function can sleep, while led's brightness_set() callback must be non-blocking. Change LPG driver to use brightness_set_blocking() instead. BUG: sleeping function called from invalid context at kernel/locking/mutex.c:580 in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 0, name: swapper/0 preempt_count: 101, expected: 0 INFO: lockdep is turned off. CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 6.1.0-rc1-00014-gbe99b089c6fc-dirty raspberrypi#85 Hardware name: Qualcomm Technologies, Inc. DB820c (DT) Call trace: dump_backtrace.part.0+0xe4/0xf0 show_stack+0x18/0x40 dump_stack_lvl+0x88/0xb4 dump_stack+0x18/0x34 __might_resched+0x170/0x254 __might_sleep+0x48/0x9c __mutex_lock+0x4c/0x400 mutex_lock_nested+0x2c/0x40 lpg_brightness_single_set+0x40/0x90 led_set_brightness_nosleep+0x34/0x60 led_heartbeat_function+0x80/0x170 call_timer_fn+0xb8/0x340 __run_timers.part.0+0x20c/0x254 run_timer_softirq+0x3c/0x7c _stext+0x14c/0x578 ____do_softirq+0x10/0x20 call_on_irq_stack+0x2c/0x5c do_softirq_own_stack+0x1c/0x30 __irq_exit_rcu+0x164/0x170 irq_exit_rcu+0x10/0x40 el1_interrupt+0x38/0x50 el1h_64_irq_handler+0x18/0x2c el1h_64_irq+0x64/0x68 cpuidle_enter_state+0xc8/0x380 cpuidle_enter+0x38/0x50 do_idle+0x244/0x2d0 cpu_startup_entry+0x24/0x30 rest_init+0x128/0x1a0 arch_post_acpi_subsys_init+0x0/0x18 start_kernel+0x6f4/0x734 __primary_switched+0xbc/0xc4 Fixes: 24e2d05 ("leds: Add driver for Qualcomm LPG") Signed-off-by: Dmitry Baryshkov <[email protected]> Signed-off-by: Pavel Machek <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 87336b6 commit 9deba7b

File tree

1 file changed

+11
-7
lines changed

1 file changed

+11
-7
lines changed

drivers/leds/rgb/leds-qcom-lpg.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -602,8 +602,8 @@ static void lpg_brightness_set(struct lpg_led *led, struct led_classdev *cdev,
602602
lpg_lut_sync(lpg, lut_mask);
603603
}
604604

605-
static void lpg_brightness_single_set(struct led_classdev *cdev,
606-
enum led_brightness value)
605+
static int lpg_brightness_single_set(struct led_classdev *cdev,
606+
enum led_brightness value)
607607
{
608608
struct lpg_led *led = container_of(cdev, struct lpg_led, cdev);
609609
struct mc_subled info;
@@ -614,10 +614,12 @@ static void lpg_brightness_single_set(struct led_classdev *cdev,
614614
lpg_brightness_set(led, cdev, &info);
615615

616616
mutex_unlock(&led->lpg->lock);
617+
618+
return 0;
617619
}
618620

619-
static void lpg_brightness_mc_set(struct led_classdev *cdev,
620-
enum led_brightness value)
621+
static int lpg_brightness_mc_set(struct led_classdev *cdev,
622+
enum led_brightness value)
621623
{
622624
struct led_classdev_mc *mc = lcdev_to_mccdev(cdev);
623625
struct lpg_led *led = container_of(mc, struct lpg_led, mcdev);
@@ -628,6 +630,8 @@ static void lpg_brightness_mc_set(struct led_classdev *cdev,
628630
lpg_brightness_set(led, cdev, mc->subled_info);
629631

630632
mutex_unlock(&led->lpg->lock);
633+
634+
return 0;
631635
}
632636

633637
static int lpg_blink_set(struct lpg_led *led,
@@ -1118,7 +1122,7 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np)
11181122
led->mcdev.num_colors = num_channels;
11191123

11201124
cdev = &led->mcdev.led_cdev;
1121-
cdev->brightness_set = lpg_brightness_mc_set;
1125+
cdev->brightness_set_blocking = lpg_brightness_mc_set;
11221126
cdev->blink_set = lpg_blink_mc_set;
11231127

11241128
/* Register pattern accessors only if we have a LUT block */
@@ -1132,7 +1136,7 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np)
11321136
return ret;
11331137

11341138
cdev = &led->cdev;
1135-
cdev->brightness_set = lpg_brightness_single_set;
1139+
cdev->brightness_set_blocking = lpg_brightness_single_set;
11361140
cdev->blink_set = lpg_blink_single_set;
11371141

11381142
/* Register pattern accessors only if we have a LUT block */
@@ -1151,7 +1155,7 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np)
11511155
else
11521156
cdev->brightness = LED_OFF;
11531157

1154-
cdev->brightness_set(cdev, cdev->brightness);
1158+
cdev->brightness_set_blocking(cdev, cdev->brightness);
11551159

11561160
init_data.fwnode = of_fwnode_handle(np);
11571161

0 commit comments

Comments
 (0)