Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 3/3] KVM: arm64: selftests: Enable stage-2 in NV preparation functions
From: Wei-Lin Chang @ 2026-03-26 21:34 UTC (permalink / raw)
  To: Itaru Kitayama
  Cc: kvm, linux-kselftest, linux-arm-kernel, kvmarm, linux-kernel,
	Paolo Bonzini, Shuah Khan, Marc Zyngier, Oliver Upton, Joey Gouly,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon
In-Reply-To: <acN_YIzr6JZmYhZ8@sm-arm-grace07>

On Wed, Mar 25, 2026 at 03:23:28PM +0900, Itaru Kitayama wrote:
> Hi Wei Lin,

Hi,

> On Wed, Mar 25, 2026 at 12:36:20AM +0000, Wei-Lin Chang wrote:
> > Introduce library functions for setting up guest stage-2 page tables,
> > then use that to give L2 an identity mapped stage-2 and enable it.
> > 
> > The translation and stage-2 page table built is simple, start level 0,
> > 4 levels, 4KB granules, normal cachable, 48-bit IA, 40-bit OA.
> > 
> > The nested page table code is adapted from lib/x86/vmx.c.
> > 
> > Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
> > ---
> >  .../selftests/kvm/include/arm64/nested.h      |  7 ++
> >  .../selftests/kvm/include/arm64/processor.h   |  9 ++
> >  .../testing/selftests/kvm/lib/arm64/nested.c  | 97 ++++++++++++++++++-
> >  3 files changed, 111 insertions(+), 2 deletions(-)
> > 
> > diff --git a/tools/testing/selftests/kvm/include/arm64/nested.h b/tools/testing/selftests/kvm/include/arm64/nested.h
> > index 739ff2ee0161..0be10a775e48 100644
> > --- a/tools/testing/selftests/kvm/include/arm64/nested.h
> > +++ b/tools/testing/selftests/kvm/include/arm64/nested.h
> > @@ -6,6 +6,13 @@
> >  #ifndef SELFTEST_KVM_NESTED_H
> >  #define SELFTEST_KVM_NESTED_H
> >  
> > +uint64_t get_l1_vtcr(void);
> 
> Using a type u64 is simpler? And I think you configure guest
> hypervisor's stage 2 translation table, I felt this gives us
> an impression somewhere the configuration IA and OA sizes etc 
> are stored.

Sure, u64 is okay.
In this version I basically just used hard-coded values whenever I not
needed IA, OA and other related values e.g. page shift, which is not
good and as Marc said would not even work on some platforms. I'll make
it more modular in the next iteration.

> 
> > +
> > +void nested_map(struct kvm_vm *vm, vm_paddr_t guest_pgd,
> > +		uint64_t nested_paddr, uint64_t paddr, uint64_t size);
> > +void nested_map_memslot(struct kvm_vm *vm, vm_paddr_t guest_pgd,
> > +			uint32_t memslot);
> > +
> >  void prepare_l2_stack(struct kvm_vm *vm, struct kvm_vcpu *vcpu);
> >  void prepare_hyp_state(struct kvm_vm *vm, struct kvm_vcpu *vcpu);
> >  void prepare_eret_destination(struct kvm_vm *vm, struct kvm_vcpu *vcpu, void *l2_pc);
> > diff --git a/tools/testing/selftests/kvm/include/arm64/processor.h b/tools/testing/selftests/kvm/include/arm64/processor.h
> > index ac97a1c436fc..5de2e932d95a 100644
> > --- a/tools/testing/selftests/kvm/include/arm64/processor.h
> > +++ b/tools/testing/selftests/kvm/include/arm64/processor.h
> > @@ -104,6 +104,15 @@
> >  #define TCR_HA			(UL(1) << 39)
> >  #define TCR_DS			(UL(1) << 59)
> >  
> > +/* VTCR_EL2 specific flags */
> > +#define VTCR_EL2_T0SZ_BITS(x)	((UL(64) - (x)) << VTCR_EL2_T0SZ_SHIFT)
> > +
> > +#define VTCR_EL2_SL0_LV0_4K	(UL(2) << VTCR_EL2_SL0_SHIFT)
> > +#define VTCR_EL2_SL0_LV1_4K	(UL(1) << VTCR_EL2_SL0_SHIFT)
> > +#define VTCR_EL2_SL0_LV2_4K	(UL(0) << VTCR_EL2_SL0_SHIFT)
> > +
> > +#define VTCR_EL2_PS_40_BITS	(UL(2) << VTCR_EL2_PS_SHIFT)
> > +
> >  /*
> >   * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
> >   */
> > diff --git a/tools/testing/selftests/kvm/lib/arm64/nested.c b/tools/testing/selftests/kvm/lib/arm64/nested.c
> > index 111d02f44cfe..910f8cd30f96 100644
> > --- a/tools/testing/selftests/kvm/lib/arm64/nested.c
> > +++ b/tools/testing/selftests/kvm/lib/arm64/nested.c
> > @@ -1,8 +1,11 @@
> >  // SPDX-License-Identifier: GPL-2.0
> >  /*
> > - * ARM64 Nested virtualization helpers
> > + * ARM64 Nested virtualization helpers, nested page table code adapted from
> > + * ../x86/vmx.c.
> >   */
> >  
> > +#include <linux/sizes.h>
> > +
> >  #include "kvm_util.h"
> >  #include "nested.h"
> >  #include "processor.h"
> > @@ -18,6 +21,87 @@ static void hvc_handler(struct ex_regs *regs)
> >  	regs->pc = (u64)after_hvc;
> >  }
> >  
> > +uint64_t get_l1_vtcr(void)
> > +{
> > +	return VTCR_EL2_PS_40_BITS | VTCR_EL2_TG0_4K | VTCR_EL2_ORGN0_WBWA |
> > +	       VTCR_EL2_IRGN0_WBWA | VTCR_EL2_SL0_LV0_4K | VTCR_EL2_T0SZ_BITS(48);
> > +}
> > +
> > +static void __nested_pg_map(struct kvm_vm *vm, uint64_t guest_pgd,
> > +		     uint64_t nested_paddr, uint64_t paddr, uint64_t flags)
> > +{
> > +	uint8_t attr_idx = flags & (PTE_ATTRINDX_MASK >> PTE_ATTRINDX_SHIFT);
> > +	uint64_t pg_attr;
> > +	uint64_t *ptep;
> > +
> > +	TEST_ASSERT((nested_paddr % vm->page_size) == 0,
> > +		"L2 IPA not on page boundary,\n"
> > +		"  nested_paddr: 0x%lx vm->page_size: 0x%x", nested_paddr, vm->page_size);
> > +	TEST_ASSERT((paddr % vm->page_size) == 0,
> > +		"Guest physical address not on page boundary,\n"
> > +		"  paddr: 0x%lx vm->page_size: 0x%x", paddr, vm->page_size);
> > +	TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
> > +		"Physical address beyond maximum supported,\n"
> > +		"  paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
> > +		paddr, vm->max_gfn, vm->page_size);
> > +
> > +	ptep = addr_gpa2hva(vm, guest_pgd) + ((nested_paddr >> 39) & 0x1ffu) * 8;
> > +	if (!*ptep)
> > +		*ptep = (vm_alloc_page_table(vm) & GENMASK(47, 12)) | PGD_TYPE_TABLE | PTE_VALID;
> 
> Same but given this is stage 2 translation tables, KVM_PTE_VALID?

I see your point, but KVM_PTE_VALID is only defined for KVM, not here in
kselftest userspace. However since I will redo the page table generator,
I can add this, let's see.
Thanks for the suggestions!

Thanks,
Wei-Lin Chang

> 
> Thanks,
> Itaru.
> > +	ptep = addr_gpa2hva(vm, *ptep & GENMASK(47, 12)) + ((nested_paddr >> 30) & 0x1ffu) * 8;
> > +	if (!*ptep)
> > +		*ptep = (vm_alloc_page_table(vm) & GENMASK(47, 12)) | PUD_TYPE_TABLE | PTE_VALID;
> > +	ptep = addr_gpa2hva(vm, *ptep & GENMASK(47, 12)) + ((nested_paddr >> 21) & 0x1ffu) * 8;
> > +	if (!*ptep)
> > +		*ptep = (vm_alloc_page_table(vm) & GENMASK(47, 12)) | PMD_TYPE_TABLE | PTE_VALID;
> > +	ptep = addr_gpa2hva(vm, *ptep & GENMASK(47, 12)) + ((nested_paddr >> 12) & 0x1ffu) * 8;
> > +
> > +	pg_attr = PTE_AF | PTE_ATTRINDX(attr_idx) | PTE_TYPE_PAGE | PTE_VALID;
> > +	pg_attr |= PTE_SHARED;
> > +
> > +	*ptep = (paddr & GENMASK(47, 12)) | pg_attr;
> > +}
> > +
> > +void nested_map(struct kvm_vm *vm, vm_paddr_t guest_pgd,
> > +		uint64_t nested_paddr, uint64_t paddr, uint64_t size)
> > +{
> > +	size_t npages = size / SZ_4K;
> > +
> > +	TEST_ASSERT(nested_paddr + size > nested_paddr, "Vaddr overflow");
> > +	TEST_ASSERT(paddr + size > paddr, "Paddr overflow");
> > +
> > +	while (npages--) {
> > +		__nested_pg_map(vm, guest_pgd, nested_paddr, paddr, MT_NORMAL);
> > +		nested_paddr += SZ_4K;
> > +		paddr += SZ_4K;
> > +	}
> > +}
> > +
> > +/*
> > + * Prepare an identity shadow page table that maps all the
> > + * physical pages in VM.
> > + */
> > +void nested_map_memslot(struct kvm_vm *vm, vm_paddr_t guest_pgd,
> > +			uint32_t memslot)
> > +{
> > +	sparsebit_idx_t i, last;
> > +	struct userspace_mem_region *region =
> > +		memslot2region(vm, memslot);
> > +
> > +	i = (region->region.guest_phys_addr >> vm->page_shift) - 1;
> > +	last = i + (region->region.memory_size >> vm->page_shift);
> > +	for (;;) {
> > +		i = sparsebit_next_clear(region->unused_phy_pages, i);
> > +		if (i > last)
> > +			break;
> > +
> > +		nested_map(vm, guest_pgd,
> > +			   (uint64_t)i << vm->page_shift,
> > +			   (uint64_t)i << vm->page_shift,
> > +			   1 << vm->page_shift);
> > +	}
> > +}
> > +
> >  void prepare_l2_stack(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
> >  {
> >  	size_t l2_stack_size;
> > @@ -32,7 +116,16 @@ void prepare_l2_stack(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
> >  
> >  void prepare_hyp_state(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
> >  {
> > -	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_HCR_EL2), HCR_EL2_RW);
> > +	vm_paddr_t guest_pgd;
> > +
> > +	guest_pgd = vm_phy_pages_alloc(vm, 1,
> > +				       KVM_GUEST_PAGE_TABLE_MIN_PADDR,
> > +				       vm->memslots[MEM_REGION_PT]);
> > +	nested_map_memslot(vm, guest_pgd, 0);
> > +
> > +	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_HCR_EL2), HCR_EL2_RW | HCR_EL2_VM);
> > +	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_VTTBR_EL2), guest_pgd);
> > +	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_VTCR_EL2), get_l1_vtcr());
> >  }
> >  
> >  void prepare_eret_destination(struct kvm_vm *vm, struct kvm_vcpu *vcpu, void *l2_pc)
> > -- 
> > 2.43.0
> > 


^ permalink raw reply

* Re: [PATCH v2 0/3] Inline helpers into Rust without full LTO
From: Arnd Bergmann @ 2026-03-26 21:33 UTC (permalink / raw)
  To: Russell King, Christian Schrefl
  Cc: Miguel Ojeda, Alice Ryhl, Ard Biesheuvel, Jamie Cunliffe,
	Will Deacon, Catalin Marinas, Miguel Ojeda, Andreas Hindborg,
	acourbot, Andrew Morton, Anton Ivanov, Björn Roy Baron,
	Boqun Feng, Danilo Krummrich, David Gow, Gary Guo, Johannes Berg,
	Justin Stitt, linux-arm-kernel, linux-kbuild, linux-kernel,
	linux-mm, linux-um, llvm, Benno Lossin, Mark Rutland, mmaurer,
	Bill Wendling, Nathan Chancellor, Nick Desaulniers,
	Nicolas Schier, Nicolas Schier, Peter Zijlstra,
	Richard Weinberger, rust-for-linux, Trevor Gross,
	Uladzislau Rezki (Sony)
In-Reply-To: <acVOL5Psz6kHlhq2@shell.armlinux.org.uk>

On Thu, Mar 26, 2026, at 16:18, Russell King (Oracle) wrote:
> On Thu, Mar 26, 2026 at 03:31:26PM +0100, Christian Schrefl wrote:
>> On 3/26/26 2:47 PM, Miguel Ojeda wrote:
>> > On Thu, Mar 26, 2026 at 11:10 AM Alice Ryhl <aliceryhl@google.com> wrote:
>
> I'm not sure if this is still true, but I believe it used to be the case
> that the -linux-gnueabi target has one behaviour for enums (fixed size)
> whereas -none-eabi, the size of the type depends on the range of values
> included in the enum.

I checked Debian's arm-none-eabi-gcc, which indeed still has this behavior:

$ echo 'enum { A, B } x = sizeof(x);' | arm-none-eabi-gcc -xc - -O2 -o- -S | grep -A1 x:
x:
	.byte	1

and I see the same thing for the hexagon target in clang, but none
of the other targets that Linux runs on. In particular, clang always
behaves like linux-gnueabi even when targeting plain eabi.

$ echo 'enum { A, B } x = sizeof(x);' | clang --target=arm-none-eabi -xc - -O2 -o- -S | grep -A1 x:
x:
	.long	4

I noticed a similar issue with m68k-linux, which has a bitfield
alignment different from anything else on gcc, but uses the normal
behavior on clang.

        Arnd


^ permalink raw reply

* [PATCH v2] arm64: defconfig: Enable Rockchip video decoder
From: Detlev Casanova @ 2026-03-26 21:33 UTC (permalink / raw)
  To: linux-kernel, Heiko Stuebner, linux-arm-kernel, kernel,
	linux-rockchip
  Cc: Detlev Casanova

The rkvdec driver is now out of staging and can be built by default.

Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
---
Changes in v2:
- Update commit message
- Add missing CCs
- Link to v1: https://patch.msgid.link/20260325-rkvdec-add-defconfig-v1-1-89a55d3bb5c4@collabora.com
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index b67d5b1fc45b..4b3f31cb4a94 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -931,6 +931,7 @@ CONFIG_VIDEO_RENESAS_VSP1=m
 CONFIG_VIDEO_RCAR_DRIF=m
 CONFIG_VIDEO_ROCKCHIP_CIF=m
 CONFIG_VIDEO_ROCKCHIP_RGA=m
+CONFIG_VIDEO_ROCKCHIP_VDEC=m
 CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m
 CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m
 CONFIG_VIDEO_SAMSUNG_S5P_MFC=m

---
base-commit: bbeb83d3182abe0d245318e274e8531e5dd7a948
change-id: 20260325-rkvdec-add-defconfig-eaa11ab14f1f

Best regards,
--  
Detlev Casanova <detlev.casanova@collabora.com>



^ permalink raw reply related

* Re: [PATCH v3 00/13] This series adds support for the MediaTek MT7927 (Filogic 380) combo
From: Javier Tia @ 2026-03-26 21:09 UTC (permalink / raw)
  To: Sean Wang
  Cc: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Deren Wu, linux-wireless, linux-kernel,
	linux-arm-kernel, linux-mediatek, Marcin FM,
	Cristian-Florin Radoi, George Salukvadze, Evgeny Kapusta,
	Samu Toljamo, Ariel Rosenfeld, Chapuis Dario,
	Thibaut François, 张旭涵

Hi Sean,

On Wed, Mar 26, 2026 Sean Wang wrote:
> This part patch 1-8 looks good overall. My only concern was a possible
> regression on mt7925, but now that the incorrect mt7925 320 MHz
> support has been fixed  in the version, this should be fine.

Thank you. Patch 5 also had a build error (is_320mhz_supported()
called is_mt7927() before it was defined in patch 6). Fixed in v4
by using mt76_chip() directly.

> I am still thinking a bit more about patches 9-11. My current
> preference is to introduce the generic layer first, and then migrate
> the mt7925 and mt7927-specific parts on top of it.
> I will handle this part on my side, since I want to carefully compare
> the vendor driver with your changes first, and make sure the mt7925
> side is solid before moving the mt7927-related changes forward. For
> the mt7927-related work, I will make sure your contribution, as well
> as the work from the other volunteers, is properly preserved when I
> carry this forward.

Understood. v4 drops patches 9-13 so you have full control over
the DMA, HW init, band_idx, and PCI device ID enablement.

Regarding your feedback on v3 patch 13 (CNM quirk) - you suggested
folding the MT792x_FW_CAP_CNM force into mt792x_get_mac80211_ops()
instead of the post-hoc memcpy. Since the PCI IDs patch is now
part of your series, would you prefer to handle the CNM fix there
as well, or should I send a standalone patch for it ahead of your
DMA/init work?

> Similar to the BT side, I would prefer to have a dedicated Linux
> firmware for mt7927 WiFi.

Noted. The driver currently requests mediatek/mt7927/ paths. Once
a dedicated firmware is available we can adjust if needed.

v4 sent with patches 1-8 + ASPM/PM disable (9 patches):
https://lore.kernel.org/linux-wireless/20260326-mt7927-wifi-support-v4-v4-0-8ab465addcfe@jetm.me/T/#u

Best,
Javier


^ permalink raw reply

* Re: [PATCH 3/3] KVM: arm64: selftests: Enable stage-2 in NV preparation functions
From: Wei-Lin Chang @ 2026-03-26 21:16 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: kvm, linux-kselftest, linux-arm-kernel, kvmarm, linux-kernel,
	Paolo Bonzini, Shuah Khan, Oliver Upton, Joey Gouly,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon
In-Reply-To: <86mrzw468z.wl-maz@kernel.org>

On Wed, Mar 25, 2026 at 09:18:20AM +0000, Marc Zyngier wrote:
> On Wed, 25 Mar 2026 00:36:20 +0000,
> Wei-Lin Chang <weilin.chang@arm.com> wrote:
> > 
> > Introduce library functions for setting up guest stage-2 page tables,
> > then use that to give L2 an identity mapped stage-2 and enable it.
> > 
> > The translation and stage-2 page table built is simple, start level 0,
> > 4 levels, 4KB granules, normal cachable, 48-bit IA, 40-bit OA.
> 
> That's a no go. The most common NV-capable out there can realistically
> only do 16kB at S2, and is limited to 36bit IPA. We can't really
> afford to say "too bad" and leave the main development platform behind.

Interesting, I didn't know that! I didn't consider the guest stage-2
granule size < host stage-2 granule size case either.

> 
> > 
> > The nested page table code is adapted from lib/x86/vmx.c.
> 
> I guess this starting point is the main issue.
> 
> > 
> > Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
> > ---
> >  .../selftests/kvm/include/arm64/nested.h      |  7 ++
> >  .../selftests/kvm/include/arm64/processor.h   |  9 ++
> >  .../testing/selftests/kvm/lib/arm64/nested.c  | 97 ++++++++++++++++++-
> >  3 files changed, 111 insertions(+), 2 deletions(-)
> > 
> > diff --git a/tools/testing/selftests/kvm/include/arm64/nested.h b/tools/testing/selftests/kvm/include/arm64/nested.h
> > index 739ff2ee0161..0be10a775e48 100644
> > --- a/tools/testing/selftests/kvm/include/arm64/nested.h
> > +++ b/tools/testing/selftests/kvm/include/arm64/nested.h
> > @@ -6,6 +6,13 @@
> >  #ifndef SELFTEST_KVM_NESTED_H
> >  #define SELFTEST_KVM_NESTED_H
> >  
> > +uint64_t get_l1_vtcr(void);
> > +
> > +void nested_map(struct kvm_vm *vm, vm_paddr_t guest_pgd,
> > +		uint64_t nested_paddr, uint64_t paddr, uint64_t size);
> > +void nested_map_memslot(struct kvm_vm *vm, vm_paddr_t guest_pgd,
> > +			uint32_t memslot);
> > +
> >  void prepare_l2_stack(struct kvm_vm *vm, struct kvm_vcpu *vcpu);
> >  void prepare_hyp_state(struct kvm_vm *vm, struct kvm_vcpu *vcpu);
> >  void prepare_eret_destination(struct kvm_vm *vm, struct kvm_vcpu *vcpu, void *l2_pc);
> > diff --git a/tools/testing/selftests/kvm/include/arm64/processor.h b/tools/testing/selftests/kvm/include/arm64/processor.h
> > index ac97a1c436fc..5de2e932d95a 100644
> > --- a/tools/testing/selftests/kvm/include/arm64/processor.h
> > +++ b/tools/testing/selftests/kvm/include/arm64/processor.h
> > @@ -104,6 +104,15 @@
> >  #define TCR_HA			(UL(1) << 39)
> >  #define TCR_DS			(UL(1) << 59)
> >  
> > +/* VTCR_EL2 specific flags */
> > +#define VTCR_EL2_T0SZ_BITS(x)	((UL(64) - (x)) << VTCR_EL2_T0SZ_SHIFT)
> > +
> > +#define VTCR_EL2_SL0_LV0_4K	(UL(2) << VTCR_EL2_SL0_SHIFT)
> > +#define VTCR_EL2_SL0_LV1_4K	(UL(1) << VTCR_EL2_SL0_SHIFT)
> > +#define VTCR_EL2_SL0_LV2_4K	(UL(0) << VTCR_EL2_SL0_SHIFT)
> > +
> > +#define VTCR_EL2_PS_40_BITS	(UL(2) << VTCR_EL2_PS_SHIFT)
> > +
> >  /*
> >   * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
> >   */
> > diff --git a/tools/testing/selftests/kvm/lib/arm64/nested.c b/tools/testing/selftests/kvm/lib/arm64/nested.c
> > index 111d02f44cfe..910f8cd30f96 100644
> > --- a/tools/testing/selftests/kvm/lib/arm64/nested.c
> > +++ b/tools/testing/selftests/kvm/lib/arm64/nested.c
> > @@ -1,8 +1,11 @@
> >  // SPDX-License-Identifier: GPL-2.0
> >  /*
> > - * ARM64 Nested virtualization helpers
> > + * ARM64 Nested virtualization helpers, nested page table code adapted from
> > + * ../x86/vmx.c.
> >   */
> >  
> > +#include <linux/sizes.h>
> > +
> >  #include "kvm_util.h"
> >  #include "nested.h"
> >  #include "processor.h"
> > @@ -18,6 +21,87 @@ static void hvc_handler(struct ex_regs *regs)
> >  	regs->pc = (u64)after_hvc;
> >  }
> >  
> > +uint64_t get_l1_vtcr(void)
> > +{
> > +	return VTCR_EL2_PS_40_BITS | VTCR_EL2_TG0_4K | VTCR_EL2_ORGN0_WBWA |
> > +	       VTCR_EL2_IRGN0_WBWA | VTCR_EL2_SL0_LV0_4K | VTCR_EL2_T0SZ_BITS(48);
> 
> Irk. See above.
> 
> > +}
> > +
> > +static void __nested_pg_map(struct kvm_vm *vm, uint64_t guest_pgd,
> > +		     uint64_t nested_paddr, uint64_t paddr, uint64_t flags)
> > +{
> > +	uint8_t attr_idx = flags & (PTE_ATTRINDX_MASK >> PTE_ATTRINDX_SHIFT);
> > +	uint64_t pg_attr;
> > +	uint64_t *ptep;
> > +
> > +	TEST_ASSERT((nested_paddr % vm->page_size) == 0,
> > +		"L2 IPA not on page boundary,\n"
> > +		"  nested_paddr: 0x%lx vm->page_size: 0x%x", nested_paddr, vm->page_size);
> > +	TEST_ASSERT((paddr % vm->page_size) == 0,
> > +		"Guest physical address not on page boundary,\n"
> > +		"  paddr: 0x%lx vm->page_size: 0x%x", paddr, vm->page_size);
> > +	TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
> > +		"Physical address beyond maximum supported,\n"
> > +		"  paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
> > +		paddr, vm->max_gfn, vm->page_size);
> > +
> > +	ptep = addr_gpa2hva(vm, guest_pgd) + ((nested_paddr >> 39) & 0x1ffu) * 8;
> > +	if (!*ptep)
> > +		*ptep = (vm_alloc_page_table(vm) & GENMASK(47, 12)) | PGD_TYPE_TABLE | PTE_VALID;
> > +	ptep = addr_gpa2hva(vm, *ptep & GENMASK(47, 12)) + ((nested_paddr >> 30) & 0x1ffu) * 8;
> > +	if (!*ptep)
> > +		*ptep = (vm_alloc_page_table(vm) & GENMASK(47, 12)) | PUD_TYPE_TABLE | PTE_VALID;
> > +	ptep = addr_gpa2hva(vm, *ptep & GENMASK(47, 12)) + ((nested_paddr >> 21) & 0x1ffu) * 8;
> > +	if (!*ptep)
> > +		*ptep = (vm_alloc_page_table(vm) & GENMASK(47, 12)) | PMD_TYPE_TABLE | PTE_VALID;
> > +	ptep = addr_gpa2hva(vm, *ptep & GENMASK(47, 12)) + ((nested_paddr >> 12) & 0x1ffu) * 8;
> > +
> > +	pg_attr = PTE_AF | PTE_ATTRINDX(attr_idx) | PTE_TYPE_PAGE | PTE_VALID;
> > +	pg_attr |= PTE_SHARED;
> > +
> > +	*ptep = (paddr & GENMASK(47, 12)) | pg_attr;
> 
> Please use named constants, and write a page table generator that is
> independent of page, IA and OA sizes, as advertised to the guest.

Ack, and yes, I should absolutely consider what is advertised to the
guest...

Thanks,
Wei-Lin Chang

> 
> Thanks,
> 
> 	M.
> 
> -- 
> Without deviation from the norm, progress is not possible.


^ permalink raw reply

* Re: [PATCH v2 0/3] Inline helpers into Rust without full LTO
From: Arnd Bergmann @ 2026-03-26 21:12 UTC (permalink / raw)
  To: Miguel Ojeda, Marek Szyprowski, Robin Murphy, Danilo Krummrich,
	Abdiel Janulgue, Daniel Almeida, Andreas Hindborg,
	Christoph Hellwig
  Cc: iommu, driver-core, acourbot, Andrew Morton, Alice Ryhl,
	Anton Ivanov, Björn Roy Baron, Boqun Feng, David Gow,
	Gary Guo, Johannes Berg, Justin Stitt, linux-arm-kernel,
	linux-kbuild, linux-kernel, linux-mm, linux-um, Russell King,
	llvm, Benno Lossin, Mark Rutland, mmaurer, Bill Wendling,
	Nathan Chancellor, Nick Desaulniers, Nicolas Schier,
	Nicolas Schier, Peter Zijlstra, Richard Weinberger,
	rust-for-linux, Trevor Gross, Uladzislau Rezki (Sony),
	Will Deacon, Geert Uytterhoeven
In-Reply-To: <20260322194616.89847-1-ojeda@kernel.org>

On Sun, Mar 22, 2026, at 20:46, Miguel Ojeda wrote:
> On Sun, 22 Mar 2026 20:21:59 +0100 Miguel Ojeda <ojeda@kernel.org> wrote:
>>
>       BINDGEN rust/bindings/bindings_generated.rs - due to target 
> missing
>     In file included from rust/helpers/helpers.c:59:
>     rust/helpers/dma.c:17:2: warning: static function 'dma_free_attrs' 
> is used in an inline function with external linkage [-Wstatic-in-inline]
>        17 |         dma_free_attrs(dev, size, cpu_addr, dma_handle, 
> attrs);
>           |         ^
>     rust/helpers/dma.c:12:1: note: use 'static' to give inline function 
> 'rust_helper_dma_free_attrs' internal linkage
>        12 | __rust_helper void rust_helper_dma_free_attrs(struct device 
> *dev, size_t size,
>           | ^
>           | static
>
> For some reason, `dma_free_attrs` is not marked `inline` in
> `include/linux/dma-mapping.h` to begin with, unlike the rest.
>
> Unless I am missing something and there is a reason for that, it looks
> like it has just been missing since it was added in commit ed6ccf10f24b
> ("dma-mapping: properly stub out the DMA API for !CONFIG_HAS_DMA").
>
> Do you want a patch?

I have an older patch to drop CONFIG_NO_DMA entirely, which 
may be better here, since we know that nobody cares about the
empty stubs.

The only targets that 'select NO_DMA' today are m68k (sun3
and dragonball), sh2 and um, which are some of the targets
that don't have any DMA masters, but there is little downside
of enabling the DMA mapping interfaces on those as well.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>

diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 11835eb59d94..19fb556357fc 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -38,7 +38,6 @@ config M68K
 	select MMU_GATHER_NO_RANGE if MMU
 	select MODULES_USE_ELF_REL
 	select MODULES_USE_ELF_RELA
-	select NO_DMA if !MMU && !COLDFIRE
 	select OLD_SIGACTION
 	select OLD_SIGSUSPEND3
 	select UACCESS_MEMCPY if !MMU
diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu
index c9a7e602d8a4..adc50396b87d 100644
--- a/arch/m68k/Kconfig.cpu
+++ b/arch/m68k/Kconfig.cpu
@@ -38,7 +38,6 @@ config SUN3
 	depends on MMU
 	select HAVE_ARCH_PFN_VALID
 	select LEGACY_TIMER_TICK
-	select NO_DMA
 	select M68020
 	help
 	  This option enables support for the Sun 3 series of workstations
@@ -558,4 +557,4 @@ config COLDFIRE_COHERENT_DMA
 config M68K_NONCOHERENT_DMA
 	bool
 	default y
-	depends on HAS_DMA && !COLDFIRE_COHERENT_DMA
+	depends on HAS_DMA && !COLDFIRE_COHERENT_DMA && !SUN3
diff --git a/arch/m68k/include/asm/pgtable_mm.h b/arch/m68k/include/asm/pgtable_mm.h
index 7501ff030c63..d095ae6c19f9 100644
--- a/arch/m68k/include/asm/pgtable_mm.h
+++ b/arch/m68k/include/asm/pgtable_mm.h
@@ -159,8 +159,10 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
 	    ? (__pgprot((pgprot_val(prot) & _CACHEMASK040) | _PAGE_NOCACHE_S))	\
 	    : (prot)))
 
+#ifndef CONFIG_SUN3
 pgprot_t pgprot_dmacoherent(pgprot_t prot);
 #define pgprot_dmacoherent(prot)	pgprot_dmacoherent(prot)
+#endif
 
 #endif /* CONFIG_COLDFIRE */
 #endif /* !__ASSEMBLER__ */
diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c
index 16063783aa80..c52584e024af 100644
--- a/arch/m68k/kernel/dma.c
+++ b/arch/m68k/kernel/dma.c
@@ -8,7 +8,7 @@
 #include <linux/kernel.h>
 #include <asm/cacheflush.h>
 
-#ifndef CONFIG_COLDFIRE
+#if !defined(CONFIG_COLDFIRE) && !defined(CONFIG_SUN3)
 void arch_dma_prep_coherent(struct page *page, size_t size)
 {
 	cache_push(page_to_phys(page), size);
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index d5795067befa..e246f295ec48 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -63,7 +63,6 @@ config SUPERH
 	select LOCK_MM_AND_FIND_VMA
 	select MODULES_USE_ELF_RELA
 	select NEED_SG_DMA_LENGTH
-	select NO_DMA if !MMU && !DMA_COHERENT
 	select NO_GENERIC_PCI_IOPORT_MAP if PCI
 	select OLD_SIGACTION
 	select OLD_SIGSUSPEND
@@ -133,10 +132,10 @@ config SWAP_IO_SPACE
 	bool
 
 config DMA_COHERENT
-	bool
+	def_bool !MMU
 
 config DMA_NONCOHERENT
-	def_bool !NO_DMA && !DMA_COHERENT
+	def_bool !DMA_COHERENT
 	select ARCH_HAS_DMA_PREP_COHERENT
 	select ARCH_HAS_SYNC_DMA_FOR_DEVICE
 	select DMA_DIRECT_REMAP
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 098cda44db22..dd3428a49614 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -25,7 +25,6 @@ config UML
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_PAGE_SIZE_4KB
-	select NO_DMA if !UML_DMA_EMULATION
 	select OF_EARLY_FLATTREE if OF
 	select GENERIC_IRQ_SHOW
 	select GENERIC_CPU_DEVICES
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 677c51ab7510..a96a22f857f1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -138,7 +138,6 @@ static inline void debug_dma_map_single(struct device *dev, const void *addr,
 }
 #endif /* CONFIG_DMA_API_DEBUG */
 
-#ifdef CONFIG_HAS_DMA
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
 	debug_dma_mapping_error(dev, dma_addr);
@@ -200,146 +199,6 @@ void *dma_vmap_noncontiguous(struct device *dev, size_t size,
 void dma_vunmap_noncontiguous(struct device *dev, void *vaddr);
 int dma_mmap_noncontiguous(struct device *dev, struct vm_area_struct *vma,
 		size_t size, struct sg_table *sgt);
-#else /* CONFIG_HAS_DMA */
-static inline dma_addr_t dma_map_page_attrs(struct device *dev,
-		struct page *page, size_t offset, size_t size,
-		enum dma_data_direction dir, unsigned long attrs)
-{
-	return DMA_MAPPING_ERROR;
-}
-static inline void dma_unmap_page_attrs(struct device *dev, dma_addr_t addr,
-		size_t size, enum dma_data_direction dir, unsigned long attrs)
-{
-}
-static inline dma_addr_t dma_map_phys(struct device *dev, phys_addr_t phys,
-		size_t size, enum dma_data_direction dir, unsigned long attrs)
-{
-	return DMA_MAPPING_ERROR;
-}
-static inline void dma_unmap_phys(struct device *dev, dma_addr_t addr,
-		size_t size, enum dma_data_direction dir, unsigned long attrs)
-{
-}
-static inline unsigned int dma_map_sg_attrs(struct device *dev,
-		struct scatterlist *sg, int nents, enum dma_data_direction dir,
-		unsigned long attrs)
-{
-	return 0;
-}
-static inline void dma_unmap_sg_attrs(struct device *dev,
-		struct scatterlist *sg, int nents, enum dma_data_direction dir,
-		unsigned long attrs)
-{
-}
-static inline int dma_map_sgtable(struct device *dev, struct sg_table *sgt,
-		enum dma_data_direction dir, unsigned long attrs)
-{
-	return -EOPNOTSUPP;
-}
-static inline dma_addr_t dma_map_resource(struct device *dev,
-		phys_addr_t phys_addr, size_t size, enum dma_data_direction dir,
-		unsigned long attrs)
-{
-	return DMA_MAPPING_ERROR;
-}
-static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
-		size_t size, enum dma_data_direction dir, unsigned long attrs)
-{
-}
-static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-	return -ENOMEM;
-}
-static inline void *dma_alloc_attrs(struct device *dev, size_t size,
-		dma_addr_t *dma_handle, gfp_t flag, unsigned long attrs)
-{
-	return NULL;
-}
-static inline void dma_free_attrs(struct device *dev, size_t size,
-		void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
-{
-}
-static inline void *dmam_alloc_attrs(struct device *dev, size_t size,
-		dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
-{
-	return NULL;
-}
-static inline void dmam_free_coherent(struct device *dev, size_t size,
-		void *vaddr, dma_addr_t dma_handle)
-{
-}
-static inline int dma_get_sgtable_attrs(struct device *dev,
-		struct sg_table *sgt, void *cpu_addr, dma_addr_t dma_addr,
-		size_t size, unsigned long attrs)
-{
-	return -ENXIO;
-}
-static inline int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
-		void *cpu_addr, dma_addr_t dma_addr, size_t size,
-		unsigned long attrs)
-{
-	return -ENXIO;
-}
-static inline bool dma_can_mmap(struct device *dev)
-{
-	return false;
-}
-static inline bool dma_pci_p2pdma_supported(struct device *dev)
-{
-	return false;
-}
-static inline int dma_set_mask(struct device *dev, u64 mask)
-{
-	return -EIO;
-}
-static inline int dma_set_coherent_mask(struct device *dev, u64 mask)
-{
-	return -EIO;
-}
-static inline u64 dma_get_required_mask(struct device *dev)
-{
-	return 0;
-}
-static inline bool dma_addressing_limited(struct device *dev)
-{
-	return false;
-}
-static inline size_t dma_max_mapping_size(struct device *dev)
-{
-	return 0;
-}
-static inline size_t dma_opt_mapping_size(struct device *dev)
-{
-	return 0;
-}
-static inline unsigned long dma_get_merge_boundary(struct device *dev)
-{
-	return 0;
-}
-static inline struct sg_table *dma_alloc_noncontiguous(struct device *dev,
-		size_t size, enum dma_data_direction dir, gfp_t gfp,
-		unsigned long attrs)
-{
-	return NULL;
-}
-static inline void dma_free_noncontiguous(struct device *dev, size_t size,
-		struct sg_table *sgt, enum dma_data_direction dir)
-{
-}
-static inline void *dma_vmap_noncontiguous(struct device *dev, size_t size,
-		struct sg_table *sgt)
-{
-	return NULL;
-}
-static inline void dma_vunmap_noncontiguous(struct device *dev, void *vaddr)
-{
-}
-static inline int dma_mmap_noncontiguous(struct device *dev,
-		struct vm_area_struct *vma, size_t size, struct sg_table *sgt)
-{
-	return -EINVAL;
-}
-#endif /* CONFIG_HAS_DMA */
 
 #ifdef CONFIG_IOMMU_DMA
 /**
diff --git a/kernel/dma/Kconfig b/kernel/dma/Kconfig
index 0748091339f7..228a3566d344 100644
--- a/kernel/dma/Kconfig
+++ b/kernel/dma/Kconfig
@@ -1,12 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
-config NO_DMA
-	bool
-
 config HAS_DMA
-	bool
-	depends on !NO_DMA
-	default y
+	def_bool y
 
 config DMA_OPS_HELPERS
 	bool


^ permalink raw reply related

* [PATCH v4 8/9] wifi: mt76: mt7925: use irq_map for chip-specific interrupt handling
From: Javier Tia @ 2026-03-26 21:12 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Deren Wu
  Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
	Marcin FM, Cristian-Florin Radoi, George Salukvadze,
	Evgeny Kapusta, Samu Toljamo, Ariel Rosenfeld, Chapuis Dario,
	Thibaut François, 张旭涵
In-Reply-To: <20260326-mt7927-wifi-support-v4-v4-0-8ab465addcfe@jetm.me>

The mac_reset and resume paths use the hardcoded MT_INT_RX_DONE_ALL
constant (bits 0-2) to re-enable RX interrupts. This is correct for
MT7925 (RX rings 0, 1, 2) but wrong for chips using different ring
indices.

Define a per-chip irq_map with the correct RX interrupt enable bits and
replace hardcoded MT_INT_RX_DONE_ALL with irq_map field reads in the
resume and mac_reset paths. Add the MT7927 irq_map with interrupt bits
matching its RX ring layout (rings 4, 6, 7), selected at probe time
based on PCI device ID.

This ensures the correct interrupt bits are enabled regardless of the
chip variant.

Tested-by: Marcin FM <marcin@lgic.pl>
Tested-by: Cristian-Florin Radoi <radoi.chris@gmail.com>
Tested-by: George Salukvadze <giosal90@gmail.com>
Tested-by: Evgeny Kapusta <3193631@gmail.com>
Tested-by: Samu Toljamo <samu.toljamo@gmail.com>
Tested-by: Ariel Rosenfeld <ariel.rosenfeld.750@gmail.com>
Tested-by: Chapuis Dario <chapuisdario4@gmail.com>
Tested-by: Thibaut François <tibo@humeurlibre.fr>
Tested-by: 张旭涵 <Loong.0x00@gmail.com>
Signed-off-by: Javier Tia <floss@jetm.me>
---
 drivers/net/wireless/mediatek/mt76/mt7925/pci.c     | 21 +++++++++++++++++++--
 drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c |  5 ++++-
 drivers/net/wireless/mediatek/mt76/mt792x_regs.h    |  3 +++
 3 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index f820d5aeb723..604c0e9ae7ba 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -266,6 +266,18 @@ static int mt7925_dma_init(struct mt792x_dev *dev)
 	return mt792x_dma_enable(dev);
 }
 
+static const struct mt792x_irq_map mt7927_irq_map = {
+	.host_irq_enable = MT_WFDMA0_HOST_INT_ENA,
+	.tx = {
+		.all_complete_mask = MT_INT_TX_DONE_ALL,
+		.mcu_complete_mask = MT_INT_TX_DONE_MCU,
+	},
+	.rx = {
+		.data_complete_mask = MT7927_RX_DONE_INT_ENA4,
+		.wm_complete_mask = MT7927_RX_DONE_INT_ENA6,
+		.wm2_complete_mask = MT7927_RX_DONE_INT_ENA7,
+	},
+};
 static int mt7925_pci_probe(struct pci_dev *pdev,
 			    const struct pci_device_id *id)
 {
@@ -310,6 +322,7 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
 	struct mt76_bus_ops *bus_ops;
 	struct mt792x_dev *dev;
 	struct mt76_dev *mdev;
+	bool is_mt7927_hw;
 	u8 features;
 	int ret;
 	u16 cmd;
@@ -358,7 +371,8 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
 	dev = container_of(mdev, struct mt792x_dev, mt76);
 	dev->fw_features = features;
 	dev->hif_ops = &mt7925_pcie_ops;
-	dev->irq_map = &irq_map;
+	is_mt7927_hw = (pdev->device == 0x6639 || pdev->device == 0x7927);
+	dev->irq_map = is_mt7927_hw ? &mt7927_irq_map : &irq_map;
 	mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
 	tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);
 
@@ -549,7 +563,10 @@ static int _mt7925_pci_resume(struct device *device, bool restore)
 	mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
 	mt76_connac_irq_enable(&dev->mt76,
 			       dev->irq_map->tx.all_complete_mask |
-			       MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
+			       dev->irq_map->rx.data_complete_mask |
+			       dev->irq_map->rx.wm_complete_mask |
+			       dev->irq_map->rx.wm2_complete_mask |
+			       MT_INT_MCU_CMD);
 	mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE);
 
 	/* put dma enabled */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
index 3072850c2752..1626a3684082 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
@@ -118,7 +118,10 @@ int mt7925e_mac_reset(struct mt792x_dev *dev)
 
 	mt76_wr(dev, dev->irq_map->host_irq_enable,
 		dev->irq_map->tx.all_complete_mask |
-		MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
+		dev->irq_map->rx.data_complete_mask |
+		dev->irq_map->rx.wm_complete_mask |
+		dev->irq_map->rx.wm2_complete_mask |
+		MT_INT_MCU_CMD);
 	mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
 
 	err = mt792xe_mcu_fw_pmctrl(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
index acf627aed609..a8c8d7d6f565 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
@@ -308,6 +308,9 @@
 #define HOST_RX_DONE_INT_ENA1		BIT(1)
 #define HOST_RX_DONE_INT_ENA2		BIT(2)
 #define HOST_RX_DONE_INT_ENA3		BIT(3)
+#define MT7927_RX_DONE_INT_ENA4		BIT(12)
+#define MT7927_RX_DONE_INT_ENA6		BIT(14)
+#define MT7927_RX_DONE_INT_ENA7		BIT(15)
 #define HOST_TX_DONE_INT_ENA0		BIT(4)
 #define HOST_TX_DONE_INT_ENA1		BIT(5)
 #define HOST_TX_DONE_INT_ENA2		BIT(6)

-- 
2.53.0



^ permalink raw reply related

* [PATCH v4 4/9] wifi: mt76: mt7925: populate EHT 320MHz MCS map in sta_rec
From: Javier Tia @ 2026-03-26 21:12 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Deren Wu
  Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
	Marcin FM, Cristian-Florin Radoi, George Salukvadze,
	Evgeny Kapusta, Samu Toljamo, Ariel Rosenfeld, Chapuis Dario,
	Thibaut François, 张旭涵
In-Reply-To: <20260326-mt7927-wifi-support-v4-v4-0-8ab465addcfe@jetm.me>

The sta_rec_eht structure has a mcs_map_bw320 field, and the channel
width mapping includes NL80211_CHAN_WIDTH_320, but the 320MHz MCS/NSS
map was never copied from the station's EHT capabilities to the MCU TLV.
This prevents negotiation of 320MHz channel width even when both the
hardware and firmware advertise support for it.

Add the missing memcpy for the 320MHz MCS map, matching the existing
pattern for BW20, BW80, and BW160.

Tested-by: Marcin FM <marcin@lgic.pl>
Tested-by: Cristian-Florin Radoi <radoi.chris@gmail.com>
Tested-by: George Salukvadze <giosal90@gmail.com>
Tested-by: Evgeny Kapusta <3193631@gmail.com>
Tested-by: Samu Toljamo <samu.toljamo@gmail.com>
Tested-by: Ariel Rosenfeld <ariel.rosenfeld.750@gmail.com>
Tested-by: Chapuis Dario <chapuisdario4@gmail.com>
Tested-by: Thibaut François <tibo@humeurlibre.fr>
Tested-by: 张旭涵 <Loong.0x00@gmail.com>
Signed-off-by: Javier Tia <floss@jetm.me>
---
 drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index dd5ecb07947b..a7f27c5014d5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -1683,6 +1683,7 @@ mt7925_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta)
 		memcpy(eht->mcs_map_bw20, &mcs_map->only_20mhz, sizeof(eht->mcs_map_bw20));
 	memcpy(eht->mcs_map_bw80, &mcs_map->bw._80, sizeof(eht->mcs_map_bw80));
 	memcpy(eht->mcs_map_bw160, &mcs_map->bw._160, sizeof(eht->mcs_map_bw160));
+	memcpy(eht->mcs_map_bw320, &mcs_map->bw._320, sizeof(eht->mcs_map_bw320));
 }
 
 static void

-- 
2.53.0



^ permalink raw reply related

* [PATCH v4 6/9] wifi: mt76: mt7925: add MT7927 chip ID helpers
From: Javier Tia @ 2026-03-26 21:12 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Deren Wu
  Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
	Marcin FM, Cristian-Florin Radoi, George Salukvadze,
	Evgeny Kapusta, Samu Toljamo, Ariel Rosenfeld, Chapuis Dario,
	Thibaut François, 张旭涵
In-Reply-To: <20260326-mt7927-wifi-support-v4-v4-0-8ab465addcfe@jetm.me>

The MediaTek MT7927 (Filogic 380) combo chip uses MT7927 WiFi silicon
that is architecturally compatible with MT7925. Extend is_mt7925() to
match chip ID 0x7927, and add is_mt7927() for code paths that need
MT7927-specific handling.

Also add 0x7927 to is_mt76_fw_txp() to match MT7925's TXP format.

Tested-by: Marcin FM <marcin@lgic.pl>
Tested-by: Cristian-Florin Radoi <radoi.chris@gmail.com>
Tested-by: George Salukvadze <giosal90@gmail.com>
Tested-by: Evgeny Kapusta <3193631@gmail.com>
Tested-by: Samu Toljamo <samu.toljamo@gmail.com>
Tested-by: Ariel Rosenfeld <ariel.rosenfeld.750@gmail.com>
Tested-by: Chapuis Dario <chapuisdario4@gmail.com>
Tested-by: Thibaut François <tibo@humeurlibre.fr>
Tested-by: 张旭涵 <Loong.0x00@gmail.com>
Signed-off-by: Javier Tia <floss@jetm.me>
---
 drivers/net/wireless/mediatek/mt76/mt76_connac.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
index 393a7952f86b..4a63ef4e5c34 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
@@ -174,7 +174,12 @@ extern const struct wiphy_wowlan_support mt76_connac_wowlan_support;
 
 static inline bool is_mt7925(struct mt76_dev *dev)
 {
-	return mt76_chip(dev) == 0x7925;
+	return mt76_chip(dev) == 0x7925 || mt76_chip(dev) == 0x7927;
+}
+
+static inline bool is_mt7927(struct mt76_dev *dev)
+{
+	return mt76_chip(dev) == 0x7927;
 }
 
 static inline bool is_320mhz_supported(struct mt76_dev *dev)
@@ -277,6 +282,7 @@ static inline bool is_mt76_fw_txp(struct mt76_dev *dev)
 	case 0x7920:
 	case 0x7922:
 	case 0x7925:
+	case 0x7927:
 	case 0x7663:
 	case 0x7622:
 		return false;

-- 
2.53.0



^ permalink raw reply related

* [PATCH v4 9/9] wifi: mt76: mt7925: disable ASPM and runtime PM for MT7927
From: Javier Tia @ 2026-03-26 21:12 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Deren Wu
  Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek
In-Reply-To: <20260326-mt7927-wifi-support-v4-v4-0-8ab465addcfe@jetm.me>

Disable PCIe ASPM unconditionally for MT7927. The CONNINFRA power
domain and WFDMA register access are unreliable with PCIe L1 active,
causing throughput to drop from 1+ Gbps to ~200 Mbps.

Disable runtime PM and deep sleep for MT7927. The combo chip shares
a CONNINFRA power domain between WiFi (PCIe) and BT (USB).
SET_OWN/CLR_OWN transitions on the LPCTL register crash the BT
firmware, requiring a full power cycle to recover. PM enablement will
be addressed in a follow-up once safe power state transitions are
determined.

Signed-off-by: Javier Tia <floss@jetm.me>
---
 drivers/net/wireless/mediatek/mt76/mt7925/init.c | 3 ++-
 drivers/net/wireless/mediatek/mt76/mt7925/pci.c  | 6 ++++--
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/init.c b/drivers/net/wireless/mediatek/mt76/mt7925/init.c
index 3ce5d6fcc69d..4766b9343953 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/init.c
@@ -230,7 +230,8 @@ int mt7925_register_device(struct mt792x_dev *dev)
 	dev->pm.idle_timeout = MT792x_PM_TIMEOUT;
 	dev->pm.stats.last_wake_event = jiffies;
 	dev->pm.stats.last_doze_event = jiffies;
-	if (!mt76_is_usb(&dev->mt76)) {
+	/* MT7927: runtime PM crashes BT firmware on the shared CONNINFRA domain */
+	if (!mt76_is_usb(&dev->mt76) && !is_mt7927(&dev->mt76)) {
 		dev->pm.enable_user = true;
 		dev->pm.enable = true;
 		dev->pm.ds_enable_user = true;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index 604c0e9ae7ba..1f05c212be02 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -350,7 +350,10 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
 	if (ret)
 		goto err_free_pci_vec;
 
-	if (mt7925_disable_aspm)
+	is_mt7927_hw = (pdev->device == 0x6639 || pdev->device == 0x7927);
+
+	/* MT7927: ASPM L1 causes unreliable WFDMA register access */
+	if (mt7925_disable_aspm || is_mt7927_hw)
 		mt76_pci_disable_aspm(pdev);
 
 	ops = mt792x_get_mac80211_ops(&pdev->dev, &mt7925_ops,
@@ -371,7 +374,6 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
 	dev = container_of(mdev, struct mt792x_dev, mt76);
 	dev->fw_features = features;
 	dev->hif_ops = &mt7925_pcie_ops;
-	is_mt7927_hw = (pdev->device == 0x6639 || pdev->device == 0x7927);
 	dev->irq_map = is_mt7927_hw ? &mt7927_irq_map : &irq_map;
 	mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
 	tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);

-- 
2.53.0



^ permalink raw reply related

* [PATCH v4 7/9] wifi: mt76: mt7925: add MT7927 firmware paths
From: Javier Tia @ 2026-03-26 21:12 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Deren Wu
  Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
	Marcin FM, Cristian-Florin Radoi, George Salukvadze,
	Evgeny Kapusta, Samu Toljamo, Ariel Rosenfeld, Chapuis Dario,
	Thibaut François, 张旭涵
In-Reply-To: <20260326-mt7927-wifi-support-v4-v4-0-8ab465addcfe@jetm.me>

Add firmware path definitions for MT7927 WiFi firmware (WIFI_RAM_CODE
and PATCH_MCU) and the corresponding MODULE_FIRMWARE declarations. Add
MT7927 cases to mt792x_ram_name() and mt792x_patch_name() so the driver
loads the correct firmware for the 0x7927 chip ID.

PCI device table entries are deferred to a later patch to allow
infrastructure setup before device enablement.

Tested-by: Marcin FM <marcin@lgic.pl>
Tested-by: Cristian-Florin Radoi <radoi.chris@gmail.com>
Tested-by: George Salukvadze <giosal90@gmail.com>
Tested-by: Evgeny Kapusta <3193631@gmail.com>
Tested-by: Samu Toljamo <samu.toljamo@gmail.com>
Tested-by: Ariel Rosenfeld <ariel.rosenfeld.750@gmail.com>
Tested-by: Chapuis Dario <chapuisdario4@gmail.com>
Tested-by: Thibaut François <tibo@humeurlibre.fr>
Tested-by: 张旭涵 <Loong.0x00@gmail.com>
Signed-off-by: Javier Tia <floss@jetm.me>
---
 drivers/net/wireless/mediatek/mt76/mt7925/pci.c | 2 ++
 drivers/net/wireless/mediatek/mt76/mt792x.h     | 6 ++++++
 2 files changed, 8 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index c4161754c01d..f820d5aeb723 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -633,6 +633,8 @@ module_pci_driver(mt7925_pci_driver);
 MODULE_DEVICE_TABLE(pci, mt7925_pci_device_table);
 MODULE_FIRMWARE(MT7925_FIRMWARE_WM);
 MODULE_FIRMWARE(MT7925_ROM_PATCH);
+MODULE_FIRMWARE(MT7927_FIRMWARE_WM);
+MODULE_FIRMWARE(MT7927_ROM_PATCH);
 MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>");
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
 MODULE_DESCRIPTION("MediaTek MT7925E (PCIe) wireless driver");
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index 8388638ed550..38790ef83e51 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -45,11 +45,13 @@
 #define MT7921_FIRMWARE_WM	"mediatek/WIFI_RAM_CODE_MT7961_1.bin"
 #define MT7922_FIRMWARE_WM	"mediatek/WIFI_RAM_CODE_MT7922_1.bin"
 #define MT7925_FIRMWARE_WM	"mediatek/mt7925/WIFI_RAM_CODE_MT7925_1_1.bin"
+#define MT7927_FIRMWARE_WM	"mediatek/mt7927/WIFI_RAM_CODE_MT6639_2_1.bin"
 
 #define MT7920_ROM_PATCH	"mediatek/WIFI_MT7961_patch_mcu_1a_2_hdr.bin"
 #define MT7921_ROM_PATCH	"mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"
 #define MT7922_ROM_PATCH	"mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin"
 #define MT7925_ROM_PATCH	"mediatek/mt7925/WIFI_MT7925_PATCH_MCU_1_1_hdr.bin"
+#define MT7927_ROM_PATCH	"mediatek/mt7927/WIFI_MT6639_PATCH_MCU_2_1_hdr.bin"
 
 #define MT792x_SDIO_HDR_TX_BYTES	GENMASK(15, 0)
 #define MT792x_SDIO_HDR_PKT_TYPE	GENMASK(17, 16)
@@ -454,6 +456,8 @@ static inline char *mt792x_ram_name(struct mt792x_dev *dev)
 		return MT7922_FIRMWARE_WM;
 	case 0x7925:
 		return MT7925_FIRMWARE_WM;
+	case 0x7927:
+		return MT7927_FIRMWARE_WM;
 	default:
 		return MT7921_FIRMWARE_WM;
 	}
@@ -468,6 +472,8 @@ static inline char *mt792x_patch_name(struct mt792x_dev *dev)
 		return MT7922_ROM_PATCH;
 	case 0x7925:
 		return MT7925_ROM_PATCH;
+	case 0x7927:
+		return MT7927_ROM_PATCH;
 	default:
 		return MT7921_ROM_PATCH;
 	}

-- 
2.53.0



^ permalink raw reply related

* [PATCH v4 5/9] wifi: mt76: mt7925: advertise EHT 320MHz capabilities for 6GHz band
From: Javier Tia @ 2026-03-26 21:12 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Deren Wu
  Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
	Marcin FM, Cristian-Florin Radoi, George Salukvadze,
	Evgeny Kapusta, Samu Toljamo, Ariel Rosenfeld, Chapuis Dario,
	Thibaut François, 张旭涵
In-Reply-To: <20260326-mt7927-wifi-support-v4-v4-0-8ab465addcfe@jetm.me>

mt7925_init_eht_caps() only populates EHT MCS/NSS maps for BW <= 80
and BW = 160, but never sets BW = 320. This means iw phy shows no
320MHz MCS map entries even though the hardware supports 320MHz
operation in the 6GHz band.

Add the missing 320MHz capability bits for 6GHz:
  - PHY_CAP0: IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ
  - PHY_CAP1: beamformee SS for 320MHz
  - PHY_CAP2: sounding dimensions for 320MHz
  - PHY_CAP6: MCS15 support for 320MHz width
  - MCS/NSS: populate bw._320 maps for 6GHz band

Introduce is_320mhz_supported() to gate 320MHz on MT7927 only, since
MT7925 does not support 320MHz operation.

Tested-by: Marcin FM <marcin@lgic.pl>
Tested-by: Cristian-Florin Radoi <radoi.chris@gmail.com>
Tested-by: George Salukvadze <giosal90@gmail.com>
Tested-by: Evgeny Kapusta <3193631@gmail.com>
Tested-by: Samu Toljamo <samu.toljamo@gmail.com>
Tested-by: Ariel Rosenfeld <ariel.rosenfeld.750@gmail.com>
Tested-by: Chapuis Dario <chapuisdario4@gmail.com>
Tested-by: Thibaut François <tibo@humeurlibre.fr>
Tested-by: 张旭涵 <Loong.0x00@gmail.com>
Signed-off-by: Javier Tia <floss@jetm.me>
---
 drivers/net/wireless/mediatek/mt76/mt76_connac.h |  5 +++++
 drivers/net/wireless/mediatek/mt76/mt7925/main.c | 22 +++++++++++++++++++++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
index 813d61bffc2c..393a7952f86b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
@@ -177,6 +177,11 @@ static inline bool is_mt7925(struct mt76_dev *dev)
 	return mt76_chip(dev) == 0x7925;
 }
 
+static inline bool is_320mhz_supported(struct mt76_dev *dev)
+{
+	return mt76_chip(dev) == 0x7927;
+}
+
 static inline bool is_mt7920(struct mt76_dev *dev)
 {
 	return mt76_chip(dev) == 0x7920;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index f128a198f81d..cfce851a94e2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -183,6 +183,10 @@ mt7925_init_eht_caps(struct mt792x_phy *phy, enum nl80211_band band,
 		IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER |
 		IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE;
 
+	if (band == NL80211_BAND_6GHZ && is_320mhz_supported(&phy->dev->mt76))
+		eht_cap_elem->phy_cap_info[0] |=
+			IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
+
 	eht_cap_elem->phy_cap_info[0] |=
 		u8_encode_bits(u8_get_bits(sts - 1, BIT(0)),
 			       IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK);
@@ -193,10 +197,20 @@ mt7925_init_eht_caps(struct mt792x_phy *phy, enum nl80211_band band,
 		u8_encode_bits(sts - 1,
 			       IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK);
 
+	if (band == NL80211_BAND_6GHZ && is_320mhz_supported(&phy->dev->mt76))
+		eht_cap_elem->phy_cap_info[1] |=
+			u8_encode_bits(sts - 1,
+				       IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK);
+
 	eht_cap_elem->phy_cap_info[2] =
 		u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK) |
 		u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK);
 
+	if (band == NL80211_BAND_6GHZ && is_320mhz_supported(&phy->dev->mt76))
+		eht_cap_elem->phy_cap_info[2] |=
+			u8_encode_bits(sts - 1,
+				       IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK);
+
 	eht_cap_elem->phy_cap_info[3] =
 		IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
 		IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
@@ -217,7 +231,8 @@ mt7925_init_eht_caps(struct mt792x_phy *phy, enum nl80211_band band,
 		u8_encode_bits(u8_get_bits(0x11, GENMASK(1, 0)),
 			       IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK);
 
-	val = width == NL80211_CHAN_WIDTH_160 ? 0x7 :
+	val = width == NL80211_CHAN_WIDTH_320 ? 0xf :
+	      width == NL80211_CHAN_WIDTH_160 ? 0x7 :
 	      width == NL80211_CHAN_WIDTH_80 ? 0x3 : 0x1;
 	eht_cap_elem->phy_cap_info[6] =
 		u8_encode_bits(u8_get_bits(0x11, GENMASK(4, 2)),
@@ -239,6 +254,11 @@ mt7925_init_eht_caps(struct mt792x_phy *phy, enum nl80211_band band,
 	eht_nss->bw._160.rx_tx_mcs9_max_nss = val;
 	eht_nss->bw._160.rx_tx_mcs11_max_nss = val;
 	eht_nss->bw._160.rx_tx_mcs13_max_nss = val;
+	if (band == NL80211_BAND_6GHZ && is_320mhz_supported(&phy->dev->mt76)) {
+		eht_nss->bw._320.rx_tx_mcs9_max_nss = val;
+		eht_nss->bw._320.rx_tx_mcs11_max_nss = val;
+		eht_nss->bw._320.rx_tx_mcs13_max_nss = val;
+	}
 }
 
 int mt7925_init_mlo_caps(struct mt792x_phy *phy)

-- 
2.53.0



^ permalink raw reply related

* [PATCH v4 3/9] wifi: mt76: mt7925: handle 320MHz bandwidth in RXV and TXS
From: Javier Tia @ 2026-03-26 21:12 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Deren Wu
  Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
	Marcin FM, Cristian-Florin Radoi, George Salukvadze,
	Evgeny Kapusta, Samu Toljamo, Ariel Rosenfeld, Chapuis Dario,
	Thibaut François, 张旭涵
In-Reply-To: <20260326-mt7927-wifi-support-v4-v4-0-8ab465addcfe@jetm.me>

The RX vector (RXV) and TX status (TXS) parsing in mac.c lack handling
for 320MHz channel width. When the hardware reports 320MHz in the
bandwidth field, mt7925_mac_fill_rx_rate() returns -EINVAL and
mt7925_mac_add_txs_skb() records no bandwidth stats.

Add IEEE80211_STA_RX_BW_320 cases to both functions. The RXV parser
also handles BW_320+1 since the hardware can report 320MHz in two
adjacent encoding positions.

Tested-by: Marcin FM <marcin@lgic.pl>
Tested-by: Cristian-Florin Radoi <radoi.chris@gmail.com>
Tested-by: George Salukvadze <giosal90@gmail.com>
Tested-by: Evgeny Kapusta <3193631@gmail.com>
Tested-by: Samu Toljamo <samu.toljamo@gmail.com>
Tested-by: Ariel Rosenfeld <ariel.rosenfeld.750@gmail.com>
Tested-by: Chapuis Dario <chapuisdario4@gmail.com>
Tested-by: Thibaut François <tibo@humeurlibre.fr>
Tested-by: 张旭涵 <Loong.0x00@gmail.com>
Signed-off-by: Javier Tia <floss@jetm.me>
---
 drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
index caaf71c31480..ad03fc554b69 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
@@ -339,6 +339,11 @@ mt7925_mac_fill_rx_rate(struct mt792x_dev *dev,
 	case IEEE80211_STA_RX_BW_160:
 		status->bw = RATE_INFO_BW_160;
 		break;
+	/* RXV can report 320 in two positions */
+	case IEEE80211_STA_RX_BW_320:
+	case IEEE80211_STA_RX_BW_320 + 1:
+		status->bw = RATE_INFO_BW_320;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -992,6 +997,10 @@ mt7925_mac_add_txs_skb(struct mt792x_dev *dev, struct mt76_wcid *wcid,
 	stats->tx_mode[mode]++;
 
 	switch (FIELD_GET(MT_TXS0_BW, txs)) {
+	case IEEE80211_STA_RX_BW_320:
+		rate.bw = RATE_INFO_BW_320;
+		stats->tx_bw[4]++;
+		break;
 	case IEEE80211_STA_RX_BW_160:
 		rate.bw = RATE_INFO_BW_160;
 		stats->tx_bw[3]++;

-- 
2.53.0



^ permalink raw reply related

* [PATCH v4 2/9] wifi: mt76: mt7925: add 320MHz bandwidth to bss_rlm_tlv
From: Javier Tia @ 2026-03-26 21:12 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Deren Wu
  Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
	张旭涵, Marcin FM, Cristian-Florin Radoi,
	George Salukvadze, Evgeny Kapusta, Samu Toljamo, Ariel Rosenfeld,
	Chapuis Dario, Thibaut François
In-Reply-To: <20260326-mt7927-wifi-support-v4-v4-0-8ab465addcfe@jetm.me>

bss_rlm_tlv() in mt7925_mcu_bss_rlm_tlv() has no case for
NL80211_CHAN_WIDTH_320. When associated to a 320MHz BSS, the switch
falls through to default and sends bw=0 (CMD_CBW_20MHZ) to firmware
via BSS_RLM TLV. Firmware then configures the RX radio for 20MHz
and cannot decode the AP's 320MHz frames, resulting in complete data
path failure at 320MHz.

Add the missing NL80211_CHAN_WIDTH_320 case with CMD_CBW_320MHZ and
center_chan2.

Tested on ASUS RT-BE92U: 320MHz throughput goes from 0 Mbps to
841 Mbps (iperf3 -t30 -P8), PHY 4803 Mbps EHT-MCS11.

Reported-by: 张旭涵 <Loong.0x00@gmail.com>
Closes: https://github.com/openwrt/mt76/issues/927
Tested-by: 张旭涵 <Loong.0x00@gmail.com>
Tested-by: Marcin FM <marcin@lgic.pl>
Tested-by: Cristian-Florin Radoi <radoi.chris@gmail.com>
Tested-by: George Salukvadze <giosal90@gmail.com>
Tested-by: Evgeny Kapusta <3193631@gmail.com>
Tested-by: Samu Toljamo <samu.toljamo@gmail.com>
Tested-by: Ariel Rosenfeld <ariel.rosenfeld.750@gmail.com>
Tested-by: Chapuis Dario <chapuisdario4@gmail.com>
Tested-by: Thibaut François <tibo@humeurlibre.fr>
Signed-off-by: Javier Tia <floss@jetm.me>
---
 drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index cf0fdea45cf7..dd5ecb07947b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -2331,6 +2331,10 @@ void mt7925_mcu_bss_rlm_tlv(struct sk_buff *skb, struct mt76_phy *phy,
 	case NL80211_CHAN_WIDTH_160:
 		req->bw = CMD_CBW_160MHZ;
 		break;
+	case NL80211_CHAN_WIDTH_320:
+		req->bw = CMD_CBW_320MHZ;
+		req->center_chan2 = ieee80211_frequency_to_channel(freq2);
+		break;
 	case NL80211_CHAN_WIDTH_5:
 		req->bw = CMD_CBW_5MHZ;
 		break;

-- 
2.53.0



^ permalink raw reply related

* [PATCH v4 0/9] wifi: mt76: mt7925: MT7927 (Filogic 380) support patches 1-9
From: Javier Tia @ 2026-03-26 21:12 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Deren Wu
  Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
	Marcin FM, Cristian-Florin Radoi, George Salukvadze,
	Evgeny Kapusta, Samu Toljamo, Ariel Rosenfeld, Chapuis Dario,
	Thibaut François, 张旭涵
In-Reply-To: <20260306-mt7927-wifi-support-v1-0-c77e7445511d@jetm.me>

This series contains the first 9 patches for MediaTek MT7927 (Filogic 380)
combo WiFi 7 + BT 5.4 support in the mt7925 driver.

Patches 1-5 add generic 320MHz EHT support (no MT7927 references).
Patches 6-7 introduce MT7927 chip ID helpers and firmware paths.
Patch 8 adds per-chip IRQ map handling.
Patch 9 disables ASPM and runtime PM for MT7927.

The remaining MT7927-specific patches (DMA configuration, hardware
initialization, band_idx, CNM quirk, and PCI device ID enablement)
will be submitted separately by Sean Wang as part of a broader
refactoring effort to introduce a generic layer that both mt7925 and
mt7927 can share. This split was agreed upon during v3 review.

The DKMS out-of-tree package [1] continues to ship the full patch set
for working hardware support.

[1] https://github.com/jetm/mediatek-mt7927-dkms

Tested hardware:
- ASUS ROG Crosshair X870E Hero (BT 0489:e13a, WiFi 14c3:6639)
- ASUS ProArt X870E-Creator WiFi (BT 0489:e13a / 13d3:3588, WiFi 14c3:6639)
- ASUS ROG Strix X870-I (WiFi 14c3:7927)
- ASUS ROG Strix X870-F Gaming WiFi (BT 0489:e13a, WiFi 14c3:7927)
- ASUS ROG Strix X870E-E (BT 13d3:3588, WiFi 14c3:7927)
- ASUS ROG STRIX B850-E GAMING WIFI (BT 0489:e13a, WiFi 14c3:7927)
- Gigabyte X870E Aorus Master X3D (BT 0489:e10f, WiFi 14c3:7927)
- Gigabyte Z790 AORUS MASTER X (BT 0489:e10f, WiFi 14c3:7927)
- Gigabyte Z790 AORUS ELITE X WiFi7 (BT 0489:e10f, WiFi 14c3:7927)
- MSI MEG X870E ACE MAX (BT 0489:e110, WiFi 14c3:7927)
- Lenovo Legion Pro 7 16ARX9 (BT 0489:e0fa, WiFi 14c3:7927)
- Lenovo Legion Pro 7 16AFR10H (BT 0489:e0fa, WiFi 14c3:7927)
- TP-Link Archer TBE550E PCIe (BT 0489:e116, WiFi 14c3:7927)
- EDUP EP-MT7927BE M.2 card (WiFi 14c3:7927)
- Foxconn/Azurewave M.2 modules (WiFi 14c3:6639)
- AMD RZ738 reference design (WiFi 14c3:0738)

Tested on Arch Linux, CachyOS, EndeavourOS, Fedora (Bazzite), NixOS,
openSUSE Tumbleweed, and Ubuntu across kernels 6.13-6.19.

Changes since v3:
- Dropped patches 9-13 (DMA, HW init, band_idx, PCI IDs). Sean Wang
  will submit these as part of a generic layer refactor. The CNM quirk
  (v3 patch 13 feedback) will be folded into mt792x_get_mac80211_ops()
  as part of that work.
- Fixed is_320mhz_supported() to use mt76_chip() directly instead of
  is_mt7927() which was not yet defined at that point (patch 5).
- Trimmed verbose inline comments in ASPM/PM patch per review feedback.
  Detail kept in commit message (patch 9).
- Added tested hardware: ASUS ROG STRIX B850-E GAMING WIFI.

Changes since v2 (suggested by Sean Wang):
- Fixed is_320mhz_supported() to check for MT7927 only, not the
  entire mt7925 family. MT7925 does not support 320MHz (patch 5).
- Dropped phy_cap_info[7] 320MHz additions (NON_OFDMA_UL_MU_MIMO
  and MU_BEAMFORMER) to keep capabilities conservative (patch 5).
- Disabled runtime PM for MT7927 (patch 9). The combo chip shares a
  CONNINFRA power domain between WiFi and BT; SET_OWN/CLR_OWN
  transitions crash BT firmware. Discovered via user reports of BT
  lockups after enabling power_save=1 (Reported-by: Nitin Gurram).

Changes since v1 (suggested by Sean Wang):
- Reorganized from 18 patches into 13 across 8 logical groups
- Common 320MHz patches first, chip-specific changes later
- Introduced mt792x_dma_config struct to reuse mt7925_dma_init()
- Replaced is_mt7927() with is_320mhz_supported() in common patches

Link to v3: https://lore.kernel.org/linux-wireless/20260325-mt7927-wifi-support-v2-v3-0-826feb8fef8e@jetm.me/
Link to v2: https://lore.kernel.org/linux-wireless/20260319-mt7927-wifi-support-v2-v2-0-d627a7fad70d@jetm.me/
Link to v1: https://lore.kernel.org/linux-wireless/20260306-mt7927-wifi-support-v1-0-c77e7445511d@jetm.me/

Signed-off-by: Javier Tia <floss@jetm.me>
---
Javier Tia (9):
      wifi: mt76: mt7925: fix stale pointer comparisons in change_vif_links
      wifi: mt76: mt7925: add 320MHz bandwidth to bss_rlm_tlv
      wifi: mt76: mt7925: handle 320MHz bandwidth in RXV and TXS
      wifi: mt76: mt7925: populate EHT 320MHz MCS map in sta_rec
      wifi: mt76: mt7925: advertise EHT 320MHz capabilities for 6GHz band
      wifi: mt76: mt7925: add MT7927 chip ID helpers
      wifi: mt76: mt7925: add MT7927 firmware paths
      wifi: mt76: mt7925: use irq_map for chip-specific interrupt handling
      wifi: mt76: mt7925: disable ASPM and runtime PM for MT7927

 drivers/net/wireless/mediatek/mt76/mt76_connac.h   | 13 ++++++++++-
 drivers/net/wireless/mediatek/mt76/mt7925/init.c   |  3 ++-
 drivers/net/wireless/mediatek/mt76/mt7925/mac.c    |  9 ++++++++
 drivers/net/wireless/mediatek/mt76/mt7925/main.c   | 26 ++++++++++++++++++---
 drivers/net/wireless/mediatek/mt76/mt7925/mcu.c    |  5 ++++
 drivers/net/wireless/mediatek/mt76/mt7925/pci.c    | 27 +++++++++++++++++++---
 .../net/wireless/mediatek/mt76/mt7925/pci_mac.c    |  5 +++-
 drivers/net/wireless/mediatek/mt76/mt792x.h        |  6 +++++
 drivers/net/wireless/mediatek/mt76/mt792x_regs.h   |  3 +++
 9 files changed, 88 insertions(+), 9 deletions(-)
---
base-commit: 9ac76f3d0bb2940db3a9684d596b9c8f301ef315
change-id: 20260326-mt7927-wifi-support-v4-5fe574b710c6

Best regards,
--  
Javier Tia <floss@jetm.me>



^ permalink raw reply

* [PATCH v4 1/9] wifi: mt76: mt7925: fix stale pointer comparisons in change_vif_links
From: Javier Tia @ 2026-03-26 21:12 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
	Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
	Ming Yen Hsieh, Deren Wu
  Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
	Marcin FM, Cristian-Florin Radoi, George Salukvadze,
	Evgeny Kapusta, Samu Toljamo, Ariel Rosenfeld, Chapuis Dario,
	Thibaut François, 张旭涵
In-Reply-To: <20260326-mt7927-wifi-support-v4-v4-0-8ab465addcfe@jetm.me>

In the error path of mt7925_change_vif_links(), the free: label iterates
over link_ids to clean up, but compares against `mconf` and `mlink`
which hold stale values from the last loop iteration rather than the
current link_id being freed.

Use array-indexed access (mconfs[link_id] / mlinks[link_id]) to compare
against the correct per-link pointers.

Fixes: 69acd6d910b0 ("wifi: mt76: mt7925: add mt7925_change_vif_links")
Tested-by: Marcin FM <marcin@lgic.pl>
Tested-by: Cristian-Florin Radoi <radoi.chris@gmail.com>
Tested-by: George Salukvadze <giosal90@gmail.com>
Tested-by: Evgeny Kapusta <3193631@gmail.com>
Tested-by: Samu Toljamo <samu.toljamo@gmail.com>
Tested-by: Ariel Rosenfeld <ariel.rosenfeld.750@gmail.com>
Tested-by: Chapuis Dario <chapuisdario4@gmail.com>
Tested-by: Thibaut François <tibo@humeurlibre.fr>
Tested-by: 张旭涵 <Loong.0x00@gmail.com>
Signed-off-by: Javier Tia <floss@jetm.me>
---
 drivers/net/wireless/mediatek/mt76/mt7925/main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index 2d358a96640c..f128a198f81d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -2047,9 +2047,9 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		rcu_assign_pointer(mvif->link_conf[link_id], NULL);
 		rcu_assign_pointer(mvif->sta.link[link_id], NULL);
 
-		if (mconf != &mvif->bss_conf)
+		if (mconfs[link_id] != &mvif->bss_conf)
 			devm_kfree(dev->mt76.dev, mconfs[link_id]);
-		if (mlink != &mvif->sta.deflink)
+		if (mlinks[link_id] != &mvif->sta.deflink)
 			devm_kfree(dev->mt76.dev, mlinks[link_id]);
 	}
 

-- 
2.53.0



^ permalink raw reply related

* Re: [PATCH v2] device property: Make modifications of fwnode "flags" thread safe
From: Danilo Krummrich @ 2026-03-26 21:03 UTC (permalink / raw)
  To: Douglas Anderson
  Cc: Greg Kroah-Hartman, Rafael J . Wysocki, stable, Andy Shevchenko,
	Mark Brown, Wolfram Sang, Andrew Lunn, Daniel Scally,
	David S. Miller, Eric Dumazet, Fabio Estevam, Frank Li,
	Heikki Krogerus, Heiner Kallweit, Jakub Kicinski, Len Brown,
	Paolo Abeni, Pengutronix Kernel Team, Rob Herring, Russell King,
	Sakari Ailus, Saravana Kannan, Sascha Hauer, devicetree,
	driver-core, imx, linux-acpi, linux-arm-kernel, linux-i2c,
	linux-kernel, linux-spi, netdev
In-Reply-To: <20260317090112.v2.1.I0a4d03104ecd5103df3d76f66c8d21b1d15a2e38@changeid>

On Tue Mar 17, 2026 at 5:01 PM CET, Douglas Anderson wrote:
> In various places in the kernel, we modify the fwnode "flags" member
> by doing either:
>   fwnode->flags |= SOME_FLAG;
>   fwnode->flags &= ~SOME_FLAG;
>
> This type of modification is not thread-safe. If two threads are both
> mucking with the flags at the same time then one can clobber the
> other.
>
> While flags are often modified while under the "fwnode_link_lock",
> this is not universally true.
>
> Create some accessor functions for setting, clearing, and testing the
> FWNODE flags and move all users to these accessor functions. New
> accessor functions use set_bit() and clear_bit(), which are
> thread-safe.
>
> Cc: stable@vger.kernel.org
> Fixes: c2c724c868c4 ("driver core: Add fw_devlink_parse_fwtree()")
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Acked-by: Mark Brown <broonie@kernel.org>
> Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Signed-off-by: Douglas Anderson <dianders@chromium.org>

    [ Fix fwnode_clear_flag() argument alignment, restore dropped blank
      line in fwnode_dev_initialized(), and remove unnecessary parentheses
      around fwnode_test_flag() calls. - Danilo ]

Applied to driver-core-testing, thanks!


^ permalink raw reply

* [PATCH v5] MAINTAINERS: Add Axiado reviewer and Maintainers
From: Karthikeyan Mitran @ 2026-03-26 20:50 UTC (permalink / raw)
  To: Arnd Bergmann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Prasad Bolisetty, Tzu-Hao Wei, Axiado Reviewers
  Cc: devicetree, linux-arm-kernel, linux-kernel, Alexandre Belloni,
	Drew Fustini, Linus Walleij, Harshit Shah, Karthikeyan Mitran

From: Prasad Bolisetty <pbolisetty@axiado.com>

Adding 3 new maintainers Prasad,Tzu-Hao, and Karthikeyan
and adding a group reviewer entry for review coverage,
Removed previous maintainer as the previous maintainer moved from project

Signed-off-by: Prasad Bolisetty <pbolisetty@axiado.com>
Acked-by: Harshit Shah <hshah@axiado.com>
Signed-off-by: Tzu-Hao Wei <twei@axiado.com>
Signed-off-by: Karthikeyan Mitran <kmitran@axiado.com>
---
----
This patch removes a Axiado SoC maintainer and adds 3 more.

A maintainer has moved on from the project, so we are adding three new maintainers (Prasad, Tzu-Hao, and Karthikeyan) along with a reviewer group for broader coverage. also commit message amended to have the same. the other patch has a dtb address hex value change from capital to lowercase.

Patch 1: Removed one and added new maintainers and reviewer group for Axiado SoC

Changes since v4: Droped the ax3000.dtsi patch,to make it purely a maintainers update

Changes in v4:
- Updated commit message to clarify maintainer removal and additions
- v4: https://lore.kernel.org/linux-devicetree/20260302-maintainers-addition-and-axiado-ax3000_dtsi-update-v4-0-84a5c9df6689@axiado.com/

Changes in v3:
- Updated commit message
- v3: https://lore.kernel.org/linux-devicetree/20260226-maintainers-addition-and-axiado-ax3000_dtsi-update-v3-0-a3b095989823@axiado.com/
---

---
 MAINTAINERS | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 55af015174a5..49f47e8c2ec3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2605,7 +2605,10 @@ F:	arch/arm/mach-aspeed/
 N:	aspeed
 
 ARM/AXIADO ARCHITECTURE
-M:	Harshit Shah <hshah@axiado.com>
+M:	Prasad Bolisetty <pbolisetty@axiado.com>
+M:	Tzu-Hao Wei <twei@axiado.com>
+M:	Karthikeyan Mitran <kmitran@axiado.com>
+R:	Axiado Reviewers <linux-maintainer@axiado.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	Documentation/devicetree/bindings/arm/axiado.yaml

---
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
change-id: 20260226-maintainers-addition-and-axiado-ax3000_dtsi-update-2f37e16b9053

Best regards,
-- 
Karthikeyan Mitran <kmitran@axiado.com>



^ permalink raw reply related

* Re: [PATCH 0/4] arm64: dts: renesas: Fix missing cells and reg
From: Marek Vasut @ 2026-03-26 12:49 UTC (permalink / raw)
  To: Geert Uytterhoeven, Marek Vasut
  Cc: linux-arm-kernel, Conor Dooley, Geert Uytterhoeven,
	Krzysztof Kozlowski, Magnus Damm, Rob Herring, devicetree,
	linux-kernel, linux-renesas-soc
In-Reply-To: <CAMuHMdVtea9q1Yoaq1sEquxEAnQ-armLRdO1cMtJnp2K2mYtOg@mail.gmail.com>

On 3/26/26 11:07 AM, Geert Uytterhoeven wrote:

Hello Geert,

> Thanks for your series!
> 
> On Thu, 26 Mar 2026 at 05:24, Marek Vasut
> <marek.vasut+renesas@mailbox.org> wrote:
>> Add missing cells and reg DT property into DTOs to fix warnings like this:
>>
>> "
>> arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dtso:30.10-34.5: Warning (unit_address_vs_reg): /fragment@2/__overlay__/ports/port@1: node has a unit name, but no reg or ranges property
>> "
> 
> All of these are dtc W=1 warnings, right?

Yes, I slowly started linting and validating the various DTs we have to 
remove leftover warnings.

-- 
Best regards,
Marek Vasut


^ permalink raw reply

* Re: [PATCH v3 net-next 02/14] dt-bindings: net: dsa: add NETC switch
From: Frank Li @ 2026-03-26 20:06 UTC (permalink / raw)
  To: Wei Fang
  Cc: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
	davem, edumazet, kuba, pabeni, robh, krzk+dt, conor+dt,
	f.fainelli, chleroy, horms, linux, andrew, netdev, linux-kernel,
	devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260326062917.3552334-3-wei.fang@nxp.com>

On Thu, Mar 26, 2026 at 02:29:05PM +0800, Wei Fang wrote:
> Add bindings for NETC switch. This switch is a PCIe function of NETC IP,
> it supports advanced QoS with 8 traffic classes and 4 drop resilience
> levels, and a full range of  TSN standards capabilities. The switch CPU

Nit: double space before TSN.

> port connects to an internal ENETC port, which is also a PCIe function
> of NETC IP. So these two ports use a light-weight "pseudo MAC" instead
> of a back-to-back MAC, because the "pseudo MAC" provides the delineation
> between switch and ENETC, this translates to lower power (less logic and

what's means "this translates", do you means
"this help reduce power and latency."

> memory) and lower delay (as there is no serialization delay across this
> link).
>
> Signed-off-by: Wei Fang <wei.fang@nxp.com>
> ---
>  .../bindings/net/dsa/nxp,netc-switch.yaml     | 130 ++++++++++++++++++
>  1 file changed, 130 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/dsa/nxp,netc-switch.yaml
>
> diff --git a/Documentation/devicetree/bindings/net/dsa/nxp,netc-switch.yaml b/Documentation/devicetree/bindings/net/dsa/nxp,netc-switch.yaml
> new file mode 100644
> index 000000000000..e34a4e3504c3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/dsa/nxp,netc-switch.yaml
> @@ -0,0 +1,130 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/dsa/nxp,netc-switch.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: NETC Switch family
> +
> +description:

Nit use ">" for multi paragraph.

others look good

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> +  The NETC presents itself as a multi-function PCIe Root Complex Integrated
> +  Endpoint (RCiEP) and provides full 802.1Q Ethernet switch functionality,
> +  advanced QoS with 8 traffic classes and 4 drop resilience levels, and a
> +  full range of TSN standards capabilities.
> +
> +  The CPU port of the switch connects to an internal ENETC. The switch and
> +  the internal ENETC are fully integrated into the NETC IP, a back-to-back
> +  MAC is not required. Instead, a light-weight "pseudo MAC" provides the
> +  delineation between the switch and ENETC. This translates to lower power
> +  (less logic and memory) and lower delay (as there is no serialization
> +  delay across this link).
> +
> +maintainers:
> +  - Wei Fang <wei.fang@nxp.com>
> +
> +properties:
> +  compatible:
> +    enum:
> +      - pci1131,eef2
> +
> +  reg:
> +    maxItems: 1
> +
> +  dsa,member:
> +    description:
> +      The property indicates DSA cluster and switch index. For NETC switch,
> +      the valid range of the switch index is 1 ~ 7, the index is reflected
> +      in the switch tag as an indication of the switch ID where the frame
> +      originated. The value 0 is reserved for ENETC VEPA switch, whose ID
> +      is hardwired to zero.
> +
> +$ref: dsa.yaml#
> +
> +patternProperties:
> +  "^(ethernet-)?ports$":
> +    type: object
> +    additionalProperties: true
> +    patternProperties:
> +      "^(ethernet-)?port@[0-9a-f]$":
> +        type: object
> +
> +        $ref: dsa-port.yaml#
> +
> +        properties:
> +          clocks:
> +            items:
> +              - description: MAC transmit/receive reference clock.
> +
> +          clock-names:
> +            items:
> +              - const: ref
> +
> +          mdio:
> +            $ref: /schemas/net/mdio.yaml#
> +            unevaluatedProperties: false
> +            description:
> +              Optional child node for switch port, otherwise use NETC EMDIO.
> +
> +        unevaluatedProperties: false
> +
> +required:
> +  - compatible
> +  - reg
> +  - dsa,member
> +
> +allOf:
> +  - $ref: /schemas/pci/pci-device.yaml
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    pcie {
> +        #address-cells = <3>;
> +        #size-cells = <2>;
> +
> +        ethernet-switch@0,2 {
> +            compatible = "pci1131,eef2";
> +            reg = <0x200 0 0 0 0>;
> +            dsa,member = <0 1>;
> +            pinctrl-names = "default";
> +            pinctrl-0 = <&pinctrl_switch>;
> +
> +            ports {
> +                #address-cells = <1>;
> +                #size-cells = <0>;
> +
> +                port@0 {
> +                    reg = <0>;
> +                    phy-handle = <&ethphy0>;
> +                    phy-mode = "mii";
> +                };
> +
> +                port@1 {
> +                    reg = <1>;
> +                    phy-handle = <&ethphy1>;
> +                    phy-mode = "mii";
> +                };
> +
> +                port@2 {
> +                    reg = <2>;
> +                    clocks = <&scmi_clk 103>;
> +                    clock-names = "ref";
> +                    phy-handle = <&ethphy2>;
> +                    phy-mode = "rgmii-id";
> +                };
> +
> +                port@3 {
> +                    reg = <3>;
> +                    ethernet = <&enetc3>;
> +                    phy-mode = "internal";
> +
> +                    fixed-link {
> +                        speed = <2500>;
> +                        full-duplex;
> +                        pause;
> +                    };
> +                };
> +            };
> +        };
> +    };
> --
> 2.34.1
>


^ permalink raw reply

* Re: [PATCH v3 0/4] iio: adc: meson-saradc: add support for Meson S4
From: Jonathan Cameron @ 2026-03-26 19:57 UTC (permalink / raw)
  To: Nick Xie
  Cc: neil.armstrong, khilman, martin.blumenstingl, jbrunet, dlechner,
	andy, krzk+dt, robh, conor+dt, linux-iio, linux-amlogic,
	linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <20260325070618.81955-1-nick@khadas.com>

On Wed, 25 Mar 2026 15:06:14 +0800
Nick Xie <nick@khadas.com> wrote:

> This series adds support for the SARADC IP block found in the Amlogic
> Meson S4 (S905Y4) SoC and enables it for the Khadas VIM1S board to
> support the onboard ADC 'Function' key.
> 
> There are no known hardware differences between the SARADC on the S4
> and the previous G12A generation. The S4 bindings utilize a fallback
> to G12A, but a dedicated driver match entry is included to ensure the
> correct part name is exposed to the userspace ABI.
> 
Applied patches 1 and 2 to the togreg branch of iio.git.

> Changes in v3:
> - Patch 1: Updated the commit message to explicitly explain why the
>   comment regarding the generic fallback was added.
> - Patch 2: Retained the driver patch and updated the commit message to
>   clarify that the dedicated match entry is kept specifically for
>   userspace ABI naming purposes.
> - Link to v2: https://lore.kernel.org/all/20260323013408.429701-1-nick@khadas.com/
> 
> Changes in v2:
> - Addressed feedback from Krzysztof Kozlowski:
>   - Updated dt-bindings commit message to explain the hardware compatibility.
>   - Separated the S4 compatible string in the YAML bindings to ensure it
>     correctly falls back to the specific "amlogic,meson-g12a-saradc" rather
>     than the generic "amlogic,meson-saradc".
>   - Updated the S4 SoC dtsi to use the correct G12A fallback.
> - Added Martin's Reviewed-by tags where appropriate.
> - Link to v1: https://lore.kernel.org/all/20260228065840.702651-1-nick@khadas.com/
> 
> 
> Nick Xie (4):
>   dt-bindings: iio: adc: amlogic,meson-saradc: add S4 compatible
>   iio: adc: meson-saradc: add support for Meson S4
>   arm64: dts: amlogic: meson-s4: add internal SARADC controller
>   arm64: dts: amlogic: meson-s4-s905y4-khadas-vim1s: add Function key
>     support
> 
>  .../iio/adc/amlogic,meson-saradc.yaml         |  4 ++++
>  .../amlogic/meson-s4-s905y4-khadas-vim1s.dts  | 19 +++++++++++++++++++
>  arch/arm64/boot/dts/amlogic/meson-s4.dtsi     | 14 ++++++++++++++
>  drivers/iio/adc/meson_saradc.c                |  8 ++++++++
>  4 files changed, 45 insertions(+)
> 



^ permalink raw reply

* Re: [PATCH net 2/2] net: xilinx: axienet: Fix BQL accounting for multi-BD TX packets
From: Sean Anderson @ 2026-03-26 19:56 UTC (permalink / raw)
  To: Gupta, Suraj, andrew+netdev@lunn.ch, davem@davemloft.net,
	edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
	Simek, Michal, Pandey, Radhey Shyam, horms@kernel.org
  Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, Katakam, Harini
In-Reply-To: <SA1PR12MB679810BDE0FD91B702A869C2C956A@SA1PR12MB6798.namprd12.prod.outlook.com>

On 3/26/26 15:51, Gupta, Suraj wrote:
> [Public]
> 
>> -----Original Message-----
>> From: Sean Anderson <sean.anderson@linux.dev>
>> Sent: Thursday, March 26, 2026 9:08 PM
>> To: Gupta, Suraj <Suraj.Gupta2@amd.com>; andrew+netdev@lunn.ch;
>> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
>> pabeni@redhat.com; Simek, Michal <michal.simek@amd.com>; Pandey,
>> Radhey Shyam <radhey.shyam.pandey@amd.com>; horms@kernel.org
>> Cc: netdev@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-
>> kernel@vger.kernel.org; Katakam, Harini <harini.katakam@amd.com>
>> Subject: Re: [PATCH net 2/2] net: xilinx: axienet: Fix BQL accounting for multi-BD
>> TX packets
>>
>> Caution: This message originated from an External Source. Use proper caution
>> when opening attachments, clicking links, or responding.
>>
>>
>> On 3/25/26 01:30, Gupta, Suraj wrote:
>> > [Public]
>> >
>> >> -----Original Message-----
>> >> From: Sean Anderson <sean.anderson@linux.dev>
>> >> Sent: Tuesday, March 24, 2026 9:39 PM
>> >> To: Gupta, Suraj <Suraj.Gupta2@amd.com>; andrew+netdev@lunn.ch;
>> >> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
>> >> pabeni@redhat.com; Simek, Michal <michal.simek@amd.com>; Pandey,
>> >> Radhey Shyam <radhey.shyam.pandey@amd.com>; horms@kernel.org
>> >> Cc: netdev@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
>> >> linux- kernel@vger.kernel.org; Katakam, Harini
>> >> <harini.katakam@amd.com>
>> >> Subject: Re: [PATCH net 2/2] net: xilinx: axienet: Fix BQL accounting
>> >> for multi-BD TX packets
>> >>
>> >> Caution: This message originated from an External Source. Use proper
>> >> caution when opening attachments, clicking links, or responding.
>> >>
>> >>
>> >> On 3/24/26 10:53, Suraj Gupta wrote:
>> >> > When a TX packet spans multiple buffer descriptors
>> >> > (scatter-gather), the per-BD byte count is accumulated into a local
>> >> > variable that resets on each NAPI poll. If the BDs for a single
>> >> > packet complete across different polls, the earlier bytes are lost and never
>> credited to BQL.
>> >> > This causes BQL to think bytes are permanently in-flight,
>> >> > eventually stalling the TX queue.
>> >> >
>> >> > Fix this by replacing the local accumulator with a persistent
>> >> > counter
>> >> > (tx_compl_bytes) that survives across polls and is reset only after
>> >> > updating BQL and stats.
>> >>
>> >> Do we need this? Can't we just do something like
>> >>
>> >
>> > Nope, the 'size' variable passed to axienet_free_tx_chain() is local
>> > to axienet_tx_poll() and goes out of scope between different polls.
>> > This means it can't track completion bytes across multiple NAPI polls.
>>
>> Yes, but that's fine since we only update completed bytes when we retire at
>> least one packet:
>>
>>         packets = axienet_free_tx_chain(lp, &size, budget);
>>         if (packets) {
>>                 netdev_completed_queue(ndev, packets, size);
>>                 u64_stats_update_begin(&lp->tx_stat_sync);
>>                 u64_stats_add(&lp->tx_packets, packets);
>>                 u64_stats_add(&lp->tx_bytes, size);
>>                 u64_stats_update_end(&lp->tx_stat_sync);
>>
>>                 /* Matches barrier in axienet_start_xmit */
>>                 smp_mb();
>>                 if (((tail - ci) & (lp->rx_bd_num - 1)) >= MAX_SKB_FRAGS + 1)
>>                         netif_wake_queue(ndev);
>>         }
>>
>> and this matches the value we use when enqueuing a packet
>>
>>         tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * (last_p - lp->tx_bd_v);
>>         smp_store_release(&lp->tx_bd_tail, new_tail_ptr);
>>         netdev_sent_queue(ndev, skb->len);
>>
> 
> Let’s say we have a packet with 4 fragments. When xmit() is called, the last buffer descriptor (the 4th one) is marked with the retiral flag[1]. Now, during completion, suppose the first 3 buffer descriptors are processed in one NAPI poll, and the 4th descriptor is handled in a subsequent poll. In this scenario, the size won’t get updated for the first 3 BDs because there’s no packet retiral for them. Then, during the second poll, the size update will only reflect the completion length of the 4th BD.

That's why I suggested using skb->len and not the size from the descriptor.

--Sean

> This means that the bytes corresponding to the first 3 fragments are never credited to BQL, which leads to incorrect accounting and, eventually, to the TX queue stalling as described.
> Proposed changes to accumulate the completion length across polls until the entire packet is processed directly addresses this gap.
> 
> [1]: https://elixir.bootlin.com/linux/v7.0-rc5/source/drivers/net/ethernet/xilinx/xilinx_axienet_main.c#L1127
> 
> 
> Regards,
> Suraj
> 
>> > Regards,
>> > Suraj
>> >
>> >> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> >> b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> >> index 415e9bc252527..1ea8a6592bce1 100644
>> >> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> >> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> >> @@ -768,6 +768,7 @@ static int axienet_free_tx_chain(struct
>> >> axienet_local *lp, u32 *sizep, int budge
>> >>                 if (cur_p->skb) {
>> >>                         struct axienet_cb *cb = (void
>> >> *)cur_p->skb->cb;
>> >>
>> >> +                       *sizep += skb->len;
>> >>                         dma_unmap_sgtable(lp->dev, &cb->sgt, DMA_TO_DEVICE, 0);
>> >>                         sg_free_table_chained(&cb->sgt, XAE_INLINE_SG_CNT);
>> >>                         napi_consume_skb(cur_p->skb, budget); @@
>> >> -783,8 +784,6 @@ static int axienet_free_tx_chain(struct axienet_local *lp,
>> u32 *sizep, int budge
>> >>                 wmb();
>> >>                 cur_p->cntrl = 0;
>> >>                 cur_p->status = 0;
>> >> -
>> >> -               *sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
>> >>         }
>> >>
>> >>         smp_store_release(&lp->tx_bd_ci, (ci + i) & (lp->tx_bd_num -
>> >> 1));
>> >>
>> >> > Fixes: c900e49d58eb ("net: xilinx: axienet: Implement BQL")
>> >> > Signed-off-by: Suraj Gupta <suraj.gupta2@amd.com>
>> >> > ---
>> >> >  drivers/net/ethernet/xilinx/xilinx_axienet.h  |  3 +++
>> >> > .../net/ethernet/xilinx/xilinx_axienet_main.c | 20
>> >> > +++++++++----------
>> >> >  2 files changed, 13 insertions(+), 10 deletions(-)
>> >> >
>> >> > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> >> > b/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> >> > index 602389843342..a4444c939451 100644
>> >> > --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> >> > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
>> >> > @@ -509,6 +509,8 @@ struct skbuf_dma_descriptor {
>> >> >   *           complete. Only updated at runtime by TX NAPI poll.
>> >> >   * @tx_bd_tail:      Stores the index of the next Tx buffer descriptor in the
>> ring
>> >> >   *              to be populated.
>> >> > + * @tx_compl_bytes: Accumulates TX completion length until a full
>> packet is
>> >> > + *              reported to the stack.
>> >> >   * @tx_packets: TX packet count for statistics
>> >> >   * @tx_bytes:        TX byte count for statistics
>> >> >   * @tx_stat_sync: Synchronization object for TX stats @@ -592,6
>> >> > +594,7 @@ struct axienet_local {
>> >> >       u32 tx_bd_num;
>> >> >       u32 tx_bd_ci;
>> >> >       u32 tx_bd_tail;
>> >> > +     u32 tx_compl_bytes;
>> >> >       u64_stats_t tx_packets;
>> >> >       u64_stats_t tx_bytes;
>> >> >       struct u64_stats_sync tx_stat_sync; diff --git
>> >> > a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> >> > b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> >> > index b06e4c37ff61..95bf61986cb7 100644
>> >> > --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> >> > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
>> >> > @@ -692,6 +692,8 @@ static void axienet_dma_stop(struct
>> >> > axienet_local
>> >> *lp)
>> >> >       axienet_lock_mii(lp);
>> >> >       __axienet_device_reset(lp);
>> >> >       axienet_unlock_mii(lp);
>> >> > +
>> >> > +     lp->tx_compl_bytes = 0;
>> >> >  }
>> >> >
>> >> >  /**
>> >> > @@ -770,8 +772,6 @@ static int axienet_device_reset(struct
>> >> > net_device
>> >> *ndev)
>> >> >   * @first_bd:        Index of first descriptor to clean up
>> >> >   * @nr_bds:  Max number of descriptors to clean up
>> >> >   * @force:   Whether to clean descriptors even if not complete
>> >> > - * @sizep:   Pointer to a u32 filled with the total sum of all bytes
>> >> > - *           in all cleaned-up descriptors. Ignored if NULL.
>> >> >   * @budget:  NAPI budget (use 0 when not called from NAPI poll)
>> >> >   *
>> >> >   * Would either be called after a successful transmit operation,
>> >> > or after @@ -780,7 +780,7 @@ static int axienet_device_reset(struct
>> >> > net_device
>> >> *ndev)
>> >> >   * Return: The number of packets handled.
>> >> >   */
>> >> >  static int axienet_free_tx_chain(struct axienet_local *lp, u32 first_bd,
>> >> > -                              int nr_bds, bool force, u32 *sizep, int budget)
>> >> > +                              int nr_bds, bool force, int budget)
>> >> >  {
>> >> >       struct axidma_bd *cur_p;
>> >> >       unsigned int status;
>> >> > @@ -819,8 +819,8 @@ static int axienet_free_tx_chain(struct
>> >> > axienet_local
>> >> *lp, u32 first_bd,
>> >> >               cur_p->cntrl = 0;
>> >> >               cur_p->status = 0;
>> >> >
>> >> > -             if (sizep)
>> >> > -                     *sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
>> >> > +             if (!force)
>> >> > +                     lp->tx_compl_bytes += status &
>> >> > + XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
>> >> >       }
>> >> >
>> >> >       if (!force) {
>> >> > @@ -999,18 +999,18 @@ static int axienet_tx_poll(struct napi_struct
>> >> > *napi, int budget)  {
>> >> >       struct axienet_local *lp = container_of(napi, struct axienet_local,
>> napi_tx);
>> >> >       struct net_device *ndev = lp->ndev;
>> >> > -     u32 size = 0;
>> >> >       int packets;
>> >> >
>> >> >       packets = axienet_free_tx_chain(lp, lp->tx_bd_ci, lp->tx_bd_num, false,
>> >> > -                                     &size, budget);
>> >> > +                                     budget);
>> >> >
>> >> >       if (packets) {
>> >> > -             netdev_completed_queue(ndev, packets, size);
>> >> > +             netdev_completed_queue(ndev, packets,
>> >> > + lp->tx_compl_bytes);
>> >> >               u64_stats_update_begin(&lp->tx_stat_sync);
>> >> >               u64_stats_add(&lp->tx_packets, packets);
>> >> > -             u64_stats_add(&lp->tx_bytes, size);
>> >> > +             u64_stats_add(&lp->tx_bytes, lp->tx_compl_bytes);
>> >> >               u64_stats_update_end(&lp->tx_stat_sync);
>> >> > +             lp->tx_compl_bytes = 0;
>> >> >
>> >> >               /* Matches barrier in axienet_start_xmit */
>> >> >               smp_mb();
>> >> > @@ -1115,7 +1115,7 @@ axienet_start_xmit(struct sk_buff *skb,
>> >> > struct
>> >> net_device *ndev)
>> >> >                               netdev_err(ndev, "TX DMA mapping error\n");
>> >> >                       ndev->stats.tx_dropped++;
>> >> >                       axienet_free_tx_chain(lp, orig_tail_ptr, ii + 1,
>> >> > -                                           true, NULL, 0);
>> >> > +                                           true, 0);
>> >> >                       dev_kfree_skb_any(skb);
>> >> >                       return NETDEV_TX_OK;
>> >> >               }



^ permalink raw reply

* RE: [PATCH net 2/2] net: xilinx: axienet: Fix BQL accounting for multi-BD TX packets
From: Gupta, Suraj @ 2026-03-26 19:51 UTC (permalink / raw)
  To: Sean Anderson, andrew+netdev@lunn.ch, davem@davemloft.net,
	edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
	Simek, Michal, Pandey, Radhey Shyam, horms@kernel.org
  Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, Katakam, Harini
In-Reply-To: <9f6a4e9f-9f93-4ced-92de-8fdc6154c694@linux.dev>

[Public]

> -----Original Message-----
> From: Sean Anderson <sean.anderson@linux.dev>
> Sent: Thursday, March 26, 2026 9:08 PM
> To: Gupta, Suraj <Suraj.Gupta2@amd.com>; andrew+netdev@lunn.ch;
> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; Simek, Michal <michal.simek@amd.com>; Pandey,
> Radhey Shyam <radhey.shyam.pandey@amd.com>; horms@kernel.org
> Cc: netdev@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-
> kernel@vger.kernel.org; Katakam, Harini <harini.katakam@amd.com>
> Subject: Re: [PATCH net 2/2] net: xilinx: axienet: Fix BQL accounting for multi-BD
> TX packets
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> On 3/25/26 01:30, Gupta, Suraj wrote:
> > [Public]
> >
> >> -----Original Message-----
> >> From: Sean Anderson <sean.anderson@linux.dev>
> >> Sent: Tuesday, March 24, 2026 9:39 PM
> >> To: Gupta, Suraj <Suraj.Gupta2@amd.com>; andrew+netdev@lunn.ch;
> >> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> >> pabeni@redhat.com; Simek, Michal <michal.simek@amd.com>; Pandey,
> >> Radhey Shyam <radhey.shyam.pandey@amd.com>; horms@kernel.org
> >> Cc: netdev@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> >> linux- kernel@vger.kernel.org; Katakam, Harini
> >> <harini.katakam@amd.com>
> >> Subject: Re: [PATCH net 2/2] net: xilinx: axienet: Fix BQL accounting
> >> for multi-BD TX packets
> >>
> >> Caution: This message originated from an External Source. Use proper
> >> caution when opening attachments, clicking links, or responding.
> >>
> >>
> >> On 3/24/26 10:53, Suraj Gupta wrote:
> >> > When a TX packet spans multiple buffer descriptors
> >> > (scatter-gather), the per-BD byte count is accumulated into a local
> >> > variable that resets on each NAPI poll. If the BDs for a single
> >> > packet complete across different polls, the earlier bytes are lost and never
> credited to BQL.
> >> > This causes BQL to think bytes are permanently in-flight,
> >> > eventually stalling the TX queue.
> >> >
> >> > Fix this by replacing the local accumulator with a persistent
> >> > counter
> >> > (tx_compl_bytes) that survives across polls and is reset only after
> >> > updating BQL and stats.
> >>
> >> Do we need this? Can't we just do something like
> >>
> >
> > Nope, the 'size' variable passed to axienet_free_tx_chain() is local
> > to axienet_tx_poll() and goes out of scope between different polls.
> > This means it can't track completion bytes across multiple NAPI polls.
>
> Yes, but that's fine since we only update completed bytes when we retire at
> least one packet:
>
>         packets = axienet_free_tx_chain(lp, &size, budget);
>         if (packets) {
>                 netdev_completed_queue(ndev, packets, size);
>                 u64_stats_update_begin(&lp->tx_stat_sync);
>                 u64_stats_add(&lp->tx_packets, packets);
>                 u64_stats_add(&lp->tx_bytes, size);
>                 u64_stats_update_end(&lp->tx_stat_sync);
>
>                 /* Matches barrier in axienet_start_xmit */
>                 smp_mb();
>                 if (((tail - ci) & (lp->rx_bd_num - 1)) >= MAX_SKB_FRAGS + 1)
>                         netif_wake_queue(ndev);
>         }
>
> and this matches the value we use when enqueuing a packet
>
>         tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * (last_p - lp->tx_bd_v);
>         smp_store_release(&lp->tx_bd_tail, new_tail_ptr);
>         netdev_sent_queue(ndev, skb->len);
>

Let’s say we have a packet with 4 fragments. When xmit() is called, the last buffer descriptor (the 4th one) is marked with the retiral flag[1]. Now, during completion, suppose the first 3 buffer descriptors are processed in one NAPI poll, and the 4th descriptor is handled in a subsequent poll. In this scenario, the size won’t get updated for the first 3 BDs because there’s no packet retiral for them. Then, during the second poll, the size update will only reflect the completion length of the 4th BD.

This means that the bytes corresponding to the first 3 fragments are never credited to BQL, which leads to incorrect accounting and, eventually, to the TX queue stalling as described.
Proposed changes to accumulate the completion length across polls until the entire packet is processed directly addresses this gap.

[1]: https://elixir.bootlin.com/linux/v7.0-rc5/source/drivers/net/ethernet/xilinx/xilinx_axienet_main.c#L1127


Regards,
Suraj

> > Regards,
> > Suraj
> >
> >> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> index 415e9bc252527..1ea8a6592bce1 100644
> >> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> @@ -768,6 +768,7 @@ static int axienet_free_tx_chain(struct
> >> axienet_local *lp, u32 *sizep, int budge
> >>                 if (cur_p->skb) {
> >>                         struct axienet_cb *cb = (void
> >> *)cur_p->skb->cb;
> >>
> >> +                       *sizep += skb->len;
> >>                         dma_unmap_sgtable(lp->dev, &cb->sgt, DMA_TO_DEVICE, 0);
> >>                         sg_free_table_chained(&cb->sgt, XAE_INLINE_SG_CNT);
> >>                         napi_consume_skb(cur_p->skb, budget); @@
> >> -783,8 +784,6 @@ static int axienet_free_tx_chain(struct axienet_local *lp,
> u32 *sizep, int budge
> >>                 wmb();
> >>                 cur_p->cntrl = 0;
> >>                 cur_p->status = 0;
> >> -
> >> -               *sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
> >>         }
> >>
> >>         smp_store_release(&lp->tx_bd_ci, (ci + i) & (lp->tx_bd_num -
> >> 1));
> >>
> >> > Fixes: c900e49d58eb ("net: xilinx: axienet: Implement BQL")
> >> > Signed-off-by: Suraj Gupta <suraj.gupta2@amd.com>
> >> > ---
> >> >  drivers/net/ethernet/xilinx/xilinx_axienet.h  |  3 +++
> >> > .../net/ethernet/xilinx/xilinx_axienet_main.c | 20
> >> > +++++++++----------
> >> >  2 files changed, 13 insertions(+), 10 deletions(-)
> >> >
> >> > diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> >> > b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> >> > index 602389843342..a4444c939451 100644
> >> > --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
> >> > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
> >> > @@ -509,6 +509,8 @@ struct skbuf_dma_descriptor {
> >> >   *           complete. Only updated at runtime by TX NAPI poll.
> >> >   * @tx_bd_tail:      Stores the index of the next Tx buffer descriptor in the
> ring
> >> >   *              to be populated.
> >> > + * @tx_compl_bytes: Accumulates TX completion length until a full
> packet is
> >> > + *              reported to the stack.
> >> >   * @tx_packets: TX packet count for statistics
> >> >   * @tx_bytes:        TX byte count for statistics
> >> >   * @tx_stat_sync: Synchronization object for TX stats @@ -592,6
> >> > +594,7 @@ struct axienet_local {
> >> >       u32 tx_bd_num;
> >> >       u32 tx_bd_ci;
> >> >       u32 tx_bd_tail;
> >> > +     u32 tx_compl_bytes;
> >> >       u64_stats_t tx_packets;
> >> >       u64_stats_t tx_bytes;
> >> >       struct u64_stats_sync tx_stat_sync; diff --git
> >> > a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> > b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> > index b06e4c37ff61..95bf61986cb7 100644
> >> > --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> > +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> >> > @@ -692,6 +692,8 @@ static void axienet_dma_stop(struct
> >> > axienet_local
> >> *lp)
> >> >       axienet_lock_mii(lp);
> >> >       __axienet_device_reset(lp);
> >> >       axienet_unlock_mii(lp);
> >> > +
> >> > +     lp->tx_compl_bytes = 0;
> >> >  }
> >> >
> >> >  /**
> >> > @@ -770,8 +772,6 @@ static int axienet_device_reset(struct
> >> > net_device
> >> *ndev)
> >> >   * @first_bd:        Index of first descriptor to clean up
> >> >   * @nr_bds:  Max number of descriptors to clean up
> >> >   * @force:   Whether to clean descriptors even if not complete
> >> > - * @sizep:   Pointer to a u32 filled with the total sum of all bytes
> >> > - *           in all cleaned-up descriptors. Ignored if NULL.
> >> >   * @budget:  NAPI budget (use 0 when not called from NAPI poll)
> >> >   *
> >> >   * Would either be called after a successful transmit operation,
> >> > or after @@ -780,7 +780,7 @@ static int axienet_device_reset(struct
> >> > net_device
> >> *ndev)
> >> >   * Return: The number of packets handled.
> >> >   */
> >> >  static int axienet_free_tx_chain(struct axienet_local *lp, u32 first_bd,
> >> > -                              int nr_bds, bool force, u32 *sizep, int budget)
> >> > +                              int nr_bds, bool force, int budget)
> >> >  {
> >> >       struct axidma_bd *cur_p;
> >> >       unsigned int status;
> >> > @@ -819,8 +819,8 @@ static int axienet_free_tx_chain(struct
> >> > axienet_local
> >> *lp, u32 first_bd,
> >> >               cur_p->cntrl = 0;
> >> >               cur_p->status = 0;
> >> >
> >> > -             if (sizep)
> >> > -                     *sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
> >> > +             if (!force)
> >> > +                     lp->tx_compl_bytes += status &
> >> > + XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
> >> >       }
> >> >
> >> >       if (!force) {
> >> > @@ -999,18 +999,18 @@ static int axienet_tx_poll(struct napi_struct
> >> > *napi, int budget)  {
> >> >       struct axienet_local *lp = container_of(napi, struct axienet_local,
> napi_tx);
> >> >       struct net_device *ndev = lp->ndev;
> >> > -     u32 size = 0;
> >> >       int packets;
> >> >
> >> >       packets = axienet_free_tx_chain(lp, lp->tx_bd_ci, lp->tx_bd_num, false,
> >> > -                                     &size, budget);
> >> > +                                     budget);
> >> >
> >> >       if (packets) {
> >> > -             netdev_completed_queue(ndev, packets, size);
> >> > +             netdev_completed_queue(ndev, packets,
> >> > + lp->tx_compl_bytes);
> >> >               u64_stats_update_begin(&lp->tx_stat_sync);
> >> >               u64_stats_add(&lp->tx_packets, packets);
> >> > -             u64_stats_add(&lp->tx_bytes, size);
> >> > +             u64_stats_add(&lp->tx_bytes, lp->tx_compl_bytes);
> >> >               u64_stats_update_end(&lp->tx_stat_sync);
> >> > +             lp->tx_compl_bytes = 0;
> >> >
> >> >               /* Matches barrier in axienet_start_xmit */
> >> >               smp_mb();
> >> > @@ -1115,7 +1115,7 @@ axienet_start_xmit(struct sk_buff *skb,
> >> > struct
> >> net_device *ndev)
> >> >                               netdev_err(ndev, "TX DMA mapping error\n");
> >> >                       ndev->stats.tx_dropped++;
> >> >                       axienet_free_tx_chain(lp, orig_tail_ptr, ii + 1,
> >> > -                                           true, NULL, 0);
> >> > +                                           true, 0);
> >> >                       dev_kfree_skb_any(skb);
> >> >                       return NETDEV_TX_OK;
> >> >               }

^ permalink raw reply

* Re: [PATCH v4 3/7] pinctrl: extract pinctrl_generic_to_map() from pinctrl_generic_pins_function_dt_node_to_map()
From: Frank Li @ 2026-03-26 19:47 UTC (permalink / raw)
  To: Conor Dooley
  Cc: Peter Rosin, Linus Walleij, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rafał Miłecki, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, linux-kernel, linux-gpio,
	devicetree, imx, linux-arm-kernel, Haibo Chen
In-Reply-To: <20260326-poncho-expanse-d30a9eded8e2@spud>

On Thu, Mar 26, 2026 at 06:55:01PM +0000, Conor Dooley wrote:
> On Thu, Mar 26, 2026 at 06:52:12PM +0000, Conor Dooley wrote:
> > On Wed, Mar 25, 2026 at 07:04:12PM -0400, Frank Li wrote:
> >
> > > diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c
> > > index efb39c6a670331775855efdc8566102b5c6202ef..20a216ae63e91b69985ea4cfcd0b57103c6ca950 100644
> > > --- a/drivers/pinctrl/pinctrl-generic.c
> > > +++ b/drivers/pinctrl/pinctrl-generic.c
> > > @@ -17,29 +17,18 @@
> > >  #include "pinctrl-utils.h"
> > >  #include "pinmux.h"
> > >
> > > -static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *pctldev,
> >
> > > +int
> > > +pinctrl_generic_to_map(struct pinctrl_dev *pctldev, struct device_node *parent,
> >
> > Can you drop this stylistic change please? The
>
> Whoops, cut myself off. To be clear, what I am asking for is to keep the
> "int" etc on the same line as the function name. This function is new,
> but you did it for the existing function too and the comparison is here.
>
> >
> > > +		       struct device_node *np, struct pinctrl_map **maps,
> > > +		       unsigned int *num_maps, unsigned int *num_reserved_maps,
> > > +		       const char **group_names, unsigned int ngroups,
> > > +		       const char **functions, unsigned int *pins)
> > >  {
> > >  	struct device *dev = pctldev->dev;
> > > -	const char **functions;
> > > +	int npins, ret, reserve = 1;
> > > +	unsigned int num_configs;
> > >  	const char *group_name;
> > >  	unsigned long *configs;
> > > -	unsigned int num_configs, pin, *pins;
> > > -	int npins, ret, reserve = 1;
> > > -
> > > -	npins = of_property_count_u32_elems(np, "pins");
> > > -
> > > -	if (npins < 1) {
> > > -		dev_err(dev, "invalid pinctrl group %pOFn.%pOFn %d\n",
> > > -			parent, np, npins);
> > > -		return npins;
> > > -	}
> > >
> > >  	group_name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn", parent, np);
> > >  	if (!group_name)
> > > @@ -51,22 +40,6 @@ static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *p
> > >  	if (!pins)
> > >  		return -ENOMEM;
> >
> > This looks suspect. You've left the pins allocation behind:
> > 	pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> > 	if (!pins)
> > 		return -ENOMEM;
> > but pinctrl_generic_pins_function_dt_subnode_to_map() has already
> > populated this array before calling the function.

what's means?

pinctrl_generic_pins_function_dt_subnode_to_map()
{
	pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
	...
	pinctrl_generic_to_map();
}

pinctrl_generic_pins_function_dt_subnode_to_map() have not use this array.

Frank
> >
> > Also, this should probably be
> > Suggested-by: Conor Dooley <conor.dooley@microchip.com>
> >
> > Cheers,
> > Conor.
> >
> > >
> > > -	functions = devm_kcalloc(dev, npins, sizeof(*functions), GFP_KERNEL);
> > > -	if (!functions)
> > > -		return -ENOMEM;
> > > -
> > > -	for (int i = 0; i < npins; i++) {
> > > -		ret = of_property_read_u32_index(np, "pins", i, &pin);
> > > -		if (ret)
> > > -			return ret;
> > > -
> > > -		pins[i] = pin;
> > > -
> > > -		ret = of_property_read_string(np, "function", &functions[i]);
> > > -		if (ret)
> > > -			return ret;
> > > -	}
> > > -
> > >  	ret = pinctrl_utils_reserve_map(pctldev, maps, num_reserved_maps, num_maps, reserve);
> > >  	if (ret)
> > >  		return ret;
> > > @@ -103,6 +76,54 @@ static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *p
> > >  	return 0;
> > >  };
> > >
> > > +static int
> > > +pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *pctldev,
> > > +						struct device_node *parent,
> > > +						struct device_node *np,
> > > +						struct pinctrl_map **maps,
> > > +						unsigned int *num_maps,
> > > +						unsigned int *num_reserved_maps,
> > > +						const char **group_names,
> > > +						unsigned int ngroups)
> > > +{
> > > +	struct device *dev = pctldev->dev;
> > > +	unsigned int pin, *pins;
> > > +	const char **functions;
> > > +	int npins, ret;
> > > +
> > > +	npins = of_property_count_u32_elems(np, "pins");
> > > +
> > > +	if (npins < 1) {
> > > +		dev_err(dev, "invalid pinctrl group %pOFn.%pOFn %d\n",
> > > +			parent, np, npins);
> > > +		return npins;
> > > +	}
> > > +
> > > +	pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> > > +	if (!pins)
> > > +		return -ENOMEM;
> > > +
> > > +	functions = devm_kcalloc(dev, npins, sizeof(*functions), GFP_KERNEL);
> > > +	if (!functions)
> > > +		return -ENOMEM;
> > > +
> > > +	for (int i = 0; i < npins; i++) {
> > > +		ret = of_property_read_u32_index(np, "pins", i, &pin);
> > > +		if (ret)
> > > +			return ret;
> > > +
> > > +		pins[i] = pin;
> > > +
> > > +		ret = of_property_read_string(np, "function", &functions[i]);
> > > +		if (ret)
> > > +			return ret;
> > > +	}
> > > +
> > > +	return pinctrl_generic_to_map(pctldev, parent, np, maps, num_maps,
> > > +				      num_reserved_maps, group_names, ngroups,
> > > +				      functions, pins);
> > > +}
> > > +
> > >  /*
> > >   * For platforms that do not define groups or functions in the driver, but
> > >   * instead use the devicetree to describe them. This function will, unlike
> > >
> > > --
> > > 2.43.0
> > >
>
>




^ permalink raw reply

* WITHDRAWN -RE: [PATCH net V2 0/2] Correct BD length masks and BQL accounting for multi-BD TX packets
From: Gupta, Suraj @ 2026-03-26 19:46 UTC (permalink / raw)
  To: Gupta, Suraj, andrew+netdev@lunn.ch, davem@davemloft.net,
	edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
	Simek, Michal, sean.anderson@linux.dev, Pandey, Radhey Shyam,
	horms@kernel.org
  Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, Katakam, Harini
In-Reply-To: <20260326185510.3840084-1-suraj.gupta2@amd.com>

[Public]

> -----Original Message-----
> From: Suraj Gupta <suraj.gupta2@amd.com>
> Sent: Friday, March 27, 2026 12:25 AM
> To: andrew+netdev@lunn.ch; davem@davemloft.net; edumazet@google.com;
> kuba@kernel.org; pabeni@redhat.com; Simek, Michal
> <michal.simek@amd.com>; sean.anderson@linux.dev; Pandey, Radhey Shyam
> <radhey.shyam.pandey@amd.com>; horms@kernel.org
> Cc: netdev@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-
> kernel@vger.kernel.org; Katakam, Harini <harini.katakam@amd.com>
> Subject: [PATCH net V2 0/2] Correct BD length masks and BQL accounting for
> multi-BD TX packets
>

Please ignore / withdraw this V2 series.

Due to a syncing issue in my outlook, I sent v2 prematurely. There is still ongoing discussion on v1 that needs to be concluded first. I'll follow up after the v1 feedback is resolved.

Thanks,
Suraj

> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> This patch series fixes two issues in the Xilinx AXI Ethernet driver:
>  1. Corrects the BD length masks to match the AXIDMA IP spec.
>  2. Fixes BQL accounting for multi-BD TX packets.
>
> ---
> Changes in V2:
> Use GENMASK() to define the BD length masks.
> ---
> Suraj Gupta (2):
>   net: xilinx: axienet: Correct BD length masks to match AXIDMA IP spec
>   net: xilinx: axienet: Fix BQL accounting for multi-BD TX packets
>
>  drivers/net/ethernet/xilinx/xilinx_axienet.h  |  7 +++++--
> .../net/ethernet/xilinx/xilinx_axienet_main.c | 20 +++++++++----------
>  2 files changed, 15 insertions(+), 12 deletions(-)
>
> --
> 2.49.1
>



^ permalink raw reply


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