aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorWeinn Jheng <clanlab.proj@gmail.com>2014-02-27 04:49:00 -0500
committerFelipe Balbi <balbi@ti.com>2014-03-07 11:03:24 -0500
commit716fb91dfe1777bd6d5e598f3d3572214b3ed296 (patch)
tree75232c404790fbeb8816f244daeb4acf78d5cafa /drivers/usb
parent3f89204bae896e1d44468886a646b84acadc3c8f (diff)
usb: gadget: u_ether: move hardware transmit to RX NAPI
In order to reduce the interrupt times in the embedded system, a receiving workqueue is introduced. This modification also enhanced the overall throughput as the benefits of reducing interrupt occurrence. This work was derived from previous work: u_ether: move hardware transmit to RX workqueue. Which should be base on codeaurora's work. However, the benchmark on my platform shows the throughput with workqueue is slightly better than NAPI. Signed-off-by: Weinn Jheng <clanlab.proj@gmail.com> Cc: David Brownell <dbrownell@users.sourceforge.net> Cc: David S. Miller <davem@davemloft.net> Cc: Stephen Hemminger <shemminger@vyatta.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Manu Gautam <mgautam@codeaurora.org> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/u_ether.c101
1 files changed, 66 insertions, 35 deletions
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index b7d4f82872b7..50d09c289137 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -48,6 +48,8 @@
48 48
49#define UETH__VERSION "29-May-2008" 49#define UETH__VERSION "29-May-2008"
50 50
51#define GETHER_NAPI_WEIGHT 32
52
51struct eth_dev { 53struct eth_dev {
52 /* lock is held while accessing port_usb 54 /* lock is held while accessing port_usb
53 */ 55 */
@@ -72,6 +74,7 @@ struct eth_dev {
72 struct sk_buff_head *list); 74 struct sk_buff_head *list);
73 75
74 struct work_struct work; 76 struct work_struct work;
77 struct napi_struct rx_napi;
75 78
76 unsigned long todo; 79 unsigned long todo;
77#define WORK_RX_MEMORY 0 80#define WORK_RX_MEMORY 0
@@ -253,18 +256,16 @@ enomem:
253 DBG(dev, "rx submit --> %d\n", retval); 256 DBG(dev, "rx submit --> %d\n", retval);
254 if (skb) 257 if (skb)
255 dev_kfree_skb_any(skb); 258 dev_kfree_skb_any(skb);
256 spin_lock_irqsave(&dev->req_lock, flags);
257 list_add(&req->list, &dev->rx_reqs);
258 spin_unlock_irqrestore(&dev->req_lock, flags);
259 } 259 }
260 return retval; 260 return retval;
261} 261}
262 262
263static void rx_complete(struct usb_ep *ep, struct usb_request *req) 263static void rx_complete(struct usb_ep *ep, struct usb_request *req)
264{ 264{
265 struct sk_buff *skb = req->context, *skb2; 265 struct sk_buff *skb = req->context;
266 struct eth_dev *dev = ep->driver_data; 266 struct eth_dev *dev = ep->driver_data;
267 int status = req->status; 267 int status = req->status;
268 bool rx_queue = 0;
268 269
269 switch (status) { 270 switch (status) {
270 271
@@ -288,30 +289,8 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
288 } else { 289 } else {
289 skb_queue_tail(&dev->rx_frames, skb); 290 skb_queue_tail(&dev->rx_frames, skb);
290 } 291 }
291 skb = NULL; 292 if (!status)
292 293 rx_queue = 1;
293 skb2 = skb_dequeue(&dev->rx_frames);
294 while (skb2) {
295 if (status < 0
296 || ETH_HLEN > skb2->len
297 || skb2->len > VLAN_ETH_FRAME_LEN) {
298 dev->net->stats.rx_errors++;
299 dev->net->stats.rx_length_errors++;
300 DBG(dev, "rx length %d\n", skb2->len);
301 dev_kfree_skb_any(skb2);
302 goto next_frame;
303 }
304 skb2->protocol = eth_type_trans(skb2, dev->net);
305 dev->net->stats.rx_packets++;
306 dev->net->stats.rx_bytes += skb2->len;
307
308 /* no buffer copies needed, unless hardware can't
309 * use skb buffers.
310 */
311 status = netif_rx(skb2);
312next_frame:
313 skb2 = skb_dequeue(&dev->rx_frames);
314 }
315 break; 294 break;
316 295
317 /* software-driven interface shutdown */ 296 /* software-driven interface shutdown */
@@ -334,22 +313,20 @@ quiesce:
334 /* FALLTHROUGH */ 313 /* FALLTHROUGH */
335 314
336 default: 315 default:
316 rx_queue = 1;
317 dev_kfree_skb_any(skb);
337 dev->net->stats.rx_errors++; 318 dev->net->stats.rx_errors++;
338 DBG(dev, "rx status %d\n", status); 319 DBG(dev, "rx status %d\n", status);
339 break; 320 break;
340 } 321 }
341 322
342 if (skb)
343 dev_kfree_skb_any(skb);
344 if (!netif_running(dev->net)) {
345clean: 323clean:
346 spin_lock(&dev->req_lock); 324 spin_lock(&dev->req_lock);
347 list_add(&req->list, &dev->rx_reqs); 325 list_add(&req->list, &dev->rx_reqs);
348 spin_unlock(&dev->req_lock); 326 spin_unlock(&dev->req_lock);
349 req = NULL; 327
350 } 328 if (rx_queue && likely(napi_schedule_prep(&dev->rx_napi)))
351 if (req) 329 __napi_schedule(&dev->rx_napi);
352 rx_submit(dev, req, GFP_ATOMIC);
353} 330}
354 331
355static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n) 332static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n)
@@ -414,16 +391,24 @@ static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)
414{ 391{
415 struct usb_request *req; 392 struct usb_request *req;
416 unsigned long flags; 393 unsigned long flags;
394 int rx_counts = 0;
417 395
418 /* fill unused rxq slots with some skb */ 396 /* fill unused rxq slots with some skb */
419 spin_lock_irqsave(&dev->req_lock, flags); 397 spin_lock_irqsave(&dev->req_lock, flags);
420 while (!list_empty(&dev->rx_reqs)) { 398 while (!list_empty(&dev->rx_reqs)) {
399
400 if (++rx_counts > qlen(dev->gadget, dev->qmult))
401 break;
402
421 req = container_of(dev->rx_reqs.next, 403 req = container_of(dev->rx_reqs.next,
422 struct usb_request, list); 404 struct usb_request, list);
423 list_del_init(&req->list); 405 list_del_init(&req->list);
424 spin_unlock_irqrestore(&dev->req_lock, flags); 406 spin_unlock_irqrestore(&dev->req_lock, flags);
425 407
426 if (rx_submit(dev, req, gfp_flags) < 0) { 408 if (rx_submit(dev, req, gfp_flags) < 0) {
409 spin_lock_irqsave(&dev->req_lock, flags);
410 list_add(&req->list, &dev->rx_reqs);
411 spin_unlock_irqrestore(&dev->req_lock, flags);
427 defer_kevent(dev, WORK_RX_MEMORY); 412 defer_kevent(dev, WORK_RX_MEMORY);
428 return; 413 return;
429 } 414 }
@@ -433,6 +418,41 @@ static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)
433 spin_unlock_irqrestore(&dev->req_lock, flags); 418 spin_unlock_irqrestore(&dev->req_lock, flags);
434} 419}
435 420
421static int gether_poll(struct napi_struct *napi, int budget)
422{
423 struct eth_dev *dev = container_of(napi, struct eth_dev, rx_napi);
424 struct sk_buff *skb;
425 unsigned int work_done = 0;
426 int status = 0;
427
428 while ((skb = skb_dequeue(&dev->rx_frames))) {
429 if (status < 0
430 || ETH_HLEN > skb->len
431 || skb->len > VLAN_ETH_FRAME_LEN) {
432 dev->net->stats.rx_errors++;
433 dev->net->stats.rx_length_errors++;
434 DBG(dev, "rx length %d\n", skb->len);
435 dev_kfree_skb_any(skb);
436 continue;
437 }
438 skb->protocol = eth_type_trans(skb, dev->net);
439 dev->net->stats.rx_packets++;
440 dev->net->stats.rx_bytes += skb->len;
441
442 status = netif_rx_ni(skb);
443 }
444
445 if (netif_running(dev->net)) {
446 rx_fill(dev, GFP_KERNEL);
447 work_done++;
448 }
449
450 if (work_done < budget)
451 napi_complete(&dev->rx_napi);
452
453 return work_done;
454}
455
436static void eth_work(struct work_struct *work) 456static void eth_work(struct work_struct *work)
437{ 457{
438 struct eth_dev *dev = container_of(work, struct eth_dev, work); 458 struct eth_dev *dev = container_of(work, struct eth_dev, work);
@@ -625,6 +645,7 @@ static void eth_start(struct eth_dev *dev, gfp_t gfp_flags)
625 /* and open the tx floodgates */ 645 /* and open the tx floodgates */
626 atomic_set(&dev->tx_qlen, 0); 646 atomic_set(&dev->tx_qlen, 0);
627 netif_wake_queue(dev->net); 647 netif_wake_queue(dev->net);
648 napi_enable(&dev->rx_napi);
628} 649}
629 650
630static int eth_open(struct net_device *net) 651static int eth_open(struct net_device *net)
@@ -651,6 +672,7 @@ static int eth_stop(struct net_device *net)
651 unsigned long flags; 672 unsigned long flags;
652 673
653 VDBG(dev, "%s\n", __func__); 674 VDBG(dev, "%s\n", __func__);
675 napi_disable(&dev->rx_napi);
654 netif_stop_queue(net); 676 netif_stop_queue(net);
655 677
656 DBG(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", 678 DBG(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
@@ -768,6 +790,7 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g,
768 return ERR_PTR(-ENOMEM); 790 return ERR_PTR(-ENOMEM);
769 791
770 dev = netdev_priv(net); 792 dev = netdev_priv(net);
793 netif_napi_add(net, &dev->rx_napi, gether_poll, GETHER_NAPI_WEIGHT);
771 spin_lock_init(&dev->lock); 794 spin_lock_init(&dev->lock);
772 spin_lock_init(&dev->req_lock); 795 spin_lock_init(&dev->req_lock);
773 INIT_WORK(&dev->work, eth_work); 796 INIT_WORK(&dev->work, eth_work);
@@ -830,6 +853,7 @@ struct net_device *gether_setup_name_default(const char *netname)
830 return ERR_PTR(-ENOMEM); 853 return ERR_PTR(-ENOMEM);
831 854
832 dev = netdev_priv(net); 855 dev = netdev_priv(net);
856 netif_napi_add(net, &dev->rx_napi, gether_poll, GETHER_NAPI_WEIGHT);
833 spin_lock_init(&dev->lock); 857 spin_lock_init(&dev->lock);
834 spin_lock_init(&dev->req_lock); 858 spin_lock_init(&dev->req_lock);
835 INIT_WORK(&dev->work, eth_work); 859 INIT_WORK(&dev->work, eth_work);
@@ -1113,6 +1137,7 @@ void gether_disconnect(struct gether *link)
1113{ 1137{
1114 struct eth_dev *dev = link->ioport; 1138 struct eth_dev *dev = link->ioport;
1115 struct usb_request *req; 1139 struct usb_request *req;
1140 struct sk_buff *skb;
1116 1141
1117 WARN_ON(!dev); 1142 WARN_ON(!dev);
1118 if (!dev) 1143 if (!dev)
@@ -1139,6 +1164,12 @@ void gether_disconnect(struct gether *link)
1139 spin_lock(&dev->req_lock); 1164 spin_lock(&dev->req_lock);
1140 } 1165 }
1141 spin_unlock(&dev->req_lock); 1166 spin_unlock(&dev->req_lock);
1167
1168 spin_lock(&dev->rx_frames.lock);
1169 while ((skb = __skb_dequeue(&dev->rx_frames)))
1170 dev_kfree_skb_any(skb);
1171 spin_unlock(&dev->rx_frames.lock);
1172
1142 link->in_ep->driver_data = NULL; 1173 link->in_ep->driver_data = NULL;
1143 link->in_ep->desc = NULL; 1174 link->in_ep->desc = NULL;
1144 1175