mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Simon Horman <horms@kernel.org>
To: han.junyang@zte.com.cn
Cc: Simon Horman <horms@kernel.org>,
	andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com, linux-kernel@vger.kernel.org,
	netdev@vger.kernel.org, ran.ming@zte.com.cn,
	han.chengfei@zte.com.cn, zhang.yanze@zte.com.cn
Subject: Re: [PATCH net-next v2 2/3] dinghai: add MSI-X interrupt pools
Date: Mon, 14 Sep 2026 08:20:45 +0100	[thread overview]
Message-ID: <20260914072045.232985-1-horms@kernel.org> (raw)
In-Reply-To: <20260911120217310cUI5W_KC5mMJa9d1oIEnh@zte.com.cn>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev/#/patchset/20260911115929435mXJzcTF08xlUAdjnT8qqm@zte.com.cn?part=2
---
dinghai: add MSI-X interrupt pools

This commit introduces a driver for ZTE DingHai Ethernet, specifically
allocating the fixed MSI-X vector layout of the device. It manages the
vectors in per-purpose pools for async event queues and vq queue pairs.

[Severity: Medium]
The commit message states:

  manage the vectors in per-purpose pools: one pool for the async event queues
  and one for the vq queue pairs, with a range reserved for RDMA in between.

Was the VQ pool allocation omitted from this patch by mistake? Looking at
zxdh_pf_irq_pools_init(), only the async pool is allocated.

> diff --git a/drivers/net/ethernet/zte/dinghai/zxdh_irq.c b/drivers/net/ethernet/zte/dinghai/zxdh_irq.c
> new file mode 100644
> index 0000000000000..437344329c7e8
> --- /dev/null
> +++ b/drivers/net/ethernet/zte/dinghai/zxdh_irq.c
[ ... ]
> +static void zxdh_irq_release(struct kref *kref)
> +{
> +	struct zxdh_irq *irq = container_of(kref, struct zxdh_irq, refcount);
> +	struct zxdh_irq_pool *pool = irq->pool;
> +
> +	lockdep_assert_held(&pool->lock);
> +	xa_erase(&pool->irqs, irq->index);
> +	/* free_irq() requires the affinity hint to be cleared before it is
> +	 * called; the asymmetry with the set path in zxdh_irq_alloc() is
> +	 * intentional.
> +	 */
> +	irq_update_affinity_hint(irq->irqn, NULL);
> +	free_cpumask_var(irq->mask);
> +	free_irq(irq->irqn, irq);
> +	kfree(irq);
> +}

[Severity: High]
Does this code leak the logical counters in pool->irqs_per_cpu?

When an IRQ is allocated, zxdh_irq_pool_request_irq() increments
pool->irqs_per_cpu[cpu]. It seems zxdh_irq_release() misses a call to
zxdh_cpu_put(), which will permanently skew load balancing and trigger the
WARN_ON(pool->irqs_per_cpu[cpu]) during zxdh_irq_pool_free().

[ ... ]
> +static struct zxdh_irq *zxdh_irq_alloc(struct zxdh_irq_pool *pool, int vecidx,
> +				       const struct cpumask *affinity)
> +{
> +	struct zxdh_core_dev *zxdh_dev = pool->dev;
> +	struct zxdh_irq *irq;
> +	int err;
> +	int cpu;
> +
> +	irq = kzalloc_obj(*irq, GFP_KERNEL);
> +	if (!irq)
> +		return ERR_PTR(-ENOMEM);
> +
> +	irq->pool = pool;
> +	irq->irqn = pci_irq_vector(zxdh_dev->pdev, vecidx);
> +	if (irq->irqn < 0) {
> +		err = irq->irqn;
> +		goto err_irqn;
> +	}
> +
> +	ATOMIC_INIT_NOTIFIER_HEAD(&irq->nh);
> +	snprintf(irq->name, ZXDH_MAX_IRQ_NAME, "async_%d@pci:%s", vecidx,
> +		 pci_name(zxdh_dev->pdev));

[Severity: Low]
Is this hardcoded name prefix intentional?

This ignores the configured pool->name. If this generic library is reused for
other pools, such as the VQ pool, they will all show up as "async_" in
/proc/interrupts.

> +
> +	err = request_irq(irq->irqn, zxdh_irq_int_handler, 0, irq->name, irq);
> +	if (err) {
> +		dev_err(zxdh_dev->device, "request_irq failed: %d\n", err);
> +		goto err_irqn;
> +	}
> +
> +	if (!zalloc_cpumask_var(&irq->mask, GFP_KERNEL)) {
> +		dev_err(zxdh_dev->device, "zalloc_cpumask_var failed\n");
> +		err = -ENOMEM;
> +		goto err_cpumask;
> +	}
> +
> +	if (affinity) {
> +		cpumask_copy(irq->mask, affinity);
> +	} else {
> +		/* No preference requested; spread over all online CPUs. */
> +		for_each_online_cpu(cpu)
> +			cpumask_set_cpu(cpu, irq->mask);
> +	}
> +	irq_update_affinity_hint(irq->irqn, irq->mask);

[Severity: Medium]
Will this actually configure the SMP hardware routing for the IRQ?

The driver uses irq_update_affinity_hint() which only sets a userspace hint
via procfs. Should this be irq_set_affinity_and_hint() instead to actually
enforce the intended hardware IRQ load balancing?

[ ... ]
> +static struct zxdh_irq *zxdh_irq_pool_request_irq(struct zxdh_irq_pool *pool,
> +						  const struct cpumask *req_mask)
> +{
> +	const struct cpumask *affinity = req_mask;
> +	cpumask_var_t auto_mask;
> +	struct zxdh_irq *irq;
> +	u32 irq_index;
> +	int err;
> +
> +	if (!zalloc_cpumask_var(&auto_mask, GFP_KERNEL))
> +		return ERR_PTR(-ENOMEM);
> +
> +	err = xa_alloc(&pool->irqs, &irq_index, NULL, pool->xa_num_irqs,
> +		       GFP_KERNEL);

[Severity: High]
Will this xa_alloc() call fail unconditionally?

The XArray API strictly forbids NULL entries for allocation because NULL
represents an unallocated slot. Passing NULL as the entry triggers a
WARN_ON_ONCE(!entry) and returns -EINVAL.

[ ... ]
> +void zxdh_irq_pool_free(struct zxdh_irq_pool *pool)
> +{
> +	struct zxdh_irq *irq;
> +	unsigned long index;
> +	u32 cpu;
> +
> +	/* On a fast teardown the table may still hold IRQs; release
> +	 * whatever is left.
> +	 */
> +	mutex_lock(&pool->lock);
> +	xa_for_each(&pool->irqs, index, irq)
> +		zxdh_irq_release(&irq->refcount);
> +	mutex_unlock(&pool->lock);

[Severity: High]
Can this manual iteration bypass the reference counting and cause a
use-after-free?

If zxdh_irq_pool_free() executes while active consumers still hold an IRQ
reference during a fast teardown, it will forcefully execute
zxdh_irq_release() on the irq object. When the consumer eventually calls
zxdh_irq_put() and accesses the freed irq and its freed pool->lock, will
this trigger a use-after-free?

[ ... ]

  reply	other threads:[~2026-09-14  7:20 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-11  3:56 [PATCH net-next v2 0/3] dinghai: firmware handshake, MSI-X pools and async event queues han.junyang
2026-09-11  3:59 ` [PATCH net-next v2 1/3] dinghai: add firmware version check and RISC-V readiness polling han.junyang
2026-09-14  7:20   ` Simon Horman
2026-09-11  4:02 ` [PATCH net-next v2 2/3] dinghai: add MSI-X interrupt pools han.junyang
2026-09-14  7:20   ` Simon Horman [this message]
2026-09-11  4:05 ` [PATCH net-next v2 3/3] dinghai: add async event queue for firmware notifications han.junyang
2026-09-14  7:20   ` Simon Horman

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=20260914072045.232985-1-horms@kernel.org \
    --to=horms@kernel.org \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=han.chengfei@zte.com.cn \
    --cc=han.junyang@zte.com.cn \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=ran.ming@zte.com.cn \
    --cc=zhang.yanze@zte.com.cn \
    /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

all inboxes | Powered by JetHome®