Occasionally the trackpad in my MacBookPro 8,3 stops working, spewing 'bcm5974: bad trackpad package, length: 8' I haven't been able to reproduce this on demand, but it's annoying when it does happen. I'm *assuming* that it's somehow forgotten what mode it's supposed to be in. The fix for this on suspend/resume was to switch it back to Wellspring mode again, so let's try that... Untested, because my trackpad seems to *know* when I'm actually running a kernel with this patch, and doesn't ever misbehave. I've played with removing the *normal* mode switch in bcm5974_start_traffic() but can't get it to produce the 'bad trackpad package' message at all in that case, so the rest function doesn't get invoked. Signed-off-by: David Woodhouse <David.Woodhouse@xxxxxxxxx> diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 2baff1b..db0b3ab 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -244,6 +244,7 @@ struct bcm5974 { struct bt_data *bt_data; /* button transferred data */ struct urb *tp_urb; /* trackpad usb request block */ u8 *tp_data; /* trackpad transferred data */ + struct work_struct reset_work; /* reset to wellspring mode */ const struct tp_finger *index[MAX_FINGERS]; /* finger index data */ struct input_mt_pos pos[MAX_FINGERS]; /* position array */ int slots[MAX_FINGERS]; /* slot assignments */ @@ -676,9 +677,14 @@ static void bcm5974_irq_trackpad(struct urb *urb) if (dev->tp_urb->actual_length == 2) goto exit; - if (report_tp_state(dev, dev->tp_urb->actual_length)) + if (report_tp_state(dev, dev->tp_urb->actual_length)) { dprintk(1, "bcm5974: bad trackpad package, length: %d\n", dev->tp_urb->actual_length); + if (dev->tp_urb->actual_length == 8) { + /* Hm. Make sure it's in wellspring mode... */ + schedule_work(&dev->reset_work); + } + } exit: error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC); @@ -815,6 +821,14 @@ static int bcm5974_resume(struct usb_interface *iface) return error; } +static void bcm5974_mode_workfn(struct work_struct *work) +{ + struct bcm5974 *dev = container_of(work, struct bcm5974, reset_work); + + dev_info(&dev->intf->dev, "Reset into wellspring mode...\n"); + bcm5974_wellspring_mode(dev, true); +} + static int bcm5974_probe(struct usb_interface *iface, const struct usb_device_id *id) { @@ -840,6 +854,7 @@ static int bcm5974_probe(struct usb_interface *iface, dev->input = input_dev; dev->cfg = *cfg; mutex_init(&dev->pm_mutex); + INIT_WORK(&dev->reset_work, bcm5974_mode_workfn); /* setup urbs */ if (cfg->tp_type == TYPE1) { @@ -936,6 +951,7 @@ static void bcm5974_disconnect(struct usb_interface *iface) dev->bt_data, dev->bt_urb->transfer_dma); usb_free_urb(dev->tp_urb); usb_free_urb(dev->bt_urb); + cancel_work_sync(&dev->reset_work); kfree(dev); } -- David Woodhouse Open Source Technology Centre David.Woodhouse@xxxxxxxxx Intel Corporation
Attachment:
smime.p7s
Description: S/MIME cryptographic signature