Date: Mon, 02 Feb 2015 08:52:46 +0100 From: Hans Petter Selasky <hps@selasky.org> To: Kohji Okuno <okuno.kohji@jp.panasonic.com> Cc: freebsd-usb@freebsd.org Subject: Re: [Bug?] Control Transfers in xHCI Message-ID: <54CF2CCE.9090101@selasky.org> In-Reply-To: <20150202.100611.2049338919815112954.okuno.kohji@jp.panasonic.com> References: <54CA4BE3.2090706@selasky.org> <20150129195714.GA3683@dchagin.static.corbina.net> <54CA9144.4030601@selasky.org> <20150202.100611.2049338919815112954.okuno.kohji@jp.panasonic.com>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------000306000605080001060004 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Hi, Please find updated patch. The control_rem is pre-decremented and not post-decremented. --HPS --------------000306000605080001060004 Content-Type: text/x-patch; name="xhci.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="xhci.patch" Index: sys/dev/usb/controller/xhci.c =================================================================== --- sys/dev/usb/controller/xhci.c (revision 277724) +++ sys/dev/usb/controller/xhci.c (working copy) @@ -1866,6 +1866,15 @@ XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_DATA_STAGE); if (temp->direction == UE_DIR_IN) dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT; + /* + * Section 3.2.9 in the XHCI + * specification about control + * transfers says that we should use a + * normal-TRB if there are more TRBs + * extending the data-stage + * TRB. Update the "trb_type". + */ + temp->trb_type = XHCI_TRB_TYPE_NORMAL; break; case XHCI_TRB_TYPE_STATUS_STAGE: dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT | @@ -2106,7 +2115,8 @@ mult = 1; temp.isoc_delta = 0; temp.isoc_frame = 0; - temp.trb_type = XHCI_TRB_TYPE_DATA_STAGE; + temp.trb_type = xfer->flags_int.control_did_data ? + XHCI_TRB_TYPE_NORMAL : XHCI_TRB_TYPE_DATA_STAGE; } else { x = 0; mult = 1; Index: sys/dev/usb/usb_core.h =================================================================== --- sys/dev/usb/usb_core.h (revision 277724) +++ sys/dev/usb/usb_core.h (working copy) @@ -101,6 +101,7 @@ * sent */ uint8_t control_act:1; /* set if control transfer is active */ uint8_t control_stall:1; /* set if control transfer should be stalled */ + uint8_t control_did_data:1; /* set if control data has been sent */ uint8_t short_frames_ok:1; /* filtered version */ uint8_t short_xfer_ok:1; /* filtered version */ Index: sys/dev/usb/usb_transfer.c =================================================================== --- sys/dev/usb/usb_transfer.c (revision 277724) +++ sys/dev/usb/usb_transfer.c (working copy) @@ -1409,6 +1409,28 @@ } /*------------------------------------------------------------------------* + * usbd_control_transfer_did_data + * + * This function returns non-zero if a control endpoint has done the + * first DATA packet after the SETUP packet. Else it returns zero. + *------------------------------------------------------------------------*/ +static uint8_t +usbd_control_transfer_did_data(struct usb_xfer *xfer) +{ + struct usb_device_request req; + + /* SETUP packet is not yet sent */ + if (xfer->flags_int.control_hdr != 0) + return (0); + + /* copy out the USB request header */ + usbd_copy_out(xfer->frbuffers, 0, &req, sizeof(req)); + + /* compare remainder to the initial value */ + return (xfer->flags_int.control_rem != UGETW(req.wLength)); +} + +/*------------------------------------------------------------------------* * usbd_setup_ctrl_transfer * * This function handles initialisation of control transfers. Control @@ -1513,6 +1535,11 @@ len = (xfer->sumlen - sizeof(struct usb_device_request)); } + /* update did data flag */ + + xfer->flags_int.control_did_data = + usbd_control_transfer_did_data(xfer); + /* check if there is a length mismatch */ if (len > xfer->flags_int.control_rem) { --------------000306000605080001060004--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?54CF2CCE.9090101>