diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/input/hid-core.c | 153 | ||||
-rw-r--r-- | drivers/usb/input/hid.h | 10 |
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 | |||
909 | static void hid_io_error(struct hid_device *hid); | ||
910 | |||
911 | /* Start up the input URB */ | ||
912 | static 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 */ | ||
929 | static 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 */ | ||
939 | static 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 */ | ||
965 | static 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)); | ||
994 | done: | ||
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 | ||
1256 | int hid_open(struct hid_device *hid) | 1361 | int 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 | ||
374 | struct hid_input { | 379 | struct 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 */ |