Re: hid-pidff bug: fails to find all required reports of saitek gamepad

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Anssi Hannula wrote:
> 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.

And of course there was an error, attached is a fixed patch :)

-- 
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:55:59.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 */

[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux