Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 354be036 authored by Manu Gautam's avatar Manu Gautam Committed by Gerrit - the friendly Code Review server
Browse files

USB: u_ether: Submit requests from rx_complete until limit reached



RX complete (completion callback of RX reqs) defers processing of
received skbs and requeuing of RX requests to workqueue. Also, in
workqueue function it pushes skb to network first and then queues
expty RX requests to hardware.
During high throughput or stressed testing there is possiblity of
USB hardware running out of RX requests for a while due to
delayed workqueue scheduling. This affects TCP TX (downlink) as
TCP ACKs for DL traffic are sent from PC to device (or RX for
u_ether). To workaround this queues RX requests from rx_complete
itself until pending skbs for network stack (that are still
processed by wq) reach a limit defined by a newly introduced
module param: 'u_ether_rx_pending_thl'. Its default value is 500.

Change-Id: I83b355d3dd3989cc425663e5b219c45661904f75
Signed-off-by: default avatarManu Gautam <mgautam@codeaurora.org>
Signed-off-by: default avatarAjay Agarwal <ajaya@codeaurora.org>
parent 11bdb3b3
Loading
Loading
Loading
Loading
+24 −4
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ struct eth_dev {
	u8			host_mac[ETH_ALEN];
	u8			dev_mac[ETH_ALEN];
	unsigned long		tx_throttle;
	unsigned long		rx_throttle;
	struct dentry		*uether_dent;
	struct dentry		*uether_dfile;
};
@@ -138,6 +139,10 @@ static inline int qlen(struct usb_gadget *gadget, unsigned qmult)
}

/*-------------------------------------------------------------------------*/
#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, 0644);

/* REVISIT there must be a better way than having two sets
 * of debug calls ...
@@ -377,9 +382,20 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
	}

clean:
	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);
@@ -1626,6 +1642,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;
@@ -1643,8 +1660,10 @@ static int uether_stat_show(struct seq_file *s, void *unused)
	struct eth_dev *dev = s->private;
	int ret = 0;

	if (dev)
	if (dev) {
		seq_printf(s, "tx_throttle = %lu\n", dev->tx_throttle);
		seq_printf(s, "rx_throttle = %lu\n", dev->rx_throttle);
	}
	return ret;
}

@@ -1663,6 +1682,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;
}