bmips: fix Tx cleanup when NAPI poll budget is zero
[openwrt/staging/noltari.git] / target / linux / bmips / files / drivers / net / ethernet / broadcom / bcm6368-enetsw.c
index 9b7c21c019c40637ccd480e8e1c06d4f5251e771..c655ae8d27753106298d0bae151c98444bbab337 100644 (file)
@@ -442,9 +442,11 @@ static int bcm6368_enetsw_receive_queue(struct net_device *dev, int budget)
 /*
  * try to or force reclaim of transmitted buffers
  */
-static int bcm6368_enetsw_tx_reclaim(struct net_device *dev, int force)
+static int bcm6368_enetsw_tx_reclaim(struct net_device *dev, int force,
+                                    int budget)
 {
        struct bcm6368_enetsw *priv = netdev_priv(dev);
+       unsigned int bytes = 0;
        int released = 0;
 
        while (priv->tx_desc_count < priv->tx_ring_size) {
@@ -481,10 +483,13 @@ static int bcm6368_enetsw_tx_reclaim(struct net_device *dev, int force)
                if (desc->len_stat & DMADESC_UNDER_MASK)
                        dev->stats.tx_errors++;
 
-               napi_consume_skb(skb, !force);
+               bytes += skb->len;
+               napi_consume_skb(skb, budget);
                released++;
        }
 
+       netdev_completed_queue(dev, released, bytes);
+
        if (netif_queue_stopped(dev) && released)
                netif_wake_queue(dev);
 
@@ -507,7 +512,7 @@ static int bcm6368_enetsw_poll(struct napi_struct *napi, int budget)
                         DMAC_IR_REG, priv->tx_chan);
 
        /* reclaim sent skb */
-       bcm6368_enetsw_tx_reclaim(dev, 0);
+       bcm6368_enetsw_tx_reclaim(dev, 0, budget);
 
        spin_lock(&priv->rx_lock);
        rx_work_done = bcm6368_enetsw_receive_queue(dev, budget);
@@ -617,6 +622,8 @@ bcm6368_enetsw_start_xmit(struct sk_buff *skb, struct net_device *dev)
        desc->len_stat = len_stat;
        wmb();
 
+       netdev_sent_queue(dev, skb->len);
+
        /* kick tx dma */
        dmac_writel(priv, priv->dma_chan_en_mask, DMAC_CHANCFG_REG,
                    priv->tx_chan);
@@ -849,7 +856,7 @@ static int bcm6368_enetsw_stop(struct net_device *dev)
        bcm6368_enetsw_disable_dma(priv, priv->rx_chan);
 
        /* force reclaim of all tx buffers */
-       bcm6368_enetsw_tx_reclaim(dev, 1);
+       bcm6368_enetsw_tx_reclaim(dev, 1, 0);
 
        /* free the rx buffer ring */
        for (i = 0; i < priv->rx_ring_size; i++) {
@@ -876,6 +883,8 @@ static int bcm6368_enetsw_stop(struct net_device *dev)
                free_irq(priv->irq_tx, dev);
        free_irq(priv->irq_rx, dev);
 
+       netdev_reset_queue(dev);
+
        return 0;
 }