--- zzzz-none-000/linux-2.6.32.60/drivers/net/usb/usbnet.c 2012-10-07 21:41:24.000000000 +0000 +++ ur8-7270-606/linux-2.6.32.60/drivers/net/usb/usbnet.c 2013-02-12 11:22:19.000000000 +0000 @@ -962,7 +962,8 @@ struct usbnet *dev = entry->dev; if (urb->status == 0) { - dev->net->stats.tx_packets++; + if (!(dev->driver_info->flags & FLAG_MULTI_PACKET)) + dev->net->stats.tx_packets++; dev->net->stats.tx_bytes += entry->length; } else { dev->net->stats.tx_errors++; @@ -1033,9 +1034,13 @@ if (info->tx_fixup) { skb = info->tx_fixup (dev, skb, GFP_ATOMIC); if (!skb) { - if (netif_msg_tx_err (dev)) + if (netif_msg_tx_err (dev)) { devdbg (dev, "can't tx_fixup skb"); - goto drop; + goto drop; + } else { + /* cdc_ncm collected packet; waits for more */ + goto not_drop; + } } } length = skb->len; @@ -1058,13 +1063,21 @@ /* 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 (!(info->flags & FLAG_SEND_ZLP) && (length % dev->maxpacket) == 0) { - urb->transfer_buffer_length++; - if (skb_tailroom(skb)) { - skb->data[skb->len] = 0; - __skb_put(skb, 1); - } + 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; } spin_lock_irqsave (&dev->txq.lock, flags); @@ -1091,6 +1104,7 @@ devdbg (dev, "drop, code %d", retval); drop: dev->net->stats.tx_dropped++; +not_drop: if (skb) dev_kfree_skb_any (skb); usb_free_urb (urb);