From owner-p4-projects@FreeBSD.ORG Sun Sep 23 12:34:32 2007 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 89AAD16A421; Sun, 23 Sep 2007 12:34:32 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4A2F216A417 for ; Sun, 23 Sep 2007 12:34:32 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 3125713C467 for ; Sun, 23 Sep 2007 12:34:32 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id l8NCYVeZ067874 for ; Sun, 23 Sep 2007 12:34:31 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id l8NCYVwK067871 for perforce@freebsd.org; Sun, 23 Sep 2007 12:34:31 GMT (envelope-from hselasky@FreeBSD.org) Date: Sun, 23 Sep 2007 12:34:31 GMT Message-Id: <200709231234.l8NCYVwK067871@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 126720 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 Sep 2007 12:34:32 -0000 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; }