lantiq: fix sleep with spinlock held in xrx200 network driver
In the xrx200_close() function we call napi_disable(), that could sleep, with priv->hw->chan[i].lock held. This could lead to deadlock and causes the kernel to complain. Look at the code I couldn't convince myself about why we need to protect that specific code part with the lock. IMHO there seems no reason to protect the refcount variables, because AFAIK ndo_close() and ndo_open() callbacks are already called with a semaphore held. Neither I could figure out why napi_disable() have to be called with that lock held. The only remaining code part for which I could guess the lock is useful for is ltq_dma_close() function call. This patch reduces the lock to the said function call, avoiding the sleep-with-spinlock-held situation Signed-off-by: Andrea Merello <andrea.merello@gmail.com> [fold into 0025-NET-MIPS-lantiq-adds-xrx200-net.patch, backport to kernel 4.4] Signed-off-by: Mathias Kresin <dev@kresin.me>
This commit is contained in:
parent
34c01e68b5
commit
b81c04382b
2 changed files with 8 additions and 6 deletions
|
@ -209,7 +209,7 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
|
||||||
+};
|
+};
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/drivers/net/ethernet/lantiq_xrx200.c
|
+++ b/drivers/net/ethernet/lantiq_xrx200.c
|
||||||
@@ -0,0 +1,1852 @@
|
@@ -0,0 +1,1853 @@
|
||||||
+/*
|
+/*
|
||||||
+ * This program is free software; you can redistribute it and/or modify it
|
+ * This program is free software; you can redistribute it and/or modify it
|
||||||
+ * under the terms of the GNU General Public License version 2 as published
|
+ * under the terms of the GNU General Public License version 2 as published
|
||||||
|
@ -1110,14 +1110,15 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
|
||||||
+ for (i = 0; i < XRX200_MAX_DMA; i++) {
|
+ for (i = 0; i < XRX200_MAX_DMA; i++) {
|
||||||
+ if (!priv->hw->chan[i].dma.irq)
|
+ if (!priv->hw->chan[i].dma.irq)
|
||||||
+ continue;
|
+ continue;
|
||||||
+ spin_lock_bh(&priv->hw->chan[i].lock);
|
+
|
||||||
+ priv->hw->chan[i].refcount--;
|
+ priv->hw->chan[i].refcount--;
|
||||||
+ if (!priv->hw->chan[i].refcount) {
|
+ if (!priv->hw->chan[i].refcount) {
|
||||||
+ if (XRX200_DMA_IS_RX(i))
|
+ if (XRX200_DMA_IS_RX(i))
|
||||||
+ napi_disable(&priv->hw->chan[i].napi);
|
+ napi_disable(&priv->hw->chan[i].napi);
|
||||||
|
+ spin_lock_bh(&priv->hw->chan[i].lock);
|
||||||
+ ltq_dma_close(&priv->hw->chan[XRX200_DMA_RX].dma);
|
+ ltq_dma_close(&priv->hw->chan[XRX200_DMA_RX].dma);
|
||||||
|
+ spin_unlock_bh(&priv->hw->chan[i].lock);
|
||||||
+ }
|
+ }
|
||||||
+ spin_unlock_bh(&priv->hw->chan[i].lock);
|
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ return 0;
|
+ return 0;
|
||||||
|
|
|
@ -209,7 +209,7 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
|
||||||
+};
|
+};
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/drivers/net/ethernet/lantiq_xrx200.c
|
+++ b/drivers/net/ethernet/lantiq_xrx200.c
|
||||||
@@ -0,0 +1,1851 @@
|
@@ -0,0 +1,1852 @@
|
||||||
+/*
|
+/*
|
||||||
+ * This program is free software; you can redistribute it and/or modify it
|
+ * This program is free software; you can redistribute it and/or modify it
|
||||||
+ * under the terms of the GNU General Public License version 2 as published
|
+ * under the terms of the GNU General Public License version 2 as published
|
||||||
|
@ -1110,14 +1110,15 @@ Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
|
||||||
+ for (i = 0; i < XRX200_MAX_DMA; i++) {
|
+ for (i = 0; i < XRX200_MAX_DMA; i++) {
|
||||||
+ if (!priv->hw->chan[i].dma.irq)
|
+ if (!priv->hw->chan[i].dma.irq)
|
||||||
+ continue;
|
+ continue;
|
||||||
+ spin_lock_bh(&priv->hw->chan[i].lock);
|
+
|
||||||
+ priv->hw->chan[i].refcount--;
|
+ priv->hw->chan[i].refcount--;
|
||||||
+ if (!priv->hw->chan[i].refcount) {
|
+ if (!priv->hw->chan[i].refcount) {
|
||||||
+ if (XRX200_DMA_IS_RX(i))
|
+ if (XRX200_DMA_IS_RX(i))
|
||||||
+ napi_disable(&priv->hw->chan[i].napi);
|
+ napi_disable(&priv->hw->chan[i].napi);
|
||||||
|
+ spin_lock_bh(&priv->hw->chan[i].lock);
|
||||||
+ ltq_dma_close(&priv->hw->chan[XRX200_DMA_RX].dma);
|
+ ltq_dma_close(&priv->hw->chan[XRX200_DMA_RX].dma);
|
||||||
|
+ spin_unlock_bh(&priv->hw->chan[i].lock);
|
||||||
+ }
|
+ }
|
||||||
+ spin_unlock_bh(&priv->hw->chan[i].lock);
|
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ return 0;
|
+ return 0;
|
||||||
|
|
Loading…
Reference in a new issue