net: timeout fixes for GENET and SYSTEMPORT
Subsystems (4)
cover net: timeout fixes for GENET and SYSTEMPORT
Hi David,
This patch series fixes occasional transmit timeout around the time the system goes into suspend. GENET and SYSTEMPORT have nearly the same logic in that regard and were both affected in the same way.
Please queue up for stable, thanks!
Doug Berger (1):
net: bcmgenet: protect stop from timeout
Florian Fainelli (1):
net: systemport: Protect stop from timeout
drivers/net/ethernet/broadcom/bcmsysport.c | 15 +++++++-------- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 13 +++++++------ 2 files changed, 14 insertions(+), 14 deletions(-)
Signature · 1 line
2.17.1
PATCH 1/2 net: bcmgenet: protect stop from timeout
From: Doug Berger <[email protected]>
A timing hazard exists when the network interface is stopped that allows a watchdog timeout to be processed by a separate core in parallel. This creates the potential for the timeout handler to wake the queues while the driver is shutting down, or access registers after their clocks have been removed.
The more common case is that the watchdog timeout will produce a warning message which doesn't lead to a crash. The chances of this are greatly increased by the fact that bcmgenet_netif_stop stops the transmit queues which can easily precipitate a watchdog time- out because of stale trans_start data in the queues.
This commit corrects the behavior by ensuring that the watchdog timeout is disabled before enterring bcmgenet_netif_stop. There are currently only two users of the bcmgenet_netif_stop function:
close and suspend.
The close case already handles the issue by exiting the RUNNING state before invoking the driver close service.
The suspend case now performs the netif_device_detach to exit the PRESENT state before the call to bcmgenet_netif_stop rather than after it.
These behaviors prevent any future scheduling of the driver timeout service during the window. The netif_tx_stop_all_queues function in bcmgenet_netif_stop is replaced with netif_tx_disable to ensure synchronization with any transmit or timeout threads that may already be executing on other cores.
For symmetry, the netif_device_attach call upon resume is moved to after the call to bcmgenet_netif_start. Since it wakes the transmit queues it is not necessary to invoke netif_tx_start_all_queues from bcmgenet_netif_start so it is moved into the driver open service.
--- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +7 -6
@@ -2855,7 +2855,6 @@ static void bcmgenet_netif_start(struct net_device *dev)umac_enable_set (priv,CMD_TX_EN |CMD_RX_EN , true); -netif_tx_start_all_queues (dev);bcmgenet_enable_tx_napi (priv);/* Monitor link interrupts now */
@@ -2937,6 +2936,8 @@ static int bcmgenet_open(struct net_device *dev)bcmgenet_netif_start (dev); +netif_tx_start_all_queues (dev); +return 0 ; err_irq1:
@@ -2958,7 +2959,7 @@ static void bcmgenet_netif_stop(struct net_device *dev)struct bcmgenet_priv *priv =netdev_priv (dev);bcmgenet_disable_tx_napi (priv); -netif_tx_stop_all_queues (dev); +netif_tx_disable (dev);/* Disable MAC receive */ umac_enable_set (priv,CMD_RX_EN , false);
@@ -3620,13 +3621,13 @@ static int bcmgenet_suspend(struct device *d)if (!netif_running (dev))return 0 ; +netif_device_detach (dev); +bcmgenet_netif_stop (dev);if (!device_may_wakeup (d))phy_suspend (dev->phydev); -netif_device_detach (dev); -/* Prepare the device for Wake-on-LAN and switch to the slow clock */ if (device_may_wakeup (d) && priv->wolopts) { ret =bcmgenet_power_down (priv,GENET_POWER_WOL_MAGIC );
@@ -3700,8 +3701,6 @@ static int bcmgenet_resume(struct device *d)/* Always enable ring 16 - descriptor ring */ bcmgenet_enable_dma (priv, dma_ctrl); -netif_device_attach (dev); -if (!device_may_wakeup (d))phy_resume (dev->phydev);
@@ -3710,6 +3709,8 @@ static int bcmgenet_resume(struct device *d)bcmgenet_netif_start (dev); +netif_device_attach (dev); +return 0 ; out_clk_disable:
Signature · 1 line
2.17.1
PATCH 2/2 net: systemport: Protect stop from timeout
In reply to Florian FainelliA timing hazard exists when the network interface is stopped that allows a watchdog timeout to be processed by a separate core in parallel. This creates the potential for the timeout handler to wake the queues while the driver is shutting down, or access registers after their clocks have been removed.
The more common case is that the watchdog timeout will produce a warning message which doesn't lead to a crash. The chances of this are greatly increased by the fact that bcm_sysport_netif_stop stops the transmit queues which can easily precipitate a watchdog time- out because of stale trans_start data in the queues.
This commit corrects the behavior by ensuring that the watchdog timeout is disabled before enterring bcm_sysport_netif_stop. There are currently only two users of the bcm_sysport_netif_stop function:
close and suspend.
The close case already handles the issue by exiting the RUNNING state before invoking the driver close service.
The suspend case now performs the netif_device_detach to exit the PRESENT state before the call to bcm_sysport_netif_stop rather than after it.
These behaviors prevent any future scheduling of the driver timeout service during the window. The netif_tx_stop_all_queues function in bcm_sysport_netif_stop is replaced with netif_tx_disable to ensure synchronization with any transmit or timeout threads that may already be executing on other cores.
For symmetry, the netif_device_attach call upon resume is moved to after the call to bcm_sysport_netif_start. Since it wakes the transmit queues it is not necessary to invoke netif_tx_start_all_queues from bcm_sysport_netif_start so it is moved into the driver open service.
--- drivers/net/ethernet/broadcom/bcmsysport.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
drivers/net/ethernet/broadcom/bcmsysport.c +7 -8
@@ -1902,9 +1902,6 @@ static void bcm_sysport_netif_start(struct net_device *dev)intrl2_1_mask_clear (priv,0xffffffff ); elseintrl2_0_mask_clear (priv ,INTRL2_0_TDMA_MBDONE_MASK ); - -/* Last call before we start the real business */ -netif_tx_start_all_queues (dev); }static void rbuf_init (struct bcm_sysport_priv *priv)
@@ -2048,6 +2045,8 @@ static int bcm_sysport_open(struct net_device *dev)bcm_sysport_netif_start (dev); +netif_tx_start_all_queues (dev); +return 0 ; out_clear_rx_int:
@@ -2071,7 +2070,7 @@ static void bcm_sysport_netif_stop(struct net_device *dev)struct bcm_sysport_priv *priv =netdev_priv (dev);/* stop all software from updating hardware */ -netif_tx_stop_all_queues (dev); +netif_tx_disable (dev);napi_disable (&priv->napi);cancel_work_sync (&priv->dim.dim.work);phy_stop (dev->phydev);
@@ -2658,12 +2657,12 @@ static int __maybe_unused bcm_sysport_suspend(struct device *d)if (!netif_running (dev))return 0 ; +netif_device_detach (dev); +bcm_sysport_netif_stop (dev);phy_suspend (dev->phydev); -netif_device_detach (dev); -/* Disable UniMAC RX */ umac_enable_set (priv,CMD_RX_EN ,0 );
@@ -2746,8 +2745,6 @@ static int __maybe_unused bcm_sysport_resume(struct device *d) goto out_free_rx_ring; } -netif_device_attach (dev); -/* RX pipe enable */ topctrl_writel (priv,0 ,RX_FLUSH_CNTL );
@@ -2788,6 +2785,8 @@ static int __maybe_unused bcm_sysport_resume(struct device *d)bcm_sysport_netif_start (dev); +netif_device_attach (dev); +return 0 ; out_free_rx_ring:
Signature · 1 line
2.17.1
David Miller
maintainerFrom: Florian Fainelli <[email protected]>
Date: Thu, 1 Nov 2018 15:55:36 -0700
Quoted 3 lines
This patch series fixes occasional transmit timeout around the time the system goes into suspend. GENET and SYSTEMPORT have nearly the same logic in that regard and were both affected in the same way.
Series applied.
Quoted 1 line
Please queue up for stable, thanks!
Queued up.