From: sashiko-bot@kernel.org
To: "Petr Oros" <poros@redhat.com>, intel-wired-lan@lists.osuosl.org
Subject: Re: [PATCH iwl-net v3 2/4] ice: avoid RTNL deadlock when notifying the RDMA auxiliary driver
Date: Fri, 13 Nov 2026 16:46:18 +0000 [thread overview]
Message-ID: <sashiko-outbox-213224@kernel.org> (raw)
In-Reply-To: <20261113161453.1234851-3-poros@redhat.com>
Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [High] ice: inconsistent QoS state on error path in ice_pf_dcb_cfg()
- [Medium] ice: unrolled DCB state and zeroed local_dcbx_cfg when
ice_pf_dcb_cfg() fails
- [Medium] ice: read of pf->cdev_info before adev_mutex in
ice_aux_dev_trylock()
--
commit 5ebebfa9f362bf112076cd4d87281d6a453d0c5c
Author: Petr Oros <poros@redhat.com>
ice: avoid RTNL deadlock when notifying the RDMA auxiliary driver
This commit replaces blocking device_lock() acquisitions when sending events
to the RDMA auxiliary driver with ice_aux_dev_trylock() to prevent an ABBA
deadlock between rtnl_lock and the auxiliary device lock.
> diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
> index 5355519726df9..dba74d940d25b 100644
> --- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
> +++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
[ ... ]
> @@ -422,16 +429,26 @@ int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)
> goto free_cfg;
> }
>
> - set_bit(IIDC_RDMA_EVENT_BEFORE_TC_CHANGE, event->type);
> - ice_send_event_to_aux(pf, event);
> - kfree(event);
> -
> /* avoid race conditions by holding the lock while disabling and
> * re-enabling the VSI
> */
> if (!locked)
> rtnl_lock();
>
> + if (!ice_dcb_tc_contig(new_cfg->etscfg.prio_table)) {
> + ret = ice_dcb_noncontig_cfg(pf);
> + goto unlock_rtnl;
> + }
> +
> + if (!ice_aux_dev_trylock(pf)) {
> + assign_bit(ICE_FLAG_DCB_ENA, pf->flags, dcb_ena);
> + ret = -EBUSY;
> + goto unlock_rtnl;
> + }
[Severity: Medium]
Does this leave local_dcbx_cfg zeroed and ICE_FLAG_DCB_ENA cleared when
ice_aux_dev_trylock() fails with -EBUSY?
When new_cfg has non-contiguous traffic classes, ice_pf_dcb_cfg() clears
ICE_FLAG_DCB_ENA at the start of the function and calls
ice_dcb_noncontig_cfg() -> ice_dcb_sw_dflt_cfg(), which zeroes
pi->qos_cfg.local_dcbx_cfg via memset() before calling the nested
ice_pf_dcb_cfg():
drivers/net/ethernet/intel/ice/ice_dcb_lib.c:ice_dcb_sw_dflt_cfg() {
...
memset(&pi->qos_cfg.local_dcbx_cfg, 0, sizeof(*dcbcfg));
...
ret = ice_pf_dcb_cfg(pf, dcbcfg, locked);
}
If the nested ice_pf_dcb_cfg() then hits contention in ice_aux_dev_trylock()
and returns -EBUSY, its dcb_ena is already false and local_dcbx_cfg is
already zeroed, and the outer ice_pf_dcb_cfg() jumps straight to unlock_rtnl
without restoring curr_cfg from old_cfg or ICE_FLAG_DCB_ENA from its saved
dcb_ena. Direct calls to ice_dcb_sw_dflt_cfg() and ice_dcb_init_cfg()
similarly zero local_dcbx_cfg before calling ice_pf_dcb_cfg() without
restoring it on -EBUSY.
In addition, for multi-TC configs, ice_pf_dcb_cfg() calls
ice_dcb_prep_multi_tc() (tearing down the devlink rate tree) before
ice_aux_dev_trylock(), and ice_dcbnl_setapp() updates the dcbnl app table,
new_cfg->dscp_mapped, new_cfg->app[], and hardware PFC mode before calling
ice_pf_dcb_cfg() without rolling them back on -EBUSY.
> @@ -458,13 +475,25 @@ int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)
> goto out;
> }
>
> - ice_pf_dcb_recfg(pf, false);
> + ice_pf_dcb_recfg(pf, true);
>
> out:
> + cdev = pf->cdev_info;
> + if (cdev) {
> + privd = cdev->iidc_priv;
> + ice_setup_dcb_qos_info(pf, &privd->qos_info);
> + }
> + clear_bit(IIDC_RDMA_EVENT_BEFORE_TC_CHANGE, event->type);
> + set_bit(IIDC_RDMA_EVENT_AFTER_TC_CHANGE, event->type);
> + ice_send_event_to_aux(pf, event);
> + ice_aux_dev_unlock(pf);
[Severity: High]
If ice_query_port_ets() fails and jumps to out, does populating
privd->qos_info and sending IIDC_RDMA_EVENT_AFTER_TC_CHANGE transition
active RDMA queue pairs to the error state?
When ice_query_port_ets() fails, curr_cfg and PRTDCB_TUP2TC already hold
new_cfg, but ice_pf_dcb_recfg() is skipped so vsi->tc_cfg.ena_tc and the VSI
scheduler nodes still only have the old traffic classes. Running
ice_setup_dcb_qos_info() at out populates privd->qos_info with the unapplied
traffic classes, so when irdma handles IIDC_RDMA_EVENT_AFTER_TC_CHANGE and
calls ice_add_rdma_qset() to resume its QPs on those TCs, ice_cfg_vsi_rdma()
and ice_ena_vsi_rdma_qset() fail with -EINVAL and irdma moves the QPs to
IB_QPS_ERR. The ice_query_port_ets() error path also leaves curr_cfg and
ICE_FLAG_DCB_ENA unrolled.
> diff --git a/drivers/net/ethernet/intel/ice/ice_idc.c b/drivers/net/ethernet/intel/ice/ice_idc.c
> index 09dfcffeb5df9..9e8bff128e0e6 100644
> --- a/drivers/net/ethernet/intel/ice/ice_idc.c
> +++ b/drivers/net/ethernet/intel/ice/ice_idc.c
> @@ -30,34 +30,62 @@ ice_get_auxiliary_drv(struct iidc_rdma_core_dev_info *cdev)
> struct iidc_rdma_core_auxiliary_drv, adrv.driver);
> }
>
> +/**
> + * ice_aux_dev_trylock - take the locks that guard the RDMA AUX driver
> + * @pf: pointer to PF struct
> + *
> + * Return: true when the locks are held, false when the auxiliary device lock
> + * was contended and nothing is held.
> + */
> +bool ice_aux_dev_trylock(struct ice_pf *pf)
> +{
> + struct iidc_rdma_core_dev_info *cdev = pf->cdev_info;
> +
> + mutex_lock(&pf->adev_mutex);
> + if (cdev && cdev->adev && !device_trylock(&cdev->adev->dev)) {
> + mutex_unlock(&pf->adev_mutex);
> + return false;
> + }
> +
> + return true;
> +}
> +
> +/**
> + * ice_aux_dev_unlock - release the locks taken by ice_aux_dev_trylock()
> + * @pf: pointer to PF struct
> + */
> +void ice_aux_dev_unlock(struct ice_pf *pf)
> +{
> + struct iidc_rdma_core_dev_info *cdev = pf->cdev_info;
> +
> + if (cdev && cdev->adev)
> + device_unlock(&cdev->adev->dev);
> + mutex_unlock(&pf->adev_mutex);
> +}
[Severity: Medium]
Can reading pf->cdev_info before acquiring pf->adev_mutex in
ice_aux_dev_trylock() cause an unbalanced device_unlock(&cdev->adev->dev) or
a use-after-free?
In ice_load(), the netdev and its dcbnl_ops are registered before
ice_init_rdma() allocates pf->cdev_info and ice_rdma_finalize_setup() ->
ice_plug_aux_dev() sets cdev->adev under pf->adev_mutex:
CPU0 CPU1
ice_dcbnl_setets() ice_load()
ice_pf_dcb_cfg() ...
ice_aux_dev_trylock() ice_init_rdma()
cdev = pf->cdev_info; /* NULL */ pf->cdev_info = kzalloc(...);
ice_rdma_finalize_setup()
ice_plug_aux_dev()
mutex_lock(&pf->adev_mutex)
cdev->adev = adev;
mutex_unlock(&pf->adev_mutex)
mutex_lock(&pf->adev_mutex)
/* cdev is NULL, skips trylock */
ice_send_event_to_aux()
ice_aux_dev_unlock()
cdev = pf->cdev_info;
device_unlock(&cdev->adev->dev) <-- unlocks unheld mutex
Conversely, if ice_aux_dev_trylock() samples a non-NULL pf->cdev_info while
racing with ice_unload() or ice_suspend() calling ice_deinit_rdma(),
dereferencing cdev->adev after mutex_lock(&pf->adev_mutex) reads freed
memory. Reading pf->cdev_info after mutex_lock(&pf->adev_mutex) (and
protecting pf->cdev_info teardown under pf->adev_mutex) would avoid both.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261113161453.1234851-1-poros@redhat.com?part=2
next prev parent reply other threads:[~2026-11-13 16:46 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 16:14 [PATCH iwl-net v3 0/4] ice: fix RTNL vs auxiliary device lock inversion Petr Oros
2026-11-13 16:14 ` [PATCH iwl-net v3 1/4] ice: check the auxiliary device pointer under adev_mutex Petr Oros
2026-11-13 16:14 ` [PATCH iwl-net v3 2/4] ice: avoid RTNL deadlock when notifying the RDMA auxiliary driver Petr Oros
2026-11-13 16:46 ` sashiko-bot [this message]
2026-11-13 16:14 ` [PATCH iwl-net v3 3/4] ice: do not block on the aux device lock in ethtool set_channels Petr Oros
2026-11-13 16:14 ` [PATCH iwl-net v3 4/4] ice: do not block on the aux device lock in ndo_setup_tc Petr Oros
2026-11-13 16:31 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-213224@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=intel-wired-lan@lists.osuosl.org \
--cc=poros@redhat.com \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox