Hi!

> >This fixes one problem:

> >Signed-off-by: Pavel Machek <pa...@ucw.cz>
> >
> >diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
> >index e3da7c0..d795d8f 100644
> >--- a/drivers/leds/led-core.c
> >+++ b/drivers/leds/led-core.c
> >@@ -164,8 +164,14 @@ static void led_blink_setup(struct led_classdev 
> >*led_cdev,
> >                  unsigned long *delay_on,
> >                  unsigned long *delay_off)
> >  {
> >+    while (work_pending(&led_cdev->set_brightness_work)) {
> >+            printk("Waiting for brightness set to finish\n");
> >+            schedule();
> >+    }
> 
> Or even better:
> 
> flush_work(&led_cdev->set_brightness_work);

Yup, thanks for a hint.

I should have acceptable patch, soon; but no promises I catched all
similar bugs, that code is quite ... tricky.

So far I have this:

diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 3c7e348..85848c5 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -57,6 +57,7 @@ static ssize_t brightness_store(struct device *dev,
        if (state == LED_OFF)
                led_trigger_remove(led_cdev);
        led_set_brightness(led_cdev, state);
+       flush_work(&led_cdev->set_brightness_work);
 
        ret = size;
 unlock:
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index e3da7c0..e9ae7f8 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -164,6 +164,11 @@ static void led_blink_setup(struct led_classdev *led_cdev,
                     unsigned long *delay_on,
                     unsigned long *delay_off)
 {
+       /*
+        * If "set brightness to 0" is pending in workqueue, we don't
+        * want that to be reordered after blink_set()
+        */
+       flush_work(&led_cdev->set_brightness_work);
        if (!test_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags) &&
            led_cdev->blink_set &&
            !led_cdev->blink_set(led_cdev, delay_on, delay_off))
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 2d451b6..ddfd2dd 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -65,6 +65,7 @@ ssize_t led_trigger_store(struct device *dev, struct 
device_attribute *attr,
        up_read(&triggers_list_lock);
 
 unlock:
+       flush_work(&led_cdev->set_brightness_work);
        mutex_unlock(&led_cdev->led_access);
        return ret;
 }
diff --git a/drivers/leds/trigger/ledtrig-timer.c 
b/drivers/leds/trigger/ledtrig-timer.c
index ca898c1..0b061bb5 100644
--- a/drivers/leds/trigger/ledtrig-timer.c
+++ b/drivers/leds/trigger/ledtrig-timer.c
@@ -104,6 +104,7 @@ static void pattern_init(struct led_classdev *led_cdev)
 
 static int timer_trig_activate(struct led_classdev *led_cdev)
 {
+       printk("timer_trig_activate\n");
        if (led_cdev->flags & LED_INIT_DEFAULT_TRIGGER) {
                pattern_init(led_cdev);
                /*
@@ -115,14 +116,18 @@ static int timer_trig_activate(struct led_classdev 
*led_cdev)
 
        led_blink_set(led_cdev, &led_cdev->blink_delay_on,
                      &led_cdev->blink_delay_off);
+       printk("timer_trig_activate done\n");
 
        return 0;
 }
 
 static void timer_trig_deactivate(struct led_classdev *led_cdev)
 {
+       printk("timer_trig_deactivate\n");
        /* Stop blinking */
        led_set_brightness(led_cdev, LED_OFF);
+
+       printk("timer_trig_deactivate done\n");
 }
 
 static struct led_trigger timer_led_trigger = {
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 3a4402a..b3fa9c9 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -363,11 +363,11 @@ int mmc_of_parse_voltage(struct device_node *np, u32 
*mask)
        int num_ranges, i;
 
        voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
-       num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
        if (!voltage_ranges) {
                pr_debug("%pOF: voltage-ranges unspecified\n", np);
                return 0;
        }
+       num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
        if (!num_ranges) {
                pr_err("%pOF: voltage-ranges empty\n", np);
                return -EINVAL;
diff --git a/drivers/platform/x86/thinkpad_acpi.c 
b/drivers/platform/x86/thinkpad_acpi.c
index 57d9ae9..3580bab 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -5867,6 +5867,8 @@ static int led_set_status(const unsigned int led,
 
        int rc = 0;
 
+       printk("LED set %d to %d\n", led, ledstatus);
+
        switch (led_supported) {
        case TPACPI_LED_570:
                /* 570 */
@@ -5876,7 +5878,7 @@ static int led_set_status(const unsigned int led,
                        return -EPERM;
                if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
                                (1 << led), led_sled_arg1[ledstatus]))
-                       rc = -EIO;
+                       return -EIO;
                break;
        case TPACPI_LED_OLD:
                /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
@@ -5900,12 +5902,14 @@ static int led_set_status(const unsigned int led,
                        return -EPERM;
                if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
                                led, led_led_arg1[ledstatus]))
-                       rc = -EIO;
+                       return -EIO;
                break;
        default:
-               rc = -ENXIO;
+               return -ENXIO;
        }
 
+       printk("LED set %d to %d... %d\n", led, ledstatus, rc);
+
        if (!rc)
                tpacpi_led_state_cache[led] = ledstatus;
 
@@ -5919,6 +5923,8 @@ static int led_sysfs_set(struct led_classdev *led_cdev,
                             struct tpacpi_led_classdev, led_classdev);
        enum led_status_t new_state;
 
+       printk("sysfs_set %d\n", brightness);
+
        if (brightness == LED_OFF)
                new_state = TPACPI_LED_OFF;
        else if (tpacpi_led_state_cache[data->led] != TPACPI_LED_BLINK)
@@ -5935,6 +5941,8 @@ static int led_sysfs_blink_set(struct led_classdev 
*led_cdev,
        struct tpacpi_led_classdev *data = container_of(led_cdev,
                             struct tpacpi_led_classdev, led_classdev);
 
+       printk("sysfs_blink_set\n");
+
        /* Can we choose the flash rate? */
        if (*delay_on == 0 && *delay_off == 0) {
                /* yes. set them to the hardware blink rate (1 Hz) */
@@ -5943,6 +5951,7 @@ static int led_sysfs_blink_set(struct led_classdev 
*led_cdev,
        } else if ((*delay_on != 500) || (*delay_off != 500))
                return -EINVAL;
 
+       printk("sysfs_blink_set: hardware can do it\n");
        return led_set_status(data->led, TPACPI_LED_BLINK);
 }
 

                                                                Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

Attachment: signature.asc
Description: Digital signature

_______________________________________________
ibm-acpi-devel mailing list
ibm-acpi-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ibm-acpi-devel

Reply via email to