--- a/sys/bus/u4b/serial/uplcom.c +++ b/sys/bus/u4b/serial/uplcom.c @@ -121,6 +121,15 @@ #define UPLCOM_INTR_INTERVAL 0 /* default */ #endif +/* + * Attach-path control-request timeout bound: uplcom_reset() plus + * uplcom_pl2303_init() chain 14 sequential synchronous EP0 requests, and + * usbd_do_request() defaults to a 5000 ms timeout, so an in-spec-but-slow + * (NAK-ing) device could pin the per-bus USB explore thread for ~70 s + * during attach. Bound each request to 250 ms instead. + */ +#define UPLCOM_INIT_TIMEOUT 250 /* ms */ + #define UPLCOM_BULK_BUF_SIZE 1024 /* bytes */ #define UPLCOM_SET_REQUEST 0x01 @@ -162,7 +171,7 @@ static usb_error_t uplcom_reset(struct uplcom_softc *, struct usb_device *); static usb_error_t uplcom_pl2303_do(struct usb_device *, int8_t, uint8_t, - uint16_t, uint16_t, uint16_t); + uint16_t, uint16_t, uint16_t, usb_timeout_t); static int uplcom_pl2303_init(struct usb_device *, uint8_t); static void uplcom_cfg_set_dtr(struct ucom_softc *, uint8_t); static void uplcom_cfg_set_rts(struct ucom_softc *, uint8_t); @@ -469,12 +478,13 @@ req.wIndex[1] = 0; USETW(req.wLength, 0); - return (usbd_do_request(udev, NULL, &req, NULL)); + return (usbd_do_request_flags(udev, NULL, &req, NULL, 0, NULL, + UPLCOM_INIT_TIMEOUT)); } static usb_error_t uplcom_pl2303_do(struct usb_device *udev, int8_t req_type, uint8_t request, - uint16_t value, uint16_t index, uint16_t length) + uint16_t value, uint16_t index, uint16_t length, usb_timeout_t timeout) { struct usb_device_request req; usb_error_t err; @@ -486,7 +496,7 @@ USETW(req.wIndex, index); USETW(req.wLength, length); - err = usbd_do_request(udev, NULL, &req, buf); + err = usbd_do_request_flags(udev, NULL, &req, buf, 0, NULL, timeout); if (err) { DPRINTF("error=%s\n", usbd_errstr(err)); return (1); @@ -499,27 +509,27 @@ { int err; - if (uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) - || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 0, 0) - || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) - || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 1) - || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) - || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 1, 0) - || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) - || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 1) - || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0, 1, 0) - || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 1, 0, 0)) + if (uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1, UPLCOM_INIT_TIMEOUT) + || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 0, 0, UPLCOM_INIT_TIMEOUT) + || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1, UPLCOM_INIT_TIMEOUT) + || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 1, UPLCOM_INIT_TIMEOUT) + || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1, UPLCOM_INIT_TIMEOUT) + || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 1, 0, UPLCOM_INIT_TIMEOUT) + || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1, UPLCOM_INIT_TIMEOUT) + || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 1, UPLCOM_INIT_TIMEOUT) + || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0, 1, 0, UPLCOM_INIT_TIMEOUT) + || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 1, 0, 0, UPLCOM_INIT_TIMEOUT)) return (EIO); if (chiptype == TYPE_PL2303HX) - err = uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x44, 0); + err = uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x44, 0, UPLCOM_INIT_TIMEOUT); else - err = uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x24, 0); + err = uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x24, 0, UPLCOM_INIT_TIMEOUT); if (err) return (EIO); - if (uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 8, 0, 0) - || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 9, 0, 0)) + if (uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 8, 0, 0, UPLCOM_INIT_TIMEOUT) + || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 9, 0, 0, UPLCOM_INIT_TIMEOUT)) return (EIO); return (0); }