]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[usb] Generalise zero-length packet generation logic
authorMichael Brown <mcb30@ipxe.org>
Sat, 12 Sep 2015 23:49:56 +0000 (00:49 +0100)
committerMichael Brown <mcb30@ipxe.org>
Sun, 13 Sep 2015 11:54:30 +0000 (12:54 +0100)
The decision on whether or not a zero-length packet needs to be
transmitted is independent of the host controller and belongs in the
USB core.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/bus/usb.c
src/drivers/usb/ehci.c
src/drivers/usb/uhci.c
src/drivers/usb/usbio.c
src/drivers/usb/xhci.c
src/include/ipxe/usb.h

index c0cd54bb7890bd13bd024c0781520891d489235a..cd80c320141d51f3e4d098865fee092e0b8dd38f 100644 (file)
@@ -530,6 +530,7 @@ int usb_stream ( struct usb_endpoint *ep, struct io_buffer *iobuf,
                 int terminate ) {
        struct usb_device *usb = ep->usb;
        struct usb_port *port = usb->port;
+       int zlp;
        int rc;
 
        /* Fail immediately if device has been unplugged */
@@ -541,8 +542,13 @@ int usb_stream ( struct usb_endpoint *ep, struct io_buffer *iobuf,
             ( ( rc = usb_endpoint_reset ( ep ) ) != 0 ) )
                return rc;
 
+       /* Append a zero-length packet if necessary */
+       zlp = terminate;
+       if ( iob_len ( iobuf ) & ( ep->mtu - 1 ) )
+               zlp = 0;
+
        /* Enqueue stream transfer */
-       if ( ( rc = ep->host->stream ( ep, iobuf, terminate ) ) != 0 ) {
+       if ( ( rc = ep->host->stream ( ep, iobuf, zlp ) ) != 0 ) {
                DBGC ( usb, "USB %s %s could not enqueue stream transfer: %s\n",
                       usb->name, usb_endpoint_name ( ep ), strerror ( rc ) );
                return rc;
index 4124692a651e4adcae36339ab3681b961a9f890a..0a89ec13328733ee6fb3400259926c5ee278c1a9 100644 (file)
@@ -1223,11 +1223,11 @@ static int ehci_endpoint_message ( struct usb_endpoint *ep,
  *
  * @v ep               USB endpoint
  * @v iobuf            I/O buffer
- * @v terminate                Terminate using a short packet
+ * @v zlp              Append a zero-length packet
  * @ret rc             Return status code
  */
 static int ehci_endpoint_stream ( struct usb_endpoint *ep,
-                                 struct io_buffer *iobuf, int terminate ) {
+                                 struct io_buffer *iobuf, int zlp ) {
        struct ehci_endpoint *endpoint = usb_endpoint_get_hostdata ( ep );
        struct ehci_device *ehci = endpoint->ehci;
        unsigned int input = ( ep->address & USB_DIR_IN );
@@ -1242,7 +1242,7 @@ static int ehci_endpoint_stream ( struct usb_endpoint *ep,
        xfer->flags = ( EHCI_FL_IOC |
                        ( input ? EHCI_FL_PID_IN : EHCI_FL_PID_OUT ) );
        xfer++;
-       if ( terminate && ( ( len & ( ep->mtu - 1 ) ) == 0 ) ) {
+       if ( zlp ) {
                xfer->data = NULL;
                xfer->len = 0;
                assert ( ! input );
index b6bb92560d4c69b3693879d3a30f15af789f91f0..4220bef720c110d687f44649c3189ce526a57cb7 100644 (file)
@@ -835,22 +835,20 @@ static int uhci_endpoint_message ( struct usb_endpoint *ep,
  *
  * @v ep               USB endpoint
  * @v iobuf            I/O buffer
- * @v terminate                Terminate using a short packet
+ * @v zlp              Append a zero-length packet
  * @ret rc             Return status code
  */
 static int uhci_endpoint_stream ( struct usb_endpoint *ep,
-                                 struct io_buffer *iobuf, int terminate ) {
+                                 struct io_buffer *iobuf, int zlp ) {
        struct uhci_endpoint *endpoint = usb_endpoint_get_hostdata ( ep );
        struct uhci_ring *ring = &endpoint->ring;
        unsigned int count;
        size_t len;
        int input;
-       int zlp;
        int rc;
 
        /* Calculate number of descriptors */
        len = iob_len ( iobuf );
-       zlp = ( terminate && ( ( len & ( ring->mtu - 1 ) ) == 0 ) );
        count = ( ( ( len + ring->mtu - 1 ) / ring->mtu ) + ( zlp ? 1 : 0 ) );
 
        /* Enqueue transfer */
index 70aa5095135c2a8d16fb4d14d3e2a7b7be7ecc7a..a80f7c8fcce4bf2341535434eb9889e3badddbab 100644 (file)
@@ -1005,17 +1005,14 @@ static int usbio_endpoint_message ( struct usb_endpoint *ep,
  *
  * @v ep               USB endpoint
  * @v iobuf            I/O buffer
- * @v terminate                Terminate using a short packet
+ * @v zlp              Append a zero-length packet
  * @ret rc             Return status code
  */
 static int usbio_endpoint_stream ( struct usb_endpoint *ep,
-                                  struct io_buffer *iobuf, int terminate ) {
-       size_t len = iob_len ( iobuf );
-       int zlen;
+                                  struct io_buffer *iobuf, int zlp ) {
 
        /* Enqueue transfer */
-       zlen = ( terminate && ( ( len & ( ep->mtu - 1 ) ) == 0 ) );
-       return usbio_endpoint_enqueue ( ep, iobuf, ( zlen ? USBIO_ZLEN : 0 ) );
+       return usbio_endpoint_enqueue ( ep, iobuf, ( zlp ? USBIO_ZLEN : 0 ) );
 }
 
 /**
index 49e67316ba8f31917a1a7bd94e86db3df18727f1..f0f8eb1d98f1bb4a74742e8d50806dd10585a4ed 100644 (file)
@@ -2546,11 +2546,11 @@ static int xhci_endpoint_message ( struct usb_endpoint *ep,
  *
  * @v ep               USB endpoint
  * @v iobuf            I/O buffer
- * @v terminate                Terminate using a short packet
+ * @v zlp              Append a zero-length packet
  * @ret rc             Return status code
  */
 static int xhci_endpoint_stream ( struct usb_endpoint *ep,
-                                 struct io_buffer *iobuf, int terminate ) {
+                                 struct io_buffer *iobuf, int zlp ) {
        struct xhci_endpoint *endpoint = usb_endpoint_get_hostdata ( ep );
        union xhci_trb trbs[ 1 /* Normal */ + 1 /* Possible zero-length */ ];
        union xhci_trb *trb = trbs;
@@ -2567,7 +2567,7 @@ static int xhci_endpoint_stream ( struct usb_endpoint *ep,
        normal->data = cpu_to_le64 ( virt_to_phys ( iobuf->data ) );
        normal->len = cpu_to_le32 ( len );
        normal->type = XHCI_TRB_NORMAL;
-       if ( terminate && ( ( len & ( ep->mtu - 1 ) ) == 0 ) ) {
+       if ( zlp ) {
                normal->flags = XHCI_TRB_CH;
                normal = &(trb++)->normal;
                normal->type = XHCI_TRB_NORMAL;
index dfe0f34823ef97788f42a86a177ae37e22000d37..0640f9e3879032853442e2adb6e59df440caed9e 100644 (file)
@@ -458,11 +458,11 @@ struct usb_endpoint_host_operations {
         *
         * @v ep                USB endpoint
         * @v iobuf             I/O buffer
-        * @v terminate         Terminate using a short packet
+        * @v zlp               Append a zero-length packet
         * @ret rc              Return status code
         */
        int ( * stream ) ( struct usb_endpoint *ep, struct io_buffer *iobuf,
-                          int terminate );
+                          int zlp );
 };
 
 /** USB endpoint driver operations */