Date: Sun, 23 Sep 2007 12:34:31 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 126720 for review Message-ID: <200709231234.l8NCYVwK067871@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=126720 Change 126720 by hselasky@hselasky_laptop001 on 2007/09/23 12:34:22 FYI; The comments follow the P4 diff from top to bottom. - the maximum frame size must be read from the USB transfer - convert kernel USB flags (USBD_XXX) into a bitmap (scripted) - computing correct buffer sizes have been factored out into the USB kernel by setting the "proxy_buffer" flag. - "xfer->actlen < xfer->sumlen" is the new way to check if a USB transfer is short. - remove redundant setting of "xfer->length" for ISOC USB transfers. - proxy buffer data size is now stored in "xfer->max_data_length". - new mechanism to proxy USB control transfers Affected files ... .. //depot/projects/usb/src/sys/dev/usb/usb_compat_linux.c#7 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/usb_compat_linux.c#7 (text+ko) ==== @@ -753,7 +753,6 @@ usb_setup_endpoint(struct usb_device *dev, struct usb_host_endpoint *uhe, uint32_t bufsize) { struct usbd_config cfg[2]; - uint16_t mfs = usbd_get_max_frame_size((usb_endpoint_descriptor_t *)&(uhe->desc)); uint8_t type = uhe->desc.bmAttributes & UE_XFERTYPE; uint8_t addr = uhe->desc.bEndpointAddress; @@ -784,7 +783,8 @@ cfg[0].callback = &usb_linux_isoc_callback; cfg[0].bufsize = 0; /* use wMaxPacketSize */ cfg[0].frames = usb_max_isoc_frames(dev); - cfg[0].flags = (USBD_USE_DMA|USBD_SHORT_XFER_OK); + cfg[0].flags.proxy_buffer = 1; + cfg[0].flags.short_xfer_ok = 1; bcopy(cfg + 0, cfg + 1, sizeof(*cfg)); @@ -802,16 +802,6 @@ bufsize = (1 << 22); } - /* we need enough room for the control header */ - if (bufsize < sizeof(usb_device_request_t)) { - bufsize = sizeof(usb_device_request_t); - } - - if (bufsize < mfs) { - /* we need to be able to hold at least one frame! */ - bufsize = mfs; - } - /* Allocate and setup one generic FreeBSD USB transfer */ cfg[0].type = type; @@ -819,7 +809,8 @@ cfg[0].direction = addr & (UE_DIR_OUT|UE_DIR_IN); cfg[0].callback = &usb_linux_non_isoc_callback; cfg[0].bufsize = bufsize; - cfg[0].flags = (USBD_USE_DMA|USBD_SHORT_XFER_OK); + cfg[0].flags.proxy_buffer = 1; + cfg[0].flags.short_xfer_ok = 1; if (usbd_transfer_setup(dev->bsd_udev, uhe->bsd_iface_index, uhe->bsd_xfer, cfg, 1, uhe, @@ -1359,7 +1350,7 @@ urb->actual_length = xfer->actlen; /* check for short transfer */ - if (xfer->actlen < xfer->length) { + if (xfer->actlen < xfer->sumlen) { /* short transfer */ if (urb->transfer_flags & URB_SHORT_NOT_OK) { urb->status = -EPIPE; /* XXX should be EREMOTEIO */ @@ -1431,10 +1422,9 @@ } xfer->priv_fifo = urb; - xfer->flags &= ~USBD_FORCE_SHORT_XFER; + xfer->flags.force_short_xfer = 0; xfer->timeout = urb->timeout; xfer->nframes = urb->number_of_packets; - xfer->length = offset; /* not really used */ usbd_start_hardware(xfer); return; } @@ -1448,10 +1438,13 @@ static void usb_linux_non_isoc_callback(struct usbd_xfer *xfer) { + enum { + REQ_SIZE = sizeof(usb_device_request_t) + }; struct urb *urb = xfer->priv_fifo; struct usb_host_endpoint *uhe = xfer->priv_sc; - uint32_t max_bulk = (uhe->fbsd_buf_size - - (uhe->fbsd_buf_size % xfer->max_packet_size)); + uint32_t max_bulk = xfer->max_data_length; + uint8_t data_frame = xfer->flags_int.control_xfr ? 1 : 0; USBD_CHECK_STATUS(xfer); @@ -1476,18 +1469,31 @@ tr_transferred: + if (xfer->flags_int.control_xfr) { + + /* sanity check - should not happen */ + + if (xfer->aframes < xfer->nframes) { + goto tr_error; + } + + /* don't transfer the setup packet again: */ + + xfer->frlengths[0] = 0; + } + if (urb->bsd_isread) { /* copy in data with regard to the URB */ - usbd_copy_out(&(xfer->buf_data), 0, - urb->bsd_data_ptr, xfer->actlen); + usbd_copy_out(xfer->frbuffers + data_frame, 0, + urb->bsd_data_ptr, xfer->frlengths[data_frame]); } - urb->bsd_length_rem -= xfer->actlen; - urb->bsd_data_ptr += xfer->actlen; - urb->actual_length += xfer->actlen; + urb->bsd_length_rem -= xfer->frlengths[data_frame]; + urb->bsd_data_ptr += xfer->frlengths[data_frame]; + urb->actual_length += xfer->frlengths[data_frame]; - /* check for short packet */ - if (xfer->actlen < xfer->length) { + /* check for short transfer */ + if (xfer->actlen < xfer->sumlen) { urb->bsd_length_rem = 0; /* short transfer */ @@ -1499,7 +1505,7 @@ } else { /* check remainder */ - if (urb->bsd_length_rem) { + if (urb->bsd_length_rem > 0) { goto setup_bulk; } @@ -1507,12 +1513,6 @@ urb->status = 0; } - /* check actual length */ - if (urb->actual_length > urb->transfer_buffer_length) { - /* premature end of a control transfer */ - urb->actual_length = 0; - } - /* call callback */ usb_linux_complete(xfer); @@ -1529,49 +1529,58 @@ urb->bsd_urb_list.tqe_prev = NULL; xfer->priv_fifo = urb; - xfer->flags &= ~USBD_FORCE_SHORT_XFER; + xfer->flags.force_short_xfer = 0; xfer->timeout = urb->timeout; - if ((uhe->desc.bmAttributes & UE_XFERTYPE) == UE_CONTROL) { - /* transfer the control header first and then the data, - * if any, to a control endpoint: + if (xfer->flags_int.control_xfr) { + + /* + * USB control transfers need special handling. + * First copy in the header, then copy in data! */ - usbd_copy_in(&(xfer->buf_data), 0, - urb->setup_packet, sizeof(usb_device_request_t)); - xfer->length = sizeof(usb_device_request_t); + usbd_copy_in(xfer->frbuffers + 0, 0, + urb->setup_packet, REQ_SIZE); + + xfer->frlengths[0] = REQ_SIZE; + + /* setup data transfer direction */ - urb->bsd_length_rem = xfer->length + urb->transfer_buffer_length; - urb->bsd_data_ptr = ((uint8_t *)(urb->transfer_buffer)) - xfer->length; - urb->actual_length = -xfer->length; urb->bsd_isread = (((uint8_t *)(urb->setup_packet))[0] & UT_READ) ? 1 : 0; - usbd_start_hardware(xfer); - return; + } else { + + /* setup data transfer direction */ + + urb->bsd_isread = (uhe->desc.bEndpointAddress & UE_DIR_IN) ? 1 : 0; } urb->bsd_length_rem = urb->transfer_buffer_length; urb->bsd_data_ptr = urb->transfer_buffer; urb->actual_length = 0; - urb->bsd_isread = (uhe->desc.bEndpointAddress & UE_DIR_IN) ? 1 : 0; setup_bulk: if (max_bulk > urb->bsd_length_rem) { max_bulk = urb->bsd_length_rem; } - if (max_bulk == urb->bsd_length_rem) { - if (urb->transfer_flags & URB_ZERO_PACKET) { - xfer->flags |= USBD_FORCE_SHORT_XFER; - } + /* check if we need to force a short transfer */ + + if ((max_bulk == urb->bsd_length_rem) && + (urb->transfer_flags & URB_ZERO_PACKET) && + (!xfer->flags_int.control_xfr)) { + xfer->flags.force_short_xfer = 1; } + /* check if we need to copy in data */ + if (!(urb->bsd_isread)) { /* copy out data with regard to the URB */ - usbd_copy_in(&(xfer->buf_data), 0, + usbd_copy_in(xfer->frbuffers + data_frame, 0, urb->bsd_data_ptr, max_bulk); } - xfer->length = max_bulk; + xfer->frlengths[data_frame] = max_bulk; + xfer->nframes = data_frame + 1; usbd_start_hardware(xfer); return; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200709231234.l8NCYVwK067871>