Commit 248401cb authored by Dave Ertman's avatar Dave Ertman Committed by Jakub Kicinski

ice: avoid bonding causing auxiliary plug/unplug under RTNL lock

RDMA is not supported in ice on a PF that has been added to a bonded
interface. To enforce this, when an interface enters a bond, we unplug
the auxiliary device that supports RDMA functionality.  This unplug
currently happens in the context of handling the netdev bonding event.
This event is sent to the ice driver under RTNL context.  This is causing
a deadlock where the RDMA driver is waiting for the RTNL lock to complete
the removal.

Defer the unplugging/re-plugging of the auxiliary device to the service
task so that it is not performed under the RTNL lock context.

Cc: stable@vger.kernel.org # 6.1.x
Reported-by: default avatarJaroslav Pulchart <jaroslav.pulchart@gooddata.com>
Link: https://lore.kernel.org/netdev/CAK8fFZ6A_Gphw_3-QMGKEFQk=sfCw1Qmq0TVZK3rtAi7vb621A@mail.gmail.com/
Fixes: 5cb1ebdb ("ice: Fix race condition during interface enslave")
Fixes: 4eace75e ("RDMA/irdma: Report the correct link speed")
Signed-off-by: default avatarDave Ertman <david.m.ertman@intel.com>
Tested-by: Arpana Arland <arpanax.arland@intel.com> (A Contingent worker at Intel)
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
Reviewed-by: default avatarLeon Romanovsky <leonro@nvidia.com>
Link: https://lore.kernel.org/r/20230310194833.3074601-1-anthony.l.nguyen@intel.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 28e8cabe
...@@ -509,6 +509,7 @@ enum ice_pf_flags { ...@@ -509,6 +509,7 @@ enum ice_pf_flags {
ICE_FLAG_VF_VLAN_PRUNING, ICE_FLAG_VF_VLAN_PRUNING,
ICE_FLAG_LINK_LENIENT_MODE_ENA, ICE_FLAG_LINK_LENIENT_MODE_ENA,
ICE_FLAG_PLUG_AUX_DEV, ICE_FLAG_PLUG_AUX_DEV,
ICE_FLAG_UNPLUG_AUX_DEV,
ICE_FLAG_MTU_CHANGED, ICE_FLAG_MTU_CHANGED,
ICE_FLAG_GNSS, /* GNSS successfully initialized */ ICE_FLAG_GNSS, /* GNSS successfully initialized */
ICE_PF_FLAGS_NBITS /* must be last */ ICE_PF_FLAGS_NBITS /* must be last */
...@@ -955,16 +956,11 @@ static inline void ice_set_rdma_cap(struct ice_pf *pf) ...@@ -955,16 +956,11 @@ static inline void ice_set_rdma_cap(struct ice_pf *pf)
*/ */
static inline void ice_clear_rdma_cap(struct ice_pf *pf) static inline void ice_clear_rdma_cap(struct ice_pf *pf)
{ {
/* We can directly unplug aux device here only if the flag bit /* defer unplug to service task to avoid RTNL lock and
* ICE_FLAG_PLUG_AUX_DEV is not set because ice_unplug_aux_dev() * clear PLUG bit so that pending plugs don't interfere
* could race with ice_plug_aux_dev() called from
* ice_service_task(). In this case we only clear that bit now and
* aux device will be unplugged later once ice_plug_aux_device()
* called from ice_service_task() finishes (see ice_service_task()).
*/ */
if (!test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags);
ice_unplug_aux_dev(pf); set_bit(ICE_FLAG_UNPLUG_AUX_DEV, pf->flags);
clear_bit(ICE_FLAG_RDMA_ENA, pf->flags); clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);
} }
#endif /* _ICE_H_ */ #endif /* _ICE_H_ */
...@@ -2316,18 +2316,15 @@ static void ice_service_task(struct work_struct *work) ...@@ -2316,18 +2316,15 @@ static void ice_service_task(struct work_struct *work)
} }
} }
if (test_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) { /* unplug aux dev per request, if an unplug request came in
/* Plug aux device per request */ * while processing a plug request, this will handle it
ice_plug_aux_dev(pf); */
if (test_and_clear_bit(ICE_FLAG_UNPLUG_AUX_DEV, pf->flags))
ice_unplug_aux_dev(pf);
/* Mark plugging as done but check whether unplug was /* Plug aux device per request */
* requested during ice_plug_aux_dev() call if (test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags))
* (e.g. from ice_clear_rdma_cap()) and if so then ice_plug_aux_dev(pf);
* plug aux device.
*/
if (!test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags))
ice_unplug_aux_dev(pf);
}
if (test_and_clear_bit(ICE_FLAG_MTU_CHANGED, pf->flags)) { if (test_and_clear_bit(ICE_FLAG_MTU_CHANGED, pf->flags)) {
struct iidc_event *event; struct iidc_event *event;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment