diff options
| author | Ben Hutchings <ben.hutchings@codethink.co.uk> | 2015-03-25 16:41:33 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-03-29 15:06:45 -0400 |
| commit | 7a1e890e2168e33fb62d84528e996b8b4b478fea (patch) | |
| tree | 2b9d47228b9d613a9934f8bddde26a6633cf748e /include/linux/usb | |
| parent | 1e9e39f4a29857a396ac7b669d109f697f66695e (diff) | |
usbnet: Fix tx_bytes statistic running backward in cdc_ncm
cdc_ncm disagrees with usbnet about how much framing overhead should
be counted in the tx_bytes statistics, and tries 'fix' this by
decrementing tx_bytes on the transmit path. But statistics must never
be decremented except due to roll-over; this will thoroughly confuse
user-space. Also, tx_bytes is only incremented by usbnet in the
completion path.
Fix this by requiring drivers that set FLAG_MULTI_FRAME to set a
tx_bytes delta along with the tx_packets count.
Fixes: beeecd42c3b4 ("net: cdc_ncm/cdc_mbim: adding NCM protocol statistics")
Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
Signed-off-by: Bjørn Mork <bjorn@mork.no>
Diffstat (limited to 'include/linux/usb')
| -rw-r--r-- | include/linux/usb/usbnet.h | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index ff3fb2bd0e90..6e0ce8c7b8cb 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h | |||
| @@ -227,7 +227,7 @@ struct skb_data { /* skb->cb is one of these */ | |||
| 227 | struct urb *urb; | 227 | struct urb *urb; |
| 228 | struct usbnet *dev; | 228 | struct usbnet *dev; |
| 229 | enum skb_state state; | 229 | enum skb_state state; |
| 230 | size_t length; | 230 | long length; |
| 231 | unsigned long packets; | 231 | unsigned long packets; |
| 232 | }; | 232 | }; |
| 233 | 233 | ||
| @@ -235,11 +235,13 @@ struct skb_data { /* skb->cb is one of these */ | |||
| 235 | * tx_fixup method before returning an skb. | 235 | * tx_fixup method before returning an skb. |
| 236 | */ | 236 | */ |
| 237 | static inline void | 237 | static inline void |
| 238 | usbnet_set_skb_tx_stats(struct sk_buff *skb, unsigned long packets) | 238 | usbnet_set_skb_tx_stats(struct sk_buff *skb, |
| 239 | unsigned long packets, long bytes_delta) | ||
| 239 | { | 240 | { |
| 240 | struct skb_data *entry = (struct skb_data *) skb->cb; | 241 | struct skb_data *entry = (struct skb_data *) skb->cb; |
| 241 | 242 | ||
| 242 | entry->packets = packets; | 243 | entry->packets = packets; |
| 244 | entry->length = bytes_delta; | ||
| 243 | } | 245 | } |
| 244 | 246 | ||
| 245 | extern int usbnet_open(struct net_device *net); | 247 | extern int usbnet_open(struct net_device *net); |
