Re: [PATCH net] net: dm9000: Fix a recursive lockup in the TX timeout path

From: Andrew Lunn

Date: Wed Sep 23 2026 - 15:42:11 EST


On Wed, Sep 23, 2026 at 04:40:55PM +0800, Ginger Li wrote:
> dm9000_timeout() takes db->lock with interrupts disabled and then calls
> dm9000_init_dm9000(), which expects the caller to hold that lock and accesses
> the chip registers directly. For DM9000B devices dm9000_init_dm9000() also
> calls dm9000_phy_write(), and that function takes db->lock again, so the TX
> timeout path deadlocks on the same CPU.
>
> dm9000_phy_write() already skips db->addr_lock when db->in_timeout is set,
> because in that case the caller holds db->lock and sleeping is not allowed
> either. Skip db->lock as well then, so that the nested call from
> dm9000_init_dm9000() works as intended.
>
> Fixes: 6741f40 ("DM9000B: driver initialization upgrade")
> Signed-off-by: Ginger Li <ginger.jzllee@xxxxxxxxx>
> ---
> drivers/net/ethernet/davicom/dm9000.c | 18 +++++++++++-------
> 1 file changed, 11 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
> --- a/drivers/net/ethernet/davicom/dm9000.c
> +++ b/drivers/net/ethernet/davicom/dm9000.c
> @@ -325,10 +325,10 @@ dm9000_phy_write(struct net_device *dev,
> unsigned long reg_save;
>
> dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
> - if (!db->in_timeout)
> + if (!db->in_timeout) {
> mutex_lock(&db->addr_lock);
> -
> - spin_lock_irqsave(&db->lock, flags);
> + spin_lock_irqsave(&db->lock, flags);
> + }

This is ugly.

Is it possible to pull the locking out of dm9000_phy_write() to give a
version which tests the lock is taken using lockdep_assert_held(). Put
a wrapper around it which takes the lock for the normal case.

I would also take a look at dm9000_phy_read() and understand why its
locking is different.

Ideally you want to remove db->in_timeout, and make sure locked or
unlocked functions are called as needed. I assume you have the
hardware, and can trigger a timeout? So you can do a bigger refactor
like this?

Andrew