From: David Daney <david.daney@xxxxxxxxxx> Date: Thu, 7 Dec 2017 16:09:33 -0800 > +static void bgx_port_check_state(struct work_struct *work) > +{ ... > + mutex_lock(&priv->lock); > + if (priv->work_queued) > + queue_delayed_work(check_state_wq, &priv->dwork, HZ); > + mutex_unlock(&priv->lock); > +} ... > +int bgx_port_disable(struct net_device *netdev) > +{ ... > + mutex_lock(&priv->lock); > + if (priv->work_queued) { > + cancel_delayed_work_sync(&priv->dwork); > + priv->work_queued = false; This can deadlock. When you do a sync work cancel, it waits until all running work instances finish. You have the priv->lock, so if bgx_port_check_status() need to still take priv->lock to complete then no further progress will be made. I think it is pointless to use this weird work_queued boolean state. Just unconditionally, and without locking, cancel the delayed work, ragardless of whether it was actually used ever or not. Thank you.