]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
net: ethernet: xilinx: Fix race condition for 10G MAC
authorKedareswara rao Appana <appana.durga.rao@xilinx.com>
Fri, 29 Apr 2016 10:04:22 +0000 (15:34 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Tue, 3 May 2016 06:35:12 +0000 (08:35 +0200)
In the driver napi is enabled after interrupts
are being registered. This may casue issue
if there is already data in the mac rx fifo.

If there is already data in the mac rx fifo
in the current driver flow it will trigger RX ISR
there we are disabling RX interrupts again it will
get enabled after processing the packets upto quota
in the napi poll.

But with the current driver flow napi will never be called
resulting no more rx packets being processed(As napi is enabled
at the end of the open function).

This patch fixes this issue.

Signed-off-by: Kedareswara rao Appana <appanad@xilinx.com>
Acked-by: Harini Katakam <harinik@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/net/ethernet/xilinx/xilinx_axienet_main.c

index d8e51934be1a32c2005694109efc6a67c8be294e..4846d28058034daeef444a2ff45fd98534e7947c 100644 (file)
@@ -1275,6 +1275,14 @@ static int axienet_open(struct net_device *ndev)
        tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
                     (unsigned long) lp);
 
+       /* Enable NAPI scheduling before enabling Axi DMA Rx IRQ, or you
+        * might run into a race condition; the RX ISR disables IRQ processing
+        * before scheduling the NAPI function to complete the processing.
+        * If NAPI scheduling is (still) disabled at that time, no more RX IRQs
+        * will be processed as only the NAPI function re-enables them!
+        */
+       napi_enable(&lp->napi);
+
        /* Enable interrupts for Axi DMA Tx */
        ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev);
        if (ret)
@@ -1292,8 +1300,6 @@ static int axienet_open(struct net_device *ndev)
                        goto err_eth_irq;
        }
 
-       napi_enable(&lp->napi);
-
        return 0;
 
 err_eth_irq:
@@ -1301,6 +1307,7 @@ err_eth_irq:
 err_rx_irq:
        free_irq(lp->tx_irq, ndev);
 err_tx_irq:
+       napi_disable(&lp->napi);
        if (lp->phy_dev)
                phy_disconnect(lp->phy_dev);
        lp->phy_dev = NULL;