From 0f537dcb9798b5cb2428ed6870b5bc9660bbc17d Mon Sep 17 00:00:00 2001 From: p-szafonimateusz Date: Tue, 3 Jun 2025 14:07:56 +0200 Subject: [PATCH] drivers/net/{e1000|igc}: fix reinit for RX/TX rings Descriptor head is managed by HW and should not be modified by SW unless: 1. device is after a reset 2. device is before enabling TX or RX Also set correct tail for RX which should point at the end of ring (descriptor ring is zero-indexed). Signed-off-by: p-szafonimateusz --- drivers/net/e1000.c | 18 +++++++++++++----- drivers/net/igc.c | 18 +++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 567fdf38f01..0a00c3de1cd 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -484,6 +484,9 @@ static void e1000_dump_mem(FAR struct e1000_driver_s *priv, * Returned Value: * None * + * Assumption: + * This function can be called only after card reset and when TX is disabled + * *****************************************************************************/ static void e1000_txclean(FAR struct e1000_driver_s *priv) @@ -524,6 +527,9 @@ static void e1000_txclean(FAR struct e1000_driver_s *priv) * Returned Value: * None * + * Assumption: + * This function can be called only after card reset and when RX is disabled + * *****************************************************************************/ static void e1000_rxclean(FAR struct e1000_driver_s *priv) @@ -531,7 +537,7 @@ static void e1000_rxclean(FAR struct e1000_driver_s *priv) priv->rx_now = 0; e1000_putreg_mem(priv, E1000_RDH, 0); - e1000_putreg_mem(priv, E1000_RDT, 0); + e1000_putreg_mem(priv, E1000_RDT, E1000_RX_DESC - 1); } /***************************************************************************** @@ -1179,6 +1185,12 @@ static void e1000_disable(FAR struct e1000_driver_s *priv) e1000_putreg_mem(priv, E1000_RCTL, 0); + /* We have to reset device, otherwise writing to RDH and THD corrupts + * the device state. + */ + + e1000_putreg_mem(priv, E1000_CTRL, E1000_CTRL_RST); + /* Reset Tx tail */ e1000_txclean(priv); @@ -1287,10 +1299,6 @@ static void e1000_enable(FAR struct e1000_driver_s *priv) e1000_rxclean(priv); - /* All RX descriptors available */ - - e1000_putreg_mem(priv, E1000_RDT, E1000_RX_DESC); - /* Enable interrupts */ e1000_putreg_mem(priv, E1000_IMS, priv->irqs); diff --git a/drivers/net/igc.c b/drivers/net/igc.c index f20f4ec8baa..763bd18c5e9 100644 --- a/drivers/net/igc.c +++ b/drivers/net/igc.c @@ -438,6 +438,9 @@ static void igc_dump_mem(FAR struct igc_driver_s *priv, FAR const char *msg) * Returned Value: * None * + * Assumption: + * This function can be called only after card reset and when TX is disabled + * *****************************************************************************/ static void igc_txclean(FAR struct igc_driver_s *priv) @@ -478,6 +481,9 @@ static void igc_txclean(FAR struct igc_driver_s *priv) * Returned Value: * None * + * Assumption: + * This function can be called only after card reset and when RX is disabled + * *****************************************************************************/ static void igc_rxclean(FAR struct igc_driver_s *priv) @@ -485,7 +491,7 @@ static void igc_rxclean(FAR struct igc_driver_s *priv) priv->rx_now = 0; igc_putreg_mem(priv, IGC_RDH0, 0); - igc_putreg_mem(priv, IGC_RDT0, 0); + igc_putreg_mem(priv, IGC_RDT0, IGC_RX_DESC - 1); } /***************************************************************************** @@ -1061,6 +1067,12 @@ static void igc_disable(FAR struct igc_driver_s *priv) igc_putreg_mem(priv, IGC_RCTL, 0); + /* We have to reset device, otherwise writing to RDH and THD corrupts + * the device state. + */ + + igc_putreg_mem(priv, IGC_CTRL, IGC_CTRL_DEVRST); + /* Reset Tx tail */ igc_txclean(priv); @@ -1214,10 +1226,6 @@ static void igc_enable(FAR struct igc_driver_s *priv) igc_rxclean(priv); - /* All RX descriptors available */ - - igc_putreg_mem(priv, IGC_RDT0, IGC_RX_DESC); - #ifdef CONFIG_DEBUG_NET_INFO /* Dump memory */