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 /drivers/net | |
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 'drivers/net')
-rw-r--r-- | drivers/net/usb/asix_common.c | 2 | ||||
-rw-r--r-- | drivers/net/usb/cdc_ncm.c | 7 | ||||
-rw-r--r-- | drivers/net/usb/sr9800.c | 2 | ||||
-rw-r--r-- | drivers/net/usb/usbnet.c | 16 |
4 files changed, 18 insertions, 9 deletions
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index 724a9b50df7a..75d6f26729a3 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c | |||
@@ -189,7 +189,7 @@ struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, | |||
189 | skb_put(skb, sizeof(padbytes)); | 189 | skb_put(skb, sizeof(padbytes)); |
190 | } | 190 | } |
191 | 191 | ||
192 | usbnet_set_skb_tx_stats(skb, 1); | 192 | usbnet_set_skb_tx_stats(skb, 1, 0); |
193 | return skb; | 193 | return skb; |
194 | } | 194 | } |
195 | 195 | ||
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 70cbea551139..c3e4da9e79ca 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c | |||
@@ -1177,13 +1177,12 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) | |||
1177 | ctx->tx_overhead += skb_out->len - ctx->tx_curr_frame_payload; | 1177 | ctx->tx_overhead += skb_out->len - ctx->tx_curr_frame_payload; |
1178 | ctx->tx_ntbs++; | 1178 | ctx->tx_ntbs++; |
1179 | 1179 | ||
1180 | /* usbnet has already counted all the framing overhead. | 1180 | /* usbnet will count all the framing overhead by default. |
1181 | * Adjust the stats so that the tx_bytes counter show real | 1181 | * Adjust the stats so that the tx_bytes counter show real |
1182 | * payload data instead. | 1182 | * payload data instead. |
1183 | */ | 1183 | */ |
1184 | dev->net->stats.tx_bytes -= skb_out->len - ctx->tx_curr_frame_payload; | 1184 | usbnet_set_skb_tx_stats(skb_out, n, |
1185 | 1185 | ctx->tx_curr_frame_payload - skb_out->len); | |
1186 | usbnet_set_skb_tx_stats(skb_out, n); | ||
1187 | 1186 | ||
1188 | return skb_out; | 1187 | return skb_out; |
1189 | 1188 | ||
diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c index 7650cdc8fe6b..953de13267df 100644 --- a/drivers/net/usb/sr9800.c +++ b/drivers/net/usb/sr9800.c | |||
@@ -144,7 +144,7 @@ static struct sk_buff *sr_tx_fixup(struct usbnet *dev, struct sk_buff *skb, | |||
144 | skb_put(skb, sizeof(padbytes)); | 144 | skb_put(skb, sizeof(padbytes)); |
145 | } | 145 | } |
146 | 146 | ||
147 | usbnet_set_skb_tx_stats(skb, 1); | 147 | usbnet_set_skb_tx_stats(skb, 1, 0); |
148 | return skb; | 148 | return skb; |
149 | } | 149 | } |
150 | 150 | ||
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 0f3ff285f6a1..777757ae1973 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
@@ -1346,9 +1346,19 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, | |||
1346 | } else | 1346 | } else |
1347 | urb->transfer_flags |= URB_ZERO_PACKET; | 1347 | urb->transfer_flags |= URB_ZERO_PACKET; |
1348 | } | 1348 | } |
1349 | entry->length = urb->transfer_buffer_length = length; | 1349 | urb->transfer_buffer_length = length; |
1350 | if (!(info->flags & FLAG_MULTI_PACKET)) | 1350 | |
1351 | usbnet_set_skb_tx_stats(skb, 1); | 1351 | if (info->flags & FLAG_MULTI_PACKET) { |
1352 | /* Driver has set number of packets and a length delta. | ||
1353 | * Calculate the complete length and ensure that it's | ||
1354 | * positive. | ||
1355 | */ | ||
1356 | entry->length += length; | ||
1357 | if (WARN_ON_ONCE(entry->length <= 0)) | ||
1358 | entry->length = length; | ||
1359 | } else { | ||
1360 | usbnet_set_skb_tx_stats(skb, 1, length); | ||
1361 | } | ||
1352 | 1362 | ||
1353 | spin_lock_irqsave(&dev->txq.lock, flags); | 1363 | spin_lock_irqsave(&dev->txq.lock, flags); |
1354 | retval = usb_autopm_get_interface_async(dev->intf); | 1364 | retval = usb_autopm_get_interface_async(dev->intf); |