diff options
| -rw-r--r-- | drivers/input/ff-core.c | 20 | ||||
| -rw-r--r-- | drivers/input/ff-memless.c | 26 | ||||
| -rw-r--r-- | drivers/input/input.c | 29 | ||||
| -rw-r--r-- | drivers/input/keyboard/atkbd.c | 13 | ||||
| -rw-r--r-- | drivers/input/mouse/psmouse-base.c | 2 | ||||
| -rw-r--r-- | include/linux/input.h | 4 |
6 files changed, 58 insertions, 36 deletions
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 72c63e5dd630..38df81fcdc3a 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c | |||
| @@ -337,16 +337,16 @@ int input_ff_create(struct input_dev *dev, int max_effects) | |||
| 337 | dev->ff = ff; | 337 | dev->ff = ff; |
| 338 | dev->flush = flush_effects; | 338 | dev->flush = flush_effects; |
| 339 | dev->event = input_ff_event; | 339 | dev->event = input_ff_event; |
| 340 | set_bit(EV_FF, dev->evbit); | 340 | __set_bit(EV_FF, dev->evbit); |
| 341 | 341 | ||
| 342 | /* Copy "true" bits into ff device bitmap */ | 342 | /* Copy "true" bits into ff device bitmap */ |
| 343 | for (i = 0; i <= FF_MAX; i++) | 343 | for (i = 0; i <= FF_MAX; i++) |
| 344 | if (test_bit(i, dev->ffbit)) | 344 | if (test_bit(i, dev->ffbit)) |
| 345 | set_bit(i, ff->ffbit); | 345 | __set_bit(i, ff->ffbit); |
| 346 | 346 | ||
| 347 | /* we can emulate RUMBLE with periodic effects */ | 347 | /* we can emulate RUMBLE with periodic effects */ |
| 348 | if (test_bit(FF_PERIODIC, ff->ffbit)) | 348 | if (test_bit(FF_PERIODIC, ff->ffbit)) |
| 349 | set_bit(FF_RUMBLE, dev->ffbit); | 349 | __set_bit(FF_RUMBLE, dev->ffbit); |
| 350 | 350 | ||
| 351 | return 0; | 351 | return 0; |
| 352 | } | 352 | } |
| @@ -362,12 +362,14 @@ EXPORT_SYMBOL_GPL(input_ff_create); | |||
| 362 | */ | 362 | */ |
| 363 | void input_ff_destroy(struct input_dev *dev) | 363 | void input_ff_destroy(struct input_dev *dev) |
| 364 | { | 364 | { |
| 365 | clear_bit(EV_FF, dev->evbit); | 365 | struct ff_device *ff = dev->ff; |
| 366 | if (dev->ff) { | 366 | |
| 367 | if (dev->ff->destroy) | 367 | __clear_bit(EV_FF, dev->evbit); |
| 368 | dev->ff->destroy(dev->ff); | 368 | if (ff) { |
| 369 | kfree(dev->ff->private); | 369 | if (ff->destroy) |
| 370 | kfree(dev->ff); | 370 | ff->destroy(ff); |
| 371 | kfree(ff->private); | ||
| 372 | kfree(ff); | ||
| 371 | dev->ff = NULL; | 373 | dev->ff = NULL; |
| 372 | } | 374 | } |
| 373 | } | 375 | } |
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index 2d1415e16834..b483b2995fa9 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c | |||
| @@ -61,7 +61,6 @@ struct ml_device { | |||
| 61 | struct ml_effect_state states[FF_MEMLESS_EFFECTS]; | 61 | struct ml_effect_state states[FF_MEMLESS_EFFECTS]; |
| 62 | int gain; | 62 | int gain; |
| 63 | struct timer_list timer; | 63 | struct timer_list timer; |
| 64 | spinlock_t timer_lock; | ||
| 65 | struct input_dev *dev; | 64 | struct input_dev *dev; |
| 66 | 65 | ||
| 67 | int (*play_effect)(struct input_dev *dev, void *data, | 66 | int (*play_effect)(struct input_dev *dev, void *data, |
| @@ -368,38 +367,38 @@ static void ml_effect_timer(unsigned long timer_data) | |||
| 368 | { | 367 | { |
| 369 | struct input_dev *dev = (struct input_dev *)timer_data; | 368 | struct input_dev *dev = (struct input_dev *)timer_data; |
| 370 | struct ml_device *ml = dev->ff->private; | 369 | struct ml_device *ml = dev->ff->private; |
| 370 | unsigned long flags; | ||
| 371 | 371 | ||
| 372 | debug("timer: updating effects"); | 372 | debug("timer: updating effects"); |
| 373 | 373 | ||
| 374 | spin_lock(&ml->timer_lock); | 374 | spin_lock_irqsave(&dev->event_lock, flags); |
| 375 | ml_play_effects(ml); | 375 | ml_play_effects(ml); |
| 376 | spin_unlock(&ml->timer_lock); | 376 | spin_unlock_irqrestore(&dev->event_lock, flags); |
| 377 | } | 377 | } |
| 378 | 378 | ||
| 379 | /* | ||
| 380 | * Sets requested gain for FF effects. Called with dev->event_lock held. | ||
| 381 | */ | ||
| 379 | static void ml_ff_set_gain(struct input_dev *dev, u16 gain) | 382 | static void ml_ff_set_gain(struct input_dev *dev, u16 gain) |
| 380 | { | 383 | { |
| 381 | struct ml_device *ml = dev->ff->private; | 384 | struct ml_device *ml = dev->ff->private; |
| 382 | int i; | 385 | int i; |
| 383 | 386 | ||
| 384 | spin_lock_bh(&ml->timer_lock); | ||
| 385 | |||
| 386 | ml->gain = gain; | 387 | ml->gain = gain; |
| 387 | 388 | ||
| 388 | for (i = 0; i < FF_MEMLESS_EFFECTS; i++) | 389 | for (i = 0; i < FF_MEMLESS_EFFECTS; i++) |
| 389 | __clear_bit(FF_EFFECT_PLAYING, &ml->states[i].flags); | 390 | __clear_bit(FF_EFFECT_PLAYING, &ml->states[i].flags); |
| 390 | 391 | ||
| 391 | ml_play_effects(ml); | 392 | ml_play_effects(ml); |
| 392 | |||
| 393 | spin_unlock_bh(&ml->timer_lock); | ||
| 394 | } | 393 | } |
| 395 | 394 | ||
| 395 | /* | ||
| 396 | * Start/stop specified FF effect. Called with dev->event_lock held. | ||
| 397 | */ | ||
| 396 | static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) | 398 | static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) |
| 397 | { | 399 | { |
| 398 | struct ml_device *ml = dev->ff->private; | 400 | struct ml_device *ml = dev->ff->private; |
| 399 | struct ml_effect_state *state = &ml->states[effect_id]; | 401 | struct ml_effect_state *state = &ml->states[effect_id]; |
| 400 | unsigned long flags; | ||
| 401 | |||
| 402 | spin_lock_irqsave(&ml->timer_lock, flags); | ||
| 403 | 402 | ||
| 404 | if (value > 0) { | 403 | if (value > 0) { |
| 405 | debug("initiated play"); | 404 | debug("initiated play"); |
| @@ -425,8 +424,6 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) | |||
| 425 | ml_play_effects(ml); | 424 | ml_play_effects(ml); |
| 426 | } | 425 | } |
| 427 | 426 | ||
| 428 | spin_unlock_irqrestore(&ml->timer_lock, flags); | ||
| 429 | |||
| 430 | return 0; | 427 | return 0; |
| 431 | } | 428 | } |
| 432 | 429 | ||
| @@ -436,7 +433,7 @@ static int ml_ff_upload(struct input_dev *dev, | |||
| 436 | struct ml_device *ml = dev->ff->private; | 433 | struct ml_device *ml = dev->ff->private; |
| 437 | struct ml_effect_state *state = &ml->states[effect->id]; | 434 | struct ml_effect_state *state = &ml->states[effect->id]; |
| 438 | 435 | ||
| 439 | spin_lock_bh(&ml->timer_lock); | 436 | spin_lock_irq(&dev->event_lock); |
| 440 | 437 | ||
| 441 | if (test_bit(FF_EFFECT_STARTED, &state->flags)) { | 438 | if (test_bit(FF_EFFECT_STARTED, &state->flags)) { |
| 442 | __clear_bit(FF_EFFECT_PLAYING, &state->flags); | 439 | __clear_bit(FF_EFFECT_PLAYING, &state->flags); |
| @@ -448,7 +445,7 @@ static int ml_ff_upload(struct input_dev *dev, | |||
| 448 | ml_schedule_timer(ml); | 445 | ml_schedule_timer(ml); |
| 449 | } | 446 | } |
| 450 | 447 | ||
| 451 | spin_unlock_bh(&ml->timer_lock); | 448 | spin_unlock_irq(&dev->event_lock); |
| 452 | 449 | ||
| 453 | return 0; | 450 | return 0; |
| 454 | } | 451 | } |
| @@ -482,7 +479,6 @@ int input_ff_create_memless(struct input_dev *dev, void *data, | |||
| 482 | ml->private = data; | 479 | ml->private = data; |
| 483 | ml->play_effect = play_effect; | 480 | ml->play_effect = play_effect; |
| 484 | ml->gain = 0xffff; | 481 | ml->gain = 0xffff; |
| 485 | spin_lock_init(&ml->timer_lock); | ||
| 486 | setup_timer(&ml->timer, ml_effect_timer, (unsigned long)dev); | 482 | setup_timer(&ml->timer, ml_effect_timer, (unsigned long)dev); |
| 487 | 483 | ||
| 488 | set_bit(FF_GAIN, dev->ffbit); | 484 | set_bit(FF_GAIN, dev->ffbit); |
diff --git a/drivers/input/input.c b/drivers/input/input.c index cc763c96fada..2266ecbfbc01 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -1292,17 +1292,24 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env) | |||
| 1292 | return 0; | 1292 | return 0; |
| 1293 | } | 1293 | } |
| 1294 | 1294 | ||
| 1295 | #define INPUT_DO_TOGGLE(dev, type, bits, on) \ | 1295 | #define INPUT_DO_TOGGLE(dev, type, bits, on) \ |
| 1296 | do { \ | 1296 | do { \ |
| 1297 | int i; \ | 1297 | int i; \ |
| 1298 | if (!test_bit(EV_##type, dev->evbit)) \ | 1298 | bool active; \ |
| 1299 | break; \ | 1299 | \ |
| 1300 | for (i = 0; i < type##_MAX; i++) { \ | 1300 | if (!test_bit(EV_##type, dev->evbit)) \ |
| 1301 | if (!test_bit(i, dev->bits##bit) || \ | 1301 | break; \ |
| 1302 | !test_bit(i, dev->bits)) \ | 1302 | \ |
| 1303 | continue; \ | 1303 | for (i = 0; i < type##_MAX; i++) { \ |
| 1304 | dev->event(dev, EV_##type, i, on); \ | 1304 | if (!test_bit(i, dev->bits##bit)) \ |
| 1305 | } \ | 1305 | continue; \ |
| 1306 | \ | ||
| 1307 | active = test_bit(i, dev->bits); \ | ||
| 1308 | if (!active && !on) \ | ||
| 1309 | continue; \ | ||
| 1310 | \ | ||
| 1311 | dev->event(dev, EV_##type, i, on ? active : 0); \ | ||
| 1312 | } \ | ||
| 1306 | } while (0) | 1313 | } while (0) |
| 1307 | 1314 | ||
| 1308 | #ifdef CONFIG_PM | 1315 | #ifdef CONFIG_PM |
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 4452eabbee6d..28e6110d1ff8 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
| @@ -1174,6 +1174,18 @@ static int atkbd_reconnect(struct serio *serio) | |||
| 1174 | return -1; | 1174 | return -1; |
| 1175 | 1175 | ||
| 1176 | atkbd_activate(atkbd); | 1176 | atkbd_activate(atkbd); |
| 1177 | |||
| 1178 | /* | ||
| 1179 | * Restore LED state and repeat rate. While input core | ||
| 1180 | * will do this for us at resume time reconnect may happen | ||
| 1181 | * because user requested it via sysfs or simply because | ||
| 1182 | * keyboard was unplugged and plugged in again so we need | ||
| 1183 | * to do it ourselves here. | ||
| 1184 | */ | ||
| 1185 | atkbd_set_leds(atkbd); | ||
| 1186 | if (!atkbd->softrepeat) | ||
| 1187 | atkbd_set_repeat_rate(atkbd); | ||
| 1188 | |||
| 1177 | } | 1189 | } |
| 1178 | 1190 | ||
| 1179 | atkbd_enable(atkbd); | 1191 | atkbd_enable(atkbd); |
| @@ -1422,6 +1434,7 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count) | |||
| 1422 | 1434 | ||
| 1423 | atkbd->dev = new_dev; | 1435 | atkbd->dev = new_dev; |
| 1424 | atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra); | 1436 | atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra); |
| 1437 | atkbd_reset_state(atkbd); | ||
| 1425 | atkbd_activate(atkbd); | 1438 | atkbd_activate(atkbd); |
| 1426 | atkbd_set_keycode_table(atkbd); | 1439 | atkbd_set_keycode_table(atkbd); |
| 1427 | atkbd_set_device_attrs(atkbd); | 1440 | atkbd_set_device_attrs(atkbd); |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 690aed905436..5bd64841bf1c 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
| @@ -1673,7 +1673,7 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) | |||
| 1673 | { | 1673 | { |
| 1674 | int type = *((unsigned int *)kp->arg); | 1674 | int type = *((unsigned int *)kp->arg); |
| 1675 | 1675 | ||
| 1676 | return sprintf(buffer, "%s\n", psmouse_protocol_by_type(type)->name); | 1676 | return sprintf(buffer, "%s", psmouse_protocol_by_type(type)->name); |
| 1677 | } | 1677 | } |
| 1678 | 1678 | ||
| 1679 | static int __init psmouse_init(void) | 1679 | static int __init psmouse_init(void) |
diff --git a/include/linux/input.h b/include/linux/input.h index 0ccfc30cd40f..c2b1a7d244d9 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
| @@ -1377,6 +1377,10 @@ extern struct class input_class; | |||
| 1377 | * methods; erase() is optional. set_gain() and set_autocenter() need | 1377 | * methods; erase() is optional. set_gain() and set_autocenter() need |
| 1378 | * only be implemented if driver sets up FF_GAIN and FF_AUTOCENTER | 1378 | * only be implemented if driver sets up FF_GAIN and FF_AUTOCENTER |
| 1379 | * bits. | 1379 | * bits. |
| 1380 | * | ||
| 1381 | * Note that playback(), set_gain() and set_autocenter() are called with | ||
| 1382 | * dev->event_lock spinlock held and interrupts off and thus may not | ||
| 1383 | * sleep. | ||
| 1380 | */ | 1384 | */ |
| 1381 | struct ff_device { | 1385 | struct ff_device { |
| 1382 | int (*upload)(struct input_dev *dev, struct ff_effect *effect, | 1386 | int (*upload)(struct input_dev *dev, struct ff_effect *effect, |
