Re: [PATCH iwl-net 1/3] ice: avoid RTNL deadlock when notifying the RDMA auxiliary driver
flat view
From: Petr Oros <hidden>
Date: 2026-10-22 10:40:27
Also in:
intel-wired-lan, linux-rdma, linux-rt-devel, lkml, stable
On 10/21/26 1:20 PM, Loktionov, Aleksandr wrote:
quoted
-----Original Message----- From: Petr Oros <redacted> Sent: Monday, October 19, 2026 8:53 AM To: netdev@vger.kernel.org Cc: Oros, Petr <redacted>; Nguyen, Anthony L [off-list ref]; Kitszel, Przemyslaw [off-list ref]; Andrew Lunn [off-list ref]; David S . Miller [off-list ref]; Eric Dumazet [off-list ref]; Jakub Kicinski [off-list ref]; Paolo Abeni [off-list ref]; Ertman, David M [off-list ref]; Shiraz Saleem [off-list ref]; Leon Romanovsky [off-list ref]; Maziarz, Kamil [off-list ref]; Rafal Rogalski [off-list ref]; Loktionov, Aleksandr [off-list ref]; Schmidt, Michal [off-list ref]; linux-rdma@vger.kernel.org; intel-wired-lan@lists.osuosl.org; linux- kernel@vger.kernel.org; stable@vger.kernel.org; Sebastian Andrzej Siewior [off-list ref]; Clark Williams [off-list ref]; Steven Rostedt [off-list ref]; Mateusz Palczewski [off-list ref]; linux-rt-devel@lists.linux.dev Subject: [PATCH iwl-net 1/3] ice: avoid RTNL deadlock when notifying the RDMA auxiliary driver ice_send_event_to_aux() blocks on the auxiliary device lock, and the dcbnl callers reach it with the RTNL lock held. The RDMA auxiliary probe takes the two in the opposite order, because __driver_attach() holds the auxiliary device lock across ib_register_device(), which needs the RTNL lock: systemd-udevd state:D really_probe <- holds device_lock(&adev->dev) icrdma_probe irdma_ib_register_device ib_register_device setup_device irdma_roce_port_immutable ib_query_port irdma_query_port ib_get_eth_speed <- blocks on rtnl_lock() lldpad state:D rtnetlink_rcv_msg <- holds rtnl_lock() dcb_doit dcbnl_ieee_set ice_dcbnl_setets ice_pf_dcb_cfg ice_send_event_to_aux <- blocks on device_lock(&adev->dev) Everything else that needs the RTNL lock piles up behind lldpad and the boot never completes. The probe side cannot be changed, so use device_trylock() and report whether the event reached the driver. IIDC_RDMA_EVENT_BEFORE_TC_CHANGE has to arrive before the traffic classes change, so ice_pf_dcb_cfg() refuses the request with -EBUSY rather than run it behind the RDMA driver's back. The critical error and MTU change events are sent from the service task, which consumes their pending bits before sending, so those are re-armed instead. AFTER_TC_CHANGE keeps its fire and forget behaviour, it can be neither refused, the hardware has already changed, nor deferred, every lock that would serialise a deferred delivery against the dcbnl callers forms another cycle. Fixes: 348048e724a0 ("ice: Implement iidc operations") Cc: stable@vger.kernel.org Signed-off-by: Petr Oros <redacted> --- drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 9 ++++++++- drivers/net/ethernet/intel/ice/ice_idc.c | 20 ++++++++++++++++---- drivers/net/ethernet/intel/ice/ice_idc_int.h | 2 +- drivers/net/ethernet/intel/ice/ice_main.c | 16 ++++++++++++---- 4 files changed, 37 insertions(+), 10 deletions(-)diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.cb/drivers/net/ethernet/intel/ice/ice_dcb_lib.c index 0bc6dd37568792..2022b46c990cb2 100644--- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c@@ -355,8 +355,10 @@ int ice_pf_dcb_cfg(struct ice_pf *pf, structice_dcbx_cfg *new_cfg, bool locked) struct iidc_rdma_event *event; int ret = ICE_DCB_NO_HW_CHG; struct ice_vsi *pf_vsi; + bool dcb_ena; curr_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg; + dcb_ena = test_bit(ICE_FLAG_DCB_ENA, pf->flags); /* FW does not care if change happened */ if (!pf->hw.port_info->qos_cfg.is_sw_lldp)@@ -406,7 +408,12 @@ int ice_pf_dcb_cfg(struct ice_pf *pf, structice_dcbx_cfg *new_cfg, bool locked) } set_bit(IIDC_RDMA_EVENT_BEFORE_TC_CHANGE, event->type); - ice_send_event_to_aux(pf, event); + if (!ice_send_event_to_aux(pf, event)) { + assign_bit(ICE_FLAG_DCB_ENA, pf->flags, dcb_ena); + kfree(event); + ret = -EBUSY;-EBUSY doesn't match to any ICE_DCB_* constant, are you sure you tested this case? It looks like it will be processed like ICE_DCB_NO_HW_CHG i.e. no change needed, isn't it?
The negative return takes the same path as the existing -EBUSY for the custom Tx scheduler. ice_dcbnl_setets() and setpfc() pass it to dcbnl unchanged, only ICE_DCB_NO_HW_CHG is mapped to zero. setapp() and cee_set_all() mask every error, that is pre-existing and also hides -ENOMEM and the AQ errors. I have noted this in the v2 message.
quoted
+ goto free_cfg; + } kfree(event); /* avoid race conditions by holding the lock while disabling anddiff --git a/drivers/net/ethernet/intel/ice/ice_idc.cb/drivers/net/ethernet/intel/ice/ice_idc.c index 102d63c3018b1f..7fd35ce966ea65 100644--- a/drivers/net/ethernet/intel/ice/ice_idc.c +++ b/drivers/net/ethernet/intel/ice/ice_idc.c@@ -34,30 +34,42 @@ ice_get_auxiliary_drv(struct iidc_rdma_core_dev_info*cdev) * ice_send_event_to_aux - send event to RDMA AUX driver * @pf: pointer to PF struct * @event: event struct...quoted
kfree(event); } } -- 2.56.0