HID: wacom: leds: actually release the LEDs on disconnect
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>
Wed, 13 Jul 2016 16:06:11 +0000 (18:06 +0200)
committerJiri Kosina <jkosina@suse.cz>
Fri, 5 Aug 2016 11:39:19 +0000 (13:39 +0200)
There is a bug (?) in devm_led_classdev_register() in which its increments
the refcount of the parent. If the parent is an input device, that means
the ref count never reaches 0 when devm_input_device_release() gets called.
This means that the LEDs and all the devres resources attached to the
input device are not released.

Manually force the release of the group so that the leds are released once
we are done using them.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Acked-by: Ping Cheng <pingc@wacom.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
drivers/hid/wacom.h
drivers/hid/wacom_sys.c

index 0c498c46de5fa6e8741f314cb5fd7ae4f2d30046..9159dd3e4b902490e46f04144751f91e3e3e5c78 100644 (file)
@@ -130,6 +130,7 @@ struct wacom_group_leds {
        u8 select; /* status led selector (0..3) */
        struct wacom_led *leds;
        unsigned int count;
+       struct device *dev;
 };
 
 struct wacom_battery {
index c5d518da0d0f164fc72db99a3f7cee05f1de47a5..3a651e28877609fcfecb0d96d8130c48567f2cfb 100644 (file)
@@ -1068,6 +1068,13 @@ static int wacom_led_register_one(struct device *dev, struct wacom *wacom,
        return 0;
 }
 
+static void wacom_led_groups_release_one(void *data)
+{
+       struct wacom_group_leds *group = data;
+
+       devres_release_group(group->dev, group);
+}
+
 static int wacom_led_groups_alloc_and_register_one(struct device *dev,
                                                   struct wacom *wacom,
                                                   int group_id, int count,
@@ -1098,7 +1105,25 @@ static int wacom_led_groups_alloc_and_register_one(struct device *dev,
                        goto err;
        }
 
-       devres_remove_group(dev, &wacom->led.groups[group_id]);
+       wacom->led.groups[group_id].dev = dev;
+
+       devres_close_group(dev, &wacom->led.groups[group_id]);
+
+       /*
+        * There is a bug (?) in devm_led_classdev_register() in which its
+        * increments the refcount of the parent. If the parent is an input
+        * device, that means the ref count never reaches 0 when
+        * devm_input_device_release() gets called.
+        * This means that the LEDs are still there after disconnect.
+        * Manually force the release of the group so that the leds are released
+        * once we are done using them.
+        */
+       error = devm_add_action_or_reset(&wacom->hdev->dev,
+                                        wacom_led_groups_release_one,
+                                        &wacom->led.groups[group_id]);
+       if (error)
+               return error;
+
        return 0;
 
 err: