From 7a8f13f33c6b898d6fd2691b1bbd1ad0936e0a33 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 22 Feb 2014 14:42:48 +0000 Subject: [PATCH] gianfar: Fix reported number of sent bytes to BQL This is a backported patch for the gianfar ethernet driver used in TPLink 4900 v1. It is supposed to fix the error which show up in dmesg with: NETDEV WATCHDOG: eth0 (fsl-gianfar): transmit queue xy timed out Full upstream patch is at: http://patchwork.ozlabs.org/patch/271242 Signed-off-by: Thomas Huehn SVN-Revision: 39692 --- ...reported_number_of_sent_bytes_to_BQL.patch | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 target/linux/mpc85xx/patches-3.10/220-fix_gianfar_reported_number_of_sent_bytes_to_BQL.patch diff --git a/target/linux/mpc85xx/patches-3.10/220-fix_gianfar_reported_number_of_sent_bytes_to_BQL.patch b/target/linux/mpc85xx/patches-3.10/220-fix_gianfar_reported_number_of_sent_bytes_to_BQL.patch new file mode 100644 index 0000000000..d0380ff8ac --- /dev/null +++ b/target/linux/mpc85xx/patches-3.10/220-fix_gianfar_reported_number_of_sent_bytes_to_BQL.patch @@ -0,0 +1,77 @@ +--- a/drivers/net/ethernet/freescale/gianfar.c ++++ b/drivers/net/ethernet/freescale/gianfar.c +@@ -2064,7 +2064,7 @@ static int gfar_start_xmit(struct sk_buf + int i, rq = 0, do_tstamp = 0; + u32 bufaddr; + unsigned long flags; +- unsigned int nr_frags, nr_txbds, length, fcb_length = GMAC_FCB_LEN; ++ unsigned int nr_frags, nr_txbds, bytes_sent, fcb_length = GMAC_FCB_LEN; + + /* TOE=1 frames larger than 2500 bytes may see excess delays + * before start of transmission. +@@ -2130,7 +2130,10 @@ static int gfar_start_xmit(struct sk_buf + } + + /* Update transmit stats */ +- tx_queue->stats.tx_bytes += skb->len; ++ bytes_sent = skb->len; ++ tx_queue->stats.tx_bytes += bytes_sent; ++ /* keep Tx bytes on wire for BQL accounting */ ++ GFAR_CB(skb)->bytes_sent = bytes_sent; + tx_queue->stats.tx_packets++; + + txbdp = txbdp_start = tx_queue->cur_tx; +@@ -2150,12 +2153,13 @@ static int gfar_start_xmit(struct sk_buf + } else { + /* Place the fragment addresses and lengths into the TxBDs */ + for (i = 0; i < nr_frags; i++) { ++ unsigned int frag_len; + /* Point at the next BD, wrapping as needed */ + txbdp = next_txbd(txbdp, base, tx_queue->tx_ring_size); + +- length = skb_shinfo(skb)->frags[i].size; ++ frag_len = skb_shinfo(skb)->frags[i].size; + +- lstatus = txbdp->lstatus | length | ++ lstatus = txbdp->lstatus | frag_len | + BD_LFLAG(TXBD_READY); + + /* Handle the last BD specially */ +@@ -2165,7 +2169,7 @@ static int gfar_start_xmit(struct sk_buf + bufaddr = skb_frag_dma_map(priv->dev, + &skb_shinfo(skb)->frags[i], + 0, +- length, ++ frag_len, + DMA_TO_DEVICE); + + /* set the TxBD length and buffer pointer */ +@@ -2231,7 +2235,7 @@ static int gfar_start_xmit(struct sk_buf + lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb); + } + +- netdev_tx_sent_queue(txq, skb->len); ++ netdev_tx_sent_queue(txq, bytes_sent); + + /* We can work in parallel with gfar_clean_tx_ring(), except + * when modifying num_txbdfree. Note that we didn't grab the lock +@@ -2551,7 +2555,7 @@ static void gfar_clean_tx_ring(struct gf + bdp = next_txbd(bdp, base, tx_ring_size); + } + +- bytes_sent += skb->len; ++ bytes_sent += GFAR_CB(skb)->bytes_sent; + + dev_kfree_skb_any(skb); + +--- a/drivers/net/ethernet/freescale/gianfar.h ++++ b/drivers/net/ethernet/freescale/gianfar.h +@@ -571,7 +571,7 @@ struct rxfcb { + }; + + struct gianfar_skb_cb { +- int alignamount; ++ unsigned int bytes_sent; /* bytes-on-wire (i.e. no FCB) */ + }; + + #define GFAR_CB(skb) ((struct gianfar_skb_cb *)((skb)->cb)) -- 2.30.2