mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
net: au1000: move free_irq out of the close-time spinlocked section
au1000_close() calls free_irq() while aup->lock is still held with spin_lock_irqsave(). free_irq() can sleep because it takes the IRQ descriptor request mutex, so it does not belong inside the close-time spinlocked section. This was found by our static analysis tool and then confirmed by manual review of the in-tree au1000_close() .ndo_stop path. The reviewed path keeps aup->lock held across the MAC reset, queue stop and free_irq(dev->irq, dev). A directed runtime validation kept that ndo_stop carrier and the same free_irq(dev->irq, dev) operation under the driver lock. Lockdep reported "BUG: sleeping function called from invalid context" and "Invalid wait context" while free_irq() was taking desc->request_mutex, with au1000_close() and free_irq() on the stack. Drop aup->lock before freeing the IRQ. The protected close-time work still stops the device and queue before IRQ teardown, but the sleepable IRQ core path now runs outside the spinlocked section. Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260619151816.1144289-1-runyu.xiao@seu.edu.cn Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
9f58a0a4d6
commit
f48763beab
@@ -943,9 +943,10 @@ static int au1000_close(struct net_device *dev)
|
||||
/* stop the device */
|
||||
netif_stop_queue(dev);
|
||||
|
||||
spin_unlock_irqrestore(&aup->lock, flags);
|
||||
|
||||
/* disable the interrupt */
|
||||
free_irq(dev->irq, dev);
|
||||
spin_unlock_irqrestore(&aup->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user