Commit 6d3865f9 authored by Jim Baxter's avatar Jim Baxter Committed by Felipe Balbi

usb: gadget: NCM: Add transmit multi-frame.

This adds multi-frame support to the NCM NTB's for
the gadget driver. This allows multiple network
packets to be put inside a single USB NTB with a
maximum size of 16kB.

It has a time out of 300ms to ensure that smaller
number of packets still maintain a normal latency.

Also the .fp_index and .next_fp_index have been
changed to .ndp_index and .next_ndp_index to
match the latest CDC-NCM specification and
help with maintenance.

Results transmitting from gadget to host.

Before the change:

TCP_STREAM Throughput (10^6bits/sec): 22.72
UDP_STREAM Throughput (10^6bits/sec): 25.94

Latency:
netperf -H 192.168.1.101 -v2 -l 50 -t TCP_RR -- -r 16384,16384
Trans.   RoundTrip  Throughput
Rate     Latency    10^6bits/s
per sec  usec/Tran  Outbound

100.83   9918.116   13.215

After the change:

TCP_STREAM Throughput (10^6bits/sec): 124.26
UDP_STREAM Throughput (10^6bits/sec): 227.48

Latency:
netperf -H 192.168.1.101 -v2 -l 50 -t TCP_RR -- -r 16384,16384
Trans.   RoundTrip  Throughput
Rate     Latency    10^6bits/s
per sec  usec/Tran  Outbound

156.80   6377.730   20.552
Signed-off-by: default avatarJim Baxter <jim_baxter@mentor.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 370af734
This diff is collapsed.
...@@ -483,7 +483,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, ...@@ -483,7 +483,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
struct net_device *net) struct net_device *net)
{ {
struct eth_dev *dev = netdev_priv(net); struct eth_dev *dev = netdev_priv(net);
int length = skb->len; int length = 0;
int retval; int retval;
struct usb_request *req = NULL; struct usb_request *req = NULL;
unsigned long flags; unsigned long flags;
...@@ -500,13 +500,13 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, ...@@ -500,13 +500,13 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
} }
spin_unlock_irqrestore(&dev->lock, flags); spin_unlock_irqrestore(&dev->lock, flags);
if (!in) { if (skb && !in) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
/* apply outgoing CDC or RNDIS filters */ /* apply outgoing CDC or RNDIS filters */
if (!is_promisc(cdc_filter)) { if (skb && !is_promisc(cdc_filter)) {
u8 *dest = skb->data; u8 *dest = skb->data;
if (is_multicast_ether_addr(dest)) { if (is_multicast_ether_addr(dest)) {
...@@ -557,11 +557,17 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, ...@@ -557,11 +557,17 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
if (dev->port_usb) if (dev->port_usb)
skb = dev->wrap(dev->port_usb, skb); skb = dev->wrap(dev->port_usb, skb);
spin_unlock_irqrestore(&dev->lock, flags); spin_unlock_irqrestore(&dev->lock, flags);
if (!skb) if (!skb) {
/* Multi frame CDC protocols may store the frame for
* later which is not a dropped frame.
*/
if (dev->port_usb->supports_multi_frame)
goto multiframe;
goto drop; goto drop;
}
length = skb->len;
} }
length = skb->len;
req->buf = skb->data; req->buf = skb->data;
req->context = skb; req->context = skb;
req->complete = tx_complete; req->complete = tx_complete;
...@@ -604,6 +610,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, ...@@ -604,6 +610,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
drop: drop:
dev->net->stats.tx_dropped++; dev->net->stats.tx_dropped++;
multiframe:
spin_lock_irqsave(&dev->req_lock, flags); spin_lock_irqsave(&dev->req_lock, flags);
if (list_empty(&dev->tx_reqs)) if (list_empty(&dev->tx_reqs))
netif_start_queue(net); netif_start_queue(net);
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/usb/composite.h> #include <linux/usb/composite.h>
#include <linux/usb/cdc.h> #include <linux/usb/cdc.h>
#include <linux/netdevice.h>
#include "gadget_chips.h" #include "gadget_chips.h"
...@@ -74,6 +75,7 @@ struct gether { ...@@ -74,6 +75,7 @@ struct gether {
bool is_fixed; bool is_fixed;
u32 fixed_out_len; u32 fixed_out_len;
u32 fixed_in_len; u32 fixed_in_len;
bool supports_multi_frame;
struct sk_buff *(*wrap)(struct gether *port, struct sk_buff *(*wrap)(struct gether *port,
struct sk_buff *skb); struct sk_buff *skb);
int (*unwrap)(struct gether *port, int (*unwrap)(struct gether *port,
......
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