diff options
author | Xiaotian Feng <xtfeng@gmail.com> | 2012-11-13 14:47:36 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-14 21:50:10 -0500 |
commit | 71c6c837a0fe9d291e0764503f09dac0fec59ce1 (patch) | |
tree | 64fc5d4c2cf468c841050bed08774bd254d5edbf /drivers/net/ethernet/xilinx | |
parent | b2942004fb5c9f3304b77e187b8a1977b3626c9b (diff) |
drivers/net: fix tasklet misuse issue
In commit 175c0dff, drivers uses tasklet_kill to avoid put disabled tasklet
on the tasklet vec. But some of the drivers uses tasklet_init & tasklet_disable
in the driver init code, then tasklet_enable when it is opened. This makes
tasklet_enable on a killed tasklet and make ksoftirqd crazy then. Normally,
drivers should use tasklet_init/tasklet_kill on device open/remove, and use
tasklet_disable/tasklet_enable on device suspend/resume.
Reported-by: Peter Wu <lekensteyn@gmail.com>
Tested-by: Peter Wu <lekensteyn@gmail.com>
Signed-off-by: Xiaotian Feng <dannyfeng@tencent.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/xilinx')
-rw-r--r-- | drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 1d04754a6637..77e6db9dcfed 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c | |||
@@ -942,6 +942,10 @@ static int axienet_open(struct net_device *ndev) | |||
942 | phy_start(lp->phy_dev); | 942 | phy_start(lp->phy_dev); |
943 | } | 943 | } |
944 | 944 | ||
945 | /* Enable tasklets for Axi DMA error handling */ | ||
946 | tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler, | ||
947 | (unsigned long) lp); | ||
948 | |||
945 | /* Enable interrupts for Axi DMA Tx */ | 949 | /* Enable interrupts for Axi DMA Tx */ |
946 | ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev); | 950 | ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev); |
947 | if (ret) | 951 | if (ret) |
@@ -950,8 +954,7 @@ static int axienet_open(struct net_device *ndev) | |||
950 | ret = request_irq(lp->rx_irq, axienet_rx_irq, 0, ndev->name, ndev); | 954 | ret = request_irq(lp->rx_irq, axienet_rx_irq, 0, ndev->name, ndev); |
951 | if (ret) | 955 | if (ret) |
952 | goto err_rx_irq; | 956 | goto err_rx_irq; |
953 | /* Enable tasklets for Axi DMA error handling */ | 957 | |
954 | tasklet_enable(&lp->dma_err_tasklet); | ||
955 | return 0; | 958 | return 0; |
956 | 959 | ||
957 | err_rx_irq: | 960 | err_rx_irq: |
@@ -960,6 +963,7 @@ err_tx_irq: | |||
960 | if (lp->phy_dev) | 963 | if (lp->phy_dev) |
961 | phy_disconnect(lp->phy_dev); | 964 | phy_disconnect(lp->phy_dev); |
962 | lp->phy_dev = NULL; | 965 | lp->phy_dev = NULL; |
966 | tasklet_kill(&lp->dma_err_tasklet); | ||
963 | dev_err(lp->dev, "request_irq() failed\n"); | 967 | dev_err(lp->dev, "request_irq() failed\n"); |
964 | return ret; | 968 | return ret; |
965 | } | 969 | } |
@@ -1613,10 +1617,6 @@ static int __devinit axienet_of_probe(struct platform_device *op) | |||
1613 | goto err_iounmap_2; | 1617 | goto err_iounmap_2; |
1614 | } | 1618 | } |
1615 | 1619 | ||
1616 | tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler, | ||
1617 | (unsigned long) lp); | ||
1618 | tasklet_disable(&lp->dma_err_tasklet); | ||
1619 | |||
1620 | return 0; | 1620 | return 0; |
1621 | 1621 | ||
1622 | err_iounmap_2: | 1622 | err_iounmap_2: |