[RFC 03/12] powerpc/pseries: Rework hash flush to remove conditional locking

From: Ritesh Harjani (IBM)

Date: Sun Sep 27 2026 - 10:35:03 EST


Clang's compiler based static context analysis does not work with locks
that are conditionally taken like in pSeries_lpar_flush_hash_range().

This also simplifies the function definition in my opinion - so this
is also a win.

No functional change intended.

Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@xxxxxxxxx>
---
arch/powerpc/platforms/pseries/lpar.c | 31 ++++++++++++++++-----------
1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index abd77c45cbf4..5dbf447d3a83 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -1526,28 +1526,19 @@ void __init pseries_lpar_read_hblkrm_characteristics(void)
bpsize, idx, hblkrm_size[bpsize][idx]);
}

-/*
- * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
- * lock.
- */
-static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
+static void pSeries_lpar_flush_hash_range_unlocked(unsigned long number, int local)
{
unsigned long vpn;
unsigned long i, pix, rc;
- unsigned long flags = 0;
struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch);
- int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
unsigned long param[PLPAR_HCALL9_BUFSIZE];
unsigned long index, shift, slot;
real_pte_t pte;
int psize, ssize;

- if (lock_tlbie)
- spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
-
if (is_supported_hlbkrm(batch->psize, batch->psize)) {
do_block_remove(number, batch, param);
- goto out;
+ return;
}

psize = batch->psize;
@@ -1587,10 +1578,24 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
param[6], param[7]);
BUG_ON(rc != H_SUCCESS);
}
+}

-out:
- if (lock_tlbie)
+/*
+ * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
+ * lock. Firmware with MMU_FTR_LOCKLESS_TLBIE does not need it.
+ */
+static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
+{
+ unsigned long flags;
+
+ if (!mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE)) {
+ spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
+ pSeries_lpar_flush_hash_range_unlocked(number, local);
spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
+ return;
+ }
+
+ pSeries_lpar_flush_hash_range_unlocked(number, local);
}

static int __init disable_bulk_remove(char *str)
--
2.39.5