diff options
| -rw-r--r-- | drivers/usb/gadget/u_ether.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 16301347ec8..10b891a026b 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -127,6 +127,7 @@ struct eth_dev { /* stats */ unsigned long tx_throttle; + unsigned long rx_throttle; unsigned int tx_aggr_cnt[DL_MAX_PKTS_PER_XFER]; unsigned int tx_pkts_rcvd; unsigned int loop_brk_cnt; @@ -183,6 +184,11 @@ static inline int qlen(struct usb_gadget *gadget) } /*-------------------------------------------------------------------------*/ +#define U_ETHER_RX_PENDING_TSHOLD 500 + +static unsigned int u_ether_rx_pending_thld = U_ETHER_RX_PENDING_TSHOLD; +module_param(u_ether_rx_pending_thld, uint, S_IRUGO | S_IWUSR); + /* REVISIT there must be a better way than having two sets * of debug calls ... @@ -440,9 +446,20 @@ quiesce: } clean: - spin_lock(&dev->req_lock); - list_add(&req->list, &dev->rx_reqs); - spin_unlock(&dev->req_lock); + if (queue && dev->rx_frames.qlen <= u_ether_rx_pending_thld) { + if (rx_submit(dev, req, GFP_ATOMIC) < 0) { + spin_lock(&dev->req_lock); + list_add(&req->list, &dev->rx_reqs); + spin_unlock(&dev->req_lock); + } + } else { + /* rx buffers draining is delayed,defer further queuing to wq */ + if (queue) + dev->rx_throttle++; + spin_lock(&dev->req_lock); + list_add(&req->list, &dev->rx_reqs); + spin_unlock(&dev->req_lock); + } if (queue) queue_work(uether_wq, &dev->rx_work); @@ -1869,6 +1886,7 @@ void gether_disconnect(struct gether *link) dev->tx_throttle); /* reset tx_throttle count */ dev->tx_throttle = 0; + dev->rx_throttle = 0; /* finish forgetting about this USB link episode */ dev->header_len = 0; @@ -1899,6 +1917,8 @@ static int uether_stat_show(struct seq_file *s, void *unused) int i; if (dev) { + seq_printf(s, "rx_throttle = %lu\n", + dev->rx_throttle); seq_printf(s, "tx_qlen=%u tx_throttle = %lu\n aggr count:", dev->tx_skb_q.qlen, dev->tx_throttle); @@ -1928,6 +1948,7 @@ static ssize_t uether_stat_reset(struct file *file, spin_lock_irqsave(&dev->lock, flags); /* Reset tx_throttle */ dev->tx_throttle = 0; + dev->rx_throttle = 0; spin_unlock_irqrestore(&dev->lock, flags); return count; } |
