Skip to content

Commit d32e5f4

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input fixes from Dmitry Torokhov: - fixes for two long standing issues (lock up and a crash) in force feedback handling in uinput driver - tweak to firmware update timing in Elan I2C touchpad driver. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: elan_i2c - extend Flash-Write delay Input: uinput - avoid crash when sending FF request to device going away Input: uinput - avoid FF flush when destroying device
2 parents c0a3a64 + 05f5c38 commit d32e5f4

File tree

4 files changed

+51
-22
lines changed

4 files changed

+51
-22
lines changed

drivers/input/ff-core.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,15 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file)
237237
EXPORT_SYMBOL_GPL(input_ff_erase);
238238

239239
/*
240-
* flush_effects - erase all effects owned by a file handle
240+
* input_ff_flush - erase all effects owned by a file handle
241+
* @dev: input device to erase effect from
242+
* @file: purported owner of the effects
243+
*
244+
* This function erases all force-feedback effects associated with
245+
* the given owner from specified device. Note that @file may be %NULL,
246+
* in which case all effects will be erased.
241247
*/
242-
static int flush_effects(struct input_dev *dev, struct file *file)
248+
int input_ff_flush(struct input_dev *dev, struct file *file)
243249
{
244250
struct ff_device *ff = dev->ff;
245251
int i;
@@ -255,6 +261,7 @@ static int flush_effects(struct input_dev *dev, struct file *file)
255261

256262
return 0;
257263
}
264+
EXPORT_SYMBOL_GPL(input_ff_flush);
258265

259266
/**
260267
* input_ff_event() - generic handler for force-feedback events
@@ -343,7 +350,7 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
343350
mutex_init(&ff->mutex);
344351

345352
dev->ff = ff;
346-
dev->flush = flush_effects;
353+
dev->flush = input_ff_flush;
347354
dev->event = input_ff_event;
348355
__set_bit(EV_FF, dev->evbit);
349356

drivers/input/misc/uinput.c

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,15 @@ static int uinput_request_reserve_slot(struct uinput_device *udev,
9898
uinput_request_alloc_id(udev, request));
9999
}
100100

101-
static void uinput_request_done(struct uinput_device *udev,
102-
struct uinput_request *request)
101+
static void uinput_request_release_slot(struct uinput_device *udev,
102+
unsigned int id)
103103
{
104104
/* Mark slot as available */
105-
udev->requests[request->id] = NULL;
106-
wake_up(&udev->requests_waitq);
105+
spin_lock(&udev->requests_lock);
106+
udev->requests[id] = NULL;
107+
spin_unlock(&udev->requests_lock);
107108

108-
complete(&request->done);
109+
wake_up(&udev->requests_waitq);
109110
}
110111

111112
static int uinput_request_send(struct uinput_device *udev,
@@ -138,20 +139,22 @@ static int uinput_request_send(struct uinput_device *udev,
138139
static int uinput_request_submit(struct uinput_device *udev,
139140
struct uinput_request *request)
140141
{
141-
int error;
142+
int retval;
142143

143-
error = uinput_request_reserve_slot(udev, request);
144-
if (error)
145-
return error;
144+
retval = uinput_request_reserve_slot(udev, request);
145+
if (retval)
146+
return retval;
146147

147-
error = uinput_request_send(udev, request);
148-
if (error) {
149-
uinput_request_done(udev, request);
150-
return error;
151-
}
148+
retval = uinput_request_send(udev, request);
149+
if (retval)
150+
goto out;
152151

153152
wait_for_completion(&request->done);
154-
return request->retval;
153+
retval = request->retval;
154+
155+
out:
156+
uinput_request_release_slot(udev, request->id);
157+
return retval;
155158
}
156159

157160
/*
@@ -169,7 +172,7 @@ static void uinput_flush_requests(struct uinput_device *udev)
169172
request = udev->requests[i];
170173
if (request) {
171174
request->retval = -ENODEV;
172-
uinput_request_done(udev, request);
175+
complete(&request->done);
173176
}
174177
}
175178

@@ -230,6 +233,18 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
230233
return uinput_request_submit(udev, &request);
231234
}
232235

236+
static int uinput_dev_flush(struct input_dev *dev, struct file *file)
237+
{
238+
/*
239+
* If we are called with file == NULL that means we are tearing
240+
* down the device, and therefore we can not handle FF erase
241+
* requests: either we are handling UI_DEV_DESTROY (and holding
242+
* the udev->mutex), or the file descriptor is closed and there is
243+
* nobody on the other side anymore.
244+
*/
245+
return file ? input_ff_flush(dev, file) : 0;
246+
}
247+
233248
static void uinput_destroy_device(struct uinput_device *udev)
234249
{
235250
const char *name, *phys;
@@ -297,6 +312,12 @@ static int uinput_create_device(struct uinput_device *udev)
297312
dev->ff->playback = uinput_dev_playback;
298313
dev->ff->set_gain = uinput_dev_set_gain;
299314
dev->ff->set_autocenter = uinput_dev_set_autocenter;
315+
/*
316+
* The standard input_ff_flush() implementation does
317+
* not quite work for uinput as we can't reasonably
318+
* handle FF requests during device teardown.
319+
*/
320+
dev->flush = uinput_dev_flush;
300321
}
301322

302323
error = input_register_device(udev->dev);
@@ -939,7 +960,7 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
939960
}
940961

941962
req->retval = ff_up.retval;
942-
uinput_request_done(udev, req);
963+
complete(&req->done);
943964
goto out;
944965

945966
case UI_END_FF_ERASE:
@@ -955,7 +976,7 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
955976
}
956977

957978
req->retval = ff_erase.retval;
958-
uinput_request_done(udev, req);
979+
complete(&req->done);
959980
goto out;
960981
}
961982

drivers/input/mouse/elan_i2c_i2c.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ static int elan_i2c_write_fw_block(struct i2c_client *client,
598598
}
599599

600600
/* Wait for F/W to update one page ROM data. */
601-
msleep(20);
601+
msleep(35);
602602

603603
error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CTRL_CMD, val);
604604
if (error) {

include/linux/input.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ int input_ff_event(struct input_dev *dev, unsigned int type, unsigned int code,
529529

530530
int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, struct file *file);
531531
int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file);
532+
int input_ff_flush(struct input_dev *dev, struct file *file);
532533

533534
int input_ff_create_memless(struct input_dev *dev, void *data,
534535
int (*play_effect)(struct input_dev *, void *, struct ff_effect *));

0 commit comments

Comments
 (0)