FAILED: patch "[PATCH] ice: prevent ice_open and ice_stop during reset" failed to apply to 4.19-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 4.19-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From e95fc8573e07c5e4825df4650fd8b8c93fad27a7 Mon Sep 17 00:00:00 2001
From: Krzysztof Goreczny <[email protected]>
Date: Fri, 26 Feb 2021 13:19:26 -0800
Subject: [PATCH] ice: prevent ice_open and ice_stop during reset
There is a possibility of race between ice_open or ice_stop calls performed by OS and reset handling routine both trying to modify VSI resources. Observed scenarios:
- reset handler deallocates memory in ice_vsi_free_arrays and ice_open tries to access it in ice_vsi_cfg_txq leading to driver crash
- reset handler deallocates memory in ice_vsi_free_arrays and ice_close tries to access it in ice_down leading to driver crash
- reset handler clears port scheduler topology and sets port state to ICE_SCHED_PORT_STATE_INIT leading to ice_ena_vsi_txq fail in ice_open
To prevent this additional checks in ice_open and ice_stop are introduced to make sure that OS is not allowed to alter VSI config while reset is in progress.
drivers/net/ethernet/intel/ice/ice.h +1 -0
@@ -642,6 +642,7 @@ int ice_fdir_create_dflt_rules(struct ice_pf *pf);int ice_aq_wait_for_event (struct ice_pf *pf,u16 opcode,unsigned long timeout,struct ice_rq_event_info *event);int ice_open (struct net_device *netdev); +int ice_open_internal (struct net_device *netdev);int ice_stop (struct net_device *netdev);void ice_service_task_schedule (struct ice_pf *pf);
drivers/net/ethernet/intel/ice/ice_lib.c +2 -2
@@ -2620,7 +2620,7 @@ int ice_ena_vsi(struct ice_vsi *vsi, bool locked)if (!locked)rtnl_lock (); - err =ice_open (vsi->netdev); + err =ice_open_internal (vsi->netdev);if (!locked)rtnl_unlock ();
@@ -2649,7 +2649,7 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked)if (!locked)rtnl_lock (); -ice_stop (vsi->netdev); +ice_vsi_close (vsi);if (!locked)rtnl_unlock ();
drivers/net/ethernet/intel/ice/ice_main.c +28 -0
@@ -6632,6 +6632,28 @@ static void ice_tx_timeout(struct net_device *netdev, unsigned int txqueue)* Returns 0 on success, negative value on failure */ int ice_open (struct net_device *netdev) +{ +struct ice_netdev_priv *np =netdev_priv (netdev); +struct ice_pf *pf = np->vsi->back; + +if (ice_is_reset_in_progress (pf->state)) { +netdev_err (netdev,"can't open net device while reset is in progress" ); +return -EBUSY ; + } + +return ice_open_internal (netdev); +} + +/** +* ice_open_internal - Called when a network interface becomes active +* @netdev: network interface device structure +* +* Internal ice_open implementation. Should not be used directly except for ice_open and reset +* handling routine +* +* Returns 0 on success, negative value on failure +*/ +int ice_open_internal (struct net_device *netdev) {struct ice_netdev_priv *np =netdev_priv (netdev);struct ice_vsi *vsi = np->vsi;
@@ -6712,6 +6734,12 @@ int ice_stop(struct net_device *netdev) {struct ice_netdev_priv *np =netdev_priv (netdev);struct ice_vsi *vsi = np->vsi; +struct ice_pf *pf = vsi->back; + +if (ice_is_reset_in_progress (pf->state)) { +netdev_err (netdev,"can't stop net device while reset is in progress" ); +return -EBUSY ; + }ice_vsi_close (vsi);