* [PATCH] libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries()
@ 2026-10-19 13:22 Haoran Wang
2026-10-19 13:29 ` netdev-bot+sinfo
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Haoran Wang @ 2026-10-19 13:22 UTC (permalink / raw)
To: Varun Prakash
Cc: Sebastian Andrzej Siewior, Clark Williams, Steven Rostedt,
linux-rt-devel, linux-scsi, netdev, linux-kernel, haoranwangsec
ppm_get_cpu_entries() disables preemption with get_cpu(), reads the
current CPU's pool with per_cpu_ptr(), then acquires spin_lock_bh()
while preemption is still disabled, and finally put_cpu().
cpu = get_cpu();
pool = per_cpu_ptr(ppm->pool, cpu);
spin_lock_bh(&pool->lock);
put_cpu();
On PREEMPT_RT kernels spin_lock_bh() becomes a sleeping lock
(rt_spin_lock). get_cpu() raises preempt_count, so acquiring the
lock right after sleeps with preempt_count still positive. Sleeping
in that state is the scheduling-while-atomic case, which under
CONFIG_DEBUG_ATOMIC_SLEEP reports a BUG and, if the lock is contended,
deadlocks on the spot. The trigger path is any iSCSI offload I/O
through a Chelsio NIC that reaches ppm_get_cpu_entries().
The preemption disable exists only to stabilize the per-CPU accessor,
the pool is serialized by pool->lock, not by preemption. Replace
get_cpu() + per_cpu_ptr() + put_cpu() with raw_smp_processor_id() +
raw_cpu_ptr(), which read the current CPU without disabling preemption.
On non-RT kernels spin_lock_bh() does not sleep, so the BUG does not
fire there; the defect is PREEMPT_RT-specific.
With the fix, preempt_count is 0 at spin_lock_bh(), so rt_spin_lock()'s
might_sleep() no longer triggers.
Signed-off-by: Haoran Wang <haoranwangsec@gmail.com>
---
drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c
index 2e3973a32..5f68c5d57 100644
--- a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c
+++ b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c
@@ -125,10 +125,9 @@ static int ppm_get_cpu_entries(struct cxgbi_ppm *ppm, unsigned int count,
if (!ppm->pool)
return -EINVAL;
- cpu = get_cpu();
- pool = per_cpu_ptr(ppm->pool, cpu);
+ cpu = raw_smp_processor_id();
+ pool = raw_cpu_ptr(ppm->pool);
spin_lock_bh(&pool->lock);
- put_cpu();
i = ppm_find_unused_entries(pool->bmap, ppm->pool_index_max,
pool->next, count, 0);
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH] libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() 2026-10-19 13:22 [PATCH] libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() Haoran Wang @ 2026-10-19 13:29 ` netdev-bot+sinfo 2026-10-19 13:29 ` Sebastian Andrzej Siewior ` (3 subsequent siblings) 4 siblings, 0 replies; 8+ messages in thread From: netdev-bot+sinfo @ 2026-10-19 13:29 UTC (permalink / raw) To: Haoran Wang Cc: Varun Prakash, Sebastian Andrzej Siewior, Clark Williams, Steven Rostedt, linux-rt-devel, linux-scsi, netdev, linux-kernel Hi! This is an automated message. This series looks like a fix, but its commit messages seem to be missing some information: - How the issue was discovered, e.g. hit in production, hit during development, syzbot report, manual code inspection, LLM or static analysis tool scan. - Whether the issue was actually triggered, or is only theoretical (e.g. found by code inspection). If it was triggered please include the symptoms, like the stack trace or error messages. - What hardware the change was tested on. For driver fixes please mention the device (and if relevant firmware version) used for testing, or say that the change was not tested on real hardware. Please do not repost the series just to address the above. Instead, reply to this email with the missing information, so that reviewers can take it into account. If the series needs another revision for other reasons, please include the information in the commit messages then. The evaluation is done by an LLM so it may be wrong, if you think that is the case please reply and explain. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() 2026-10-19 13:22 [PATCH] libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() Haoran Wang 2026-10-19 13:29 ` netdev-bot+sinfo @ 2026-10-19 13:29 ` Sebastian Andrzej Siewior 2026-10-20 13:22 ` sashiko-bot ` (2 subsequent siblings) 4 siblings, 0 replies; 8+ messages in thread From: Sebastian Andrzej Siewior @ 2026-10-19 13:29 UTC (permalink / raw) To: Haoran Wang Cc: Varun Prakash, Clark Williams, Steven Rostedt, linux-rt-devel, linux-scsi, netdev, linux-kernel On 2026-10-19 21:22:27 [+0800], Haoran Wang wrote: > diff --git a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c > index 2e3973a32..5f68c5d57 100644 > --- a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c > +++ b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c > @@ -125,10 +125,9 @@ static int ppm_get_cpu_entries(struct cxgbi_ppm *ppm, unsigned int count, > if (!ppm->pool) > return -EINVAL; > > - cpu = get_cpu(); > - pool = per_cpu_ptr(ppm->pool, cpu); > + cpu = raw_smp_processor_id(); > + pool = raw_cpu_ptr(ppm->pool); cpu needs too be obtained after the lock has been acquired. Please also explain why it is okay to obtain pool belonging to CPU1 on CPU0. > spin_lock_bh(&pool->lock); > - put_cpu(); > > i = ppm_find_unused_entries(pool->bmap, ppm->pool_index_max, > pool->next, count, 0); Sebastian ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() 2026-10-19 13:22 [PATCH] libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() Haoran Wang 2026-10-19 13:29 ` netdev-bot+sinfo 2026-10-19 13:29 ` Sebastian Andrzej Siewior @ 2026-10-20 13:22 ` sashiko-bot 2026-10-22 7:25 ` netdev-bot+sashiko [not found] ` <CANZ3JQQrrntu0TefPZC79pKSmsOfwAngRJyuaVm81DYaJNFHFQ@mail.gmail.com> 4 siblings, 0 replies; 8+ messages in thread From: sashiko-bot @ 2026-10-20 13:22 UTC (permalink / raw) To: Haoran Wang; +Cc: linux-rt-devel, linux-scsi, linux-kernel Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Critical] libcxgb: CPU migration between raw_smp_processor_id() and raw_cpu_ptr() -- commit 45e692c0f47c6b069f27d74df45dc3a4a6360a3d Author: Haoran Wang <haoranwangsec@gmail.com> libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() This commit replaces get_cpu(), per_cpu_ptr(), and put_cpu() in ppm_get_cpu_entries() with raw_smp_processor_id() and raw_cpu_ptr() to avoid acquiring spin_lock_bh() with preemption disabled on PREEMPT_RT kernels. > diff --git a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c > index 2e3973a32d9d1..5f68c5d5766e5 100644 > --- a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c > +++ b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c > @@ -125,10 +125,9 @@ static int ppm_get_cpu_entries(struct cxgbi_ppm *ppm, unsigned int count, > if (!ppm->pool) > return -EINVAL; > > - cpu = get_cpu(); > - pool = per_cpu_ptr(ppm->pool, cpu); > + cpu = raw_smp_processor_id(); > + pool = raw_cpu_ptr(ppm->pool); > spin_lock_bh(&pool->lock); > - put_cpu(); > > i = ppm_find_unused_entries(pool->bmap, ppm->pool_index_max, > pool->next, count, 0); [Severity: Critical] Can the task be preempted and migrated to another CPU between raw_smp_processor_id() and raw_cpu_ptr(ppm->pool)? Because preemption is enabled here, if a task in a preemptible iSCSI offload path (such as cxgbit_ddp_reserve() -> cxgbi_ppm_ppods_reserve() -> ppm_get_cpu_entries()) is migrated from CPU A to CPU B between the two calls, cpu will hold CPU A while pool will point to CPU B's per-CPU pool. ppm_get_cpu_entries() will then allocate bits in CPU B's pool->bmap, but compute the global pagepod index using CPU A's ID: drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c:ppm_get_cpu_entries() { ... i += cpu * ppm->pool_index_max; ppm_mark_entries(ppm, i, count, caller_data); return i; } Because those bits were never marked in CPU A's pool->bmap, a subsequent allocation on CPU A can hand out the same global index while it is still active, overwriting ppm->ppod_data[i] and corrupting in-flight iSCSI DDP DMA transfers. Later, when cxgbi_ppm_ppod_release() -> ppm_unmark_entries() releases the entries, it derives the pool from the global index: drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c:ppm_unmark_entries() { ... if (i < ppm->pool_rsvd) { unsigned int cpu; struct cxgbi_ppm_pool *pool; cpu = i / ppm->pool_index_max; i %= ppm->pool_index_max; pool = per_cpu_ptr(ppm->pool, cpu); spin_lock_bh(&pool->lock); bitmap_clear(pool->bmap, i, count); ... } This clears the bits in CPU A's pool->bmap while permanently leaking the bits that were set in CPU B's pool->bmap. Would keeping per_cpu_ptr(ppm->pool, cpu) after raw_smp_processor_id() avoid this mismatch by ensuring cpu and pool always refer to the same per-CPU pool even if migration occurs? ([ --- ]) -- Sashiko AI review · https://sashiko.dev/#/patchset/179241614797.5916.13928836073297916808@whr?part=1 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() 2026-10-19 13:22 [PATCH] libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() Haoran Wang ` (2 preceding siblings ...) 2026-10-20 13:22 ` sashiko-bot @ 2026-10-22 7:25 ` netdev-bot+sashiko [not found] ` <CANZ3JQQrrntu0TefPZC79pKSmsOfwAngRJyuaVm81DYaJNFHFQ@mail.gmail.com> 4 siblings, 0 replies; 8+ messages in thread From: netdev-bot+sashiko @ 2026-10-22 7:25 UTC (permalink / raw) To: haoranwangsec Cc: varun, bigeasy, clrkwllms, rostedt, linux-rt-devel, linux-scsi, netdev, linux-kernel, kuba Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider. Critical: 0 · High: 1 · Medium: 0 · Low: 1 If you believe none of the issues are legitimate, please reply to each issue of Medium severity or higher and explain why the AI is wrong. If any of them are legitimate and you plan to respin, please let patchwork know by including "pw-bot: cr" as a separate line at the end of your reply (one such reply per series is enough). - [High] The patch introduces a cpu/pool mismatch race in ppm_get_cpu_entries()… - [Low] The commit is a bug fix for a user-visible 'BUG: sleeping function called from invalid context' on PREEMPT_RT. -- libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() This patch changes ppm_get_cpu_entries(). It drops get_cpu(), per_cpu_ptr() and put_cpu() and uses raw_smp_processor_id() and raw_cpu_ptr() instead. The aim is to stop spin_lock_bh() from being taken with preemption disabled, which triggers a sleeping-in-atomic BUG on PREEMPT_RT. > Signed-off-by: Haoran Wang <haoranwangsec@gmail.com> [Severity: Low] This fixes a user-visible BUG on PREEMPT_RT, but the commit has no Fixes: tag. The get_cpu()/per_cpu_ptr()/spin_lock_bh()/put_cpu() sequence has not changed since it was added in: Fixes: 47da7e62b391 ("cxgb4: add iSCSI DDP page pod manager") Should that tag be added, possibly with a Cc: stable? > diff --git a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c > index 2e3973a32d9d..5f68c5d5766e 100644 > --- a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c > +++ b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c > @@ -125,10 +125,9 @@ static int ppm_get_cpu_entries(struct cxgbi_ppm *ppm, unsigned int count, > if (!ppm->pool) > return -EINVAL; > > - cpu = get_cpu(); > - pool = per_cpu_ptr(ppm->pool, cpu); > + cpu = raw_smp_processor_id(); > + pool = raw_cpu_ptr(ppm->pool); [Severity: High] Can cpu and pool refer to different CPUs here? The new code reads the current CPU twice, with preemption and migration both enabled. Say the task moves from CPU A to CPU B between raw_smp_processor_id() and raw_cpu_ptr(). The bit is then reserved in CPU B's bitmap under CPU B's lock, but the returned index is built from the old cpu value: drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c:ppm_get_cpu_entries() { ... i += cpu * ppm->pool_index_max; ppm_mark_entries(ppm, i, count, caller_data); ... } The index and the ppod_data[] entry now point into CPU A's slice, while bit i in CPU A's bitmap is still clear. Could a task on CPU A then get the same index, hardware page pod and ppod_data slot while the first transfer is still in flight? cxgbi_ppm_ppods_reserve() turns this index into hwidx and the DDP tag. cxgbit_ddp_reserve() and cxgbi_ddp_reserve() then program that tag into the adapter. The caller_data in ppod_data[] is also what cxgbi_parse_pdu_itt() uses later to match responses to tasks. On release, ppm_unmark_entries() gets the pool back from the index: cpu = i / ppm->pool_index_max; i %= ppm->pool_index_max; pool = per_cpu_ptr(ppm->pool, cpu); spin_lock_bh(&pool->lock); bitmap_clear(pool->bmap, i, count); That would clear the bit in CPU A's pool, which may free another transfer's live entry. The bit that was really set in CPU B's pool would never be cleared. One preemptible caller that holds no spinlock is the iSCSI target TX path: iscsit_send_r2t() cxgbit_get_r2t_ttt() cxgbit_ddp_reserve() cxgbi_ppm_ppods_reserve() ppm_get_cpu_entries() iscsit_get_r2t_from_list() drops r2t_lock before it returns, so this whole chain runs unlocked. A remote initiator can drive it simply by sending WRITE commands to a Chelsio-offloaded target. The raw_ accessors are not checked by CONFIG_DEBUG_PREEMPT, so nothing would warn. The race exists on any SMP kernel built with CONFIG_PREEMPT, PREEMPT_LAZY or PREEMPT_RT. Given that, do these parts of the commit message still hold? The preemption disable exists only to stabilize the per-CPU accessor, the pool is serialized by pool->lock, not by preemption. ...the defect is PREEMPT_RT-specific. The returned index encodes cpu, so cpu and pool still have to match even though pool->lock serializes the bitmap. Would it work to keep the saved cpu and derive the pool from it? For example: cpu = raw_smp_processor_id(); pool = per_cpu_ptr(ppm->pool, cpu); Another option would be to wrap the lookup in migrate_disable()/migrate_enable(). [ ... ] -- Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/179241614797.5916.13928836073297916808%40whr ^ permalink raw reply [flat|nested] 8+ messages in thread
[parent not found: <CANZ3JQQrrntu0TefPZC79pKSmsOfwAngRJyuaVm81DYaJNFHFQ@mail.gmail.com>]
* [PATCH v3] libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() [not found] ` <CANZ3JQQrrntu0TefPZC79pKSmsOfwAngRJyuaVm81DYaJNFHFQ@mail.gmail.com> @ 2026-11-09 10:07 ` Haoran Wang 2026-11-09 10:11 ` netdev-bot+sinfo 2026-11-09 20:03 ` David Laight 0 siblings, 2 replies; 8+ messages in thread From: Haoran Wang @ 2026-11-09 10:07 UTC (permalink / raw) To: Sebastian Andrzej Siewior Cc: netdev, linux-kernel, linux-rt-devel, andrew+netdev, davem, edumazet, kuba, pabeni, rostedt, haoranwangsec ppm_get_cpu_entries() disables preemption with get_cpu(), reads the current CPU's pool with per_cpu_ptr(), then acquires the pool's spin_lock_bh() while preemption is still disabled, and finally put_cpu(). On PREEMPT_RT kernels spin_lock_bh() becomes a sleeping lock (rt_spin_lock), so the task may sleep with preempt_count elevated: scheduling while atomic, reported as a BUG by CONFIG_DEBUG_ATOMIC_SLEEP and a deadlock once the lock is contended. Any iSCSI offload I/O through a Chelsio NIC that reaches ppm_get_cpu_entries() triggers it. Read the current CPU with raw_cpu_ptr() without raising preempt_count, and derive the global index base from pool->base (initialised when the pools are allocated) instead of cpu * pool_index_max, so the base always matches the pool that was locked. The owning CPU remains in the debug output, now derived from pool->base. Signed-off-by: Haoran Wang <haoranwangsec@gmail.com> --- (Resent with the complete Cc list; the earlier copy reached only you.) Hi Sebastian, thanks for the review. v3 below addresses your comments: - The commit message now describes what the patch does; the review rationale moved into the changelog below the --- separator. - PREEMPT_RT spelled out. - pr_debug() keeps printing the owning CPU of the pool, derived as pool->base / ppm->pool_index_max; the global index stays i + pool->base. - Tested on: x86_64, compile-tested with CONFIG_PREEMPT_RT=y and CONFIG_DEBUG_ATOMIC_SLEEP=y; no Chelsio hardware at hand, so the change is not exercised on real offload I/O. Changes since v2: - Keep the owning CPU in the pr_debug() output, derived from pool->base / ppm->pool_index_max (suggested by Sebastian). - Reword the commit message to describe what the patch does and move the review discussion into this changelog; spell PREEMPT_RT. Changes since v1: - Drop the cpu variable: read the global-index base from pool->base (initialised at pool allocation) instead of a cpu captured before the lock, so the base is always consistent with the pool that was locked. The per-CPU pools are shards of the global ppod index space and not tied to the running CPU (ppm_unmark_entries() derives the owning pool from the index itself), so locking another CPU's pool after a migration is a cache-locality matter, not a correctness one. drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) --- a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c +++ b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c @@ -119,16 +119,13 @@ unsigned long caller_data) { struct cxgbi_ppm_pool *pool; - unsigned int cpu; int i; if (!ppm->pool) return -EINVAL; - cpu = get_cpu(); - pool = per_cpu_ptr(ppm->pool, cpu); + pool = raw_cpu_ptr(ppm->pool); spin_lock_bh(&pool->lock); - put_cpu(); i = ppm_find_unused_entries(pool->bmap, ppm->pool_index_max, pool->next, count, 0); @@ -145,10 +142,10 @@ spin_unlock_bh(&pool->lock); pr_debug("%s: cpu %u, idx %d + %d (%d), next %u.\n", - __func__, cpu, i, count, i + cpu * ppm->pool_index_max, - pool->next); + __func__, pool->base / ppm->pool_index_max, i, count, + i + pool->base, pool->next); - i += cpu * ppm->pool_index_max; + i += pool->base; ppm_mark_entries(ppm, i, count, caller_data); return i; @@ -375,6 +372,7 @@ memset(ppool, 0, alloc_sz); spin_lock_init(&ppool->lock); + ppool->base = count; count += ppmax; } ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3] libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() 2026-11-09 10:07 ` [PATCH v3] " Haoran Wang @ 2026-11-09 10:11 ` netdev-bot+sinfo 2026-11-09 20:03 ` David Laight 1 sibling, 0 replies; 8+ messages in thread From: netdev-bot+sinfo @ 2026-11-09 10:11 UTC (permalink / raw) To: Haoran Wang Cc: Sebastian Andrzej Siewior, netdev, linux-kernel, linux-rt-devel, andrew+netdev, davem, edumazet, kuba, pabeni, rostedt Hi! This is an automated message. This series looks like a fix, but its commit messages seem to be missing some information: - How the issue was discovered, e.g. hit in production, hit during development, syzbot report, manual code inspection, LLM or static analysis tool scan. Please do not repost the series just to address the above. Instead, reply to this email with the missing information, so that reviewers can take it into account. If the series needs another revision for other reasons, please include the information in the commit messages then. The evaluation is done by an LLM so it may be wrong, if you think that is the case please reply and explain. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3] libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() 2026-11-09 10:07 ` [PATCH v3] " Haoran Wang 2026-11-09 10:11 ` netdev-bot+sinfo @ 2026-11-09 20:03 ` David Laight 1 sibling, 0 replies; 8+ messages in thread From: David Laight @ 2026-11-09 20:03 UTC (permalink / raw) To: Haoran Wang Cc: Sebastian Andrzej Siewior, netdev, linux-kernel, linux-rt-devel, andrew+netdev, davem, edumazet, kuba, pabeni, rostedt On Mon, 09 Nov 2026 18:07:48 +0800 Haoran Wang <haoranwangsec@gmail.com> wrote: > ppm_get_cpu_entries() disables preemption with get_cpu(), reads the > current CPU's pool with per_cpu_ptr(), then acquires the pool's > spin_lock_bh() while preemption is still disabled, and finally put_cpu(). > > On PREEMPT_RT kernels spin_lock_bh() becomes a sleeping lock > (rt_spin_lock), so the task may sleep with preempt_count elevated: > scheduling while atomic, reported as a BUG by CONFIG_DEBUG_ATOMIC_SLEEP > and a deadlock once the lock is contended. Any iSCSI offload I/O > through a Chelsio NIC that reaches ppm_get_cpu_entries() triggers it. > > Read the current CPU with raw_cpu_ptr() without raising preempt_count, > and derive the global index base from pool->base (initialised when the > pools are allocated) instead of cpu * pool_index_max, so the base > always matches the pool that was locked. The owning CPU remains in the > debug output, now derived from pool->base. I think you really need to explain why it doesn't matter that the pool for the 'wrong' cpu is used. You don't need a big explanation of why you can't call spin_lock_bh() with preemption disabled, it is probably enough just to say that you can't (the most reason would be 'can sleep on PREEMPT_RT kernels). This is separate from any issues of acquiring the wrong lock. I'm not sure about the trace, if you are tracing the cpu the data belongs to - then that should be what you call it. Once you hold the lock I think the cpu is fixed (even under PREEMPT_RT) so you could trace the actual cpu as well - especially if anything 'funny' might happen because the data wor the wrong cpu is being used. Of course, it the code is just trying to avoid lock contention (and maybe reduce cache line bouncing) it may not matter at all which copy of the data you get. In fact one for each cpu may be excessive - think of systems with 1000s of cpu not single digits. David > > Signed-off-by: Haoran Wang <haoranwangsec@gmail.com> > > --- > (Resent with the complete Cc list; the earlier copy reached only you.) > > Hi Sebastian, > > thanks for the review. v3 below addresses your comments: > > - The commit message now describes what the patch does; the review > rationale moved into the changelog below the --- separator. > - PREEMPT_RT spelled out. > - pr_debug() keeps printing the owning CPU of the pool, derived as > pool->base / ppm->pool_index_max; the global index stays > i + pool->base. > - Tested on: x86_64, compile-tested with CONFIG_PREEMPT_RT=y and > CONFIG_DEBUG_ATOMIC_SLEEP=y; no Chelsio hardware at hand, so the > change is not exercised on real offload I/O. > > Changes since v2: > - Keep the owning CPU in the pr_debug() output, derived from > pool->base / ppm->pool_index_max (suggested by Sebastian). > - Reword the commit message to describe what the patch does and move > the review discussion into this changelog; spell PREEMPT_RT. > > Changes since v1: > - Drop the cpu variable: read the global-index base from pool->base > (initialised at pool allocation) instead of a cpu captured before > the lock, so the base is always consistent with the pool that was > locked. The per-CPU pools are shards of the global ppod index > space and not tied to the running CPU (ppm_unmark_entries() derives > the owning pool from the index itself), so locking another CPU's > pool after a migration is a cache-locality matter, not a > correctness one. > > drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c | 12 +++++------- > 1 file changed, 5 insertions(+), 7 deletions(-) > > --- a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c > +++ b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_ppm.c > @@ -119,16 +119,13 @@ > unsigned long caller_data) > { > struct cxgbi_ppm_pool *pool; > - unsigned int cpu; > int i; > > if (!ppm->pool) > return -EINVAL; > > - cpu = get_cpu(); > - pool = per_cpu_ptr(ppm->pool, cpu); > + pool = raw_cpu_ptr(ppm->pool); > spin_lock_bh(&pool->lock); > - put_cpu(); > > i = ppm_find_unused_entries(pool->bmap, ppm->pool_index_max, > pool->next, count, 0); > @@ -145,10 +142,10 @@ > spin_unlock_bh(&pool->lock); > > pr_debug("%s: cpu %u, idx %d + %d (%d), next %u.\n", > - __func__, cpu, i, count, i + cpu * ppm->pool_index_max, > - pool->next); > + __func__, pool->base / ppm->pool_index_max, i, count, > + i + pool->base, pool->next); > > - i += cpu * ppm->pool_index_max; > + i += pool->base; > ppm_mark_entries(ppm, i, count, caller_data); > > return i; > @@ -375,6 +372,7 @@ > > memset(ppool, 0, alloc_sz); > spin_lock_init(&ppool->lock); > + ppool->base = count; > count += ppmax; > } > > ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-11-09 20:03 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-19 13:22 [PATCH] libcxgb: use raw_cpu_ptr() in ppm_get_cpu_entries() Haoran Wang
2026-10-19 13:29 ` netdev-bot+sinfo
2026-10-19 13:29 ` Sebastian Andrzej Siewior
2026-10-20 13:22 ` sashiko-bot
2026-10-22 7:25 ` netdev-bot+sashiko
[not found] ` <CANZ3JQQrrntu0TefPZC79pKSmsOfwAngRJyuaVm81DYaJNFHFQ@mail.gmail.com>
2026-11-09 10:07 ` [PATCH v3] " Haoran Wang
2026-11-09 10:11 ` netdev-bot+sinfo
2026-11-09 20:03 ` David Laight
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®