aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorClaudiu Manoil <claudiu.manoil@freescale.com>2013-08-30 08:01:15 -0400
committerDavid S. Miller <davem@davemloft.net>2013-09-03 22:14:28 -0400
commit50ad076ba43d88956707cd9d6849715de5e282bf (patch)
treea6f58ef984281520b61b9ebd2bda53aa624f8a2e /drivers/net
parent7a163bfb7ce50895bbe67300ea610d31b9c09230 (diff)
gianfar: Fix reported number of sent bytes to BQL
Fix the amount of sent bytes reported to BQL by reporting the number of bytes on wire in the xmit routine, and recording that value for each skb in order to be correctly confirmed on Tx confirmation cleanup. Reporting skb->len to BQL just before exiting xmit is not correct due to possible insertions of TOE block and alignment bytes in the skb->data, which are being stripped off by the controller before transmission on wire. This led to mismatch of (incorrectly) reported bytes to BQL b/w xmit and Tx confirmation, resulting in Tx timeout firing, for the h/w tx timestamping acceleration case. There's no easy way to obtain the number of bytes on wire in the Tx confirmation routine, so skb->cb is used to convey that information from xmit to Tx confirmation, for now (as proposed by Eric). Revived the currently unused GFAR_CB() construct for that purpose. Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com> Cc: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c18
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h2
2 files changed, 12 insertions, 8 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index b2c91dcd245f..c4eaadeb572f 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2092,7 +2092,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
2092 int do_tstamp, do_csum, do_vlan; 2092 int do_tstamp, do_csum, do_vlan;
2093 u32 bufaddr; 2093 u32 bufaddr;
2094 unsigned long flags; 2094 unsigned long flags;
2095 unsigned int nr_frags, nr_txbds, length, fcb_len = 0; 2095 unsigned int nr_frags, nr_txbds, bytes_sent, fcb_len = 0;
2096 2096
2097 rq = skb->queue_mapping; 2097 rq = skb->queue_mapping;
2098 tx_queue = priv->tx_queue[rq]; 2098 tx_queue = priv->tx_queue[rq];
@@ -2147,7 +2147,10 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
2147 } 2147 }
2148 2148
2149 /* Update transmit stats */ 2149 /* Update transmit stats */
2150 tx_queue->stats.tx_bytes += skb->len; 2150 bytes_sent = skb->len;
2151 tx_queue->stats.tx_bytes += bytes_sent;
2152 /* keep Tx bytes on wire for BQL accounting */
2153 GFAR_CB(skb)->bytes_sent = bytes_sent;
2151 tx_queue->stats.tx_packets++; 2154 tx_queue->stats.tx_packets++;
2152 2155
2153 txbdp = txbdp_start = tx_queue->cur_tx; 2156 txbdp = txbdp_start = tx_queue->cur_tx;
@@ -2167,12 +2170,13 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
2167 } else { 2170 } else {
2168 /* Place the fragment addresses and lengths into the TxBDs */ 2171 /* Place the fragment addresses and lengths into the TxBDs */
2169 for (i = 0; i < nr_frags; i++) { 2172 for (i = 0; i < nr_frags; i++) {
2173 unsigned int frag_len;
2170 /* Point at the next BD, wrapping as needed */ 2174 /* Point at the next BD, wrapping as needed */
2171 txbdp = next_txbd(txbdp, base, tx_queue->tx_ring_size); 2175 txbdp = next_txbd(txbdp, base, tx_queue->tx_ring_size);
2172 2176
2173 length = skb_shinfo(skb)->frags[i].size; 2177 frag_len = skb_shinfo(skb)->frags[i].size;
2174 2178
2175 lstatus = txbdp->lstatus | length | 2179 lstatus = txbdp->lstatus | frag_len |
2176 BD_LFLAG(TXBD_READY); 2180 BD_LFLAG(TXBD_READY);
2177 2181
2178 /* Handle the last BD specially */ 2182 /* Handle the last BD specially */
@@ -2182,7 +2186,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
2182 bufaddr = skb_frag_dma_map(priv->dev, 2186 bufaddr = skb_frag_dma_map(priv->dev,
2183 &skb_shinfo(skb)->frags[i], 2187 &skb_shinfo(skb)->frags[i],
2184 0, 2188 0,
2185 length, 2189 frag_len,
2186 DMA_TO_DEVICE); 2190 DMA_TO_DEVICE);
2187 2191
2188 /* set the TxBD length and buffer pointer */ 2192 /* set the TxBD length and buffer pointer */
@@ -2250,7 +2254,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
2250 lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb); 2254 lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb);
2251 } 2255 }
2252 2256
2253 netdev_tx_sent_queue(txq, skb->len); 2257 netdev_tx_sent_queue(txq, bytes_sent);
2254 2258
2255 /* We can work in parallel with gfar_clean_tx_ring(), except 2259 /* We can work in parallel with gfar_clean_tx_ring(), except
2256 * when modifying num_txbdfree. Note that we didn't grab the lock 2260 * when modifying num_txbdfree. Note that we didn't grab the lock
@@ -2570,7 +2574,7 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
2570 bdp = next_txbd(bdp, base, tx_ring_size); 2574 bdp = next_txbd(bdp, base, tx_ring_size);
2571 } 2575 }
2572 2576
2573 bytes_sent += skb->len; 2577 bytes_sent += GFAR_CB(skb)->bytes_sent;
2574 2578
2575 dev_kfree_skb_any(skb); 2579 dev_kfree_skb_any(skb);
2576 2580
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 46f56f36118f..04112b98ff5d 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -575,7 +575,7 @@ struct rxfcb {
575}; 575};
576 576
577struct gianfar_skb_cb { 577struct gianfar_skb_cb {
578 int alignamount; 578 unsigned int bytes_sent; /* bytes-on-wire (i.e. no FCB) */
579}; 579};
580 580
581#define GFAR_CB(skb) ((struct gianfar_skb_cb *)((skb)->cb)) 581#define GFAR_CB(skb) ((struct gianfar_skb_cb *)((skb)->cb))