CDC NCM missing Zero Length Packets

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

I am testing the USB-CDC NCM host driver. One issue that was found by one USB device stack provider, is that the current implementation is not sending ZLP or short packets if the dwNtbOutMaxSize reported by the device is greater than CDC_NCM_NTB_MAX_SIZE_TX (=16383 bytes).

As written in the specification, ZLP shall not be sent "If exactly dwNtbInMaxSize or dwNtbOutMaxSize bytes are sent, and the size is a multiple of wMaxPacketSize for the given pipe".

This requirement is covered in cdc_ncm.c after zero padding (line 858):

    /* final zero padding */
    cdc_ncm_zero_fill(skb_out->data, last_offset, offset, ctx->tx_max);

    /* store last offset */
    last_offset = offset;

    if ((last_offset < ctx->tx_max) && ((last_offset %
            le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0)) {
        /* force short packet */
        *(((u8 *)skb_out->data) + last_offset) = 0;
        last_offset++;
    }

Unfortunately "ctx->tx_max" ist not equal to dwNtbOutMaxSize if dwNtbOutMaxSize is greater than CDC_NCM_NTB_MAX_SIZE_TX, because it will be reset to CDC_NCM_NTB_MAX_SIZE_TX in that case (see line 220 & 289).

   ctx->tx_max = le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize);

   ...

   /* verify maximum size of transmitted NTB in bytes */
   if ((ctx->tx_max <
       (CDC_NCM_MIN_HDR_SIZE + CDC_NCM_MIN_DATAGRAM_SIZE)) ||
       (ctx->tx_max > CDC_NCM_NTB_MAX_SIZE_TX)) {
       pr_debug("Using default maximum transmit length=%d\n",
                       CDC_NCM_NTB_MAX_SIZE_TX);
       ctx->tx_max = CDC_NCM_NTB_MAX_SIZE_TX;
   }

Therefore the short packet will not be sent although the USB device stack is still waiting for dwNtbOutMaxSize bytes of data to be filled by the host.

In my opinion possible solutions are:

1. Set CDC_NCM_NTB_MAX_SIZE_TX to the maximum amount of bytes supported by NCM16 (=65535 bytes). In addition to that I disabled the zero padding, due to the big overhead of data. With this configuration I achieved a maximum stable throughput of 131 Mbit/s of transmitting data.

2. Enable "urb->transfer_flags |= URB_ZERO_PACKET;" within usbnet.c (line 1091) if ZLP shall be sent by the NCM implementation. This could be done by an additional flag which shall be set within the cdc_ncm.c if needed.

    /* don't assume the hardware handles USB_ZERO_PACKET
     * NOTE:  strictly conforming cdc-ether devices should expect
     * the ZLP here, but ignore the one-byte packet.
     * NOTE2: CDC NCM specification is different from CDC ECM when
     * handling ZLP/short packets, so cdc_ncm driver will make short
     * packet itself if needed.
     */
    if (length % dev->maxpacket == 0) {
        if (!(info->flags & FLAG_SEND_ZLP)) {
            if (!(info->flags & FLAG_MULTI_PACKET)) {
                urb->transfer_buffer_length++;
                if (skb_tailroom(skb)) {
                    skb->data[skb->len] = 0;
                    __skb_put(skb, 1);
                }
            }
        } else
            urb->transfer_flags |= URB_ZERO_PACKET;
    }

Kind regards,
Matthias
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux