Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net] net: airoha: Add missing bits in airoha_qdma_cleanup_tx_queue()
From: Lorenzo Bianconi @ 2026-04-10 21:49 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: linux-arm-kernel, linux-mediatek, netdev, Lorenzo Bianconi

Similar to airoha_qdma_cleanup_rx_queue(), reset DMA TX descriptors in
airoha_qdma_cleanup_tx_queue routine. Moreover, reset TX_DMA_IDX to
TX_CPU_IDX to notify the NIC the QDMA TX ring is empty.

Fixes: 23020f0493270 ("net: airoha: Introduce ethernet support for EN7581 SoC")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/ethernet/airoha/airoha_eth.c | 31 ++++++++++++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 9285a68f435f..963ab7b8d166 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1044,13 +1044,17 @@ static int airoha_qdma_init_tx(struct airoha_qdma *qdma)
 
 static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q)
 {
-	struct airoha_eth *eth = q->qdma->eth;
-	int i;
+	struct airoha_qdma *qdma = q->qdma;
+	struct airoha_eth *eth = qdma->eth;
+	int i, qid = q - &qdma->q_tx[0];
+	struct airoha_queue_entry *e;
+	u16 index;
 
 	spin_lock_bh(&q->lock);
 	for (i = 0; i < q->ndesc; i++) {
-		struct airoha_queue_entry *e = &q->entry[i];
+		struct airoha_qdma_desc *desc = &q->desc[i];
 
+		e = &q->entry[i];
 		if (!e->dma_addr)
 			continue;
 
@@ -1060,8 +1064,29 @@ static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q)
 		e->dma_addr = 0;
 		e->skb = NULL;
 		list_add_tail(&e->list, &q->tx_list);
+
+		/* Reset DMA descriptor */
+		WRITE_ONCE(desc->ctrl, 0);
+		WRITE_ONCE(desc->addr, 0);
+		WRITE_ONCE(desc->data, 0);
+		WRITE_ONCE(desc->msg0, 0);
+		WRITE_ONCE(desc->msg1, 0);
+		WRITE_ONCE(desc->msg2, 0);
+
 		q->queued--;
 	}
+
+	e = list_first_entry(&q->tx_list, struct airoha_queue_entry,
+			     list);
+	index = e - q->entry;
+	/* Set TX_DMA_IDX to TX_CPU_IDX to notify the hw the QDMA TX ring is
+	 * empty.
+	 */
+	airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
+			FIELD_PREP(TX_RING_CPU_IDX_MASK, index));
+	airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK,
+			FIELD_PREP(TX_RING_DMA_IDX_MASK, index));
+
 	spin_unlock_bh(&q->lock);
 }
 

---
base-commit: 12ff2a4aee6c86746623d5aed24389dbf6dffded
change-id: 20260410-airoha_qdma_cleanup_tx_queue-fix-net-93375f5ee80f

Best regards,
-- 
Lorenzo Bianconi <lorenzo@kernel.org>



^ permalink raw reply related

* Re: [PATCH v4 03/10] iommu/arm-smmu-v3: Store IOTLB cache tags in struct arm_smmu_attach_state
From: Jason Gunthorpe @ 2026-04-10 21:41 UTC (permalink / raw)
  To: Nicolin Chen
  Cc: will, robin.murphy, joro, jpb, praan, smostafa, linux-arm-kernel,
	iommu, linux-kernel, linux-tegra, jonathan.cameron
In-Reply-To: <adlqZLZMr9VfnKse@Asurada-Nvidia>

On Fri, Apr 10, 2026 at 02:23:48PM -0700, Nicolin Chen wrote:

> Reworking the SVA code, I found arm_smmu_update_s1_domain_cd_entry
> is marked as __maybe_unused and not getting called anywhere(?). Do
> you recall why we kept it?

I intended to send the vBTM support that uses it, and now that this is
done it can work properly without races. So lets hang on, I was
meaning to look at that soon

Jason


^ permalink raw reply

* RE: [RFC PATCH] arm64: mm: support set_memory_encrypted/decrypted for vmalloc addresses
From: Kameron Carr @ 2026-04-10 21:36 UTC (permalink / raw)
  To: 'Catalin Marinas'
  Cc: will, suzuki.poulose, steven.price, ryan.roberts, dev.jain, yang,
	shijie, kevin.brodsky, linux-arm-kernel, linux-kernel
In-Reply-To: <adjZpFIgXQYOvyTq@arm.com>

On Friday, April 10, 2026 4:06 AM, Catalin Marinas wrote:
> Could you give more details about the user of set_memory_decrypted() on
> vmalloc()'ed addresses? I think this came up in the past and I wondered
> whether something like GFP_DECRYPTED would be simpler to implement (even
> posted a hack but without vmalloc() support). If it is known upfront
> that the memory will be decrypted, it's easier/cheaper to do this on the
> page allocation time to change the linear map and just use
> pgprot_decrypted() for vmap(). No need to rewrite the page table after
> mapping the pages.

Thank you for the review. I understand that my approach is not ideal in
terms of speed / cost. For my use case it was not an issue since the
memory is typically only initialized once during device initialization,
but I understand there could be a larger performance impact in other
uses.

The use case I am interested in is Hyper-V netvsc
(drivers/net/hyperv/netvsc.c). The network driver allocates large send
and receive buffers (typically 16MB+) with vzalloc(), then registers them
as Guest Physical Address Descriptor Lists (GPADLs) via
vmbus_establish_gpadl(). Inside __vmbus_establish_gpadl()
(drivers/hv/channel.c), set_memory_decrypted() is called on the buffer so
the hypervisor can access the shared memory.

In this use case, whether to decrypt the memory can always be known at
time of allocation, so a solution like GFP_DECRYPTED is an option.

I think I found the hack you mentioned
(https://lore.kernel.org/linux-arm-kernel/ZmNJdSxSz-sYpVgI@arm.com/). The
feedback in Michael Kelley's reply covers the key considerations well. He
likely had netvsc's use of vmalloc in mind when he made the point
"GFP_DECRYPTED should work for the three memory allocation interfaces and
their variants: alloc_pages(), kmalloc(), and vmalloc()." His other
points already cover the concerns I had in mind around handling errors
from set_memory_decrypted()/encrypted(), etc.

What is the current status of your proposed GFP_DECRYPTED implementation?
Is this something you are actively working on?

I'd be happy to work on an RFC following the GFP_DECRYPTED approach if
you think that's the right direction.

Regards,
Kameron Carr



^ permalink raw reply

* [PATCH 2/3] drm/exynos: remove bridge when component_add fails
From: Osama Abdelkader @ 2026-04-10 21:27 UTC (permalink / raw)
  To: luca.ceresoli, Inki Dae, Seung-Woo Kim, Kyungmin Park,
	David Airlie, Simona Vetter, Krzysztof Kozlowski, Alim Akhtar,
	dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel
  Cc: Osama Abdelkader
In-Reply-To: <20260410212801.413827-2-osama.abdelkader@gmail.com>

when component_add fails in exynos_mic_probe remove drm
bridge before return

Signed-off-by: Osama Abdelkader <osama.abdelkader@gmail.com>
---
 drivers/gpu/drm/exynos/exynos_drm_mic.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
index 29a8366513fa..5e771b236bf0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -437,6 +437,7 @@ static int exynos_mic_probe(struct platform_device *pdev)
 
 err_pm:
 	pm_runtime_disable(dev);
+	drm_bridge_remove(&mic->bridge);
 err:
 	return ret;
 }
-- 
2.43.0



^ permalink raw reply related

* Re: [PATCH v4 03/10] iommu/arm-smmu-v3: Store IOTLB cache tags in struct arm_smmu_attach_state
From: Nicolin Chen @ 2026-04-10 21:23 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: will, robin.murphy, joro, jpb, praan, smostafa, linux-arm-kernel,
	iommu, linux-kernel, linux-tegra, jonathan.cameron
In-Reply-To: <20260410204709.GB2588311@nvidia.com>

On Fri, Apr 10, 2026 at 05:47:09PM -0300, Jason Gunthorpe wrote:
> On Fri, Apr 10, 2026 at 11:52:01AM -0700, Nicolin Chen wrote:
> > > Only readers *with the possibility of concurrent access* should be
> > > marked with READ_ONCE. IIRC this is just the invalidation walker.
> > 
> > I added a cleanup patch to the beginning of the series and corrected
> > all the new reads/writes too.
> > 
> > > Places like this have to be protected by a lock or the whole thing is
> > > wrong, so it should have a lockdep annoation.
> > 
> > Hmm, is the lockdep_is_held() in rcu_dereference_protected() enough?
> 
> Yes.. but I didn't notice it there, not where I usually look for
> lockdeps :)

I added two new asserts in the find/get() and put notes in kdocs.

> But also that should have failed in your testing in the SVA case, so
> make sure you test with lockdep on, and segfault some app using SVA to
> trigger the error clean up flow.

Ack. I recall I tried SVA case with CONFIG_LOCKDEP=y. But it did
not cover the error clean up flow..

Reworking the SVA code, I found arm_smmu_update_s1_domain_cd_entry
is marked as __maybe_unused and not getting called anywhere(?). Do
you recall why we kept it?

> > > But why does arm_smmu_mm_release() need a tag in the first place? ASID
> > > isn't going to be used when EPD0|EPD1 is set, so the tag can just be
> > > 0. Probably make a patch with that change early on..
> > 
> > I see. I added a cleanup patch.
> 
> Also double check it still generates a hitless update, I think it
> should but worth confirming.

Both EDP0 and ASID are in the word0 of a CD:
    CTXDESC_CD_0_ASID
    CTXDESC_CD_0_TCR_EPD0

So, used_qword_diff is 0x1. I think we are good.

> Also is ASID 0 used at all?

Setting EPD0/1 disables any PT walk. HW could still use an ASID to
match the cache lines. But, in this release pathway, the cache will
be flushed also. And completely aborting any ASID usage makes sense
to me. So, passing ASID=0 to guarantee a TLB miss should work.

Thanks
Nicolin


^ permalink raw reply

* Re: [PATCH 3/4] pinctrl: vt8500: Enable compile testing
From: Sander Vanheule @ 2026-04-10 21:22 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Linus Walleij, Andreas Färber
  Cc: linux-gpio, linux-kernel, Andrew Jeffery, linux-aspeed, openbmc,
	linux-arm-kernel, Joel Stanley, linux-realtek-soc, James Tai,
	Yu-Chun Lin
In-Reply-To: <20260410-pinctrl-testing-v1-3-6f708c855867@oss.qualcomm.com>

Hi Krzysztof,

On Fri, 2026-04-10 at 15:04 +0200, Krzysztof Kozlowski wrote:
> Enable compile testing for Realtek pin controller drivers for increased

Small nit, but this looks like a copy-paste error from the other patch.

	Realtek -> VIA/Wondermedia (or vt8500, whatever you prefer)

Best,
Sander


^ permalink raw reply

* Re: [PATCH RFC net-next 02/10] net: stmmac: rename dev_id to userver
From: Jitendra Vegiraju @ 2026-04-10 21:04 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Andrew Lunn, Alexandre Torgue, Andrew Lunn, Chen-Yu Tsai,
	David S. Miller, Eric Dumazet, Jakub Kicinski, linux-arm-kernel,
	linux-stm32, linux-sunxi, netdev, Paolo Abeni, Samuel Holland
In-Reply-To: <adi3Vks-N0a83ylE@shell.armlinux.org.uk>

[-- Attachment #1: Type: text/plain, Size: 2139 bytes --]

On Fri, Apr 10, 2026 at 1:39 AM Russell King (Oracle)
<linux@armlinux.org.uk> wrote:
>
> On Thu, Apr 09, 2026 at 04:07:42PM -0700, Jitendra Vegiraju wrote:
> > Hi Russell,
> >
> > On Wed, Apr 8, 2026 at 2:27 AM Russell King (Oracle)
> > <rmk+kernel@armlinux.org.uk> wrote:
> > >
> > > The Synopsys Databook and several implementation TRMs identify bits
> > > 15:8 of the version register in dwmac v3.xx and v4.xx as "userver".
> > > We even print its value with "User ID". Rather than using "dev_id",
> > > use "userver" instead.
> > >
> > > Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
> > > ---
> > >  drivers/net/ethernet/stmicro/stmmac/hwif.c | 18 +++++++++---------
> > >  1 file changed, 9 insertions(+), 9 deletions(-)
> > >
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> > > index 3774af66db48..830ff816ab4f 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> > > @@ -15,7 +15,7 @@
> > >
> > >  struct stmmac_version {
> > >         u8 snpsver;
> > > -       u8 dev_id;
> > > +       u8 userver;
> > >  };
> > From the XGMAC databook that I have access to bits(15:8) identify the
> > DEVID field of MAC_version register.
> > The userver field is from bits(23:16) of the same register. This is a
> > customer defined field (configured with coreConsultant).
> > Currently stmmac doesn't care about bits(23:16).
>
> Thanks for the additional information.
>
> I don't have any XGMAC documentation, but this indicates that it differs
> between XGMAC and previous cores - GMAC and GMAC4 cores, 15:8 are
> documented as userver, and 31:16 are marked as reserved.
>
> Note that the dev_info() also prints 15:8 as "User ID" not "Device ID".
>
> To confirm, is the XGMAC version register at offset 0x20 ? Later GMAC
> cores moved it to 0x110.
The XGMAC version register is at offset 0x110.

>
> --
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5435 bytes --]

^ permalink raw reply

* [patch V1.1 11/38] misc: sgi-gru: Remove get_cycles() [ab]use
From: Thomas Gleixner @ 2026-04-10 20:56 UTC (permalink / raw)
  To: LKML
  Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
	linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
	linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
	Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
	Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
	Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
	linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
	Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
	Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
	linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
	linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
	sparclinux
In-Reply-To: <20260410120318.320727701@kernel.org>

Calculating a timeout from get_cycles() is a historical leftover without
any functional requirement.

Use ktime_get() instead.

Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
V2: Fix typo
---
 drivers/misc/sgi-gru/gruhandles.c   |   20 ++++++++------------
 drivers/misc/sgi-gru/grukservices.c |    3 ++-
 drivers/misc/sgi-gru/grutlbpurge.c  |    5 ++---
 3 files changed, 12 insertions(+), 16 deletions(-)

--- a/drivers/misc/sgi-gru/gruhandles.c
+++ b/drivers/misc/sgi-gru/gruhandles.c
@@ -6,26 +6,22 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/timekeeping.h>
 #include "gru.h"
 #include "grulib.h"
 #include "grutables.h"
 
-/* 10 sec */
 #include <linux/sync_core.h>
-#include <asm/tsc.h>
-#define GRU_OPERATION_TIMEOUT	((cycles_t) tsc_khz*10*1000)
-#define CLKS2NSEC(c)		((c) * 1000000 / tsc_khz)
+
+#define GRU_OPERATION_TIMEOUT_NSEC	(((ktime_t)10 * NSEC_PER_SEC))
 
 /* Extract the status field from a kernel handle */
 #define GET_MSEG_HANDLE_STATUS(h)	(((*(unsigned long *)(h)) >> 16) & 3)
 
 struct mcs_op_statistic mcs_op_statistics[mcsop_last];
 
-static void update_mcs_stats(enum mcs_op op, unsigned long clks)
+static void update_mcs_stats(enum mcs_op op, unsigned long nsec)
 {
-	unsigned long nsec;
-
-	nsec = CLKS2NSEC(clks);
 	atomic_long_inc(&mcs_op_statistics[op].count);
 	atomic_long_add(nsec, &mcs_op_statistics[op].total);
 	if (mcs_op_statistics[op].max < nsec)
@@ -58,21 +54,21 @@ static void report_instruction_timeout(v
 
 static int wait_instruction_complete(void *h, enum mcs_op opc)
 {
+	ktime_t start_time = ktime_get();
 	int status;
-	unsigned long start_time = get_cycles();
 
 	while (1) {
 		cpu_relax();
 		status = GET_MSEG_HANDLE_STATUS(h);
 		if (status != CCHSTATUS_ACTIVE)
 			break;
-		if (GRU_OPERATION_TIMEOUT < (get_cycles() - start_time)) {
+		if (GRU_OPERATION_TIMEOUT_NSEC < (ktime_get() - start_time)) {
 			report_instruction_timeout(h);
-			start_time = get_cycles();
+			start_time = ktime_get();
 		}
 	}
 	if (gru_options & OPT_STATS)
-		update_mcs_stats(opc, get_cycles() - start_time);
+		update_mcs_stats(opc, (unsigned long)(ktime_get() - start_time));
 	return status;
 }
 
--- a/drivers/misc/sgi-gru/grukservices.c
+++ b/drivers/misc/sgi-gru/grukservices.c
@@ -20,6 +20,7 @@
 #include <linux/uaccess.h>
 #include <linux/delay.h>
 #include <linux/export.h>
+#include <linux/random.h>
 #include <asm/io_apic.h>
 #include "gru.h"
 #include "grulib.h"
@@ -1106,7 +1107,7 @@ static int quicktest3(unsigned long arg)
 	int ret = 0;
 
 	memset(buf2, 0, sizeof(buf2));
-	memset(buf1, get_cycles() & 255, sizeof(buf1));
+	memset(buf1, get_random_u32() & 255, sizeof(buf1));
 	gru_copy_gpa(uv_gpa(buf2), uv_gpa(buf1), BUFSIZE);
 	if (memcmp(buf1, buf2, BUFSIZE)) {
 		printk(KERN_DEBUG "GRU:%d quicktest3 error\n", smp_processor_id());
--- a/drivers/misc/sgi-gru/grutlbpurge.c
+++ b/drivers/misc/sgi-gru/grutlbpurge.c
@@ -22,13 +22,12 @@
 #include <linux/delay.h>
 #include <linux/timex.h>
 #include <linux/srcu.h>
+#include <linux/random.h>
 #include <asm/processor.h>
 #include "gru.h"
 #include "grutables.h"
 #include <asm/uv/uv_hub.h>
 
-#define gru_random()	get_cycles()
-
 /* ---------------------------------- TLB Invalidation functions --------
  * get_tgh_handle
  *
@@ -49,7 +48,7 @@ static inline int get_off_blade_tgh(stru
 	int n;
 
 	n = GRU_NUM_TGH - gru->gs_tgh_first_remote;
-	n = gru_random() % n;
+	n = get_random_u32() % n;
 	n += gru->gs_tgh_first_remote;
 	return n;
 }


^ permalink raw reply

* [patch V1.1 02/38] x86: Cleanup include recursion hell
From: Thomas Gleixner @ 2026-04-10 20:55 UTC (permalink / raw)
  To: LKML
  Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
	linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
	linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
	Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
	Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
	Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
	linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
	Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
	Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
	linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
	linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
	sparclinux
In-Reply-To: <20260410120317.709923681@kernel.org>

Including a random architecture specific header which requires global
headers just to avoid including that header at the two usage sites is
really beyond lazy and tasteless. Including global headers just to get the
__percpu macro from linux/compiler_types.h falls into the same category.

Remove the linux/percpu.h and asm/cpumask.h includes from msr.h and smp.h
and fix the resulting fallout by a simple forward struct declaration and by
including the x86 specific asm/cpumask.h header where it is actually
required.

Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
V1.1: Fix PARAVIRT_XXL fallout....
---
 arch/x86/include/asm/cache.h             |    1 +
 arch/x86/include/asm/msr.h               |    5 +++--
 arch/x86/include/asm/paravirt.h          |    3 ++-
 arch/x86/include/asm/pvclock.h           |    1 +
 arch/x86/include/asm/smp.h               |    2 --
 arch/x86/include/asm/vdso/gettimeofday.h |    5 ++---
 arch/x86/kernel/cpu/mce/core.c           |    1 +
 arch/x86/kernel/nmi.c                    |    1 +
 arch/x86/kernel/smpboot.c                |    1 +
 9 files changed, 12 insertions(+), 8 deletions(-)

--- a/arch/x86/include/asm/cache.h
+++ b/arch/x86/include/asm/cache.h
@@ -2,6 +2,7 @@
 #ifndef _ASM_X86_CACHE_H
 #define _ASM_X86_CACHE_H
 
+#include <vdso/page.h>
 #include <linux/linkage.h>
 
 /* L1 cache line size */
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -8,12 +8,11 @@
 
 #include <asm/asm.h>
 #include <asm/errno.h>
-#include <asm/cpumask.h>
 #include <uapi/asm/msr.h>
 #include <asm/shared/msr.h>
 
+#include <linux/compiler_types.h>
 #include <linux/types.h>
-#include <linux/percpu.h>
 
 struct msr_info {
 	u32			msr_no;
@@ -256,6 +255,8 @@ int msr_set_bit(u32 msr, u8 bit);
 int msr_clear_bit(u32 msr, u8 bit);
 
 #ifdef CONFIG_SMP
+struct cpumask;
+
 int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
 int rdmsrq_on_cpu(unsigned int cpu, u32 msr_no, u64 *q);
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -16,9 +16,10 @@
 
 #ifndef __ASSEMBLER__
 #include <linux/types.h>
-#include <linux/cpumask.h>
 #include <asm/frame.h>
 
+struct cpumask;
+
 /* The paravirtualized I/O functions */
 static inline void slow_down_io(void)
 {
--- a/arch/x86/include/asm/pvclock.h
+++ b/arch/x86/include/asm/pvclock.h
@@ -2,6 +2,7 @@
 #ifndef _ASM_X86_PVCLOCK_H
 #define _ASM_X86_PVCLOCK_H
 
+#include <asm/barrier.h>
 #include <asm/clocksource.h>
 #include <asm/pvclock-abi.h>
 
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -5,8 +5,6 @@
 #include <linux/cpumask.h>
 #include <linux/thread_info.h>
 
-#include <asm/cpumask.h>
-
 DECLARE_PER_CPU_CACHE_HOT(int, cpu_number);
 
 DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map);
--- a/arch/x86/include/asm/vdso/gettimeofday.h
+++ b/arch/x86/include/asm/vdso/gettimeofday.h
@@ -11,13 +11,12 @@
 #define __ASM_VDSO_GETTIMEOFDAY_H
 
 #ifndef __ASSEMBLER__
-
+#include <clocksource/hyperv_timer.h>
 #include <uapi/linux/time.h>
+
 #include <asm/vgtod.h>
 #include <asm/unistd.h>
-#include <asm/msr.h>
 #include <asm/pvclock.h>
-#include <clocksource/hyperv_timer.h>
 #include <asm/vdso/sys_call.h>
 
 #define VDSO_HAS_TIME 1
--- a/arch/x86/kernel/cpu/mce/core.c
+++ b/arch/x86/kernel/cpu/mce/core.c
@@ -48,6 +48,7 @@
 #include <linux/vmcore_info.h>
 
 #include <asm/fred.h>
+#include <asm/cpumask.h>
 #include <asm/cpu_device_id.h>
 #include <asm/processor.h>
 #include <asm/traps.h>
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -26,6 +26,7 @@
 #include <linux/sched/clock.h>
 #include <linux/kvm_types.h>
 
+#include <asm/cpumask.h>
 #include <asm/cpu_entry_area.h>
 #include <asm/traps.h>
 #include <asm/mach_traps.h>
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -70,6 +70,7 @@
 #include <asm/irq.h>
 #include <asm/realmode.h>
 #include <asm/cpu.h>
+#include <asm/cpumask.h>
 #include <asm/numa.h>
 #include <asm/tlbflush.h>
 #include <asm/mtrr.h>


^ permalink raw reply

* Re: [PATCH 1/1] virt: arm-cca-guest: fix error check for RSI_INCOMPLETE
From: Gavin Shan @ 2026-04-10 20:50 UTC (permalink / raw)
  To: Sami Mujawar, linux-arm-kernel, linux-kernel
  Cc: catalin.marinas, will, steven.price, suzuki.poulose, YeoReum.Yun,
	Jagdish Gediya
In-Reply-To: <20260410163636.259443-1-sami.mujawar@arm.com>

On 4/11/26 2:36 AM, Sami Mujawar wrote:
> The RSI interface can return RSI_INCOMPLETE when a report spans
> multiple granules. This is an expected condition and should not be
> treated as a fatal error.
> 
> Currently, arm_cca_report_new() checks for `info.result != RSI_SUCCESS`
> and bails out, which incorrectly flags RSI_INCOMPLETE as a failure.
> Fix the check to only break out on results other than RSI_SUCCESS or
> RSI_INCOMPLETE.
> 
> This ensures partial reports are handled correctly and avoids spurious
> -ENXIO errors when generating attestation reports.
> 
> Fixes: 7999edc484ca ("virt: arm-cca-guest: TSM_REPORT support for realms")
> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
> Reported-by: Jagdish Gediya <Jagdish.Gediya@arm.com>
> ---
>   drivers/virt/coco/arm-cca-guest/arm-cca-guest.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
> 

Reviewed-by: Gavin Shan <gshan@redhat.com>



^ permalink raw reply

* Re: [PATCH net-next v3 00/12] net: airoha: Support multiple net_devices connected to the same GDM port
From: Jakub Kicinski @ 2026-04-10 20:49 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Paolo Abeni,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Christian Marangi,
	Benjamin Larsson, linux-arm-kernel, linux-mediatek, netdev,
	devicetree, Xuegang Lu
In-Reply-To: <adiop-9Mo4ADfvfw@lore-desk>

On Fri, 10 Apr 2026 09:37:11 +0200 Lorenzo Bianconi wrote:
> > On Mon, 06 Apr 2026 12:34:05 +0200 Lorenzo Bianconi wrote:  
> > > EN7581 or AN7583 SoCs support connecting multiple external SerDes (e.g.
> > > Ethernet or USB SerDes) to GDM3 or GDM4 ports via a hw arbiter that
> > > manages the traffic in a TDM manner. As a result multiple net_devices can
> > > connect to the same GDM{3,4} port and there is a theoretical "1:n"
> > > relation between GDM ports and net_devices.  
> > 
> > Looks like this driver uses page pool.
> > If you're sharing the same page pool across multiple netdevs
> > it must not be linked to a netdev.  
> 
> are you referring to slow.netdev pointer? If so, this is not set in airoha_eth
> driver.

Yes. Alright, thanks for checking. Pretty sure I saw it set somewhere 
in a file called airoha* but must be another component :)


^ permalink raw reply

* Re: [PATCH v4 03/10] iommu/arm-smmu-v3: Store IOTLB cache tags in struct arm_smmu_attach_state
From: Jason Gunthorpe @ 2026-04-10 20:47 UTC (permalink / raw)
  To: Nicolin Chen
  Cc: will, robin.murphy, joro, jpb, praan, smostafa, linux-arm-kernel,
	iommu, linux-kernel, linux-tegra, jonathan.cameron
In-Reply-To: <adlG0QTAzdh9vA4M@Asurada-Nvidia>

On Fri, Apr 10, 2026 at 11:52:01AM -0700, Nicolin Chen wrote:
> > Only readers *with the possibility of concurrent access* should be
> > marked with READ_ONCE. IIRC this is just the invalidation walker.
> 
> I added a cleanup patch to the beginning of the series and corrected
> all the new reads/writes too.
> 
> > Places like this have to be protected by a lock or the whole thing is
> > wrong, so it should have a lockdep annoation.
> 
> Hmm, is the lockdep_is_held() in rcu_dereference_protected() enough?

Yes.. but I didn't notice it there, not where I usually look for
lockdeps :)

But also that should have failed in your testing in the SVA case, so
make sure you test with lockdep on, and segfault some app using SVA to
trigger the error clean up flow.

> > But why does arm_smmu_mm_release() need a tag in the first place? ASID
> > isn't going to be used when EPD0|EPD1 is set, so the tag can just be
> > 0. Probably make a patch with that change early on..
> 
> I see. I added a cleanup patch.

Also double check it still generates a hitless update, I think it
should but worth confirming.

Also is ASID 0 used at all?

Jason


^ permalink raw reply

* Re: [PATCH V3 7/7] arm64/hw_breakpoint: Enable FEAT_Debugv8p9
From: Rob Herring @ 2026-04-10 19:55 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Anshuman Khandual, linux-arm-kernel, linux-kernel,
	Jonathan Corbet, Marc Zyngier, Oliver Upton, James Morse,
	Suzuki K Poulose, Catalin Marinas, Will Deacon, Mark Brown,
	kvmarm
In-Reply-To: <adeE4MD0RgapI8aL@J2N7QTR9R3>

On Thu, Apr 9, 2026 at 5:52 AM Mark Rutland <mark.rutland@arm.com> wrote:
>
> On Thu, Apr 02, 2026 at 12:46:56PM -0500, Rob Herring wrote:
> > On Thu, Apr 2, 2026 at 5:37 AM Mark Rutland <mark.rutland@arm.com> wrote:
> > >
> > > On Tue, Mar 31, 2026 at 05:58:00PM -0500, Rob Herring wrote:
> > > > On Mon, Dec 16, 2024 at 10:58:29AM +0000, Mark Rutland wrote:
> > > > > On Mon, Dec 16, 2024 at 09:38:31AM +0530, Anshuman Khandual wrote:
> > > That said, the use of 'bp_per_reg' looks suspect given their
> > > arch_install_hw_breakpoint() and arch_uninstall_hw_breakpoint() modify
> > > that non-atomically.
> >
> > You don't believe the comment saying counter->ctx->lock is held?
>
> Sorry, my concern here was that hw_breakpoint_handler() (which cannot
> hold the lock) consumes bp_per_reg[], and could race with the non-atomic
> modification in arch_install_hw_breakpoint() or
> arch_uninstall_hw_breakpoint().
>
> I've sent a more elaborate mail to x86 folk, with that and another issue
> caused by taking a breakpoint under arch_uninstall_hw_breakpoint():
>
>   https://lore.kernel.org/lkml/adZWmPW8S9Y2pwkv@J2N7QTR9R3.cambridge.arm.com/
>
> I think we have a similar latent issue where we can take an breakpoint
> or watchpoint ad infinitum, described in more detail at the end of this
> mail.
>
> [...]
>
> > > > > | What prevents a race with an exception handler? e.g.
> > > > > |
> > > > > | * Does the structure of the code prevent that somehow?
> > > >
> > > > If you can't set a breakpoint/watchpoint in NOKPROBE_SYMBOL() annotated
> > > > code, you can't race.
> > >
> > > As above, I agree (with caveats), but I couldn't spot where this is
> > > enforced.
> > >
> > > > However, there's no such annotation for data. It looks like the kernel
> > > > policy is "don't do that" or disable all breakpoints/watchpoints.
> > >
> > > If we have to transiently disable watchpoints/breakpoints when
> > > manipulating the relevant HW registers, that sounds fine to me.
> >
> > For wp/bp_on_reg, the ordering is 'data access, h/w accesses'. I think
> > we just need a barrier to enforce that ordering so the data access
> > (and then watchpoint) don't trigger in the middle of the h/w accesses.
>
> I assume that by 'h/w accesses' you mean MSRs to the system registers
> controlling breakpoints/watchpoints. Ordering-wise, I don't believe
> memory barriers are necessary here (explain in more detail below).
> However, I also think there's a latent issue here that might bite us
> with the new banking, described at the end of this mail.
>
> Both breakpoint and watchpoint exceptions are synchronous, meanning that
> they can only be taken from the specific instruction that triggered
> them.  However, updates to the watchpoint control registers *do* need a
> context synchronization event before they're guarnateed to take effect.
>
> For a sequence:
>
>     // Initially:
>     // - MDSCR, MDCR, DAIF.D permit debug exceptions at CurrentEL
>     // - No watchpoints enabled
>
>     0x000:  LDR <val>, [<addr>]
>     0x004:  MSR DBGWVR<n>_EL1, <addr>
>     0x008:  MSR DBGWCR<n>_EL1, <configure_and_enable>
>     0x010:  LDR <val>, [<addr>]
>     0x014:  ISB
>     0x018:  LDR <val>, [<addr>]
>
> ... we know:
>
>     (a) The LDR at 0x000 *cannot* trigger the watchpoint.

Why not? Can't the LDR complete after the MSR? Is ordering ensured
between those? Surely the watchpoint triggers on completion of the
load and that wouldn't stall the PE from doing the MSR(s)?

>     (b) The LDR at 0x010 *might* trigger the matchpoint.
>     (c) The LDR at 0x018 *must* trigger the watchpoint.
>
> For C code, we can enforce this order with barrier(), e.g.
>
>         val = *addr;
>         barrier();
>         write_sysreg(addr, DBGWVR<n>_EL1);
>         write_sysreg(configure_and_enable, DBGWCR<n>_EL1);
>         isb();
>
> ... where the compiler cannot re-order the memory access (or
> write_sysreg(), or isb()) across the barrier(), and as isb() has a
> memory clobber, the same is true for isb().
>
> Likewise, for the inverse sequence:
>
>     // Initially:
>     // - MDSCR, MDCR, DAIF.D permit debug exceptions at CurrentEL
>     // - Watchpoint configured and enabled for <addr>
>
>     0x100:  LDR <val>, [<addr>]
>     0x104:  MSR DBGWCR<n>_EL1, <disable>
>     0x108:  LDR <val>, [<addr>]
>     0x110:  ISB
>     0x114:  LDR <val>, [<addr>]
>
> ... we know:
>
>     (a) The LDR at 0x100 *must* trigger the watchpoint.
>     (b) The LDR at 0x108 *might* trigger the watchpoint.
>     (c) The LDR at 0x114 *cannot* trigger the watchpoint.
>
> > Any guidance on the flavor of dsb here? (And is there any guarantee
> > that the access is visible to the watchpoint h/w after a dsb
> > completes?)
>
> Hopefully the above was sufficient?
>
> As mentioned above, I think we have a latent issue where we can take a
> breakpoint or watchpoint under arch_uninstall_hw_breakpoint(), where we
> have:
>
>     arch_uninstall_hw_breakpoint(bp) {
>         ...
>         hw_breakpoint_control(bp, HW_BREAKPOINT_UNINSTALL) {
>             ...
>             hw_breakpoint_slot_setup(slots, max_slots, bp, HW_BREAKPOINT_UNINSTALL) {
>                  ...
>                  *slot = NULL;
>                  ...
>             }
>             ...
>             write_wb_reg(ctrl_reg, i, 0) {
>                 ...
>                 write_sysreg(0, ...);
>                 isb();
>                 ...
>             }
>         }
>     }
>
> The HW breakpoint/watchpoint associated with 'bp' could be triggered
> between setting '*slot' to NULL and the ISB. If that happens, then
> do_breakpoint() won't find 'bp', and will return *without* disabling the
> HW breakpoint or attempting to step.
>
> If that first exception was taken *before* the MSR in write_sysreg(),
> then nothing has changed, and the breakpoint/watchpoint will then be
> taken again ad infinitum.
>
> If that first exception was taken *after* the MSR in write_sysreg(), the
> context synchronization provided by exception entry/return will prevent
> it from being taken again.
>
> Building v6.19 and testing (with pseudo-NMI enabled):
>
> | #  grep write_wb_reg /proc/kallsyms
> | ffff80008004b980 t write_wb_reg
> | # ./perf-6.19 stat -a -C 1 -e 'mem:0xffff80008004b980/4:xk' true

I'll give it a try with v4, but that should be prevented with my
changes to exclude kprobe regions.

Rob


^ permalink raw reply

* Re: [PATCH v2 3/4] perf/arm64: Add BRBE support for bpf_get_branch_snapshot()
From: Rob Herring @ 2026-04-10 19:23 UTC (permalink / raw)
  To: Puranjay Mohan
  Cc: bpf, Puranjay Mohan, Alexei Starovoitov, Andrii Nakryiko,
	Daniel Borkmann, Martin KaFai Lau, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, Will Deacon, Mark Rutland,
	Catalin Marinas, Leo Yan, Breno Leitao, linux-arm-kernel,
	linux-perf-users, kernel-team
In-Reply-To: <20260318171706.2840512-4-puranjay@kernel.org>

On Wed, Mar 18, 2026 at 10:16:57AM -0700, Puranjay Mohan wrote:
> Enable the bpf_get_branch_snapshot() BPF helper on ARM64 by implementing
> the perf_snapshot_branch_stack static call for ARM's Branch Record Buffer
> Extension (BRBE).
> 
> The BPF helper bpf_get_branch_snapshot() allows BPF programs to capture
> hardware branch records on-demand. This was previously only available on
> x86 (Intel LBR) but not on ARM64 despite BRBE being available since
> ARMv9.
> 
> BRBE is paused before disabling interrupts because local_irq_save() can
> trigger trace_hardirqs_off() which performs stack walking and pollutes
> the branch buffer. The sysreg read/write and ISB used to pause BRBE are
> branchless, so pausing first avoids this pollution.
> 
> All exceptions are masked after pausing BRBE using local_daif_save() to
> prevent pseudo-NMI from PMU counter overflow from interfering with the
> snapshot read. A PMU overflow arriving between the pause and
> local_daif_save() can re-enable BRBE via the interrupt handler; the
> snapshot detects this by re-checking BRBFCR_EL1.PAUSED and bailing out.
> 
> Branch records are read using the existing perf_entry_from_brbe_regset()
> helper with a NULL event pointer, which bypasses event-specific filtering
> and captures all recorded branches. The BPF program is responsible for
> filtering entries based on its own criteria. The BRBE buffer is
> invalidated after reading to maintain contiguity for other consumers.
> 
> On heterogeneous big.LITTLE systems, only some CPUs may implement
> FEAT_BRBE. The perf_snapshot_branch_stack static call is system-wide, so
> a per-CPU brbe_active flag is used to prevent BRBE sysreg access on CPUs
> that do not implement FEAT_BRBE, where such access would be UNDEFINED.

Is this something you've seen? IIRC, the existing assumption is all CPUs 
have FEAT_BRBE or that perf has been limited to those CPUs. It is 
allowed that the number of records can vary.

> 
> Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
> ---
>  drivers/perf/arm_brbe.c  | 79 +++++++++++++++++++++++++++++++++++++++-
>  drivers/perf/arm_brbe.h  |  9 +++++
>  drivers/perf/arm_pmuv3.c |  5 ++-
>  3 files changed, 90 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/perf/arm_brbe.c b/drivers/perf/arm_brbe.c
> index ba554e0c846c..527c2d5ebba6 100644
> --- a/drivers/perf/arm_brbe.c
> +++ b/drivers/perf/arm_brbe.c
> @@ -8,9 +8,13 @@
>   */
>  #include <linux/types.h>
>  #include <linux/bitmap.h>
> +#include <linux/percpu.h>
>  #include <linux/perf/arm_pmu.h>
> +#include <asm/daifflags.h>
>  #include "arm_brbe.h"
>  
> +static DEFINE_PER_CPU(bool, brbe_active);
> +
>  #define BRBFCR_EL1_BRANCH_FILTERS (BRBFCR_EL1_DIRECT   | \
>  				   BRBFCR_EL1_INDIRECT | \
>  				   BRBFCR_EL1_RTN      | \
> @@ -533,6 +537,8 @@ void brbe_enable(const struct arm_pmu *arm_pmu)
>  	/* Finally write SYS_BRBFCR_EL to unpause BRBE */
>  	write_sysreg_s(brbfcr, SYS_BRBFCR_EL1);
>  	/* Synchronization in PMCR write ensures ordering WRT PMU enabling */
> +
> +	this_cpu_write(brbe_active, true);
>  }
>  
>  void brbe_disable(void)
> @@ -544,6 +550,7 @@ void brbe_disable(void)
>  	 */
>  	write_sysreg_s(BRBFCR_EL1_PAUSED, SYS_BRBFCR_EL1);
>  	write_sysreg_s(0, SYS_BRBCR_EL1);
> +	this_cpu_write(brbe_active, false);
>  }
>  
>  static const int brbe_type_to_perf_type_map[BRBINFx_EL1_TYPE_DEBUG_EXIT + 1][2] = {
> @@ -618,10 +625,10 @@ static bool perf_entry_from_brbe_regset(int index, struct perf_branch_entry *ent
>  
>  	brbe_set_perf_entry_type(entry, brbinf);
>  
> -	if (!branch_sample_no_cycles(event))
> +	if (!event || !branch_sample_no_cycles(event))
>  		entry->cycles = brbinf_get_cycles(brbinf);
>  
> -	if (!branch_sample_no_flags(event)) {
> +	if (!event || !branch_sample_no_flags(event)) {
>  		/* Mispredict info is available for source only and complete branch records. */
>  		if (!brbe_record_is_target_only(brbinf)) {
>  			entry->mispred = brbinf_get_mispredict(brbinf);
> @@ -803,3 +810,71 @@ void brbe_read_filtered_entries(struct perf_branch_stack *branch_stack,
>  done:
>  	branch_stack->nr = nr_filtered;
>  }
> +
> +/*
> + * Best-effort BRBE snapshot for BPF tracing. Pause BRBE to avoid
> + * self-recording and return 0 if the snapshot state appears disturbed.
> + */
> +int arm_brbe_snapshot_branch_stack(struct perf_branch_entry *entries, unsigned int cnt)
> +{
> +	unsigned long flags;
> +	int nr_hw, nr_banks, nr_copied = 0;
> +	u64 brbidr, brbfcr, brbcr;
> +
> +	if (!cnt || !__this_cpu_read(brbe_active))
> +		return 0;
> +
> +	/* Pause BRBE first to avoid recording our own branches. */
> +	brbfcr = read_sysreg_s(SYS_BRBFCR_EL1);
> +	brbcr = read_sysreg_s(SYS_BRBCR_EL1);
> +	write_sysreg_s(brbfcr | BRBFCR_EL1_PAUSED, SYS_BRBFCR_EL1);
> +	isb();

Is there something that guarantees BRBE is enabled when you enter this 
function and that it is not disabled in this window? A context switch 
could disable it unless it's a global event for example.

> +
> +	/* Block local exception delivery while reading the buffer. */
> +	flags = local_daif_save();
> +
> +	/*
> +	 * A PMU overflow before local_daif_save() could have re-enabled
> +	 * BRBE, clearing the PAUSED bit. The overflow handler already
> +	 * restored BRBE to its correct state, so just bail out.
> +	 */
> +	if (!(read_sysreg_s(SYS_BRBFCR_EL1) & BRBFCR_EL1_PAUSED)) {
> +		local_daif_restore(flags);
> +		return 0;
> +	}
> +
> +	brbidr = read_sysreg_s(SYS_BRBIDR0_EL1);
> +	if (!valid_brbidr(brbidr))

This is not possibly true if brbe_active is true. If BRBIDR is not 
valid, then we would have rejected any event requesting branch stack.

> +		goto out;
> +
> +	nr_hw = FIELD_GET(BRBIDR0_EL1_NUMREC_MASK, brbidr);
> +	nr_banks = DIV_ROUND_UP(nr_hw, BRBE_BANK_MAX_ENTRIES);
> +
> +	for (int bank = 0; bank < nr_banks; bank++) {
> +		int nr_remaining = nr_hw - (bank * BRBE_BANK_MAX_ENTRIES);
> +		int nr_this_bank = min(nr_remaining, BRBE_BANK_MAX_ENTRIES);
> +
> +		select_brbe_bank(bank);
> +
> +		for (int i = 0; i < nr_this_bank; i++) {

I don't love all this being duplicated. Perhaps an iterator would help 
here (and the other copy):

static void next_slot(int *bank, int *bank_idx, int nr_hw)
{
	*bank_idx++;
	if (*bank_idx + (*bank * BRBE_BANK_MAX_ENTRIES) == nr_hw)
		bank = BRBE_MAX_BANKS;
	else if ((*bank_idx % BRBE_BANK_MAX_ENTRIES) == 0) {
		*bank_idx = 0;
		select_brbe_bank(++(*bank));
	}
	
} 

#define for_each_bank_slot(i, nr_hw) \
for (int bank = 0, int i = 0; bank < BRBE_MAX_BANKS; next_slot(&bank, 
&i))

Then here you just have:

for_each_bank_slot(i, FIELD_GET(BRBIDR0_EL1_NUMREC_MASK, brbidr)) {
	...
}

Feel free to come up with better naming. :)

> +			if (nr_copied >= cnt)
> +				goto done;
> +
> +			if (!perf_entry_from_brbe_regset(i, &entries[nr_copied], NULL))
> +				goto done;
> +
> +			nr_copied++;
> +		}
> +	}
> +
> +done:
> +	brbe_invalidate();
> +out:
> +	/* Restore BRBCR before unpausing via BRBFCR, matching brbe_enable(). */
> +	write_sysreg_s(brbcr, SYS_BRBCR_EL1);
> +	isb();
> +	write_sysreg_s(brbfcr, SYS_BRBFCR_EL1);
> +	local_daif_restore(flags);
> +
> +	return nr_copied;
> +}


^ permalink raw reply

* Re: [PATCH v4 03/10] iommu/arm-smmu-v3: Store IOTLB cache tags in struct arm_smmu_attach_state
From: Nicolin Chen @ 2026-04-10 18:52 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: will, robin.murphy, joro, jpb, praan, smostafa, linux-arm-kernel,
	iommu, linux-kernel, linux-tegra, jonathan.cameron
In-Reply-To: <20260409234223.GX3357077@nvidia.com>

On Thu, Apr 09, 2026 at 08:42:23PM -0300, Jason Gunthorpe wrote:
> On Thu, Mar 19, 2026 at 12:51:49PM -0700, Nicolin Chen wrote:
> > So far, an IOTLB tag (ASID or VMID) has been stored in the arm_smmu_domain
> > +static int __arm_smmu_domain_find_iotlb_tag(struct arm_smmu_domain *smmu_domain,
> > +					    struct arm_smmu_inv *tag)
> > +{
> > +	struct arm_smmu_invs *invs = rcu_dereference_protected(
> > +		smmu_domain->invs, lockdep_is_held(&arm_smmu_asid_lock));
> > +	size_t i;
> > +
> > +	arm_smmu_inv_assert_iotlb_tag(tag);
> > +
> > +	for (i = 0; i != invs->num_invs; i++) {
> > +		if (invs->inv[i].type == tag->type &&
> > +		    invs->inv[i].smmu == tag->smmu &&
> > +		    READ_ONCE(invs->inv[i].users)) {
> > +			*tag = invs->inv[i];
> 
> This users thing has become to hard to understand and it isn't how it
> should be.
> 
> All writers *with the possibility of concurrent access* need to use
> WRITE_ONCE since there is a RCU reader. IIRC that is just
> arm_smmu_invs_unref()
> 
> The one in arm_smmu_invs_merge() is just writing to newly allocated
> memory so it shouldn't be marked.
> 
> Only readers *with the possibility of concurrent access* should be
> marked with READ_ONCE. IIRC this is just the invalidation walker.

I added a cleanup patch to the beginning of the series and corrected
all the new reads/writes too.

> Places like this have to be protected by a lock or the whole thing is
> wrong, so it should have a lockdep annoation.

Hmm, is the lockdep_is_held() in rcu_dereference_protected() enough?

> Now what is the locking supposed to be? It looks wrong, it probably
> wants to be arm_smmu_asid_lock, but arm_smmu_mm_release() doesn't grab
> it.
> 
> But why does arm_smmu_mm_release() need a tag in the first place? ASID
> isn't going to be used when EPD0|EPD1 is set, so the tag can just be
> 0. Probably make a patch with that change early on..

I see. I added a cleanup patch.

> All the locking is important because this:
> 
> > +/* Find an existing IOTLB cache tag in smmu_domain->invs (users counter != 0) */
> 
> Must be held as an invarient into the caller, meaning the caller must
> hold arm_smmu_asid_lock while it has an active tag on the stack, and
> that should be documented here. As well as a lockdep of course.
> 
> From what I can tell the final result is correct (aside from
> arm_smmu_mm_release), just under documented.

Re-checking the locking in these functions and updating the kdocs.

Thanks
Nicolin


^ permalink raw reply

* Re: [PATCH v5 0/4] arm64: Work around C1-Pro erratum 4193714 (CVE-2026-0995)
From: Catalin Marinas @ 2026-04-10 18:47 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: Will Deacon, James Morse, Mark Rutland, Mark Brown
In-Reply-To: <20260407102848.2266988-1-catalin.marinas@arm.com>

On Tue, 07 Apr 2026 11:28:40 +0100, Catalin Marinas wrote:
> That's version 5 of the C1-Pro workaround. Version 3 here:
> 
> https://lore.kernel.org/r/20260402101246.3870036-1-catalin.marinas@arm.com
> 
> Changes since v4:
> 
> - Static sme_dvmsync_cpus mask to avoid allocating under stop_machine().
>   Sashiko was right, even GFP_ATOMIC won't work under a raw_spin_lock()
> 
> [...]

Applied to arm64 (for-next/c1-pro-erratum-4193714). I won't push it to
Linus in the first round, waiting for a bit more testing from Will. If
all goes well, I'll send it in the second part of the merging window.

[1/4] arm64: tlb: Introduce __tlbi_sync_s1ish_{kernel,batch}() for TLB maintenance
      https://git.kernel.org/arm64/c/6bfbf574a391
[2/4] arm64: tlb: Pass the corresponding mm to __tlbi_sync_s1ish()
      https://git.kernel.org/arm64/c/d9fb08ba946a
[3/4] arm64: cputype: Add C1-Pro definitions
      https://git.kernel.org/arm64/c/2c99561016c5
[4/4] arm64: errata: Work around early CME DVMSync acknowledgement
      https://git.kernel.org/arm64/c/0baba94a9779


^ permalink raw reply

* [PATCH] arm: Kconfig: fix duplicate words in help text
From: Michael Ugrin @ 2026-04-10 18:22 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-kernel, Michael Ugrin

Remove two instances of duplicate 'the'.

Signed-off-by: Michael Ugrin <mugrinphoto@gmail.com>
---
 arch/arm/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ec33376f8e2ba..e62af2a34f59f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1486,7 +1486,7 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND
 	bool "Extend with bootloader kernel arguments"
 	help
 	  The command-line arguments provided by the boot loader will be
-	  appended to the the device tree bootargs property.
+	  appended to the device tree bootargs property.
 
 endchoice
 
@@ -1628,7 +1628,7 @@ config DMI
 	  continue to boot on existing non-UEFI platforms.
 
 	  NOTE: This does *NOT* enable or encourage the use of DMI quirks,
-	  i.e., the the practice of identifying the platform via DMI to
+	  i.e., the practice of identifying the platform via DMI to
 	  decide whether certain workarounds for buggy hardware and/or
 	  firmware need to be enabled. This would require the DMI subsystem
 	  to be enabled much earlier than we do on ARM, which is non-trivial.
-- 
2.51.2.windows.1



^ permalink raw reply related

* Re: [PATCH v2 2/4] perf: Fix uninitialized bitfields in perf_clear_branch_entry_bitfields()
From: Rob Herring @ 2026-04-10 18:17 UTC (permalink / raw)
  To: Leo Yan
  Cc: Puranjay Mohan, bpf, Puranjay Mohan, Alexei Starovoitov,
	Andrii Nakryiko, Daniel Borkmann, Martin KaFai Lau,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Will Deacon,
	Mark Rutland, Catalin Marinas, Breno Leitao, linux-arm-kernel,
	linux-perf-users, kernel-team
In-Reply-To: <20260409162826.GX356832@e132581.arm.com>

On Thu, Apr 09, 2026 at 05:28:26PM +0100, Leo Yan wrote:
> On Wed, Mar 18, 2026 at 10:16:56AM -0700, Puranjay Mohan wrote:
> 
> [...]
> 
> > diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
> > index 48d851fbd8ea..d7f39b7e9cda 100644
> > --- a/include/linux/perf_event.h
> > +++ b/include/linux/perf_event.h
> 
> BTW, I found you didn't include correct maintainers for perf core
> changes.  You might need to loop them in the new version.

Yes. And use get_maintainers.pl please. b4 tool will do that for you. 
That will get everyone including authors of commits in "Fixes". That 
would be Marc Z in this case.

Rob


^ permalink raw reply

* ✅ PASS (MISSED 51 of 56): Test report for for-kernelci (7.0.0-rc7, upstream-arm-next, 5988aa32)
From: cki-project @ 2026-04-10 18:13 UTC (permalink / raw)
  To: catalin.marinas, will, linux-arm-kernel

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK
              Test: OK

Tested-by: CKI Project <cki-project@redhat.com>

Kernel information:
    Commit message: Merge branch 'for-next/c1-pro-erratum-4193714' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:2444539166

Tests that were not ran because of internal issues:
    /distribution/check-install [aarch64]
    /distribution/command [aarch64]
    /test/misc/machineinfo [aarch64]
    Boot test [aarch64]
    CKI/restraint [aarch64]
    Hardware - Firmware test suite [aarch64]
    Reboot test [aarch64]
    SELinux Custom Module Setup [aarch64]
    selinux-policy: serge-testsuite [aarch64]
    Storage - blktests - throtl [aarch64]
    Storage - blktests - ublk [aarch64]
    stress: stress-ng - cpu-cache [aarch64]
    stress: stress-ng - memory [aarch64]
    xfstests - btrfs [aarch64]
    xfstests - ext4 [aarch64]
    xfstests - xfs [aarch64]


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



^ permalink raw reply

* Re: [PATCH v2 2/3] pwm: rp1: Add RP1 PWM controller driver
From: Uwe Kleine-König @ 2026-04-10 17:31 UTC (permalink / raw)
  To: Andrea della Porta
  Cc: linux-pwm, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Florian Fainelli, Broadcom internal kernel review list,
	devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
	Naushir Patuck, Stanimir Varbanov, mbrugger
In-Reply-To: <0d99317b9150310dfbd98de1cb2a890f0bffe7cd.1775829499.git.andrea.porta@suse.com>

[-- Attachment #1: Type: text/plain, Size: 14571 bytes --]

Hello Andrea,

nice work for a v2!

On Fri, Apr 10, 2026 at 04:09:58PM +0200, Andrea della Porta wrote:
> From: Naushir Patuck <naush@raspberrypi.com>
> 
> The Raspberry Pi RP1 southbridge features an embedded PWM
> controller with 4 output channels, alongside an RPM interface
> to read the fan speed on the Raspberry Pi 5.
> 
> Add the supporting driver.
> 
> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
> Co-developed-by: Stanimir Varbanov <svarbanov@suse.de>
> Signed-off-by: Stanimir Varbanov <svarbanov@suse.de>
> Signed-off-by: Andrea della Porta <andrea.porta@suse.com>
> ---
>  drivers/pwm/Kconfig   |   9 ++
>  drivers/pwm/Makefile  |   1 +
>  drivers/pwm/pwm-rp1.c | 344 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 354 insertions(+)
>  create mode 100644 drivers/pwm/pwm-rp1.c
> 
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index 6f3147518376a..32031f2af75af 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -625,6 +625,15 @@ config PWM_ROCKCHIP
>  	  Generic PWM framework driver for the PWM controller found on
>  	  Rockchip SoCs.
>  
> +config PWM_RASPBERRYPI_RP1
> +	bool "RP1 PWM support"
> +	depends on MISC_RP1 || COMPILE_TEST
> +	depends on HAS_IOMEM
> +	select REGMAP_MMIO
> +	select MFD_SYSCON
> +	help
> +	  PWM framework driver for Raspberry Pi RP1 controller.
> +
>  config PWM_SAMSUNG
>  	tristate "Samsung PWM support"
>  	depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> index 0dc0d2b69025d..59f29f60f9123 100644
> --- a/drivers/pwm/Makefile
> +++ b/drivers/pwm/Makefile
> @@ -56,6 +56,7 @@ obj-$(CONFIG_PWM_RENESAS_RZG2L_GPT)	+= pwm-rzg2l-gpt.o
>  obj-$(CONFIG_PWM_RENESAS_RZ_MTU3)	+= pwm-rz-mtu3.o
>  obj-$(CONFIG_PWM_RENESAS_TPU)	+= pwm-renesas-tpu.o
>  obj-$(CONFIG_PWM_ROCKCHIP)	+= pwm-rockchip.o
> +obj-$(CONFIG_PWM_RASPBERRYPI_RP1)	+= pwm-rp1.o
>  obj-$(CONFIG_PWM_SAMSUNG)	+= pwm-samsung.o
>  obj-$(CONFIG_PWM_SIFIVE)	+= pwm-sifive.o
>  obj-$(CONFIG_PWM_SL28CPLD)	+= pwm-sl28cpld.o
> diff --git a/drivers/pwm/pwm-rp1.c b/drivers/pwm/pwm-rp1.c
> new file mode 100644
> index 0000000000000..b88c697d9567e
> --- /dev/null
> +++ b/drivers/pwm/pwm-rp1.c
> @@ -0,0 +1,344 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * pwm-rp1.c
> + *
> + * Raspberry Pi RP1 PWM.
> + *
> + * Copyright © 2026 Raspberry Pi Ltd.
> + *
> + * Author: Naushir Patuck (naush@raspberrypi.com)
> + *
> + * Based on the pwm-bcm2835 driver by:
> + * Bart Tanghe <bart.tanghe@thomasmore.be>
> + *
> + * Datasheet: https://pip-assets.raspberrypi.com/categories/892-raspberry-pi-5/documents/RP-008370-DS-1-rp1-peripherals.pdf?disposition=inline
> + *
> + * Limitations:
> + * - Channels can be enabled/disabled and their duty cycle and period can
> + *   be updated glitchlessly. Update are synchronized with the next strobe
> + *   at the end of the current period of the respective channel, once the
> + *   update bit is set. The update flag is global, not per-channel.
> + * - Channels are phase-capable, but on RPi5, the firmware can use a channel
> + *   phase register to report the RPM of the fan connected to that PWM
> + *   channel. As a result, phase control will be ignored for now.
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pwm.h>
> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +
> +#define RP1_PWM_GLOBAL_CTRL	0x000
> +#define RP1_PWM_CHANNEL_CTRL(x)	(0x014 + ((x) * 0x10))
> +#define RP1_PWM_RANGE(x)	(0x018 + ((x) * 0x10))
> +#define RP1_PWM_PHASE(x)	(0x01C + ((x) * 0x10))
> +#define RP1_PWM_DUTY(x)		(0x020 + ((x) * 0x10))
> +
> +/* 8:FIFO_POP_MASK + 0:Trailing edge M/S modulation */
> +#define RP1_PWM_CHANNEL_DEFAULT		(BIT(8) + BIT(0))

Please add a #define for BIT(8) and then use that and
FIELD_PREP(RP1_PWM_MODE, RP1_PWM_MODE_SOMENICENAME) to define the
constant. Also I would define it below the register defines.

> +#define RP1_PWM_CHANNEL_ENABLE(x)	BIT(x)
> +#define RP1_PWM_POLARITY		BIT(3)
> +#define RP1_PWM_SET_UPDATE		BIT(31)
> +#define RP1_PWM_MODE_MASK		GENMASK(1, 0)

s/_MASK// please

It would be great if the bitfield's names started with the register
name.

> +
> +#define RP1_PWM_NUM_PWMS	4
> +
> +struct rp1_pwm {
> +	struct regmap	*regmap;
> +	struct clk	*clk;
> +	unsigned long	clk_rate;
> +	bool		clk_enabled;
> +};
> +
> +struct rp1_pwm_waveform {
> +	u32	period_ticks;
> +	u32	duty_ticks;
> +	bool	enabled;
> +	bool	inverted_polarity;
> +};
> +
> +static const struct regmap_config rp1_pwm_regmap_config = {
> +	.reg_bits    = 32,
> +	.val_bits    = 32,
> +	.reg_stride  = 4,
> +	.max_register = 0x60,

I'm not a fan of aligning the = in a struct, still more if it fails like
here. Please consistently align all =s, or even better, use a single
space before each =. (Same for the struct definitions above, but I won't
insist.)

> +};
> +
> +static void rp1_pwm_apply_config(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> +	struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
> +	u32 value;
> +
> +	/* update the changed registers on the next strobe to avoid glitches */
> +	regmap_read(rp1->regmap, RP1_PWM_GLOBAL_CTRL, &value);
> +	value |= RP1_PWM_SET_UPDATE;
> +	regmap_write(rp1->regmap, RP1_PWM_GLOBAL_CTRL, value);

I assume there is a glitch if I update two channels and the old
configuration of the first channel ends while I'm in the middle of
configuring the second?

> +}
> +
> +static int rp1_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> +	struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
> +
> +	/* init channel to reset defaults */
> +	regmap_write(rp1->regmap, RP1_PWM_CHANNEL_CTRL(pwm->hwpwm), RP1_PWM_CHANNEL_DEFAULT);
> +	return 0;
> +}
> +
> +static int rp1_pwm_round_waveform_tohw(struct pwm_chip *chip,
> +				       struct pwm_device *pwm,
> +				       const struct pwm_waveform *wf,
> +				       void *_wfhw)
> +{
> +	struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
> +	struct rp1_pwm_waveform *wfhw = _wfhw;
> +	u64 clk_rate = rp1->clk_rate;
> +	u64 ticks;

	if (!wf->period_length_ns)
		wfhw->enabled = false
		return 0;

> +	ticks = mul_u64_u64_div_u64(wf->period_length_ns, clk_rate, NSEC_PER_SEC);

To ensure this doesn't overflow please fail to probe the driver if
clk_rate > 1 GHz with an explaining comment. (Or alternatively calculate
the length of period_ticks = U32_MAX and skip the calculation if
wf->period_length_ns is bigger.)

> +	if (ticks > U32_MAX)
> +		ticks = U32_MAX;
> +	wfhw->period_ticks = ticks;

What happens if wf->period_length_ns > 0 but ticks == 0?

> +	if (wf->duty_offset_ns + wf->duty_length_ns >= wf->period_length_ns) {

The maybe surprising effect here is that in the two cases

	wf->duty_offset_ns == wf->period_length_ns and wf->duty_length_ns == 0

and
	
	wf->duty_length_ns == wf->period_length_ns and wf->duty_offset_ns == 0

you're configuring inverted polarity. I doesn't matter technically
because the result is the same, but for consumers still using pwm_state
this is irritating. That's why pwm-stm32 uses inverted polarity only if
also wf->duty_length_ns and wf->duty_offset_ns are non-zero.

> +		ticks = mul_u64_u64_div_u64(wf->period_length_ns - wf->duty_length_ns,
> +					    clk_rate, NSEC_PER_SEC);

The rounding is wrong here. You should pick the biggest duty_length not
bigger than wf->duty_length_ns, so you have to use

	ticks = wfhw->period_ticks - mul_u64_u64_div_u64(wf->duty_length_ns, clk_rate, NSEC_PER_SEC):

. I see this is a hole in the pwmtestperf coverage.

> +		wfhw->inverted_polarity = true;
> +	} else {
> +		ticks = mul_u64_u64_div_u64(wf->duty_length_ns, clk_rate, NSEC_PER_SEC);
> +		wfhw->inverted_polarity = false;
> +	}
> +
> +	if (ticks > wfhw->period_ticks)
> +		ticks = wfhw->period_ticks;

You can and should assume that wf->duty_length_ns <=
wf->period_length_ns. Then the if condition can never become true.

> +	wfhw->duty_ticks = ticks;
> +
> +	wfhw->enabled = !!wfhw->duty_ticks;
> +
> +	return 0;
> +}
> +
> +static int rp1_pwm_round_waveform_fromhw(struct pwm_chip *chip,
> +					 struct pwm_device *pwm,
> +					 const void *_wfhw,
> +					 struct pwm_waveform *wf)
> +{
> +	struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
> +	const struct rp1_pwm_waveform *wfhw = _wfhw;
> +	u64 clk_rate = rp1->clk_rate;
> +	u32 ticks;
> +
> +	memset(wf, 0, sizeof(*wf));

	wf = (struct pwm_waveform){ };

is usually more efficient.

> +	if (!wfhw->enabled)
> +		return 0;
> +
> +	wf->period_length_ns = DIV_ROUND_UP_ULL((u64)wfhw->period_ticks * NSEC_PER_SEC, clk_rate);
> +
> +	if (wfhw->inverted_polarity) {
> +		wf->duty_length_ns = DIV_ROUND_UP_ULL((u64)wfhw->duty_ticks * NSEC_PER_SEC,
> +						      clk_rate);
> +	} else {
> +		wf->duty_offset_ns = DIV_ROUND_UP_ULL((u64)wfhw->duty_ticks * NSEC_PER_SEC,
> +						      clk_rate);
> +		ticks = wfhw->period_ticks - wfhw->duty_ticks;
> +		wf->duty_length_ns = DIV_ROUND_UP_ULL((u64)ticks * NSEC_PER_SEC, clk_rate);
> +	}

This needs adaption after the rounding issue in tohw is fixed.

> +	return 0;
> +}
> +
> +static int rp1_pwm_write_waveform(struct pwm_chip *chip,
> +				  struct pwm_device *pwm,
> +				  const void *_wfhw)
> +{
> +	struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
> +	const struct rp1_pwm_waveform *wfhw = _wfhw;
> +	u32 value;
> +
> +	/* set period and duty cycle */
> +	regmap_write(rp1->regmap,
> +		     RP1_PWM_RANGE(pwm->hwpwm), wfhw->period_ticks);
> +	regmap_write(rp1->regmap,
> +		     RP1_PWM_DUTY(pwm->hwpwm), wfhw->duty_ticks);
> +
> +	/* set polarity */
> +	regmap_read(rp1->regmap, RP1_PWM_CHANNEL_CTRL(pwm->hwpwm), &value);
> +	if (!wfhw->inverted_polarity)
> +		value &= ~RP1_PWM_POLARITY;
> +	else
> +		value |= RP1_PWM_POLARITY;
> +	regmap_write(rp1->regmap, RP1_PWM_CHANNEL_CTRL(pwm->hwpwm), value);
> +
> +	/* enable/disable */
> +	regmap_read(rp1->regmap, RP1_PWM_GLOBAL_CTRL, &value);
> +	if (wfhw->enabled)
> +		value |= RP1_PWM_CHANNEL_ENABLE(pwm->hwpwm);
> +	else
> +		value &= ~RP1_PWM_CHANNEL_ENABLE(pwm->hwpwm);
> +	regmap_write(rp1->regmap, RP1_PWM_GLOBAL_CTRL, value);

You can exit early if wfhw->enabled is false after clearing the channel
enable bit.

> +	rp1_pwm_apply_config(chip, pwm);
> +
> +	return 0;
> +}
> +
> +static int rp1_pwm_read_waveform(struct pwm_chip *chip,
> +				 struct pwm_device *pwm,
> +				 void *_wfhw)
> +{
> +	struct rp1_pwm *rp1 = pwmchip_get_drvdata(chip);
> +	struct rp1_pwm_waveform *wfhw = _wfhw;
> +	u32 value;
> +
> +	regmap_read(rp1->regmap, RP1_PWM_GLOBAL_CTRL, &value);
> +	wfhw->enabled = !!(value & RP1_PWM_CHANNEL_ENABLE(pwm->hwpwm));
> +
> +	regmap_read(rp1->regmap, RP1_PWM_CHANNEL_CTRL(pwm->hwpwm), &value);
> +	wfhw->inverted_polarity = !!(value & RP1_PWM_POLARITY);
> +
> +	if (wfhw->enabled) {
> +		regmap_read(rp1->regmap, RP1_PWM_RANGE(pwm->hwpwm), &wfhw->period_ticks);
> +		regmap_read(rp1->regmap, RP1_PWM_DUTY(pwm->hwpwm), &wfhw->duty_ticks);
> +	} else {
> +		wfhw->period_ticks = 0;
> +		wfhw->duty_ticks = 0;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct pwm_ops rp1_pwm_ops = {
> +	.sizeof_wfhw = sizeof(struct rp1_pwm_waveform),
> +	.request = rp1_pwm_request,
> +	.round_waveform_tohw = rp1_pwm_round_waveform_tohw,
> +	.round_waveform_fromhw = rp1_pwm_round_waveform_fromhw,
> +	.read_waveform = rp1_pwm_read_waveform,
> +	.write_waveform = rp1_pwm_write_waveform,
> +};
> +
> +static int rp1_pwm_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	unsigned long clk_rate;
> +	struct pwm_chip *chip;
> +	void __iomem	*base;
> +	struct rp1_pwm *rp1;
> +	int ret;
> +
> +	chip = devm_pwmchip_alloc(dev, RP1_PWM_NUM_PWMS, sizeof(*rp1));
> +	if (IS_ERR(chip))
> +		return PTR_ERR(chip);
> +
> +	rp1 = pwmchip_get_drvdata(chip);
> +
> +	base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	rp1->regmap = devm_regmap_init_mmio(dev, base, &rp1_pwm_regmap_config);
> +	if (IS_ERR(rp1->regmap))
> +		return dev_err_probe(dev, PTR_ERR(rp1->regmap), "Cannot initialize regmap\n");
> +
> +	ret = of_syscon_register_regmap(np, rp1->regmap);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Failed to register syscon\n");
> +
> +	rp1->clk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(rp1->clk))
> +		return dev_err_probe(dev, PTR_ERR(rp1->clk), "Clock not found\n");
> +
> +	ret = clk_prepare_enable(rp1->clk);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Failed to enable clock\n");
> +	rp1->clk_enabled = true;
> +
> +	ret = devm_clk_rate_exclusive_get(dev, rp1->clk);
> +	if (ret) {
> +		dev_err_probe(dev, ret, "Fail to get exclusive rate\n");

s/Fail/Failed/

> +		goto err_disable_clk;
> +	}
> +
> +	clk_rate = clk_get_rate(rp1->clk);
> +	if (!clk_rate) {
> +		ret = dev_err_probe(dev, -EINVAL, "Failed to get clock rate\n");
> +		goto err_disable_clk;
> +	}
> +	rp1->clk_rate = clk_rate;
> +
> +	chip->ops = &rp1_pwm_ops;
> +
> +	platform_set_drvdata(pdev, chip);
> +
> +	ret = devm_pwmchip_add(dev, chip);
> +	if (ret) {
> +		dev_err_probe(dev, ret, "Failed to register PWM chip\n");
> +		goto err_disable_clk;
> +	}
> +
> +	return 0;
> +
> +err_disable_clk:
> +	clk_disable_unprepare(rp1->clk);
> +
> +	return ret;
> +}

On remove you miss to balance the call to clk_prepare_enable() (if no
failed call to clk_prepare_enable() in rp1_pwm_resume() happend).

> +
> +static int rp1_pwm_suspend(struct device *dev)
> +{
> +	struct rp1_pwm *rp1 = dev_get_drvdata(dev);
> +
> +	if (rp1->clk_enabled) {
> +		clk_disable_unprepare(rp1->clk);
> +		rp1->clk_enabled = false;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rp1_pwm_resume(struct device *dev)
> +{
> +	struct rp1_pwm *rp1 = dev_get_drvdata(dev);
> +	int ret;
> +
> +	ret = clk_prepare_enable(rp1->clk);
> +	if (ret) {
> +		dev_err(dev, "Failed to enable clock on resume: %d\n", ret);

Please use %pe for error codes.

> +		return ret;
> +	}
> +
> +	rp1->clk_enabled = true;
> +
> +	return 0;
> +}

Best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH 1/1] virt: arm-cca-guest: fix error check for RSI_INCOMPLETE
From: Suzuki K Poulose @ 2026-04-10 17:29 UTC (permalink / raw)
  To: Sami Mujawar, linux-arm-kernel, linux-kernel
  Cc: catalin.marinas, will, steven.price, gshan, YeoReum.Yun,
	Jagdish Gediya
In-Reply-To: <20260410163636.259443-1-sami.mujawar@arm.com>

On 10/04/2026 17:36, Sami Mujawar wrote:
> The RSI interface can return RSI_INCOMPLETE when a report spans
> multiple granules. This is an expected condition and should not be
> treated as a fatal error.
> 
> Currently, arm_cca_report_new() checks for `info.result != RSI_SUCCESS`
> and bails out, which incorrectly flags RSI_INCOMPLETE as a failure.
> Fix the check to only break out on results other than RSI_SUCCESS or
> RSI_INCOMPLETE.
> 
> This ensures partial reports are handled correctly and avoids spurious
> -ENXIO errors when generating attestation reports.
> 
> Fixes: 7999edc484ca ("virt: arm-cca-guest: TSM_REPORT support for realms")
> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
> Reported-by: Jagdish Gediya <Jagdish.Gediya@arm.com>

Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>


> ---
>   drivers/virt/coco/arm-cca-guest/arm-cca-guest.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> index 0c9ea24a200c..66d00b6ceb78 100644
> --- a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> +++ b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> @@ -157,7 +157,8 @@ static int arm_cca_report_new(struct tsm_report *report, void *data)
>   		} while (info.result == RSI_INCOMPLETE &&
>   			 info.offset < RSI_GRANULE_SIZE);
>   
> -		if (info.result != RSI_SUCCESS) {
> +		/* Break out in case of failure */
> +		if (info.result != RSI_SUCCESS && info.result != RSI_INCOMPLETE) {
>   			ret = -ENXIO;
>   			token_size = 0;
>   			goto exit_free_granule_page;



^ permalink raw reply

* [PATCH v5 4/4] arm64: defconfig: Enable ARCH_HPE
From: nick.hawkins @ 2026-04-10 17:16 UTC (permalink / raw)
  To: catalin.marinas, will
  Cc: robh, krzk+dt, conor+dt, krzysztof.kozlowski, devicetree,
	linux-arm-kernel, linux-kernel, Nick Hawkins
In-Reply-To: <20260410171611.2547255-1-nick.hawkins@hpe.com>

From: Nick Hawkins <nick.hawkins@hpe.com>

Enable ARCH_HPE in the arm64 defconfig to include HPE GSC BMC SoC
support in the default build.

Signed-off-by: Nick Hawkins <nick.hawkins@hpe.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index xxxxxxxxxxxxxxx..xxxxxxxxxxxxxxx 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -xx,6 +xx,7 @@
 CONFIG_ARCH_HISI=y
+CONFIG_ARCH_HPE=y
 CONFIG_ARCH_KEEMBAY=y
-- 
2.34.1


^ permalink raw reply

* [PATCH v5 3/4] arm64: dts: hpe: Add HPE GSC SoC and DL340 Gen12 board DTS
From: nick.hawkins @ 2026-04-10 17:16 UTC (permalink / raw)
  To: catalin.marinas, will
  Cc: robh, krzk+dt, conor+dt, krzysztof.kozlowski, devicetree,
	linux-arm-kernel, linux-kernel, Nick Hawkins
In-Reply-To: <20260410171611.2547255-1-nick.hawkins@hpe.com>

From: Nick Hawkins <nick.hawkins@hpe.com>

Add SoC-level DTSI for the HPE GSC ARM64 BMC SoC, covering the CPU
cluster, GIC v3 interrupt controller, ARM64 generic timer, and console
UART.

Add the board-level DTS for the HPE DL340 Gen12, which includes
gsc.dtsi and adds memory and chosen nodes.

Signed-off-by: Nick Hawkins <nick.hawkins@hpe.com>
---
 arch/arm64/boot/dts/hpe/Makefile           |   2 +
 arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts |  18 ++++
 arch/arm64/boot/dts/hpe/gsc.dtsi           | 104 +++++++++++++++++++++
 3 files changed, 124 insertions(+)
 create mode 100644 arch/arm64/boot/dts/hpe/Makefile
 create mode 100644 arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts
 create mode 100644 arch/arm64/boot/dts/hpe/gsc.dtsi

diff --git a/arch/arm64/boot/dts/hpe/Makefile b/arch/arm64/boot/dts/hpe/Makefile
new file mode 100644
index 000000000000..6b547b8a8154
--- /dev/null
+++ b/arch/arm64/boot/dts/hpe/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+dtb-$(CONFIG_ARCH_HPE) += gsc-dl340gen12.dtb
diff --git a/arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts b/arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts
new file mode 100644
index 000000000000..7a3d9f1c4b2e
--- /dev/null
+++ b/arch/arm64/boot/dts/hpe/gsc-dl340gen12.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+#include "gsc.dtsi"
+
+/ {
+	compatible = "hpe,gsc-dl340gen12", "hpe,gsc";
+	model = "HPE ProLiant DL340 Gen12";
+
+	chosen {
+		stdout-path = &uartc;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>;
+	};
+};
diff --git a/arch/arm64/boot/dts/hpe/gsc.dtsi b/arch/arm64/boot/dts/hpe/gsc.dtsi
new file mode 100644
index 000000000000..1f4c2a7b3d91
--- /dev/null
+++ b/arch/arm64/boot/dts/hpe/gsc.dtsi
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for HPE GSC
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	osc: clock-33333333 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-output-names = "osc";
+		clock-frequency = <33333333>;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0 0xa0008048>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <1>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0 0xa0008048>;
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	soc: soc@80000000 {
+		compatible = "simple-bus";
+		reg = <0x80000000 0x80000000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		uarta: serial@c00000e0 {
+			compatible = "ns16550a";
+			reg = <0xc00000e0 0x8>;
+			clock-frequency = <1846153>;
+			interrupt-parent = <&gic>;
+			interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <0>;
+		};
+
+		uartb: serial@c00000e8 {
+			compatible = "ns16550a";
+			reg = <0xc00000e8 0x8>;
+			clock-frequency = <1846153>;
+			interrupt-parent = <&gic>;
+			interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <0>;
+		};
+
+		uartc: serial@c00000f0 {
+			compatible = "ns16550a";
+			reg = <0xc00000f0 0x8>;
+			clock-frequency = <1846153>;
+			interrupt-parent = <&gic>;
+			interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <0>;
+		};
+
+		uarte: serial@c00003e0 {
+			compatible = "ns16550a";
+			reg = <0xc00003e0 0x8>;
+			clock-frequency = <1846153>;
+			interrupt-parent = <&gic>;
+			interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <0>;
+		};
+
+		gic: gic@ce000000 {
+			compatible = "arm,gic-v3";
+			reg = <0xce000000 0x10000>,
+			      <0xce060000 0x40000>,
+			      <0xce200000 0x40000>;
+			#address-cells = <0>;
+			#interrupt-cells = <3>;
+			#redistributor-regions = <1>;
+			interrupt-controller;
+			redistributor-stride = <0x0 0x20000>;
+		};
+	};
+};
-- 
2.34.1


^ permalink raw reply related

* [PATCH v5 2/4] arm64: Kconfig: Add ARCH_HPE platform
From: nick.hawkins @ 2026-04-10 17:16 UTC (permalink / raw)
  To: catalin.marinas, will
  Cc: robh, krzk+dt, conor+dt, krzysztof.kozlowski, devicetree,
	linux-arm-kernel, linux-kernel, Nick Hawkins
In-Reply-To: <20260410171611.2547255-1-nick.hawkins@hpe.com>

From: Nick Hawkins <nick.hawkins@hpe.com>

Add the ARCH_HPE config for HPE ARM64 BMC SoCs to Kconfig.platforms.

Signed-off-by: Nick Hawkins <nick.hawkins@hpe.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
 arch/arm64/Kconfig.platforms | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 54eb1d7fd419..b4217809c774 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -168,6 +168,17 @@ config ARCH_HISI
 	help
 	  This enables support for Hisilicon ARMv8 SoC family
 
+config ARCH_HPE
+	bool "HPE SoC Support"
+	select PINCTRL
+	select GENERIC_IRQ_CHIP
+	select CLKSRC_MMIO
+	help
+	  This enables support for HPE ARM-based SoC chips used
+	  on HPE servers. HPE SoCs serve as the Baseboard
+	  Management Controller (BMC) providing out-of-band server
+	  management.
+
 config ARCH_KEEMBAY
 	bool "Keem Bay SoC"
 	help
-- 
2.34.1


^ permalink raw reply related

* [PATCH v5 1/4] dt-bindings: arm: hpe,gxp: Add HPE GSC platform compatible
From: nick.hawkins @ 2026-04-10 17:16 UTC (permalink / raw)
  To: catalin.marinas, will
  Cc: robh, krzk+dt, conor+dt, krzysztof.kozlowski, devicetree,
	linux-arm-kernel, linux-kernel, Nick Hawkins
In-Reply-To: <20260410171611.2547255-1-nick.hawkins@hpe.com>

From: Nick Hawkins <nick.hawkins@hpe.com>

Add the HPE GSC ARM64 BMC SoC compatibles to the existing
hpe,gxp.yaml binding.

The initial board compatible is hpe,gsc-dl340gen12 for the DL340 Gen12
server platform.

Add the arm64 DTS path to the existing ARM/HPE GXP MAINTAINERS entry,
renamed to ARM/HPE GXP/GSC ARCHITECTURE.

Signed-off-by: Nick Hawkins <nick.hawkins@hpe.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
 Documentation/devicetree/bindings/arm/hpe,gxp.yaml | 7 ++++++-
 MAINTAINERS                                        | 3 ++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/hpe,gxp.yaml b/Documentation/devicetree/bindings/arm/hpe,gxp.yaml
index 224bbcb93f95..6f057cd58571 100644
--- a/Documentation/devicetree/bindings/arm/hpe,gxp.yaml
+++ b/Documentation/devicetree/bindings/arm/hpe,gxp.yaml
@@ -4,7 +4,7 @@
 $id: http://devicetree.org/schemas/arm/hpe,gxp.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: HPE BMC GXP platforms
+title: HPE BMC GXP and GSC platforms
 
 maintainers:
   - Nick Hawkins <nick.hawkins@hpe.com>
 @@ -15,6 +15,11 @@ properties:
     oneOf:
+      - description: GSC Based Boards
+        items:
+          - enum:
+              - hpe,gsc-dl340gen12
+          - const: hpe,gsc
       - description: GXP Based Boards
         items:
           - enum:
               - hpe,gxp-dl360gen10
           - const: hpe,gxp
 
 required:
   - compatible
diff --git a/MAINTAINERS b/MAINTAINERS
index 2265e2c9bfbe..80c66de5e342 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2859,7 +2859,7 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
 F:	arch/arm/mach-sa1100/include/mach/jornada720.h
 F:	arch/arm/mach-sa1100/jornada720.c
 
-ARM/HPE GXP ARCHITECTURE
+ARM/HPE GXP/GSC ARCHITECTURE
 M:	Jean-Marie Verdun <verdun@hpe.com>
 M:	Nick Hawkins <nick.hawkins@hpe.com>
 S:	Maintained
@@ -2870,6 +2870,7 @@ F:	Documentation/devicetree/bindings/spi/hpe,gxp-spifi.yaml
 F:	Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml
 F:	Documentation/hwmon/gxp-fan-ctrl.rst
 F:	arch/arm/boot/dts/hpe/
+F:	arch/arm64/boot/dts/hpe/
 F:	drivers/clocksource/timer-gxp.c
 F:	drivers/hwmon/gxp-fan-ctrl.c
 F:	drivers/i2c/busses/i2c-gxp.c
-- 
2.34.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox