diff --git a/common/usb.c b/common/usb.c index dc8e312c5f..61439e39eb 100644 --- a/common/usb.c +++ b/common/usb.c @@ -193,12 +193,15 @@ int usb_disable_asynch(int disable) */ /* - * submits an Interrupt Message + * submits an Interrupt Message. Some drivers may implement non-blocking + * polling: when non-block is true and the device is not responding return + * -EAGAIN instead of waiting for device to respond. */ -int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, int interval) +int usb_int_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, int interval, bool nonblock) { - return submit_int_msg(dev, pipe, buffer, transfer_len, interval); + return submit_int_msg(dev, pipe, buffer, transfer_len, interval, + nonblock); } /* diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 07932d1cb4..902473643e 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -317,10 +317,9 @@ static inline void usb_kbd_poll_for_event(struct usb_device *dev) struct usb_kbd_pdata *data = dev->privptr; /* Submit a interrupt transfer request */ - usb_submit_int_msg(dev, data->intpipe, &data->new[0], data->intpktsize, - data->intinterval); - - usb_kbd_irq_worker(dev); + if (usb_int_msg(dev, data->intpipe, &data->new[0], + data->intpktsize, data->intinterval, true) >= 0) + usb_kbd_irq_worker(dev); #elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) || \ defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE) #if defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) @@ -480,8 +479,8 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) if (usb_get_report(dev, iface->desc.bInterfaceNumber, 1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE) < 0) { #else - if (usb_submit_int_msg(dev, data->intpipe, data->new, data->intpktsize, - data->intinterval) < 0) { + if (usb_int_msg(dev, data->intpipe, data->new, data->intpktsize, + data->intinterval, false) < 0) { #endif printf("Failed to get keyboard state from device %04x:%04x\n", dev->descriptor.idVendor, dev->descriptor.idProduct); diff --git a/common/usb_storage.c b/common/usb_storage.c index be0b2df5d9..c3784aff8f 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -654,8 +654,8 @@ static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us) int timeout; us->ip_wanted = 1; - submit_int_msg(us->pusb_dev, us->irqpipe, - (void *) &us->ip_data, us->irqmaxp, us->irqinterval); + usb_int_msg(us->pusb_dev, us->irqpipe, + (void *)&us->ip_data, us->irqmaxp, us->irqinterval, false); timeout = 1000; while (timeout--) { if (us->ip_wanted == 0) diff --git a/drivers/usb/emul/sandbox_keyb.c b/drivers/usb/emul/sandbox_keyb.c index cff017668f..f7247eef8c 100644 --- a/drivers/usb/emul/sandbox_keyb.c +++ b/drivers/usb/emul/sandbox_keyb.c @@ -181,7 +181,8 @@ static int sandbox_keyb_control(struct udevice *dev, struct usb_device *udev, } static int sandbox_keyb_interrupt(struct udevice *dev, struct usb_device *udev, - unsigned long pipe, void *buffer, int length, int interval) + unsigned long pipe, void *buffer, int length, int interval, + bool nonblock) { struct sandbox_keyb_priv *priv = dev_get_priv(dev); uint8_t *data = buffer; diff --git a/drivers/usb/emul/usb-emul-uclass.c b/drivers/usb/emul/usb-emul-uclass.c index fbe11f3135..0aeddf826a 100644 --- a/drivers/usb/emul/usb-emul-uclass.c +++ b/drivers/usb/emul/usb-emul-uclass.c @@ -248,7 +248,8 @@ int usb_emul_bulk(struct udevice *emul, struct usb_device *udev, } int usb_emul_int(struct udevice *emul, struct usb_device *udev, - unsigned long pipe, void *buffer, int length, int interval) + unsigned long pipe, void *buffer, int length, int interval, + bool nonblock) { struct dm_usb_ops *ops = usb_get_emul_ops(emul); @@ -256,7 +257,8 @@ int usb_emul_int(struct udevice *emul, struct usb_device *udev, return -ENOSYS; debug("%s: dev=%s\n", __func__, emul->name); - return ops->interrupt(emul, udev, pipe, buffer, length, interval); + return ops->interrupt(emul, udev, pipe, buffer, length, interval, + nonblock); } int usb_emul_setup_device(struct udevice *dev, struct usb_string *strings, diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 884613fe4e..bc20a6154c 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -1111,7 +1111,8 @@ static int _submit_control_msg(struct dwc2_priv *priv, struct usb_device *dev, } int _submit_int_msg(struct dwc2_priv *priv, struct usb_device *dev, - unsigned long pipe, void *buffer, int len, int interval) + unsigned long pipe, void *buffer, int len, int interval, + bool nonblock) { unsigned long timeout; int ret; @@ -1239,9 +1240,10 @@ int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, } int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, int interval) + int len, int interval, bool nonblock) { - return _submit_int_msg(&local, dev, pipe, buffer, len, interval); + return _submit_int_msg(&local, dev, pipe, buffer, len, interval, + nonblock); } /* U-Boot USB control interface */ @@ -1295,13 +1297,14 @@ static int dwc2_submit_bulk_msg(struct udevice *dev, struct usb_device *udev, static int dwc2_submit_int_msg(struct udevice *dev, struct usb_device *udev, unsigned long pipe, void *buffer, int length, - int interval) + int interval, bool nonblock) { struct dwc2_priv *priv = dev_get_priv(dev); debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev); - return _submit_int_msg(priv, udev, pipe, buffer, length, interval); + return _submit_int_msg(priv, udev, pipe, buffer, length, interval, + nonblock); } static int dwc2_usb_ofdata_to_platdata(struct udevice *dev) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c70a365840..742759eef5 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1473,7 +1473,8 @@ out: } static int _ehci_submit_int_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int length, int interval) + void *buffer, int length, int interval, + bool nonblock) { void *backbuffer; struct int_queue *queue; @@ -1523,9 +1524,10 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, } int submit_int_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int length, int interval) + void *buffer, int length, int interval, bool nonblock) { - return _ehci_submit_int_msg(dev, pipe, buffer, length, interval); + return _ehci_submit_int_msg(dev, pipe, buffer, length, interval, + nonblock); } struct int_queue *create_int_queue(struct usb_device *dev, @@ -1567,10 +1569,11 @@ static int ehci_submit_bulk_msg(struct udevice *dev, struct usb_device *udev, static int ehci_submit_int_msg(struct udevice *dev, struct usb_device *udev, unsigned long pipe, void *buffer, int length, - int interval) + int interval, bool nonblock) { debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev); - return _ehci_submit_int_msg(udev, pipe, buffer, length, interval); + return _ehci_submit_int_msg(udev, pipe, buffer, length, interval, + nonblock); } static struct int_queue *ehci_create_int_queue(struct udevice *dev, diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index ed5e3f8d12..76b9c8d4f4 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1704,7 +1704,7 @@ int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, } int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, int interval) + int transfer_len, int interval, bool nonblock) { info("submit_int_msg"); return submit_common_msg(&gohci, dev, pipe, buffer, transfer_len, NULL, @@ -2156,7 +2156,7 @@ static int ohci_submit_bulk_msg(struct udevice *dev, struct usb_device *udev, static int ohci_submit_int_msg(struct udevice *dev, struct usb_device *udev, unsigned long pipe, void *buffer, int length, - int interval) + int interval, bool nonblock) { ohci_t *ohci = dev_get_priv(usb_get_bus(dev)); diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index b29c67e189..58a98ea793 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -385,7 +385,7 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, } int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, int interval) + int len, int interval, bool nonblock) { PDEBUG(0, "dev = %p pipe = %#lx buf = %p size = %d int = %d\n", dev, pipe, buffer, len, interval); diff --git a/drivers/usb/host/usb-sandbox.c b/drivers/usb/host/usb-sandbox.c index 15055b351a..bc91241aa7 100644 --- a/drivers/usb/host/usb-sandbox.c +++ b/drivers/usb/host/usb-sandbox.c @@ -102,7 +102,7 @@ static int sandbox_submit_bulk(struct udevice *bus, struct usb_device *udev, static int sandbox_submit_int(struct udevice *bus, struct usb_device *udev, unsigned long pipe, void *buffer, int length, - int interval) + int interval, bool nonblock) { struct udevice *emul; int ret; @@ -113,7 +113,8 @@ static int sandbox_submit_int(struct udevice *bus, struct usb_device *udev, usbmon_trace(bus, pipe, NULL, emul); if (ret) return ret; - ret = usb_emul_int(emul, udev, pipe, buffer, length, interval); + ret = usb_emul_int(emul, udev, pipe, buffer, length, interval, + nonblock); return ret; } diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index b79eadefa0..733e32db2b 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -34,7 +34,7 @@ int usb_disable_asynch(int disable) } int submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer, - int length, int interval) + int length, int interval, bool nonblock) { struct udevice *bus = udev->controller_dev; struct dm_usb_ops *ops = usb_get_ops(bus); @@ -42,7 +42,8 @@ int submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer, if (!ops->interrupt) return -ENOSYS; - return ops->interrupt(bus, udev, pipe, buffer, length, interval); + return ops->interrupt(bus, udev, pipe, buffer, length, interval, + nonblock); } int submit_control_msg(struct usb_device *udev, unsigned long pipe, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index aaa1a6ce2b..cddaefb83d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1110,7 +1110,8 @@ unknown: * @return 0 */ static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe, - void *buffer, int length, int interval) + void *buffer, int length, int interval, + bool nonblock) { if (usb_pipetype(pipe) != PIPE_INTERRUPT) { printf("non-interrupt pipe (type=%lu)", usb_pipetype(pipe)); @@ -1278,9 +1279,10 @@ int submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer, } int submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer, - int length, int interval) + int length, int interval, bool nonblock) { - return _xhci_submit_int_msg(udev, pipe, buffer, length, interval); + return _xhci_submit_int_msg(udev, pipe, buffer, length, interval, + nonblock); } /** @@ -1387,10 +1389,11 @@ static int xhci_submit_bulk_msg(struct udevice *dev, struct usb_device *udev, static int xhci_submit_int_msg(struct udevice *dev, struct usb_device *udev, unsigned long pipe, void *buffer, int length, - int interval) + int interval, bool nonblock) { debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev); - return _xhci_submit_int_msg(udev, pipe, buffer, length, interval); + return _xhci_submit_int_msg(udev, pipe, buffer, length, interval, + nonblock); } static int xhci_alloc_device(struct udevice *dev, struct usb_device *udev) diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c index e2aa313850..497e211c4c 100644 --- a/drivers/usb/musb-new/musb_uboot.c +++ b/drivers/usb/musb-new/musb_uboot.c @@ -113,7 +113,7 @@ static int _musb_submit_bulk_msg(struct musb_host_data *host, static int _musb_submit_int_msg(struct musb_host_data *host, struct usb_device *dev, unsigned long pipe, - void *buffer, int len, int interval) + void *buffer, int len, int interval, bool nonblock) { construct_urb(&host->urb, &host->hep, dev, USB_ENDPOINT_XFER_INT, pipe, buffer, len, NULL, interval); @@ -274,9 +274,10 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, } int submit_int_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int length, int interval) + void *buffer, int length, int interval, bool nonblock) { - return _musb_submit_int_msg(&musb_host, dev, pipe, buffer, length, interval); + return _musb_submit_int_msg(&musb_host, dev, pipe, buffer, length, + interval, nonblock); } struct int_queue *create_int_queue(struct usb_device *dev, @@ -326,10 +327,11 @@ static int musb_submit_bulk_msg(struct udevice *dev, struct usb_device *udev, static int musb_submit_int_msg(struct udevice *dev, struct usb_device *udev, unsigned long pipe, void *buffer, int length, - int interval) + int interval, bool nonblock) { struct musb_host_data *host = dev_get_priv(dev); - return _musb_submit_int_msg(host, udev, pipe, buffer, length, interval); + return _musb_submit_int_msg(host, udev, pipe, buffer, length, interval, + nonblock); } static struct int_queue *musb_create_int_queue(struct udevice *dev, diff --git a/include/usb.h b/include/usb.h index cf8ec98177..2775b36e11 100644 --- a/include/usb.h +++ b/include/usb.h @@ -185,7 +185,7 @@ int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, struct devrequest *setup); int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, int interval); + int transfer_len, int interval, bool nonblock); #if defined CONFIG_USB_EHCI_HCD || defined CONFIG_USB_MUSB_HOST \ || CONFIG_IS_ENABLED(DM_USB) @@ -262,8 +262,8 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, void *data, unsigned short size, int timeout); int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout); -int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, int interval); +int usb_int_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, int interval, bool nonblock); int usb_disable_asynch(int disable); int usb_maxpacket(struct usb_device *dev, unsigned long pipe); int usb_get_configuration_no(struct usb_device *dev, int cfgno, @@ -709,7 +709,7 @@ struct dm_usb_ops { */ int (*interrupt)(struct udevice *bus, struct usb_device *udev, unsigned long pipe, void *buffer, int length, - int interval); + int interval, bool nonblock); /** * create_int_queue() - Create and queue interrupt packets @@ -1030,7 +1030,8 @@ int usb_emul_bulk(struct udevice *emul, struct usb_device *udev, * @return 0 if OK, -ve on error */ int usb_emul_int(struct udevice *emul, struct usb_device *udev, - unsigned long pipe, void *buffer, int length, int interval); + unsigned long pipe, void *buffer, int length, int interval, + bool nonblock); /** * usb_emul_find() - Find an emulator for a particular device