Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 87aaadbf authored by Yoshihiro Shimoda's avatar Yoshihiro Shimoda Committed by Greg Kroah-Hartman
Browse files

ravb: Fix races between ravb_tx_timeout_work() and net related ops



[ Upstream commit 9870257a0a338cd8d6c1cddab74e703f490f6779 ]

Fix races between ravb_tx_timeout_work() and functions of net_device_ops
and ethtool_ops by using rtnl_trylock() and rtnl_unlock(). Note that
since ravb_close() is under the rtnl lock and calls cancel_work_sync(),
ravb_tx_timeout_work() should calls rtnl_trylock(). Otherwise, a deadlock
may happen in ravb_tx_timeout_work() like below:

CPU0			CPU1
			ravb_tx_timeout()
			schedule_work()
...
__dev_close_many()
// Under rtnl lock
ravb_close()
cancel_work_sync()
// Waiting
			ravb_tx_timeout_work()
			rtnl_lock()
			// This is possible to cause a deadlock

If rtnl_trylock() fails, rescheduling the work with sleep for 1 msec.

Fixes: c156633f ("Renesas Ethernet AVB driver proper")
Signed-off-by: default avatarYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: default avatarSergey Shtylyov <s.shtylyov@omp.ru>
Link: https://lore.kernel.org/r/20231127122420.3706751-1-yoshihiro.shimoda.uh@renesas.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent be70b329
Loading
Loading
Loading
Loading
+10 −1
Original line number Original line Diff line number Diff line
@@ -1484,6 +1484,12 @@ static void ravb_tx_timeout_work(struct work_struct *work)
	struct net_device *ndev = priv->ndev;
	struct net_device *ndev = priv->ndev;
	int error;
	int error;


	if (!rtnl_trylock()) {
		usleep_range(1000, 2000);
		schedule_work(&priv->work);
		return;
	}

	netif_tx_stop_all_queues(ndev);
	netif_tx_stop_all_queues(ndev);


	/* Stop PTP Clock driver */
	/* Stop PTP Clock driver */
@@ -1516,7 +1522,7 @@ static void ravb_tx_timeout_work(struct work_struct *work)
		 */
		 */
		netdev_err(ndev, "%s: ravb_dmac_init() failed, error %d\n",
		netdev_err(ndev, "%s: ravb_dmac_init() failed, error %d\n",
			   __func__, error);
			   __func__, error);
		return;
		goto out_unlock;
	}
	}
	ravb_emac_init(ndev);
	ravb_emac_init(ndev);


@@ -1526,6 +1532,9 @@ static void ravb_tx_timeout_work(struct work_struct *work)
		ravb_ptp_init(ndev, priv->pdev);
		ravb_ptp_init(ndev, priv->pdev);


	netif_tx_start_all_queues(ndev);
	netif_tx_start_all_queues(ndev);

out_unlock:
	rtnl_unlock();
}
}


/* Packet transmit function for Ethernet AVB */
/* Packet transmit function for Ethernet AVB */