summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2014-09-24 14:06:11 +0200
committerMarek Vasut <marex@denx.de>2014-11-04 06:04:01 +0100
commit8e553119839eba13140a2294418a831c114ddea2 (patch)
tree184a65f1bfb0a41d04f5ad1664d1d2cc7289994a /common
parent8f8d7d2451115059c36e0551eea9d8770c346ea2 (diff)
downloadu-boot-imx-8e553119839eba13140a2294418a831c114ddea2.zip
u-boot-imx-8e553119839eba13140a2294418a831c114ddea2.tar.gz
u-boot-imx-8e553119839eba13140a2294418a831c114ddea2.tar.bz2
usb: kbd: Add (optional) support for using an interrupt queue for polling
Waiting an interrupt packet to complete in usb_kbd_poll_for_event, causes a 40 ms latency for each call to usb_kbd_testc, which is undesirable. Using control messages leads to lower (but still not 0) latency, but some devices do not work well with control messages (e.g. my kvm behaves funny with them). This commit adds support for using the int_queue mechanism which at least the ehci-hcd driver supports. This allows polling with 0 latency, while using interrupt packets. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'common')
-rw-r--r--common/usb_kbd.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/common/usb_kbd.c b/common/usb_kbd.c
index a303d95..bc7145e 100644
--- a/common/usb_kbd.c
+++ b/common/usb_kbd.c
@@ -102,6 +102,7 @@ struct usb_kbd_pdata {
unsigned long intpipe;
int intpktsize;
int intinterval;
+ struct int_queue *intq;
uint32_t repeat_delay;
@@ -324,6 +325,15 @@ static inline void usb_kbd_poll_for_event(struct usb_device *dev)
1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE);
if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE))
usb_kbd_irq_worker(dev);
+#elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE)
+ struct usb_kbd_pdata *data = dev->privptr;
+ if (poll_int_queue(dev, data->intq)) {
+ usb_kbd_irq_worker(dev);
+ /* We've consumed all queued int packets, create new */
+ destroy_int_queue(dev, data->intq);
+ data->intq = create_int_queue(dev, data->intpipe, 1,
+ USB_KBD_BOOT_REPORT_SIZE, data->new);
+ }
#endif
}
@@ -441,8 +451,14 @@ static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum)
usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE, 0);
debug("USB KBD: enable interrupt pipe...\n");
+#ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE
+ data->intq = create_int_queue(dev, data->intpipe, 1,
+ USB_KBD_BOOT_REPORT_SIZE, data->new);
+ if (!data->intq) {
+#else
if (usb_submit_int_msg(dev, data->intpipe, data->new, data->intpktsize,
data->intinterval) < 0) {
+#endif
printf("Failed to get keyboard state from device %04x:%04x\n",
dev->descriptor.idVendor, dev->descriptor.idProduct);
/* Abort, we don't want to use that non-functional keyboard. */
@@ -526,6 +542,9 @@ int usb_kbd_deregister(int force)
data = usb_kbd_dev->privptr;
if (stdio_deregister_dev(dev, force) != 0)
return 1;
+#ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE
+ destroy_int_queue(usb_kbd_dev, data->intq);
+#endif
free(data->new);
free(data);
}