Re: CDC NCM missing Zero Length Packets

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

 



On Sat, Apr 23, 2011 at 12:05:39PM +0200, Hans Petter Selasky wrote:
> On Saturday 23 April 2011 09:36:09 Matthias Benesch wrote:
> > Am 22.04.2011 22:45, schrieb Hans Petter Selasky:
> > > On Friday 22 April 2011 16:32:42 Matthias Benesch wrote:
> > >> 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;
> > >>       
> > >>       }
> > > 
> > > Hi Matthias,
> > > 
> > > How about setting
> > > 
> > > #define CDC_NCM_NTB_MAX_SIZE_TX                 16384   /* bytes */
> > > 
> > > to 16385 bytes. Then if the maximum is exceeded a short packet will
> > > always be sent, without affecting performance with regard to zero
> > > padding?
> > > 
> > > --HPS
> > > --
> > > 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
> > 
> > Hi Hans Petter,
> > 
> > Thanks for the tip. I have not thought about a easy solution like that.
> > I just tested to set
> > 
> > #define CDC_NCM_NTB_MAX_SIZE_TX                 16384   /* bytes */
> > 
> > to 16383 bytes.
> > 
> > I have to say that I am not quite familar with the DMA engines of USB
> > chipsets. But is it usefull to to pad zeros up to the 16385 bytes if the
> > USB device has reported a dwNtbOutMaxSize greater than that? Because
> > within the source code is written that "it would be more efficient for
> > USB HS mobile device with DMA engine to receive a full size NTB, than
> > canceling DMA transfer and receiving a short packet." But this will not
> > be reached, due to the fact that we are not zero padding up to
> > dwNtbOutMaxSize.
> 
> Hi Matthias,
> 
> The answer to your question depends on the hardware and software solution 
> used. The idea behind the comment is to reduce the number of IRQ's in the 
> hardware on the device side. Short packets are sometimes handled specially and 
> can be PIO'ed out of the FIFO instead of DMA'ed. Then it is better to PIO 0-4 
> bytes (16385 case) instead of 511 bytes (16383 case). Again, this depends on 
> the USB hardware and USB software used.
> 
> > 
> > What is the minimum usefull amount of zero padding in that case? Is it
> > maybe possible to just fill zeros up to the multiple of wMaxPacketSize?
> > Or to do not use zero padding in case of dwNtbOutMaxSize >
> > CDC_NCM_NTB_MAX_SIZE_TX?
> 
> There are two ways to cause short termination:
> 
> a) ZLP feature
> b) append a byte when the transfer length modulus wMaxPacket equals zero.
> 
> Solution b) was used because it is more generic, though a ZLP should also work 
> with most device side hardware.
> 
> I guess some more people will fill in details on this thread when they are 
> back from easter vacation, CC'ed, and submit a patch to fix this issue.

Why can't you send a patch based on the change of the above mentioned
#define?

thanks,

greg k-h
--
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