Commit 073285fd authored by Alexey Orishko's avatar Alexey Orishko Committed by David S. Miller

usbnet: changes for upcoming cdc_ncm driver

Changes:
include/linux/usb/usbnet.h:
- a new flag to indicate driver's capability to accumulate IP packets in Tx
 direction and extract several packets from single skb in Rx direction.
drivers/net/usb/usbnet.c:
- the procedure of counting packets in usbnet was updated due to the
 accumulating of IP packets in the driver
- no short packets are sent if indicated by the flag in driver_info
 structure
Signed-off-by: default avatarAlexey Orishko <alexey.orishko@stericsson.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5ee49376
...@@ -391,14 +391,19 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) ...@@ -391,14 +391,19 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
goto error; goto error;
// else network stack removes extra byte if we forced a short packet // else network stack removes extra byte if we forced a short packet
if (skb->len) if (skb->len) {
usbnet_skb_return (dev, skb); /* all data was already cloned from skb inside the driver */
else { if (dev->driver_info->flags & FLAG_MULTI_PACKET)
netif_dbg(dev, rx_err, dev->net, "drop\n"); dev_kfree_skb_any(skb);
error: else
dev->net->stats.rx_errors++; usbnet_skb_return(dev, skb);
skb_queue_tail (&dev->done, 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) ...@@ -971,7 +976,8 @@ static void tx_complete (struct urb *urb)
struct usbnet *dev = entry->dev; struct usbnet *dev = entry->dev;
if (urb->status == 0) { 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; dev->net->stats.tx_bytes += entry->length;
} else { } else {
dev->net->stats.tx_errors++; dev->net->stats.tx_errors++;
...@@ -1044,8 +1050,13 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, ...@@ -1044,8 +1050,13 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
if (info->tx_fixup) { if (info->tx_fixup) {
skb = info->tx_fixup (dev, skb, GFP_ATOMIC); skb = info->tx_fixup (dev, skb, GFP_ATOMIC);
if (!skb) { if (!skb) {
netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n"); if (netif_msg_tx_err(dev)) {
goto drop; 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; length = skb->len;
...@@ -1067,13 +1078,18 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, ...@@ -1067,13 +1078,18 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
/* don't assume the hardware handles USB_ZERO_PACKET /* don't assume the hardware handles USB_ZERO_PACKET
* NOTE: strictly conforming cdc-ether devices should expect * NOTE: strictly conforming cdc-ether devices should expect
* the ZLP here, but ignore the one-byte packet. * 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 (length % dev->maxpacket == 0) {
if (!(info->flags & FLAG_SEND_ZLP)) { if (!(info->flags & FLAG_SEND_ZLP)) {
urb->transfer_buffer_length++; if (!(info->flags & FLAG_MULTI_PACKET)) {
if (skb_tailroom(skb)) { urb->transfer_buffer_length++;
skb->data[skb->len] = 0; if (skb_tailroom(skb)) {
__skb_put(skb, 1); skb->data[skb->len] = 0;
__skb_put(skb, 1);
}
} }
} else } else
urb->transfer_flags |= URB_ZERO_PACKET; urb->transfer_flags |= URB_ZERO_PACKET;
...@@ -1122,6 +1138,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, ...@@ -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); netif_dbg(dev, tx_err, dev->net, "drop, code %d\n", retval);
drop: drop:
dev->net->stats.tx_dropped++; dev->net->stats.tx_dropped++;
not_drop:
if (skb) if (skb)
dev_kfree_skb_any (skb); dev_kfree_skb_any (skb);
usb_free_urb (urb); usb_free_urb (urb);
......
...@@ -97,6 +97,12 @@ struct driver_info { ...@@ -97,6 +97,12 @@ struct driver_info {
#define FLAG_LINK_INTR 0x0800 /* updates link (carrier) status */ #define FLAG_LINK_INTR 0x0800 /* updates link (carrier) status */
/*
* Indicates to usbnet, that USB driver accumulates multiple IP packets.
* Affects statistic (counters) and short packet handling.
*/
#define FLAG_MULTI_PACKET 0x1000
/* init device ... can sleep, or cause probe() failure */ /* init device ... can sleep, or cause probe() failure */
int (*bind)(struct usbnet *, struct usb_interface *); int (*bind)(struct usbnet *, struct usb_interface *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment