diff options
author | Woojung Huh <woojung.huh@microchip.com> | 2016-04-25 18:22:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-04-28 16:36:11 -0400 |
commit | 74d79a2e30c476ccc7d45ecf978f38d815287f81 (patch) | |
tree | c31c0e3a0a8bd7c25351654145168a762cfb146f /drivers/net/usb | |
parent | 1d9619d5337df6cf56eb66b6c8213d1317583513 (diff) |
lan78xx: fix statistics counter error
Fix rx_bytes, tx_bytes and tx_frames error in netdev.stats.
- rx_bytes counted bytes excluding size of struct ethhdr.
- tx_packets didn't count multiple packets in a single urb
- tx_bytes included 8 bytes of extra commands.
Signed-off-by: Woojung Huh <woojung.huh@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/lan78xx.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index f20890ee03f3..0460b81a8784 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c | |||
@@ -269,6 +269,7 @@ struct skb_data { /* skb->cb is one of these */ | |||
269 | struct lan78xx_net *dev; | 269 | struct lan78xx_net *dev; |
270 | enum skb_state state; | 270 | enum skb_state state; |
271 | size_t length; | 271 | size_t length; |
272 | int num_of_packet; | ||
272 | }; | 273 | }; |
273 | 274 | ||
274 | struct usb_context { | 275 | struct usb_context { |
@@ -2464,7 +2465,7 @@ static void tx_complete(struct urb *urb) | |||
2464 | struct lan78xx_net *dev = entry->dev; | 2465 | struct lan78xx_net *dev = entry->dev; |
2465 | 2466 | ||
2466 | if (urb->status == 0) { | 2467 | if (urb->status == 0) { |
2467 | dev->net->stats.tx_packets++; | 2468 | dev->net->stats.tx_packets += entry->num_of_packet; |
2468 | dev->net->stats.tx_bytes += entry->length; | 2469 | dev->net->stats.tx_bytes += entry->length; |
2469 | } else { | 2470 | } else { |
2470 | dev->net->stats.tx_errors++; | 2471 | dev->net->stats.tx_errors++; |
@@ -2681,10 +2682,11 @@ void lan78xx_skb_return(struct lan78xx_net *dev, struct sk_buff *skb) | |||
2681 | return; | 2682 | return; |
2682 | } | 2683 | } |
2683 | 2684 | ||
2684 | skb->protocol = eth_type_trans(skb, dev->net); | ||
2685 | dev->net->stats.rx_packets++; | 2685 | dev->net->stats.rx_packets++; |
2686 | dev->net->stats.rx_bytes += skb->len; | 2686 | dev->net->stats.rx_bytes += skb->len; |
2687 | 2687 | ||
2688 | skb->protocol = eth_type_trans(skb, dev->net); | ||
2689 | |||
2688 | netif_dbg(dev, rx_status, dev->net, "< rx, len %zu, type 0x%x\n", | 2690 | netif_dbg(dev, rx_status, dev->net, "< rx, len %zu, type 0x%x\n", |
2689 | skb->len + sizeof(struct ethhdr), skb->protocol); | 2691 | skb->len + sizeof(struct ethhdr), skb->protocol); |
2690 | memset(skb->cb, 0, sizeof(struct skb_data)); | 2692 | memset(skb->cb, 0, sizeof(struct skb_data)); |
@@ -2934,13 +2936,16 @@ static void lan78xx_tx_bh(struct lan78xx_net *dev) | |||
2934 | 2936 | ||
2935 | skb_totallen = 0; | 2937 | skb_totallen = 0; |
2936 | pkt_cnt = 0; | 2938 | pkt_cnt = 0; |
2939 | count = 0; | ||
2940 | length = 0; | ||
2937 | for (skb = tqp->next; pkt_cnt < tqp->qlen; skb = skb->next) { | 2941 | for (skb = tqp->next; pkt_cnt < tqp->qlen; skb = skb->next) { |
2938 | if (skb_is_gso(skb)) { | 2942 | if (skb_is_gso(skb)) { |
2939 | if (pkt_cnt) { | 2943 | if (pkt_cnt) { |
2940 | /* handle previous packets first */ | 2944 | /* handle previous packets first */ |
2941 | break; | 2945 | break; |
2942 | } | 2946 | } |
2943 | length = skb->len; | 2947 | count = 1; |
2948 | length = skb->len - TX_OVERHEAD; | ||
2944 | skb2 = skb_dequeue(tqp); | 2949 | skb2 = skb_dequeue(tqp); |
2945 | goto gso_skb; | 2950 | goto gso_skb; |
2946 | } | 2951 | } |
@@ -2961,14 +2966,13 @@ static void lan78xx_tx_bh(struct lan78xx_net *dev) | |||
2961 | for (count = pos = 0; count < pkt_cnt; count++) { | 2966 | for (count = pos = 0; count < pkt_cnt; count++) { |
2962 | skb2 = skb_dequeue(tqp); | 2967 | skb2 = skb_dequeue(tqp); |
2963 | if (skb2) { | 2968 | if (skb2) { |
2969 | length += (skb2->len - TX_OVERHEAD); | ||
2964 | memcpy(skb->data + pos, skb2->data, skb2->len); | 2970 | memcpy(skb->data + pos, skb2->data, skb2->len); |
2965 | pos += roundup(skb2->len, sizeof(u32)); | 2971 | pos += roundup(skb2->len, sizeof(u32)); |
2966 | dev_kfree_skb(skb2); | 2972 | dev_kfree_skb(skb2); |
2967 | } | 2973 | } |
2968 | } | 2974 | } |
2969 | 2975 | ||
2970 | length = skb_totallen; | ||
2971 | |||
2972 | gso_skb: | 2976 | gso_skb: |
2973 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 2977 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
2974 | if (!urb) { | 2978 | if (!urb) { |
@@ -2980,6 +2984,7 @@ gso_skb: | |||
2980 | entry->urb = urb; | 2984 | entry->urb = urb; |
2981 | entry->dev = dev; | 2985 | entry->dev = dev; |
2982 | entry->length = length; | 2986 | entry->length = length; |
2987 | entry->num_of_packet = count; | ||
2983 | 2988 | ||
2984 | spin_lock_irqsave(&dev->txq.lock, flags); | 2989 | spin_lock_irqsave(&dev->txq.lock, flags); |
2985 | ret = usb_autopm_get_interface_async(dev->intf); | 2990 | ret = usb_autopm_get_interface_async(dev->intf); |