ar71xx: ack completed tx descriptors only after the full frame has been completed
authorFelix Fietkau <nbd@openwrt.org>
Thu, 11 Sep 2014 15:14:05 +0000 (15:14 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Thu, 11 Sep 2014 15:14:05 +0000 (15:14 +0000)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Backport of r42457

SVN-Revision: 42475

target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c

index 2a7567ede5f6f007603de80a4fb469d37dad10f1..892d5e69e928ef4677998aabc949f14ab3e94492 100644 (file)
@@ -901,11 +901,12 @@ static int ag71xx_tx_packets(struct ag71xx *ag)
        struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag);
        int sent = 0;
        int bytes_compl = 0;
+       int n = 0;
 
        DBG("%s: processing TX ring\n", ag->dev->name);
 
-       while (ring->dirty != ring->curr) {
-               unsigned int i = ring->dirty % ring->size;
+       while (ring->dirty + n != ring->curr) {
+               unsigned int i = (ring->dirty + n) % ring->size;
                struct ag71xx_desc *desc = ring->buf[i].desc;
                struct sk_buff *skb = ring->buf[i].skb;
 
@@ -916,17 +917,22 @@ static int ag71xx_tx_packets(struct ag71xx *ag)
                        break;
                }
 
-               ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS);
+               n++;
+               if (!skb)
+                       continue;
 
-               if (skb) {
-                       dev_kfree_skb_any(skb);
-                       ring->buf[i].skb = NULL;
+               dev_kfree_skb_any(skb);
+               ring->buf[i].skb = NULL;
 
-                       bytes_compl += ring->buf[i].len;
-                       sent++;
-               }
+               bytes_compl += ring->buf[i].len;
 
-               ring->dirty++;
+               sent++;
+               ring->dirty += n;
+
+               while (n > 0) {
+                       ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS);
+                       n--;
+               }
        }
 
        DBG("%s: %d packets sent out\n", ag->dev->name, sent);