aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2016-07-13 12:06:11 -0400
committerJiri Kosina <jkosina@suse.cz>2016-08-05 07:39:19 -0400
commit589e5060206b97a9602534d19d53264d35cd969f (patch)
tree4188bd6d26b9f19f1101eeac5c83714f261a348b
parent97f5541fc0c7ed107103e6f87a6522f5327ab4b0 (diff)
HID: wacom: leds: actually release the LEDs on disconnect
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>
-rw-r--r--drivers/hid/wacom.h1
-rw-r--r--drivers/hid/wacom_sys.c27
2 files changed, 27 insertions, 1 deletions
diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h
index 0c498c46de5f..9159dd3e4b90 100644
--- a/drivers/hid/wacom.h
+++ b/drivers/hid/wacom.h
@@ -130,6 +130,7 @@ struct wacom_group_leds {
130 u8 select; /* status led selector (0..3) */ 130 u8 select; /* status led selector (0..3) */
131 struct wacom_led *leds; 131 struct wacom_led *leds;
132 unsigned int count; 132 unsigned int count;
133 struct device *dev;
133}; 134};
134 135
135struct wacom_battery { 136struct wacom_battery {
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index c5d518da0d0f..3a651e288776 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -1068,6 +1068,13 @@ static int wacom_led_register_one(struct device *dev, struct wacom *wacom,
1068 return 0; 1068 return 0;
1069} 1069}
1070 1070
1071static void wacom_led_groups_release_one(void *data)
1072{
1073 struct wacom_group_leds *group = data;
1074
1075 devres_release_group(group->dev, group);
1076}
1077
1071static int wacom_led_groups_alloc_and_register_one(struct device *dev, 1078static int wacom_led_groups_alloc_and_register_one(struct device *dev,
1072 struct wacom *wacom, 1079 struct wacom *wacom,
1073 int group_id, int count, 1080 int group_id, int count,
@@ -1098,7 +1105,25 @@ static int wacom_led_groups_alloc_and_register_one(struct device *dev,
1098 goto err; 1105 goto err;
1099 } 1106 }
1100 1107
1101 devres_remove_group(dev, &wacom->led.groups[group_id]); 1108 wacom->led.groups[group_id].dev = dev;
1109
1110 devres_close_group(dev, &wacom->led.groups[group_id]);
1111
1112 /*
1113 * There is a bug (?) in devm_led_classdev_register() in which its
1114 * increments the refcount of the parent. If the parent is an input
1115 * device, that means the ref count never reaches 0 when
1116 * devm_input_device_release() gets called.
1117 * This means that the LEDs are still there after disconnect.
1118 * Manually force the release of the group so that the leds are released
1119 * once we are done using them.
1120 */
1121 error = devm_add_action_or_reset(&wacom->hdev->dev,
1122 wacom_led_groups_release_one,
1123 &wacom->led.groups[group_id]);
1124 if (error)
1125 return error;
1126
1102 return 0; 1127 return 0;
1103 1128
1104err: 1129err: