[PATCH net] net: ibm: emac: mal: fix NAPI locking

Runyu Xiao posted 1 patch 1 month, 2 weeks ago
drivers/net/ethernet/ibm/emac/mal.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
[PATCH net] net: ibm: emac: mal: fix NAPI locking
Posted by Runyu Xiao 1 month, 2 weeks ago
Since commit 413f0271f396 ("net: protect NAPI enablement with
netdev_lock()"), napi_enable() and napi_disable() take netdev_lock().

mal_register_commac() and mal_unregister_commac() call these helpers
while holding mal->lock with interrupts disabled. In the unregister
path, napi_disable() may also wait for polling to finish, while the poll
completion path takes mal->lock.

Take netdev_lock() before mal->lock, use the locked NAPI helpers, and
drop mal->lock before napi_disable_locked().

Fixes: 413f0271f396 ("net: protect NAPI enablement with netdev_lock()")
Cc: stable@vger.kernel.org
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
---
 drivers/net/ethernet/ibm/emac/mal.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
index 74526002d52b..42027665f2a9 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -34,6 +34,7 @@ int mal_register_commac(struct mal_instance *mal, struct mal_commac *commac)
 {
 	unsigned long flags;
 
+	netdev_lock(mal->napi.dev);
 	spin_lock_irqsave(&mal->lock, flags);
 
 	MAL_DBG(mal, "reg(%08x, %08x)" NL,
@@ -43,7 +44,8 @@ int mal_register_commac(struct mal_instance *mal, struct mal_commac *commac)
 	/* Don't let multiple commacs claim the same channel(s) */
 	if ((mal->tx_chan_mask & commac->tx_chan_mask) ||
 	    (mal->rx_chan_mask & commac->rx_chan_mask)) {
 		spin_unlock_irqrestore(&mal->lock, flags);
+		netdev_unlock(mal->napi.dev);
 		printk(KERN_WARNING "mal%d: COMMAC channels conflict!\n",
 		       mal->index);
 		return -EBUSY;
@@ -51,11 +52,12 @@ int mal_register_commac(struct mal_instance *mal, struct mal_commac *commac)
 
 	if (list_empty(&mal->list))
-		napi_enable(&mal->napi);
+		napi_enable_locked(&mal->napi);
 	mal->tx_chan_mask |= commac->tx_chan_mask;
 	mal->rx_chan_mask |= commac->rx_chan_mask;
 	list_add(&commac->list, &mal->list);
 
 	spin_unlock_irqrestore(&mal->lock, flags);
+	netdev_unlock(mal->napi.dev);
 
 	return 0;
 }
@@ -64,7 +66,9 @@ void mal_unregister_commac(struct mal_instance	*mal,
 		struct mal_commac *commac)
 {
 	unsigned long flags;
+	bool disable_napi;
 
+	netdev_lock(mal->napi.dev);
 	spin_lock_irqsave(&mal->lock, flags);
 
 	MAL_DBG(mal, "unreg(%08x, %08x)" NL,
@@ -73,10 +79,12 @@ void mal_unregister_commac(struct mal_instance	*mal,
 	mal->tx_chan_mask &= ~commac->tx_chan_mask;
 	mal->rx_chan_mask &= ~commac->rx_chan_mask;
 	list_del_init(&commac->list);
-	if (list_empty(&mal->list))
-		napi_disable(&mal->napi);
+	disable_napi = list_empty(&mal->list);
 
 	spin_unlock_irqrestore(&mal->lock, flags);
+	if (disable_napi)
+		napi_disable_locked(&mal->napi);
+	netdev_unlock(mal->napi.dev);
 }
 
 int mal_set_rcbs(struct mal_instance *mal, int channel, unsigned long size)
-- 
2.34.1
Re: [PATCH net] net: ibm: emac: mal: fix NAPI locking
Posted by Simon Horman 1 month, 2 weeks ago
On Tue, Aug 11, 2026 at 03:08:13PM +0800, Runyu Xiao wrote:
> Since commit 413f0271f396 ("net: protect NAPI enablement with
> netdev_lock()"), napi_enable() and napi_disable() take netdev_lock().
> 
> mal_register_commac() and mal_unregister_commac() call these helpers
> while holding mal->lock with interrupts disabled. In the unregister
> path, napi_disable() may also wait for polling to finish, while the poll
> completion path takes mal->lock.
> 
> Take netdev_lock() before mal->lock, use the locked NAPI helpers, and
> drop mal->lock before napi_disable_locked().
> 
> Fixes: 413f0271f396 ("net: protect NAPI enablement with netdev_lock()")
> Cc: stable@vger.kernel.org
> Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>

Reviewed-by: Simon Horman <horms@kernel.org>