aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2006-01-31 12:58:38 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-03-20 17:49:56 -0500
commitaef4e266964bc15861b5835c1f5b9d2ebc155c2a (patch)
tree49d606bc0843231942231b801dc3010ca32ab4f7 /drivers/usb
parentfb669cc01ed778c4926f395e44a9b61644597d38 (diff)
[PATCH] usbhid: add error handling
This patch (as628c) adds error handling to the USB HID core. When an error is reported for an interrupt URB, the driver will do delayed retries, at increasing intervals, for up to one second. If that doesn't work, it will try to reset the device. Testing by users has shown that both the retries and the resets end up getting used. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/input/hid-core.c153
-rw-r--r--drivers/usb/input/hid.h10
2 files changed, 142 insertions, 21 deletions
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index f187a719f17e..6b8a51cad375 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -903,6 +903,99 @@ static int hid_input_report(int type, struct urb *urb, int interrupt, struct pt_
903} 903}
904 904
905/* 905/*
906 * Input submission and I/O error handler.
907 */
908
909static void hid_io_error(struct hid_device *hid);
910
911/* Start up the input URB */
912static int hid_start_in(struct hid_device *hid)
913{
914 unsigned long flags;
915 int rc = 0;
916
917 spin_lock_irqsave(&hid->inlock, flags);
918 if (hid->open > 0 && !test_bit(HID_SUSPENDED, &hid->iofl) &&
919 !test_and_set_bit(HID_IN_RUNNING, &hid->iofl)) {
920 rc = usb_submit_urb(hid->urbin, GFP_ATOMIC);
921 if (rc != 0)
922 clear_bit(HID_IN_RUNNING, &hid->iofl);
923 }
924 spin_unlock_irqrestore(&hid->inlock, flags);
925 return rc;
926}
927
928/* I/O retry timer routine */
929static void hid_retry_timeout(unsigned long _hid)
930{
931 struct hid_device *hid = (struct hid_device *) _hid;
932
933 dev_dbg(&hid->intf->dev, "retrying intr urb\n");
934 if (hid_start_in(hid))
935 hid_io_error(hid);
936}
937
938/* Workqueue routine to reset the device */
939static void hid_reset(void *_hid)
940{
941 struct hid_device *hid = (struct hid_device *) _hid;
942 int rc_lock, rc;
943
944 dev_dbg(&hid->intf->dev, "resetting device\n");
945 rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
946 if (rc_lock >= 0) {
947 rc = usb_reset_device(hid->dev);
948 if (rc_lock)
949 usb_unlock_device(hid->dev);
950 }
951 clear_bit(HID_RESET_PENDING, &hid->iofl);
952
953 if (rc == 0) {
954 hid->retry_delay = 0;
955 if (hid_start_in(hid))
956 hid_io_error(hid);
957 } else if (!(rc == -ENODEV || rc == -EHOSTUNREACH || rc == -EINTR))
958 err("can't reset device, %s-%s/input%d, status %d",
959 hid->dev->bus->bus_name,
960 hid->dev->devpath,
961 hid->ifnum, rc);
962}
963
964/* Main I/O error handler */
965static void hid_io_error(struct hid_device *hid)
966{
967 unsigned long flags;
968
969 spin_lock_irqsave(&hid->inlock, flags);
970
971 /* Stop when disconnected */
972 if (usb_get_intfdata(hid->intf) == NULL)
973 goto done;
974
975 /* When an error occurs, retry at increasing intervals */
976 if (hid->retry_delay == 0) {
977 hid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */
978 hid->stop_retry = jiffies + msecs_to_jiffies(1000);
979 } else if (hid->retry_delay < 100)
980 hid->retry_delay *= 2;
981
982 if (time_after(jiffies, hid->stop_retry)) {
983
984 /* Retries failed, so do a port reset */
985 if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
986 if (schedule_work(&hid->reset_work))
987 goto done;
988 clear_bit(HID_RESET_PENDING, &hid->iofl);
989 }
990 }
991
992 mod_timer(&hid->io_retry,
993 jiffies + msecs_to_jiffies(hid->retry_delay));
994done:
995 spin_unlock_irqrestore(&hid->inlock, flags);
996}
997
998/*
906 * Input interrupt completion handler. 999 * Input interrupt completion handler.
907 */ 1000 */
908 1001
@@ -913,25 +1006,35 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs)
913 1006
914 switch (urb->status) { 1007 switch (urb->status) {
915 case 0: /* success */ 1008 case 0: /* success */
1009 hid->retry_delay = 0;
916 hid_input_report(HID_INPUT_REPORT, urb, 1, regs); 1010 hid_input_report(HID_INPUT_REPORT, urb, 1, regs);
917 break; 1011 break;
918 case -ECONNRESET: /* unlink */ 1012 case -ECONNRESET: /* unlink */
919 case -ENOENT: 1013 case -ENOENT:
920 case -EPERM:
921 case -ESHUTDOWN: /* unplug */ 1014 case -ESHUTDOWN: /* unplug */
922 case -EILSEQ: /* unplug timeout on uhci */ 1015 clear_bit(HID_IN_RUNNING, &hid->iofl);
923 return; 1016 return;
1017 case -EILSEQ: /* protocol error or unplug */
1018 case -EPROTO: /* protocol error or unplug */
924 case -ETIMEDOUT: /* NAK */ 1019 case -ETIMEDOUT: /* NAK */
925 break; 1020 clear_bit(HID_IN_RUNNING, &hid->iofl);
1021 hid_io_error(hid);
1022 return;
926 default: /* error */ 1023 default: /* error */
927 warn("input irq status %d received", urb->status); 1024 warn("input irq status %d received", urb->status);
928 } 1025 }
929 1026
930 status = usb_submit_urb(urb, SLAB_ATOMIC); 1027 status = usb_submit_urb(urb, SLAB_ATOMIC);
931 if (status) 1028 if (status) {
932 err("can't resubmit intr, %s-%s/input%d, status %d", 1029 clear_bit(HID_IN_RUNNING, &hid->iofl);
933 hid->dev->bus->bus_name, hid->dev->devpath, 1030 if (status != -EPERM) {
934 hid->ifnum, status); 1031 err("can't resubmit intr, %s-%s/input%d, status %d",
1032 hid->dev->bus->bus_name,
1033 hid->dev->devpath,
1034 hid->ifnum, status);
1035 hid_io_error(hid);
1036 }
1037 }
935} 1038}
936 1039
937/* 1040/*
@@ -1093,8 +1196,9 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs)
1093 case 0: /* success */ 1196 case 0: /* success */
1094 break; 1197 break;
1095 case -ESHUTDOWN: /* unplug */ 1198 case -ESHUTDOWN: /* unplug */
1096 case -EILSEQ: /* unplug timeout on uhci */
1097 unplug = 1; 1199 unplug = 1;
1200 case -EILSEQ: /* protocol error or unplug */
1201 case -EPROTO: /* protocol error or unplug */
1098 case -ECONNRESET: /* unlink */ 1202 case -ECONNRESET: /* unlink */
1099 case -ENOENT: 1203 case -ENOENT:
1100 break; 1204 break;
@@ -1141,8 +1245,9 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs)
1141 hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs); 1245 hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs);
1142 break; 1246 break;
1143 case -ESHUTDOWN: /* unplug */ 1247 case -ESHUTDOWN: /* unplug */
1144 case -EILSEQ: /* unplug timectrl on uhci */
1145 unplug = 1; 1248 unplug = 1;
1249 case -EILSEQ: /* protocol error or unplug */
1250 case -EPROTO: /* protocol error or unplug */
1146 case -ECONNRESET: /* unlink */ 1251 case -ECONNRESET: /* unlink */
1147 case -ENOENT: 1252 case -ENOENT:
1148 case -EPIPE: /* report not available */ 1253 case -EPIPE: /* report not available */
@@ -1255,14 +1360,9 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
1255 1360
1256int hid_open(struct hid_device *hid) 1361int hid_open(struct hid_device *hid)
1257{ 1362{
1258 if (hid->open++) 1363 ++hid->open;
1259 return 0; 1364 if (hid_start_in(hid))
1260 1365 hid_io_error(hid);
1261 hid->urbin->dev = hid->dev;
1262
1263 if (usb_submit_urb(hid->urbin, GFP_KERNEL))
1264 return -EIO;
1265
1266 return 0; 1366 return 0;
1267} 1367}
1268 1368
@@ -1787,6 +1887,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
1787 1887
1788 init_waitqueue_head(&hid->wait); 1888 init_waitqueue_head(&hid->wait);
1789 1889
1890 INIT_WORK(&hid->reset_work, hid_reset, hid);
1891 setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid);
1892
1893 spin_lock_init(&hid->inlock);
1790 spin_lock_init(&hid->outlock); 1894 spin_lock_init(&hid->outlock);
1791 spin_lock_init(&hid->ctrllock); 1895 spin_lock_init(&hid->ctrllock);
1792 1896
@@ -1855,11 +1959,16 @@ static void hid_disconnect(struct usb_interface *intf)
1855 if (!hid) 1959 if (!hid)
1856 return; 1960 return;
1857 1961
1962 spin_lock_irq(&hid->inlock); /* Sync with error handler */
1858 usb_set_intfdata(intf, NULL); 1963 usb_set_intfdata(intf, NULL);
1964 spin_unlock_irq(&hid->inlock);
1859 usb_kill_urb(hid->urbin); 1965 usb_kill_urb(hid->urbin);
1860 usb_kill_urb(hid->urbout); 1966 usb_kill_urb(hid->urbout);
1861 usb_kill_urb(hid->urbctrl); 1967 usb_kill_urb(hid->urbctrl);
1862 1968
1969 del_timer_sync(&hid->io_retry);
1970 flush_scheduled_work();
1971
1863 if (hid->claimed & HID_CLAIMED_INPUT) 1972 if (hid->claimed & HID_CLAIMED_INPUT)
1864 hidinput_disconnect(hid); 1973 hidinput_disconnect(hid);
1865 if (hid->claimed & HID_CLAIMED_HIDDEV) 1974 if (hid->claimed & HID_CLAIMED_HIDDEV)
@@ -1934,6 +2043,10 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
1934{ 2043{
1935 struct hid_device *hid = usb_get_intfdata (intf); 2044 struct hid_device *hid = usb_get_intfdata (intf);
1936 2045
2046 spin_lock_irq(&hid->inlock); /* Sync with error handler */
2047 set_bit(HID_SUSPENDED, &hid->iofl);
2048 spin_unlock_irq(&hid->inlock);
2049 del_timer(&hid->io_retry);
1937 usb_kill_urb(hid->urbin); 2050 usb_kill_urb(hid->urbin);
1938 dev_dbg(&intf->dev, "suspend\n"); 2051 dev_dbg(&intf->dev, "suspend\n");
1939 return 0; 2052 return 0;
@@ -1944,10 +2057,8 @@ static int hid_resume(struct usb_interface *intf)
1944 struct hid_device *hid = usb_get_intfdata (intf); 2057 struct hid_device *hid = usb_get_intfdata (intf);
1945 int status; 2058 int status;
1946 2059
1947 if (hid->open) 2060 clear_bit(HID_SUSPENDED, &hid->iofl);
1948 status = usb_submit_urb(hid->urbin, GFP_NOIO); 2061 status = hid_start_in(hid);
1949 else
1950 status = 0;
1951 dev_dbg(&intf->dev, "resume status %d\n", status); 2062 dev_dbg(&intf->dev, "resume status %d\n", status);
1952 return status; 2063 return status;
1953} 2064}
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index 8b0d4346ce9c..4e1b784fe527 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -31,6 +31,8 @@
31#include <linux/types.h> 31#include <linux/types.h>
32#include <linux/slab.h> 32#include <linux/slab.h>
33#include <linux/list.h> 33#include <linux/list.h>
34#include <linux/timer.h>
35#include <linux/workqueue.h>
34 36
35/* 37/*
36 * USB HID (Human Interface Device) interface class code 38 * USB HID (Human Interface Device) interface class code
@@ -370,6 +372,9 @@ struct hid_control_fifo {
370 372
371#define HID_CTRL_RUNNING 1 373#define HID_CTRL_RUNNING 1
372#define HID_OUT_RUNNING 2 374#define HID_OUT_RUNNING 2
375#define HID_IN_RUNNING 3
376#define HID_RESET_PENDING 4
377#define HID_SUSPENDED 5
373 378
374struct hid_input { 379struct hid_input {
375 struct list_head list; 380 struct list_head list;
@@ -393,12 +398,17 @@ struct hid_device { /* device report descriptor */
393 int ifnum; /* USB interface number */ 398 int ifnum; /* USB interface number */
394 399
395 unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ 400 unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
401 struct timer_list io_retry; /* Retry timer */
402 unsigned long stop_retry; /* Time to give up, in jiffies */
403 unsigned int retry_delay; /* Delay length in ms */
404 struct work_struct reset_work; /* Task context for resets */
396 405
397 unsigned int bufsize; /* URB buffer size */ 406 unsigned int bufsize; /* URB buffer size */
398 407
399 struct urb *urbin; /* Input URB */ 408 struct urb *urbin; /* Input URB */
400 char *inbuf; /* Input buffer */ 409 char *inbuf; /* Input buffer */
401 dma_addr_t inbuf_dma; /* Input buffer dma */ 410 dma_addr_t inbuf_dma; /* Input buffer dma */
411 spinlock_t inlock; /* Input fifo spinlock */
402 412
403 struct urb *urbctrl; /* Control URB */ 413 struct urb *urbctrl; /* Control URB */
404 struct usb_ctrlrequest *cr; /* Control request struct */ 414 struct usb_ctrlrequest *cr; /* Control request struct */