aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/input-polldev.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2014-04-28 16:16:00 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-05-14 19:40:03 -0400
commitd1fefd5b73ba9fe301441e84ebea06044d8f5ea4 (patch)
tree6fb8fb7babfc6194047603a859ee5f60da190a62 /drivers/input/input-polldev.c
parent27245519f0de50b005323c6cd8560ce77c1b42ae (diff)
Input: remove race when instantiating polled device attributes
Polled device's attributes controlling polling rate and whether polling is enabled are attached to input device. We should have device core instantiate them for us, so that they are created by the time new device notification is sent to userspace, instead of doing it ourselves afterwards. Tested-by: Alexander Shiyan <shc_work@mail.ru> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/input-polldev.c')
-rw-r--r--drivers/input/input-polldev.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
index 7f161d93203c..4b191908d5de 100644
--- a/drivers/input/input-polldev.c
+++ b/drivers/input/input-polldev.c
@@ -147,6 +147,11 @@ static struct attribute_group input_polldev_attribute_group = {
147 .attrs = sysfs_attrs 147 .attrs = sysfs_attrs
148}; 148};
149 149
150static const struct attribute_group *input_polldev_attribute_groups[] = {
151 &input_polldev_attribute_group,
152 NULL
153};
154
150/** 155/**
151 * input_allocate_polled_device - allocate memory for polled device 156 * input_allocate_polled_device - allocate memory for polled device
152 * 157 *
@@ -204,24 +209,21 @@ int input_register_polled_device(struct input_polled_dev *dev)
204 209
205 input_set_drvdata(input, dev); 210 input_set_drvdata(input, dev);
206 INIT_DELAYED_WORK(&dev->work, input_polled_device_work); 211 INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
212
207 if (!dev->poll_interval) 213 if (!dev->poll_interval)
208 dev->poll_interval = 500; 214 dev->poll_interval = 500;
209 if (!dev->poll_interval_max) 215 if (!dev->poll_interval_max)
210 dev->poll_interval_max = dev->poll_interval; 216 dev->poll_interval_max = dev->poll_interval;
217
211 input->open = input_open_polled_device; 218 input->open = input_open_polled_device;
212 input->close = input_close_polled_device; 219 input->close = input_close_polled_device;
213 220
221 input->dev.groups = input_polldev_attribute_groups;
222
214 error = input_register_device(input); 223 error = input_register_device(input);
215 if (error) 224 if (error)
216 return error; 225 return error;
217 226
218 error = sysfs_create_group(&input->dev.kobj,
219 &input_polldev_attribute_group);
220 if (error) {
221 input_unregister_device(input);
222 return error;
223 }
224
225 /* 227 /*
226 * Take extra reference to the underlying input device so 228 * Take extra reference to the underlying input device so
227 * that it survives call to input_unregister_polled_device() 229 * that it survives call to input_unregister_polled_device()
@@ -245,9 +247,6 @@ EXPORT_SYMBOL(input_register_polled_device);
245 */ 247 */
246void input_unregister_polled_device(struct input_polled_dev *dev) 248void input_unregister_polled_device(struct input_polled_dev *dev)
247{ 249{
248 sysfs_remove_group(&dev->input->dev.kobj,
249 &input_polldev_attribute_group);
250
251 input_unregister_device(dev->input); 250 input_unregister_device(dev->input);
252} 251}
253EXPORT_SYMBOL(input_unregister_polled_device); 252EXPORT_SYMBOL(input_unregister_polled_device);