Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: bcm5974 - switch back to normal mode when closing

Staying in multi-touch mode after closing the device sometimes makes
the keyboard drop keys or repeat keys irratically. The conjecture is
that some internal buffer starts to overflow, resulting in undefined
behavior. Switching back to normal mode when closing the device makes
the problem go away.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by

Henrik Rydberg and committed by
Dmitry Torokhov
cd72ad3f 9ce1ca28

+9 -4
+9 -4
drivers/input/mouse/bcm5974.c
··· 351 351 #define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300 352 352 #define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0 353 353 #define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01 354 + #define BCM5974_WELLSPRING_MODE_NORMAL_VALUE 0x08 354 355 355 - static int bcm5974_wellspring_mode(struct bcm5974 *dev) 356 + static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on) 356 357 { 357 358 char *data = kmalloc(8, GFP_KERNEL); 358 359 int retval = 0, size; ··· 378 377 } 379 378 380 379 /* apply the mode switch */ 381 - data[0] = BCM5974_WELLSPRING_MODE_VENDOR_VALUE; 380 + data[0] = on ? 381 + BCM5974_WELLSPRING_MODE_VENDOR_VALUE : 382 + BCM5974_WELLSPRING_MODE_NORMAL_VALUE; 382 383 383 384 /* write configuration */ 384 385 size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), ··· 395 392 goto out; 396 393 } 397 394 398 - dprintk(2, "bcm5974: switched to wellspring mode.\n"); 395 + dprintk(2, "bcm5974: switched to %s mode.\n", 396 + on ? "wellspring" : "normal"); 399 397 400 398 out: 401 399 kfree(data); ··· 485 481 */ 486 482 static int bcm5974_start_traffic(struct bcm5974 *dev) 487 483 { 488 - if (bcm5974_wellspring_mode(dev)) { 484 + if (bcm5974_wellspring_mode(dev, true)) { 489 485 dprintk(1, "bcm5974: mode switch failed\n"); 490 486 goto error; 491 487 } ··· 508 504 { 509 505 usb_kill_urb(dev->tp_urb); 510 506 usb_kill_urb(dev->bt_urb); 507 + bcm5974_wellspring_mode(dev, false); 511 508 } 512 509 513 510 /*