Dmitriy Geels wrote: > 2009/3/8 Anssi Hannula <anssi.hannula@xxxxxxxxx>: >> Dmitriy Geels wrote: >>> 2009/3/7 Anssi Hannula <anssi.hannula@xxxxxxxxx>: >>>> Provide the kernel log again, this time with debug=2 set for hid module >>>> and having run "fftest" with only one effect and then "ffmvforce". >>> here is it: http://paste.org.ru/index.pl?4bwah8 >> Apply attached patch that adds more debug output and try this again. > Here is log: http://paste.org.ru/index.pl?0mtjuz > Sorry for the long delay. Try the attached (untested) patch. It adds a simple timeout to the hid ctrl and out urbs, discarding the faulty urb instead of getting stuck. -- Anssi Hannula
--- drivers/hid/usbhid/hid-core.c | 18 ++++++++++++++++++ drivers/hid/usbhid/usbhid.h | 2 ++ 2 files changed, 20 insertions(+) Index: linux-2629-pidff/drivers/hid/usbhid/hid-core.c =================================================================== --- linux-2629-pidff.orig/drivers/hid/usbhid/hid-core.c 2009-02-13 03:47:15.000000000 +0200 +++ linux-2629-pidff/drivers/hid/usbhid/hid-core.c 2009-05-08 02:40:47.000000000 +0300 @@ -251,6 +251,8 @@ static int hid_submit_out(struct hid_dev return -1; } + add_timer(&usbhid->urb_out_timeout, jiffies + msecs_to_jiffies(8000)); + return 0; } @@ -303,6 +305,8 @@ static int hid_submit_ctrl(struct hid_de return -1; } + add_timer(&usbhid->urb_ctrl_timeout, jiffies + msecs_to_jiffies(8000)); + return 0; } @@ -317,6 +321,8 @@ static void hid_irq_out(struct urb *urb) unsigned long flags; int unplug = 0; + del_timer(usbhid->urb_out_timeout); + switch (urb->status) { case 0: /* success */ break; @@ -364,6 +370,7 @@ static void hid_ctrl(struct urb *urb) unsigned long flags; int unplug = 0; + del_timer(usbhid->urb_ctrl_timeout); spin_lock_irqsave(&usbhid->ctrllock, flags); switch (urb->status) { @@ -405,6 +412,13 @@ static void hid_ctrl(struct urb *urb) wake_up(&usbhid->wait); } +static void hid_urb_timeout(unsigned long timer_data) +{ + struct urb *hid_urb = (struct urb *)timer_data; + dev_warn(&hid_urb->dev->dev, "hid urb timeout\n"); + usb_unlink_urb(hid_urb); +} + void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) { int head; @@ -851,6 +865,8 @@ static int usbhid_start(struct hid_devic init_waitqueue_head(&usbhid->wait); INIT_WORK(&usbhid->reset_work, hid_reset); setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); + setup_timer(&usbhid->urb_out_timeout, hid_urb_timeout, (unsigned long) usbhid->urbout); + setup_timer(&usbhid->urb_ctrl_timeout, hid_urb_timeout, (unsigned long) usbhid->urbctrl); spin_lock_init(&usbhid->inlock); spin_lock_init(&usbhid->outlock); @@ -915,6 +931,8 @@ static void usbhid_stop(struct hid_devic del_timer_sync(&usbhid->io_retry); cancel_work_sync(&usbhid->reset_work); + del_timer_sync(&usbhid->hid_out_timeout); + del_timer_sync(&usbhid->hid_ctrl_timeout); if (hid->claimed & HID_CLAIMED_INPUT) hidinput_disconnect(hid); Index: linux-2629-pidff/drivers/hid/usbhid/usbhid.h =================================================================== --- linux-2629-pidff.orig/drivers/hid/usbhid/usbhid.h 2009-05-08 01:53:33.000000000 +0300 +++ linux-2629-pidff/drivers/hid/usbhid/usbhid.h 2009-05-08 01:54:02.000000000 +0300 @@ -85,6 +85,8 @@ struct usbhid_device { spinlock_t outlock; /* Output fifo spinlock */ unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ + struct timer_list urb_out_timeout; /* Timeout for out urb */ + struct timer_list urb_ctrl_timeout; /* Timeout for ctrl urb */ struct timer_list io_retry; /* Retry timer */ unsigned long stop_retry; /* Time to give up, in jiffies */ unsigned int retry_delay; /* Delay length in ms */