Skip to content

Commit fb59bf2

Browse files
lsahn-ghdavem330
authored andcommitted
usbnet: optimize usbnet_bh() to reduce CPU load
The current source pushes skb into dev-done queue by calling skb_dequeue_tail() and then pop it by skb_dequeue() to branch to rx_cleanup state for freeing urb/skb in usbnet_bh(). It takes extra CPU load, 2.21% (skb_queue_tail) as follows, - 11.58% 0.26% swapper [k] usbnet_bh - 11.32% usbnet_bh - 6.43% skb_dequeue 6.34% _raw_spin_unlock_irqrestore - 2.21% skb_queue_tail 2.19% _raw_spin_unlock_irqrestore - 1.68% consume_skb - 0.97% kfree_skbmem 0.80% kmem_cache_free 0.53% skb_release_data To reduce the extra CPU load use return values to call helper function usb_free_skb() to free the resources instead of calling skb_queue_tail() and skb_dequeue() for push and pop respectively. - 7.87% 0.25% swapper [k] usbnet_bh - 7.62% usbnet_bh - 4.81% skb_dequeue 4.74% _raw_spin_unlock_irqrestore - 1.75% consume_skb - 0.98% kfree_skbmem 0.78% kmem_cache_free 0.58% skb_release_data 0.53% smsc95xx_rx_fixup Signed-off-by: Leesoo Ahn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9cb8bae commit fb59bf2

File tree

1 file changed

+17
-12
lines changed

1 file changed

+17
-12
lines changed

drivers/net/usb/usbnet.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -555,32 +555,30 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
555555

556556
/*-------------------------------------------------------------------------*/
557557

558-
static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
558+
static inline int rx_process(struct usbnet *dev, struct sk_buff *skb)
559559
{
560560
if (dev->driver_info->rx_fixup &&
561561
!dev->driver_info->rx_fixup (dev, skb)) {
562562
/* With RX_ASSEMBLE, rx_fixup() must update counters */
563563
if (!(dev->driver_info->flags & FLAG_RX_ASSEMBLE))
564564
dev->net->stats.rx_errors++;
565-
goto done;
565+
return -EPROTO;
566566
}
567567
// else network stack removes extra byte if we forced a short packet
568568

569569
/* all data was already cloned from skb inside the driver */
570570
if (dev->driver_info->flags & FLAG_MULTI_PACKET)
571-
goto done;
571+
return -EALREADY;
572572

573573
if (skb->len < ETH_HLEN) {
574574
dev->net->stats.rx_errors++;
575575
dev->net->stats.rx_length_errors++;
576576
netif_dbg(dev, rx_err, dev->net, "rx length %d\n", skb->len);
577-
} else {
578-
usbnet_skb_return(dev, skb);
579-
return;
577+
return -EPROTO;
580578
}
581579

582-
done:
583-
skb_queue_tail(&dev->done, skb);
580+
usbnet_skb_return(dev, skb);
581+
return 0;
584582
}
585583

586584
/*-------------------------------------------------------------------------*/
@@ -1514,6 +1512,14 @@ static int rx_alloc_submit(struct usbnet *dev, gfp_t flags)
15141512
return ret;
15151513
}
15161514

1515+
static inline void usb_free_skb(struct sk_buff *skb)
1516+
{
1517+
struct skb_data *entry = (struct skb_data *)skb->cb;
1518+
1519+
usb_free_urb(entry->urb);
1520+
dev_kfree_skb(skb);
1521+
}
1522+
15171523
/*-------------------------------------------------------------------------*/
15181524

15191525
// tasklet (work deferred from completions, in_irq) or timer
@@ -1528,15 +1534,14 @@ static void usbnet_bh (struct timer_list *t)
15281534
entry = (struct skb_data *) skb->cb;
15291535
switch (entry->state) {
15301536
case rx_done:
1531-
entry->state = rx_cleanup;
1532-
rx_process (dev, skb);
1537+
if (rx_process(dev, skb))
1538+
usb_free_skb(skb);
15331539
continue;
15341540
case tx_done:
15351541
kfree(entry->urb->sg);
15361542
fallthrough;
15371543
case rx_cleanup:
1538-
usb_free_urb (entry->urb);
1539-
dev_kfree_skb (skb);
1544+
usb_free_skb(skb);
15401545
continue;
15411546
default:
15421547
netdev_dbg(dev->net, "bogus skb state %d\n", entry->state);

0 commit comments

Comments
 (0)