Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: gadget: udc: Handle gadget_connect failure during bind operation

In the event, gadget_connect call (which invokes pullup) fails,
propagate the error to udc bind operation which inturn sends the
error to configfs. The userspace can then retry enumeartion if
it chooses to.

Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Link: https://lore.kernel.org/r/20230510075252.31023-3-quic_kriskura@quicinc.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Krishna Kurapati and committed by
Greg Kroah-Hartman
d34f9baf 813f44d5

+17 -4
+17 -4
drivers/usb/gadget/udc/core.c
··· 1122 1122 /* ------------------------------------------------------------------------- */ 1123 1123 1124 1124 /* Acquire connect_lock before calling this function. */ 1125 - static void usb_udc_connect_control_locked(struct usb_udc *udc) __must_hold(&udc->connect_lock) 1125 + static int usb_udc_connect_control_locked(struct usb_udc *udc) __must_hold(&udc->connect_lock) 1126 1126 { 1127 + int ret; 1128 + 1127 1129 if (udc->vbus && udc->started) 1128 - usb_gadget_connect_locked(udc->gadget); 1130 + ret = usb_gadget_connect_locked(udc->gadget); 1129 1131 else 1130 - usb_gadget_disconnect_locked(udc->gadget); 1132 + ret = usb_gadget_disconnect_locked(udc->gadget); 1133 + 1134 + return ret; 1131 1135 } 1132 1136 1133 1137 /** ··· 1587 1583 goto err_start; 1588 1584 } 1589 1585 usb_gadget_enable_async_callbacks(udc); 1590 - usb_udc_connect_control_locked(udc); 1586 + ret = usb_udc_connect_control_locked(udc); 1587 + if (ret) 1588 + goto err_connect_control; 1589 + 1591 1590 mutex_unlock(&udc->connect_lock); 1592 1591 1593 1592 kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); 1594 1593 return 0; 1594 + 1595 + err_connect_control: 1596 + usb_gadget_disable_async_callbacks(udc); 1597 + if (gadget->irq) 1598 + synchronize_irq(gadget->irq); 1599 + usb_gadget_udc_stop_locked(udc); 1595 1600 1596 1601 err_start: 1597 1602 driver->unbind(udc->gadget);