[PATCH 16/20] GTA01: replace mutex with spinlock in neo1973_vib_vib_set

Jonas Bonn jonas.bonn at gmail.com
Wed Oct 1 21:47:28 CEST 2008


This function (set_brightness) may be called in interrupt context and
therefore should not sleep; use a spin_lock instead of a mutex to ensure
this.

This should take care of the following BUG:

[21474678.340000] BUG: sleeping function called from invalid context at kernel/mutex.c:207
[21474678.340000] in_atomic():1, irqs_disabled():0
[21474678.340000] no locks held by python/1255.
[21474678.340000] [<c002d928>] (dump_stack+0x0/0x18) from [<c003b08c>] (__might_sleep+0xdc/0xf8)
[21474678.340000] [<c003afb0>] (__might_sleep+0x0/0xf8) from [<c02efc08>] (mutex_lock_nested+0x2c/0x264)
[21474678.340000]  r5:c03ed754 r4:c03ed6dc
[21474678.340000] [<c02efbdc>] (mutex_lock_nested+0x0/0x264) from [<c022e180>] (neo1973_vib_vib_set+0x2c/0x6c)
[21474678.340000] [<c022e154>] (neo1973_vib_vib_set+0x0/0x6c) from [<c022e6a4>] (led_timer_function+0x8c/0xb4)
[21474678.340000]  r6:c041a1a0 r5:c7f34820 r4:0000012c
[21474678.340000] [<c022e618>] (led_timer_function+0x0/0xb4) from [<c004aeb4>] (run_timer_softirq+0x180/0x20c)
[21474678.340000]  r5:c7f3482c r4:00000102
[21474678.340000] [<c004ad34>] (run_timer_softirq+0x0/0x20c) from [<c0046368>] (__do_softirq+0x64/0xd8)
[21474678.340000]  r8:00000000 r7:00000001 r6:0000000a r5:c0419ff8 r4:00000041
[21474678.340000] [<c0046304>] (__do_softirq+0x0/0xd8) from [<c0046764>] (irq_exit+0x48/0x5c)
[21474678.340000]  r6:00000000 r5:c03d128c r4:0000001e
[21474678.340000] [<c004671c>] (irq_exit+0x0/0x5c) from [<c0028050>] (__exception_text_start+0x50/0x68)
[21474678.340000] [<c0028000>] (__exception_text_start+0x0/0x68) from [<c0028a8c>] (__irq_usr+0x4c/0xe0)
[21474678.340000] Exception stack(0xc7d7bfb0 to 0xc7d7bff8)
[21474678.340000] bfa0:                                     0055bb3a 0000004a 00000000 0055baf0
[21474678.340000] bfc0: 0000004a 0052ae30 00000025 005168e0 00000073 00000025 401281ec 00000000
[21474678.340000] bfe0: 0000006f be9b8470 006e0069 400a8844 60000010 ffffffff
[21474678.340000]  r6:00004000 r5:f4000000 r4:ffffffff

Signed-off-by: Jonas Bonn <jonas.bonn at gmail.com>
---
 drivers/leds/leds-neo1973-vibrator.c |   12 +++++-------
 1 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/leds/leds-neo1973-vibrator.c b/drivers/leds/leds-neo1973-vibrator.c
index 1c4db5d..494fb83 100644
--- a/drivers/leds/leds-neo1973-vibrator.c
+++ b/drivers/leds/leds-neo1973-vibrator.c
@@ -33,7 +33,7 @@
 struct neo1973_vib_priv {
 	struct led_classdev cdev;
 	unsigned int gpio;
-	struct mutex mutex;
+	spinlock_t lock;
 	unsigned int has_pwm;
 	struct s3c2410_pwm pwm;
 };
@@ -41,6 +41,7 @@ struct neo1973_vib_priv {
 static void neo1973_vib_vib_set(struct led_classdev *led_cdev,
 		enum led_brightness value)
 {
+	unsigned long flags;
 	struct neo1973_vib_priv *vp =
 		container_of(led_cdev, struct neo1973_vib_priv, cdev);
 
@@ -56,7 +57,7 @@ static void neo1973_vib_vib_set(struct led_classdev *led_cdev,
 	 * value == 128 -> 50% duty cycle (medium power)
 	 * value == 0 -> 0% duty cycle (zero power)
 	 */
-	mutex_lock(&vp->mutex);
+	spin_lock_irqsave(&vp->lock, flags);
 	if (vp->has_pwm)
 		s3c2410_pwm_duty_cycle(value / 4, &vp->pwm);
 	else {
@@ -65,8 +66,7 @@ static void neo1973_vib_vib_set(struct led_classdev *led_cdev,
 		else
 			neo1973_gpb_setpin(vp->gpio, 0);
 	}
-
-	mutex_unlock(&vp->mutex);
+	spin_unlock_irqrestore(&vp->lock, flags);
 }
 
 static struct neo1973_vib_priv neo1973_vib_led = {
@@ -159,7 +159,7 @@ static int __init neo1973_vib_probe(struct platform_device *pdev)
 #ifdef CONFIG_MACH_NEO1973_GTA02
 configured:
 #endif
-	mutex_init(&neo1973_vib_led.mutex);
+	spin_lock_init(&neo1973_vib_led.lock);
 
 	return led_classdev_register(&pdev->dev, &neo1973_vib_led.cdev);
 }
@@ -177,8 +177,6 @@ static int neo1973_vib_remove(struct platform_device *pdev)
 
 	led_classdev_unregister(&neo1973_vib_led.cdev);
 
-	mutex_destroy(&neo1973_vib_led.mutex);
-
 	return 0;
 }
 
-- 
1.5.4.3




More information about the openmoko-kernel mailing list