> -----Original Message-----
> From: Petr Oros <[email protected]>
> Sent: Monday, October 19, 2026 8:53 AM
> To: [email protected]
> Cc: Oros, Petr <[email protected]>; Nguyen, Anthony L
> <[email protected]>; Kitszel, Przemyslaw
> <[email protected]>; Andrew Lunn <[email protected]>;
> David S . Miller <[email protected]>; Eric Dumazet
> <[email protected]>; Jakub Kicinski <[email protected]>; Paolo Abeni
> <[email protected]>; Ertman, David M <[email protected]>; Shiraz
> Saleem <[email protected]>; Leon Romanovsky <[email protected]>;
> Maziarz, Kamil <[email protected]>; Rafal Rogalski
> <[email protected]>; Loktionov, Aleksandr
> <[email protected]>; Schmidt, Michal <[email protected]>;
> [email protected]; [email protected]; linux-
> [email protected]; [email protected]; Sebastian Andrzej
> Siewior <[email protected]>; Clark Williams <[email protected]>;
> Steven Rostedt <[email protected]>; Mateusz Palczewski
> <[email protected]>; [email protected]
> 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: [email protected]
> Signed-off-by: Petr Oros <[email protected]>
> ---
>  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.c
> b/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, struct
> ice_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, struct
> ice_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?


> +             goto free_cfg;
> +     }
>       kfree(event);
> 
>       /* avoid race conditions by holding the lock while disabling and
> diff --git a/drivers/net/ethernet/intel/ice/ice_idc.c
> b/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

...

>                       kfree(event);
>               }
>       }
> --
> 2.56.0

Reply via email to