|
@@ -391,14 +391,19 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
|
|
|
goto error;
|
|
|
// else network stack removes extra byte if we forced a short packet
|
|
|
|
|
|
- if (skb->len)
|
|
|
- usbnet_skb_return (dev, skb);
|
|
|
- else {
|
|
|
- netif_dbg(dev, rx_err, dev->net, "drop\n");
|
|
|
-error:
|
|
|
- dev->net->stats.rx_errors++;
|
|
|
- skb_queue_tail (&dev->done, skb);
|
|
|
+ if (skb->len) {
|
|
|
+ /* all data was already cloned from skb inside the driver */
|
|
|
+ if (dev->driver_info->flags & FLAG_MULTI_PACKET)
|
|
|
+ dev_kfree_skb_any(skb);
|
|
|
+ else
|
|
|
+ usbnet_skb_return(dev, skb);
|
|
|
+ return;
|
|
|
}
|
|
|
+
|
|
|
+ netif_dbg(dev, rx_err, dev->net, "drop\n");
|
|
|
+error:
|
|
|
+ dev->net->stats.rx_errors++;
|
|
|
+ skb_queue_tail(&dev->done, skb);
|
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
@@ -971,7 +976,8 @@ static void tx_complete (struct urb *urb)
|
|
|
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++;
|
|
@@ -1044,8 +1050,13 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
|
|
|
if (info->tx_fixup) {
|
|
|
skb = info->tx_fixup (dev, skb, GFP_ATOMIC);
|
|
|
if (!skb) {
|
|
|
- netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n");
|
|
|
- goto drop;
|
|
|
+ if (netif_msg_tx_err(dev)) {
|
|
|
+ netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n");
|
|
|
+ goto drop;
|
|
|
+ } else {
|
|
|
+ /* cdc_ncm collected packet; waits for more */
|
|
|
+ goto not_drop;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
length = skb->len;
|
|
@@ -1067,13 +1078,18 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
|
|
|
/* 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)) {
|
|
|
- urb->transfer_buffer_length++;
|
|
|
- if (skb_tailroom(skb)) {
|
|
|
- skb->data[skb->len] = 0;
|
|
|
- __skb_put(skb, 1);
|
|
|
+ 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;
|
|
@@ -1122,6 +1138,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
|
|
|
netif_dbg(dev, tx_err, dev->net, "drop, code %d\n", retval);
|
|
|
drop:
|
|
|
dev->net->stats.tx_dropped++;
|
|
|
+not_drop:
|
|
|
if (skb)
|
|
|
dev_kfree_skb_any (skb);
|
|
|
usb_free_urb (urb);
|