diff options
Diffstat (limited to 'freebsd/sys/dev/usb/usb_transfer.c')
-rw-r--r-- | freebsd/sys/dev/usb/usb_transfer.c | 59 |
1 files changed, 50 insertions, 9 deletions
diff --git a/freebsd/sys/dev/usb/usb_transfer.c b/freebsd/sys/dev/usb/usb_transfer.c index b2528186..205a72f7 100644 --- a/freebsd/sys/dev/usb/usb_transfer.c +++ b/freebsd/sys/dev/usb/usb_transfer.c @@ -334,6 +334,7 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm) usb_frcount_t n_frlengths; usb_frcount_t n_frbuffers; usb_frcount_t x; + uint16_t maxp_old; uint8_t type; uint8_t zmps; @@ -419,6 +420,11 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm) if (xfer->max_packet_count > parm->hc_max_packet_count) { xfer->max_packet_count = parm->hc_max_packet_count; } + + /* store max packet size value before filtering */ + + maxp_old = xfer->max_packet_size; + /* filter "wMaxPacketSize" according to HC capabilities */ if ((xfer->max_packet_size > parm->hc_max_packet_size) || @@ -451,6 +457,13 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm) } } + /* + * Check if the max packet size was outside its allowed range + * and clamped to a valid value: + */ + if (maxp_old != xfer->max_packet_size) + xfer->flags_int.maxp_was_clamped = 1; + /* compute "max_frame_size" */ usbd_update_max_frame_size(xfer); @@ -2396,7 +2409,9 @@ usbd_transfer_enqueue(struct usb_xfer_queue *pq, struct usb_xfer *xfer) void usbd_transfer_done(struct usb_xfer *xfer, usb_error_t error) { - USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED); + struct usb_xfer_root *info = xfer->xroot; + + USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED); DPRINTF("err=%s\n", usbd_errstr(error)); @@ -2410,10 +2425,10 @@ usbd_transfer_done(struct usb_xfer *xfer, usb_error_t error) xfer->flags_int.control_act = 0; return; } - /* only set transfer error if not already set */ - if (!xfer->error) { + /* only set transfer error, if not already set */ + if (xfer->error == USB_ERR_NORMAL_COMPLETION) xfer->error = error; - } + /* stop any callouts */ usb_callout_stop(&xfer->timeout_handle); @@ -2425,14 +2440,14 @@ usbd_transfer_done(struct usb_xfer *xfer, usb_error_t error) usbd_transfer_dequeue(xfer); #if USB_HAVE_BUSDMA - if (mtx_owned(xfer->xroot->xfer_mtx)) { + if (mtx_owned(info->xfer_mtx)) { struct usb_xfer_queue *pq; /* * If the private USB lock is not locked, then we assume * that the BUS-DMA load stage has been passed: */ - pq = &xfer->xroot->dma_q; + pq = &info->dma_q; if (pq->curr == xfer) { /* start the next BUS-DMA load, if any */ @@ -2442,10 +2457,10 @@ usbd_transfer_done(struct usb_xfer *xfer, usb_error_t error) #endif /* keep some statistics */ if (xfer->error) { - xfer->xroot->bus->stats_err.uds_requests + info->bus->stats_err.uds_requests [xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++; } else { - xfer->xroot->bus->stats_ok.uds_requests + info->bus->stats_ok.uds_requests [xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++; } @@ -2685,7 +2700,7 @@ usbd_transfer_timeout_ms(struct usb_xfer *xfer, /* defer delay */ usb_callout_reset(&xfer->timeout_handle, - USB_MS_TO_TICKS(ms), cb, xfer); + USB_MS_TO_TICKS(ms) + USB_CALLOUT_ZERO_TICKS, cb, xfer); } /*------------------------------------------------------------------------* @@ -2811,6 +2826,22 @@ usbd_callback_wrapper_sub(struct usb_xfer *xfer) /* end of control transfer, if any */ xfer->flags_int.control_act = 0; +#if USB_HAVE_TT_SUPPORT + switch (xfer->error) { + case USB_ERR_NORMAL_COMPLETION: + case USB_ERR_SHORT_XFER: + case USB_ERR_STALLED: + case USB_ERR_CANCELLED: + /* nothing to do */ + break; + default: + /* try to reset the TT, if any */ + USB_BUS_LOCK(bus); + uhub_tt_buffer_reset_async_locked(xfer->xroot->udev, xfer->endpoint); + USB_BUS_UNLOCK(bus); + break; + } +#endif /* check if we should block the execution queue */ if ((xfer->error != USB_ERR_CANCELLED) && (xfer->flags.pipe_bof)) { @@ -3377,3 +3408,13 @@ usbd_xfer_get_timestamp(struct usb_xfer *xfer) { return (xfer->isoc_time_complete); } + +/* + * The following function returns non-zero if the max packet size + * field was clamped to a valid value. Else it returns zero. + */ +uint8_t +usbd_xfer_maxp_was_clamped(struct usb_xfer *xfer) +{ + return (xfer->flags_int.maxp_was_clamped); +} |