* Re: [PATCH 0/2] pinctrl: mediatek: Enable MT8189 as loadable module
From: Linus Walleij @ 2026-06-08 19:29 UTC (permalink / raw)
To: Justin Yeh
Cc: Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
Project_Global_Chrome_Upstream_Group, linux-mediatek, linux-gpio,
linux-kernel, linux-arm-kernel
In-Reply-To: <20260529100308.51271-1-justin.yeh@mediatek.com>
On Fri, May 29, 2026 at 12:04 PM Justin Yeh <justin.yeh@mediatek.com> wrote:
> This series enables PINCTRL_MT8189 to be built as a loadable kernel
> module, which is required for GKI (Generic Kernel Image) + vendor_dlkm
> deployments where vendor-specific drivers must be kept separate from
> the GKI vmlinux.
Maybe tell us that this is for Android?
> Patch 1 restores the tristate option that was recently changed to bool,
No the driver was merged with tristate.
See
commit a3fe1324c3c5c292ec79bd756497c1c44ff247d2 (tag: pinctrl-v6.17-1)
"pinctrl: mediatek: Add pinctrl driver for mt8189"
> preventing module builds. Patch 2 adds the missing MODULE_LICENSE macro
> that's required when building as a module.
So that should be squashed into one patch or it will not bisect.
> Together these changes allow MT8189 pinctrl to be properly packaged as
> a vendor kernel module while maintaining the existing built-in option.
So why do we change this only for MT8189 and not for all
Mediatek pinctrl drivers?
I would just add this tristate option and license to all of them while
you're at it or I will get like 20 identical patches and it's a waste
of time for me.
Yours,
Linus Walleij
^ permalink raw reply
* -next boot failures during KVM setup
From: Mark Brown @ 2026-06-08 19:19 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton; +Cc: Aishwarya.TCV, linux-arm-kernel
[-- Attachment #1: Type: text/plain, Size: 1413 bytes --]
I'm seeing boot failures on a range of physical arm64 platforms in
today's -next. Turning on earlycon it looks like we're getting bad
pointer dereferences during KVM initialisation:
[ 0.728923] kvm [1]: nv: 570 coarse grained trap handlers
[ 0.735138] kvm [1]: nv: 710 fine grained trap handlers
[ 0.741326] kvm [1]: IPA Size Limit: 40 bits
[ 0.748840] Unable to handle kernel paging request at virtual address ffff00000478e000
[ 0.757027] Mem abort info:
[ 0.759917] ESR = 0x0000000096000147
[ 0.763772] EC = 0x25: DABT (current EL), IL = 32 bits
[ 0.851526] pc : dcache_clean_inval_poc+0x24/0x48
[ 0.856367] lr : kvm_arm_init+0xbb0/0x13f0
...
[ 0.937120] Call trace:
[ 0.939628] dcache_clean_inval_poc+0x24/0x48 (P)
[ 0.944457] do_one_initcall+0x60/0x1d4
[ 0.948393] kernel_init_freeable+0x250/0x2d8
https://lava.sirena.org.uk/scheduler/job/2849583#L848
(with other platforms I've got earlycon logs showing basically the same
thing). I have some bisects but they seem to have been confused by
earlier driver core issues, I've tweaked to try to avoid that and am
retrying. FVP and qemu seem unaffected:
https://lava.sirena.org.uk/scheduler/job/2848374#L888
https://lava.sirena.org.uk/scheduler/job/2848966#L447
The affected platforms thus far are all SMP Cortex A53/5 systems, but
that's the vast majority of my lab. They have both GICv3 and GICv2.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH] i2c: stm32f7: fix timing computation ignoring i2c-analog-filter
From: Andi Shyti @ 2026-06-08 18:27 UTC (permalink / raw)
To: Guillermo Rodríguez
Cc: Pierre-Yves MORDRET, Alain Volmat, Maxime Coquelin,
Alexandre Torgue, Wolfram Sang, linux-i2c, linux-stm32,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260526091210.20383-1-guille.rodriguez@gmail.com>
Hi Guillermo,
On Tue, May 26, 2026 at 11:12:09AM +0200, Guillermo Rodríguez wrote:
> stm32f7_i2c_compute_timing() uses i2c_dev->analog_filter to pick
> the analog filter delay, but i2c_dev->analog_filter is parsed from
> the "i2c-analog-filter" DT property only after the compute_timing
> loop in stm32f7_i2c_setup_timing(), so in practice the timing
> calculations always ignore the analog filter. On an STM32MP1 board
> with clock-frequency = <400000> and i2c-analog-filter set, measured
> SCL frequency was ~382 kHz.
>
> This also affects (widens) the computed SDADEL range. At high bus
> clock speeds, this can select an SDADEL value that violates tVD;DAT
> (data valid time).
>
> Fix by parsing "i2c-analog-filter" before the compute_timing loop.
>
> Fixes: 83c3408f7b9c ("i2c: stm32f7: support DT binding i2c-analog-filter")
> Cc: stable@vger.kernel.org
> Signed-off-by: Guillermo Rodríguez <guille.rodriguez@gmail.com>
merged to i2c/i2c-host-fixes.
Thanks,
Andi
^ permalink raw reply
* [PATCH v1] clocksource/drivers/timer-atmel-pit: Fix init failure cleanup
From: Yuho Choi @ 2026-06-08 18:20 UTC (permalink / raw)
To: Daniel Lezcano, Thomas Gleixner, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea
Cc: Boris Brezillon, linux-arm-kernel, linux-kernel, Yuho Choi
After clk_prepare_enable(data->mck) succeeds, at91sam926x_pit_dt_init()
can still fail while parsing the IRQ, registering the clocksource, or
requesting the IRQ. These paths only free the driver data, leaving the
master clock enabled.
Unwind each initialized state on failure. Stop the PIT after it has been
started, dispose the IRQ mapping after it has been created, disable and
put the master clock, and unmap the registers before freeing the driver
data.
Fixes: 699e36e5b8e9 ("clocksource/drivers/timer-atmel-pit: Enable mck clock")
Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
---
drivers/clocksource/timer-atmel-pit.c | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c
index 888b06731e54..edd427ab93e6 100644
--- a/drivers/clocksource/timer-atmel-pit.c
+++ b/drivers/clocksource/timer-atmel-pit.c
@@ -12,7 +12,9 @@
#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -185,13 +187,13 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
if (IS_ERR(data->mck)) {
pr_err("Unable to get mck clk\n");
ret = PTR_ERR(data->mck);
- goto exit;
+ goto exit_iounmap;
}
ret = clk_prepare_enable(data->mck);
if (ret) {
pr_err("Unable to enable mck\n");
- goto exit;
+ goto exit_clk_put;
}
/* Get the interrupts property */
@@ -199,7 +201,7 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
if (!data->irq) {
pr_err("Unable to get IRQ from DT\n");
ret = -EINVAL;
- goto exit;
+ goto exit_clk_disable;
}
/*
@@ -227,7 +229,7 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
ret = clocksource_register_hz(&data->clksrc, pit_rate);
if (ret) {
pr_err("Failed to register clocksource\n");
- goto exit;
+ goto exit_pit_disable;
}
/* Set up irq handler */
@@ -237,7 +239,7 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
if (ret) {
pr_err("Unable to setup IRQ\n");
clocksource_unregister(&data->clksrc);
- goto exit;
+ goto exit_pit_disable;
}
/* Set up and register clockevents */
@@ -256,6 +258,15 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
return 0;
+exit_pit_disable:
+ pit_write(data->base, AT91_PIT_MR, 0);
+ irq_dispose_mapping(data->irq);
+exit_clk_disable:
+ clk_disable_unprepare(data->mck);
+exit_clk_put:
+ clk_put(data->mck);
+exit_iounmap:
+ iounmap(data->base);
exit:
kfree(data);
return ret;
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v4 2/4] perf: Use a union to clear branch entry bitfields
From: James Clark @ 2026-06-08 18:06 UTC (permalink / raw)
To: Puranjay Mohan, bpf
Cc: Puranjay Mohan, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Andrii Nakryiko, Martin KaFai Lau,
Eduard Zingerman, Song Liu, Yonghong Song, Will Deacon,
Mark Rutland, Catalin Marinas, Leo Yan, Rob Herring,
Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Ian Rogers, Adrian Hunter, Shuah Khan, Breno Leitao,
Ravi Bangoria, Stephane Eranian, Kumar Kartikeya Dwivedi,
Usama Arif, linux-arm-kernel, linux-perf-users, linux-kselftest,
linux-kernel, kernel-team
In-Reply-To: <20260527121207.2312181-3-puranjay@kernel.org>
On 27/05/2026 1:11 pm, Puranjay Mohan wrote:
> perf_clear_branch_entry_bitfields() zeroes individual bitfields of struct
> perf_branch_entry but has repeatedly fallen out of sync when new fields
> were added (new_type and priv were missed).
>
> Wrap the bitfields in an anonymous struct inside a union with a u64
> bitfields member, and clear them all with a single assignment. This
> avoids having to update the clearing function every time a new bitfield
> is added.
>
> Fixes: bfe4daf850f4 ("perf/core: Add perf_clear_branch_entry_bitfields() helper")
> Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
> ---
> include/linux/perf_event.h | 9 +--------
> include/uapi/linux/perf_event.h | 25 +++++++++++++++----------
> tools/include/uapi/linux/perf_event.h | 25 +++++++++++++++----------
> 3 files changed, 31 insertions(+), 28 deletions(-)
>
> diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
> index 48d851fbd8ea..f7360c43f902 100644
> --- a/include/linux/perf_event.h
> +++ b/include/linux/perf_event.h
> @@ -1474,14 +1474,7 @@ static inline u32 perf_sample_data_size(struct perf_sample_data *data,
> */
> static inline void perf_clear_branch_entry_bitfields(struct perf_branch_entry *br)
> {
> - br->mispred = 0;
> - br->predicted = 0;
> - br->in_tx = 0;
> - br->abort = 0;
> - br->cycles = 0;
> - br->type = 0;
> - br->spec = PERF_BR_SPEC_NA;
> - br->reserved = 0;
> + br->bitfields = 0;
The comment above here says:
* The to and from fields are not cleared because they are
* systematically modified by caller.
But this is an inline function and the to/from fields are always
assigned right after calling it. Surely the compiler can work that out
and this was a premature optimization.
If we rename it to perf_clear_branch_entry() and do:
*br = (struct perf_branch_entry) {0};
Then we can delete a big comment, remove a potential source of bugs if
even more members are added, not have to update the uapi headers and
simplify it instead of working around the original issue.
> }
>
> extern void perf_output_sample(struct perf_output_handle *handle,
> diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
> index fd10aa8d697f..c2e7b1b1c4fa 100644
> --- a/include/uapi/linux/perf_event.h
> +++ b/include/uapi/linux/perf_event.h
> @@ -1491,16 +1491,21 @@ union perf_mem_data_src {
> struct perf_branch_entry {
> __u64 from;
> __u64 to;
> - __u64 mispred : 1, /* target mispredicted */
> - predicted : 1, /* target predicted */
> - in_tx : 1, /* in transaction */
> - abort : 1, /* transaction abort */
> - cycles : 16, /* cycle count to last branch */
> - type : 4, /* branch type */
> - spec : 2, /* branch speculation info */
> - new_type : 4, /* additional branch type */
> - priv : 3, /* privilege level */
> - reserved : 31;
> + union {
> + struct {
> + __u64 mispred : 1, /* target mispredicted */
> + predicted : 1, /* target predicted */
> + in_tx : 1, /* in transaction */
> + abort : 1, /* transaction abort */
> + cycles : 16, /* cycle count to last branch */
> + type : 4, /* branch type */
> + spec : 2, /* branch speculation info */
> + new_type : 4, /* additional branch type */
> + priv : 3, /* privilege level */
> + reserved : 31;
> + };
> + __u64 bitfields;
> + };
> };
>
> /* Size of used info bits in struct perf_branch_entry */
> diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
> index fd10aa8d697f..c2e7b1b1c4fa 100644
> --- a/tools/include/uapi/linux/perf_event.h
> +++ b/tools/include/uapi/linux/perf_event.h
> @@ -1491,16 +1491,21 @@ union perf_mem_data_src {
> struct perf_branch_entry {
> __u64 from;
> __u64 to;
> - __u64 mispred : 1, /* target mispredicted */
> - predicted : 1, /* target predicted */
> - in_tx : 1, /* in transaction */
> - abort : 1, /* transaction abort */
> - cycles : 16, /* cycle count to last branch */
> - type : 4, /* branch type */
> - spec : 2, /* branch speculation info */
> - new_type : 4, /* additional branch type */
> - priv : 3, /* privilege level */
> - reserved : 31;
> + union {
> + struct {
> + __u64 mispred : 1, /* target mispredicted */
> + predicted : 1, /* target predicted */
> + in_tx : 1, /* in transaction */
> + abort : 1, /* transaction abort */
> + cycles : 16, /* cycle count to last branch */
> + type : 4, /* branch type */
> + spec : 2, /* branch speculation info */
> + new_type : 4, /* additional branch type */
> + priv : 3, /* privilege level */
> + reserved : 31;
> + };
> + __u64 bitfields;
> + };
> };
>
> /* Size of used info bits in struct perf_branch_entry */
^ permalink raw reply
* Re: [PATCH v2 0/2] soc: aspeed: Add BMC and host driver for PCIe BMC device
From: Andrew Lunn @ 2026-06-08 18:05 UTC (permalink / raw)
To: Grégoire Layet
Cc: joel, andrew, jacky_chou, yh_chung, ninad, linux-aspeed,
linux-arm-kernel, linux-kernel
In-Reply-To: <cover.1780929570.git.gregoire.layet@9elements.com>
On Mon, Jun 08, 2026 at 02:51:21PM +0000, Grégoire Layet wrote:
> This is a v2 for upstreaming the VUART over PCIe BMC device driver from the ASPEED kernel SDK (branch master-v6.18) [1].
> There are two drivers: a BMC-side driver and a host-side driver.
> Together they enable host<->BMC VUART communication via PCIe.
I would like to see somewhere a comment about security. From the
replies i got the host can access anything on the LPC bus of the
aspeed. What are the implications of that? What are typically on such
a bus? TPMs are often there, but does a BMC have a TPM?
Andrew
^ permalink raw reply
* [PATCH net-next v3] net: airoha: defer GDM3/GDM4 WAN mode and GDM2 loopback to QoS offload
From: Lorenzo Bianconi @ 2026-06-08 18:03 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Lorenzo Bianconi
Cc: linux-arm-kernel, linux-mediatek, netdev, Madhur Agrawal
GDM3 and GDM4 ports require GDM2 loopback to be enabled for hardware
QoS offload to function. Without it, HTB and ETS offload on these ports
do not work.
Previously, GDM3/GDM4 ports were automatically configured as WAN with
GDM2 loopback enabled during ndo_init(). Move this setup to be performed
on demand when QoS offload is created or destroyed. GDM3 and GDM4 now
default to LAN mode at init time, while GDM2 is always WAN.
Hook airoha_enable_qos_for_gdm34() into TC_HTB_CREATE so that requesting
HTB offload on a GDM3/GDM4 LAN port switches it to WAN mode and enables
GDM2 loopback, with proper rollback on failure. Hook the counterpart
airoha_disable_qos_for_gdm34() into TC_HTB_DESTROY to restore LAN mode
when the offloaded qdisc is torn down.
Add airoha_disable_gdm2_loopback() as the teardown counterpart of the
existing airoha_enable_gdm2_loopback().
Move QDMA TX/RX DMA enable from airoha_dev_open() to airoha_probe() and
the corresponding disable from airoha_dev_stop() to airoha_qdma_cleanup(),
removing the per-QDMA atomic refcount that was needed for the open/close
path. DMA is now always active from probe to remove.
Tested-by: Madhur Agrawal <madhur.agrawal@airoha.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
Changes in v3:
- Do not introduce ethtool private flags support to configure LAN/WAN
for GDM3/4 and rely on tc qdisc offload for it instead.
- Set GDM3/4 ports as LAN by default.
- Move QDMA TX/RX DMA enable from airoha_dev_open() to airoha_probe()
and the corresponding disable from airoha_dev_stop() to airoha_qdma_cleanup().
- Link to v2: https://lore.kernel.org/r/20260607-airoha-ethtool-priv_flags-v2-1-742c7aa1e182@kernel.org
Changes in v2:
- Rework airoha_dev_set_wan_flag routine
- Enable GDM_STRIP_CRC_MASK in airoha_disable_gdm2_loopback()
- Do not always reset REG_SRC_PORT_FC_MAP6 in
airoha_disable_gdm2_loopback() but use the same condition used in
airoha_enable_gdm2_loopback().
- Link to v1: https://lore.kernel.org/r/20260606-airoha-ethtool-priv_flags-v1-1-401b2c9fe9f1@kernel.org
---
drivers/net/ethernet/airoha/airoha_eth.c | 177 ++++++++++++++++++++++--------
drivers/net/ethernet/airoha/airoha_eth.h | 2 -
drivers/net/ethernet/airoha/airoha_regs.h | 1 +
3 files changed, 131 insertions(+), 49 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 5a8e84fa9918..9bfb1e5b2b54 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1516,6 +1516,10 @@ static void airoha_qdma_cleanup(struct airoha_qdma *qdma)
{
int i;
+ airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
+ GLOBAL_CFG_TX_DMA_EN_MASK |
+ GLOBAL_CFG_RX_DMA_EN_MASK);
+
for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
if (!qdma->q_rx[i].ndesc)
continue;
@@ -1806,11 +1810,6 @@ static int airoha_dev_open(struct net_device *netdev)
}
port->users++;
- airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG,
- GLOBAL_CFG_TX_DMA_EN_MASK |
- GLOBAL_CFG_RX_DMA_EN_MASK);
- atomic_inc(&qdma->users);
-
if (!airoha_is_lan_gdm_dev(dev) &&
airoha_ppe_is_enabled(qdma->eth, 1))
pse_port = FE_PSE_PORT_PPE2;
@@ -1863,19 +1862,6 @@ static int airoha_dev_stop(struct net_device *netdev)
REG_GDM_FWD_CFG(port->id),
FE_PSE_PORT_DROP);
- if (atomic_dec_and_test(&qdma->users)) {
- airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
- GLOBAL_CFG_TX_DMA_EN_MASK |
- GLOBAL_CFG_RX_DMA_EN_MASK);
-
- for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
- if (!qdma->q_tx[i].ndesc)
- continue;
-
- airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
- }
- }
-
return 0;
}
@@ -1960,6 +1946,49 @@ static int airoha_enable_gdm2_loopback(struct airoha_gdm_dev *dev)
return 0;
}
+static int airoha_disable_gdm2_loopback(struct airoha_gdm_dev *dev)
+{
+ struct airoha_gdm_port *port = dev->port;
+ struct airoha_eth *eth = dev->eth;
+ int i, src_port;
+ u32 pse_port;
+
+ src_port = eth->soc->ops.get_sport(dev->port, dev->nbq);
+ if (src_port < 0)
+ return src_port;
+
+ airoha_fe_clear(eth,
+ REG_SP_DFT_CPORT(src_port >> fls(SP_CPORT_DFT_MASK)),
+ SP_CPORT_MASK(src_port & SP_CPORT_DFT_MASK));
+
+ airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),
+ GDM_STRIP_CRC_MASK);
+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),
+ FE_PSE_PORT_DROP);
+ airoha_fe_clear(eth, REG_GDM_LPBK_CFG(AIROHA_GDM2_IDX),
+ LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK);
+ pse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2
+ : FE_PSE_PORT_PPE1;
+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX),
+ pse_port);
+
+ airoha_fe_rmw(eth, REG_FE_WAN_PORT, WAN0_MASK,
+ FIELD_PREP(WAN0_MASK, AIROHA_GDM2_IDX));
+
+ for (i = 0; i < eth->soc->num_ppe; i++)
+ airoha_fe_clear(eth, REG_PPE_DFT_CPORT(i, AIROHA_GDM2_IDX),
+ DFT_CPORT_MASK(AIROHA_GDM2_IDX));
+
+ /* Enable VIP and IFC for GDM2 */
+ airoha_fe_set(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX));
+ airoha_fe_set(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX));
+
+ if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth))
+ airoha_fe_wr(eth, REG_SRC_PORT_FC_MAP6, FC_MAP6_DEF_VALUE);
+
+ return 0;
+}
+
static struct airoha_gdm_dev *
airoha_get_wan_gdm_dev(struct airoha_eth *eth)
{
@@ -2002,40 +2031,14 @@ static int airoha_dev_init(struct net_device *netdev)
struct airoha_gdm_dev *dev = netdev_priv(netdev);
struct airoha_gdm_port *port = dev->port;
- switch (port->id) {
- case AIROHA_GDM3_IDX:
- case AIROHA_GDM4_IDX: {
- struct airoha_eth *eth = dev->eth;
-
- /* GDM2 supports a single net_device */
- if (eth->ports[1] && eth->ports[1]->devs[0])
- break;
-
- if (airoha_get_wan_gdm_dev(eth))
- break;
-
- fallthrough;
- }
- case AIROHA_GDM2_IDX:
- /* GDM2 is always used as wan */
+ if (port->id == AIROHA_GDM2_IDX) {
+ /* GDM2 is always used as WAN */
dev->flags |= AIROHA_PRIV_F_WAN;
- break;
- default:
- break;
}
airoha_dev_set_qdma(dev);
airoha_set_macaddr(dev, netdev->dev_addr);
- if (!airoha_is_lan_gdm_dev(dev) &&
- (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX)) {
- int err;
-
- err = airoha_enable_gdm2_loopback(dev);
- if (err)
- return err;
- }
-
return 0;
}
@@ -3008,6 +3011,79 @@ static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev,
return 0;
}
+static int airoha_enable_qos_for_gdm34(struct net_device *netdev)
+{
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
+ u32 pse_port;
+ int err;
+
+ if (port->id != AIROHA_GDM3_IDX &&
+ port->id != AIROHA_GDM4_IDX) {
+ /* HW QoS is always supported by GDM1 and GDM2 */
+ return 0;
+ }
+
+ if (!airoha_is_lan_gdm_dev(dev)) /* Already enabled */
+ return 0;
+
+ /* Verify the WAN device is not already configured */
+ if (airoha_get_wan_gdm_dev(dev->eth))
+ return -EBUSY;
+
+ dev->flags |= AIROHA_PRIV_F_WAN;
+ airoha_dev_set_qdma(dev);
+ err = airoha_enable_gdm2_loopback(dev);
+ if (err)
+ goto error_disable_wan;
+
+ err = airoha_set_macaddr(dev, netdev->dev_addr);
+ if (err)
+ goto error_disable_loopback;
+
+ pse_port = airoha_ppe_is_enabled(dev->eth, 1) ? FE_PSE_PORT_PPE2
+ : FE_PSE_PORT_PPE1;
+ airoha_set_gdm_port_fwd_cfg(dev->eth, REG_GDM_FWD_CFG(port->id),
+ pse_port);
+
+ return 0;
+
+error_disable_loopback:
+ /* Restore previous LAN configuration */
+ airoha_disable_gdm2_loopback(dev);
+error_disable_wan:
+ dev->flags &= ~AIROHA_PRIV_F_WAN;
+ airoha_dev_set_qdma(dev);
+
+ return err;
+}
+
+static void airoha_disable_qos_for_gdm34(struct net_device *netdev)
+{
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_gdm_port *port = dev->port;
+ int err;
+
+ if (port->id != AIROHA_GDM3_IDX &&
+ port->id != AIROHA_GDM4_IDX) {
+ return;
+ }
+
+ if (airoha_is_lan_gdm_dev(dev)) /* Already disabled */
+ return;
+
+ err = airoha_disable_gdm2_loopback(dev);
+ if (err)
+ netdev_warn(netdev,
+ "failed disabling GDM2 loopback: %d\n", err);
+
+ dev->flags &= ~AIROHA_PRIV_F_WAN;
+ airoha_dev_set_qdma(dev);
+ airoha_set_macaddr(dev, netdev->dev_addr);
+ airoha_set_gdm_port_fwd_cfg(dev->eth, REG_GDM_FWD_CFG(port->id),
+ FE_PSE_PORT_PPE1);
+}
+
static int airoha_tc_htb_destroy(struct net_device *netdev)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
@@ -3016,6 +3092,8 @@ static int airoha_tc_htb_destroy(struct net_device *netdev)
for_each_set_bit(q, dev->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS)
airoha_tc_remove_htb_queue(netdev, q);
+ airoha_disable_qos_for_gdm34(netdev);
+
return 0;
}
@@ -3040,7 +3118,7 @@ static int airoha_tc_setup_qdisc_htb(struct net_device *dev,
{
switch (opt->command) {
case TC_HTB_CREATE:
- break;
+ return airoha_enable_qos_for_gdm34(dev);
case TC_HTB_DESTROY:
return airoha_tc_htb_destroy(dev);
case TC_HTB_NODE_MODIFY:
@@ -3414,6 +3492,11 @@ static int airoha_probe(struct platform_device *pdev)
if (err)
goto error_napi_stop;
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
+ airoha_qdma_set(ð->qdma[i], REG_QDMA_GLOBAL_CFG,
+ GLOBAL_CFG_TX_DMA_EN_MASK |
+ GLOBAL_CFG_RX_DMA_EN_MASK);
+
return 0;
error_napi_stop:
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index 8f42973f9cf5..cd0706a0c07f 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -526,8 +526,6 @@ struct airoha_qdma {
struct airoha_eth *eth;
void __iomem *regs;
- atomic_t users;
-
struct airoha_irq_bank irq_banks[AIROHA_MAX_NUM_IRQ_BANKS];
struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
diff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h
index 436f3c8779c1..4e17dfbcf2b8 100644
--- a/drivers/net/ethernet/airoha/airoha_regs.h
+++ b/drivers/net/ethernet/airoha/airoha_regs.h
@@ -376,6 +376,7 @@
#define REG_SRC_PORT_FC_MAP6 0x2298
#define FC_ID_OF_SRC_PORT_MASK(_n) GENMASK(4 + ((_n) << 3), ((_n) << 3))
+#define FC_MAP6_DEF_VALUE 0x1b1a1918
#define REG_CDM5_RX_OQ1_DROP_CNT 0x29d4
---
base-commit: 903db046d5579bef0ea699eae4b279dd6455fc9f
change-id: 20260606-airoha-ethtool-priv_flags-b6aa70caa780
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* Re: [PATCH] i2c: imx: fix clock and pinctrl state inconsistency in runtime PM
From: Andi Shyti @ 2026-06-08 17:46 UTC (permalink / raw)
To: Carlos Song (OSS)
Cc: o.rempel, kernel, Frank.Li, s.hauer, festevam, carlos.song,
linux-i2c, imx, linux-arm-kernel, linux-kernel, stable
In-Reply-To: <20260520104939.2897110-1-carlos.song@oss.nxp.com>
Hi Carlos,
On Wed, May 20, 2026 at 06:49:39PM +0800, Carlos Song (OSS) wrote:
> From: Carlos Song <carlos.song@nxp.com>
>
> In i2c_imx_runtime_suspend(), the clock is disabled before switching
> the pinctrl state to sleep. If pinctrl_pm_select_sleep_state() fails,
> the runtime suspend is aborted but the clock remains disabled, causing
> a system crash when the hardware is subsequently accessed.
>
> Fix this by switching the pinctrl state before disabling the clock so
> that a pinctrl failure leaves the clock enabled and the hardware
> accessible.
>
> In i2c_imx_runtime_resume(), restore the pinctrl state back to sleep
> if clk_enable() fails to keep the two consistent.
>
> Fixes: 576eba03c994 ("i2c: imx: switch different pinctrl state in different system power status")
> Cc: stable@vger.kernel.org
> Signed-off-by: Carlos Song <carlos.song@nxp.com>
merged to i2c/i2c-host-fixes.
Thanks,
Andi
^ permalink raw reply
* Re: [PATCH 3/3] dt-bindings: perf: marvell: Extend CN10K TAD PMU binding for CN20K
From: Conor Dooley @ 2026-06-08 17:34 UTC (permalink / raw)
To: Geetha sowjanya
Cc: linux-perf-users, linux-kernel, linux-arm-kernel, devicetree,
mark.rutland, will, krzk+dt
In-Reply-To: <20260607125101.17778-4-gakula@marvell.com>
[-- Attachment #1: Type: text/plain, Size: 2479 bytes --]
On Sun, Jun 07, 2026 at 06:21:01PM +0530, Geetha sowjanya wrote:
> Allow marvell,cn20k-tad-pmu alongside marvell,cn10k-tad-pmu, document
> CN20K in the title and description, add a maintainer, and include a
> CN20K example node with the same required properties as CN10K.
This is great and all, but is evident from the diff (other than the fact
it talks about an example that does not exist).
What is missing is an explanation of why a fallback comaptible is not
usable.
pw-bot: changes-requested
Thanks,
Conor.
>
> Signed-off-by: Geetha sowjanya <gakula@marvell.com>
> ---
> .../bindings/perf/marvell-cn10k-tad.yaml | 20 +++++++++++--------
> 1 file changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/perf/marvell-cn10k-tad.yaml b/Documentation/devicetree/bindings/perf/marvell-cn10k-tad.yaml
> index 362142252667..1612052b59ae 100644
> --- a/Documentation/devicetree/bindings/perf/marvell-cn10k-tad.yaml
> +++ b/Documentation/devicetree/bindings/perf/marvell-cn10k-tad.yaml
> @@ -4,23 +4,27 @@
> $id: http://devicetree.org/schemas/perf/marvell-cn10k-tad.yaml#
> $schema: http://devicetree.org/meta-schemas/core.yaml#
>
> -title: Marvell CN10K LLC-TAD performance monitor
> +title: Marvell CN10K / CN20K LLC-TAD performance monitor
>
> maintainers:
> - Bhaskara Budiredla <bbudiredla@marvell.com>
> + - Geetha sowjanya <gakula@marvell.com>
>
> description: |
> - The Tag-and-Data units (TADs) maintain coherence and contain CN10K
> - shared on-chip last level cache (LLC). The tad pmu measures the
> - performance of last-level cache. Each tad pmu supports up to eight
> - counters.
> + The Tag-and-Data units (TADs) maintain coherence and contain the
> + shared on-chip last level cache (LLC) on Marvell CN10K and CN20K SoCs.
> + The TAD PMU measures last-level cache performance. Each TAD PMU
> + supports up to eight counters.
>
> - The DT setup comprises of number of tad blocks, the sizes of pmu
> - regions, tad blocks and overall base address of the HW.
> + The DT setup describes the number of TAD blocks, the sizes of PMU
> + regions and TAD pages, and the overall MMIO base of the hardware.
>
> properties:
> compatible:
> - const: marvell,cn10k-tad-pmu
> + items:
> + - enum:
> + - marvell,cn10k-tad-pmu
> + - marvell,cn20k-tad-pmu
>
> reg:
> maxItems: 1
> --
> 2.25.1
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v2 6/6] irqchip/gic-v5: Enable GICv5 IWB ACPI probe ordering detection
From: Rafael J. Wysocki @ 2026-06-08 17:18 UTC (permalink / raw)
To: Lorenzo Pieralisi
Cc: Rafael J. Wysocki, Len Brown, Sunil V L, Marc Zyngier,
Thomas Gleixner, Huacai Chen, Anup Patel, Hanjun Guo,
Sudeep Holla, Catalin Marinas, Will Deacon, linux-riscv,
linux-kernel, linux-acpi, linux-arm-kernel, loongarch
In-Reply-To: <20260603-gic-v5-acpi-iwb-probe-deferral-v2-6-23ffa16b6ebb@kernel.org>
On Wed, Jun 3, 2026 at 10:21 AM Lorenzo Pieralisi <lpieralisi@kernel.org> wrote:
>
> Register an ACPI hook in the ACPI interrupt management code for GICv5 to
> retrieve the ACPI interrupt controller handle (if any) of the controller
> handling a specific GSI, by updating the acpi_set_irq_model() call with
> the gic_v5_get_gsi_handle() function pointer parameter.
>
> gicv5_get_gsi_handle() allows ACPI core to detect the ACPI handle
> of the controller that manages a specific GSI interrupt.
>
> Update the IWB driver to clear device dependencies in ACPI core once the
> IWB driver has probed.
>
> Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
> Cc: Thomas Gleixner <tglx@kernel.org>
> Cc: Marc Zyngier <maz@kernel.org>
> ---
> drivers/irqchip/irq-gic-v5-iwb.c | 5 +++++
> drivers/irqchip/irq-gic-v5.c | 13 +++++++++++--
> 2 files changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/irqchip/irq-gic-v5-iwb.c b/drivers/irqchip/irq-gic-v5-iwb.c
> index 9103feb70ce8..a02cb9537b15 100644
> --- a/drivers/irqchip/irq-gic-v5-iwb.c
> +++ b/drivers/irqchip/irq-gic-v5-iwb.c
> @@ -269,6 +269,11 @@ static int gicv5_iwb_device_probe(struct platform_device *pdev)
> if (IS_ERR(iwb_node))
> return PTR_ERR(iwb_node);
>
> +#ifdef CONFIG_ACPI
> + if (has_acpi_companion(&pdev->dev))
> + acpi_dev_clear_dependencies(ACPI_COMPANION(&pdev->dev));
> +#endif
I would rather add a wrapper for this, along with an empty stub for
the !CONFIG_ACPI case.
> +
> return 0;
> }
>
> diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c
> index 03cc2830b260..26cfaea1af41 100644
> --- a/drivers/irqchip/irq-gic-v5.c
> +++ b/drivers/irqchip/irq-gic-v5.c
> @@ -1217,11 +1217,19 @@ static struct fwnode_handle *gsi_domain_handle;
> static struct fwnode_handle *gic_v5_get_gsi_domain_id(u32 gsi)
> {
> if (FIELD_GET(GICV5_GSI_IC_TYPE, gsi) == GICV5_GSI_IWB_TYPE)
> - return iort_iwb_handle(FIELD_GET(GICV5_GSI_IWB_FRAME_ID, gsi));
> + return iort_iwb_handle_fwnode(FIELD_GET(GICV5_GSI_IWB_FRAME_ID, gsi));
Why is this change needed?
>
> return gsi_domain_handle;
> }
>
> +static acpi_handle gic_v5_get_gsi_handle(u32 gsi)
> +{
> + if (FIELD_GET(GICV5_GSI_IC_TYPE, gsi) == GICV5_GSI_IWB_TYPE)
> + return iort_iwb_handle(FIELD_GET(GICV5_GSI_IWB_FRAME_ID, gsi));
> +
> + return NULL;
> +}
> +
> static int __init gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end)
> {
> struct acpi_madt_gicv5_irs *irs = (struct acpi_madt_gicv5_irs *)header;
> @@ -1242,7 +1250,8 @@ static int __init gic_acpi_init(union acpi_subtable_headers *header, const unsig
> if (ret)
> goto out_irs;
>
> - acpi_set_irq_model(ACPI_IRQ_MODEL_GIC_V5, gic_v5_get_gsi_domain_id, NULL);
> + acpi_set_irq_model(ACPI_IRQ_MODEL_GIC_V5, gic_v5_get_gsi_domain_id,
> + gic_v5_get_gsi_handle);
>
> return 0;
>
>
> --
^ permalink raw reply
* Re: [PATCH] ARM: footbridge: convert to sparse IRQs
From: Ethan Nelson-Moore @ 2026-06-08 17:13 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Dmitry Torokhov, linux-arm-kernel, linux-input, linux-serial,
Russell King, Greg Kroah-Hartman, Jiri Slaby, Russell King,
Linus Walleij, Kees Cook, Nathan Chancellor,
Sebastian Andrzej Siewior, Steven Rostedt, Thomas Weißschuh,
Peter Zijlstra
In-Reply-To: <86765df4-0d2d-435e-85d8-b9bd4f3ea85d@app.fastmail.com>
Hi, Arnd,
On Mon, Jun 8, 2026 at 10:11 AM Arnd Bergmann <arnd@arndb.de> wrote:
> I think this is correct, as footbridge is the only one that selects
> CONFIG_ARCH_MIGHT_HAVE_PC_SERIO and defines I8042_KBD_IRQ on arm.
I came to the same conclusion.
Ethan
^ permalink raw reply
* Re: [PATCH] ARM: footbridge: convert to sparse IRQs
From: Arnd Bergmann @ 2026-06-08 17:11 UTC (permalink / raw)
To: Dmitry Torokhov, Ethan Nelson-Moore
Cc: linux-arm-kernel, linux-input, linux-serial, Russell King,
Greg Kroah-Hartman, Jiri Slaby, Russell King, Linus Walleij,
Kees Cook, Nathan Chancellor, Sebastian Andrzej Siewior,
Steven Rostedt, Thomas Weißschuh, Peter Zijlstra
In-Reply-To: <aibz3auoiq4CFa9l@google.com>
On Mon, Jun 8, 2026, at 18:56, Dmitry Torokhov wrote:
> On Sat, May 09, 2026 at 10:20:49PM -0700, Ethan Nelson-Moore wrote:
>> diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
>> index a8f4b2d70e59..cea72bd888af 100644
>>
>> -#if defined(__arm__)
>> -/* defined in include/asm-arm/arch-xxx/irqs.h */
>> -#include <asm/irq.h>
>> +#ifdef CONFIG_ARCH_FOOTBRIDGE
>> +/* defined in arch/arm/mach-footbridge/include/mach/irqs.h */
>> +#include <mach/irqs.h>
>> #elif defined(CONFIG_PPC)
>> extern int of_i8042_kbd_irq;
>> extern int of_i8042_aux_irq;
>
> This does not look right. Did you mean to drop inclusion of asm/irq.h
> for all other arms?
I think this is correct, as footbridge is the only one that selects
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO and defines I8042_KBD_IRQ on arm.
Arnd
^ permalink raw reply
* Re: [PATCH v2 1/3] dt-bindings: arm: sunxi: Add NetCube Systems OpenNMC (dobermann)
From: Conor Dooley @ 2026-06-08 17:10 UTC (permalink / raw)
To: Lukas Schmid
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti, Maxime Ripard, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel, linux-riscv
In-Reply-To: <20260605191322.1920944-2-lukas.schmid@netcube.li>
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v2 1/3] dt-bindings: arm: fsl: add Variscite DART-MX8M PLUS Boards
From: Conor Dooley @ 2026-06-08 17:07 UTC (permalink / raw)
To: Stefano Radaelli
Cc: linux-kernel, devicetree, imx, linux-arm-kernel, pierluigi.p,
Stefano Radaelli, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Shawn Guo, Daniel Baluta, Josua Mayer, Dario Binacchi,
Maud Spierings, Alexander Stein, Ernest Van Hoecke,
Francesco Dolcini, Hugo Villeneuve
In-Reply-To: <c65129896fc6ce80044ee1d89e12dcdff34945be.1780912513.git.stefano.r@variscite.com>
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [RFC PATCH 2/2] firmware: arm_scmi: Add bus support for autoloading
From: Daniel Lezcano @ 2026-06-08 17:06 UTC (permalink / raw)
To: Cristian Marussi
Cc: arm-scmi, guomin_chen, linux-arm-kernel, peng.fan, quic_xinqzhan,
sudeep.holla
In-Reply-To: <aibzLcZiVwtUHAgV@pluto>
Hi Cristian,
thanks for your answer
On 6/8/26 18:51, Cristian Marussi wrote:
> On Mon, Jun 08, 2026 at 04:51:03PM +0200, Daniel Lezcano wrote:
>> On Mon, Feb 03, 2025 at 10:01:54AM +0000, Cristian Marussi wrote:
>>> Emit proper MODALIAS uevents when SCMI devices are created and make sure
>>> all the standard protocol devices are requested when the bus is
>>> initialized.
>>>
>>> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
>>> ---
>>
>> Hi Cristian,
>>
>
> Hi Daniel,
>
> nice to hear from you in the SCMI land :P
>
>> what is the status of this patch ?
>
> ....I'd say forgotten/abandoned...I worked on that a bit when I realized
> only part of the stack was autoloaded...then it did NOT received much
> love and then I forgot it....buried by other prios....
>
> Indeed I have still the local branch...but after a quick check I think
> is the same as the RFC posted.
>
> bbd14b0f7733 firmware: arm_scmi: Add bus support for autoloading
> 8d982393b505 firmware: arm_scmi: Generate aliases for SCMI modules
> 383c127faa97 (scmi_vendors_autoload_V2) firmware: arm_scmi: Add aliases to transport modules
> 00caa894bce2 firmware: arm_scmi: Add module aliases to i.MX vendor protocols
> d900620c46bb firmware: arm_scmi: Support vendor protocol modules autoloading
> 4fe57bbeb6dc firmware: arm_scmi: Allow transport properties for multiple instances
> ad236e5a7f01 Linux 6.13-rc1
>
> ...where scmi_vendors_autoload_V2 is merged already...
Actually, I'm puzzled.
On our platform, until 7.1-rc1 we had to add a modprobe.d script to load
the scmi_cpufreq driver because autoload was not suppported.
Now (7.1-rc1) it seems to be automatically loaded.
I imagined the autoload module has been added between 7.0 and 7.1, but
the series you are mentioning is from 6.13.
What I am missing ?
^ permalink raw reply
* Re: [PATCH v7 3/5] i3c: mipi-i3c-hci: add microchip sama7d65 SoC compatible with the required quirk
From: Frank Li @ 2026-06-08 17:04 UTC (permalink / raw)
To: Manikandan Muralidharan
Cc: alexandre.belloni, Frank.Li, robh, krzk+dt, conor+dt,
nicolas.ferre, claudiu.beznea, linux, mturquette, sboyd, bmasney,
aubin.constans, Ryan.Wanner, romain.sioen, tytso, cristian.birsan,
adrian.hunter, npitre, linux-i3c, devicetree, linux-kernel,
linux-arm-kernel, linux-clk
In-Reply-To: <20260525092405.1514213-4-manikandan.m@microchip.com>
On Mon, May 25, 2026 at 02:54:03PM +0530, Manikandan Muralidharan wrote:
> Add support for microchip sama7d65 SoC I3C HCI master only IP
> with additional clock support to enable bulk clock acquisition
> and apply the required quirks.
>
> Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
> Signed-off-by: Manikandan Muralidharan <manikandan.m@microchip.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> ---
> Changes in v7:
> - Use (void *)(ulong) cast instead of direct (void *) cast in
> of_device_id.data for pointer-size safety across architectures
> - Update commit message body to explicitly mention quirk application
>
> Changes in v6:
> - Reorder local variable definitions in i3c_hci_probe in descending
> order of line length
>
> Changes in v5:
> - Remove HCI_QUIRK_CLK_SUPPORT quirk and call
> devm_clk_bulk_get_all_enabled unconditionally, eliminating the
> need for a clock-specific quirk flag
>
> Changes in v4:
> - Remove the clock index variable MCHP_I3C_CLK_IDX as it is no
> longer needed after switching to bulk clock handling
>
> Changes in v3:
> - Make use of existing HCI_QUIRK_* code base instead of introducing
> separate MCHP_HCI_QUIRK_* flags
> - Introduce HCI_QUIRK_CLK_SUPPORT to handle peripheral and system
> generic clk in bulk
>
> Changes in v2:
> - Platform specific changes integrated in the existing mipi-i3c-hci
> driver by introducing separate MCHP_HCI_QUIRK_* quirks and vendor
> specific quirk files rather than a standalone driver
>
> drivers/i3c/master/mipi-i3c-hci/core.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
> index b781dbed2165..4cdf2abd4219 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/core.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
> @@ -8,6 +8,7 @@
> */
>
> #include <linux/bitfield.h>
> +#include <linux/clk.h>
> #include <linux/device.h>
> #include <linux/errno.h>
> #include <linux/i3c/master.h>
> @@ -969,6 +970,7 @@ static int i3c_hci_init(struct i3c_hci *hci)
> static int i3c_hci_probe(struct platform_device *pdev)
> {
> const struct mipi_i3c_hci_platform_data *pdata = pdev->dev.platform_data;
> + struct clk_bulk_data *clks;
> struct i3c_hci *hci;
> int irq, ret;
>
> @@ -1001,6 +1003,11 @@ static int i3c_hci_probe(struct platform_device *pdev)
> if (!hci->quirks && platform_get_device_id(pdev))
> hci->quirks = platform_get_device_id(pdev)->driver_data;
>
> + ret = devm_clk_bulk_get_all_enabled(&pdev->dev, &clks);
> + if (ret < 0)
> + return dev_err_probe(&pdev->dev, ret,
> + "Failed to get clocks\n");
> +
> ret = i3c_hci_init(hci);
> if (ret)
> return ret;
> @@ -1031,6 +1038,9 @@ static void i3c_hci_remove(struct platform_device *pdev)
>
> static const __maybe_unused struct of_device_id i3c_hci_of_match[] = {
> { .compatible = "mipi-i3c-hci", },
> + { .compatible = "microchip,sama7d65-i3c-hci",
> + .data = (void *)(ulong)(HCI_QUIRK_PIO_MODE | HCI_QUIRK_OD_PP_TIMING |
> + HCI_QUIRK_RESP_BUF_THLD) },
> {},
> };
> MODULE_DEVICE_TABLE(of, i3c_hci_of_match);
> --
> 2.25.1
>
^ permalink raw reply
* [PATCH v5 1/1] crypto: atmel-ecc - fix multi-device use-after-free and registration races
From: Lothar Rubusch @ 2026-06-08 17:03 UTC (permalink / raw)
To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
claudiu.beznea, tudor.ambarus, krzk+dt
Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch
During parallel driver initialization or driver teardown sequences
in setups with multiple atmel-ecc instances, a race condition exists
between atmel_ecc_i2c_client_alloc() and the probe/remove paths.
A concurrent transformation request can fetch an i2c_client instance
from the global i2c_client_list before the kpp is fully registered, or
while it is actively being unbound, resulting in a use-after-free (UAF)
risk.
1. The initialization problem in probe(): Adding first an i2c client to the
i2c_client_list, and then registering the kpp algorim may result in a race,
when this happens for a second (or further) probed device. In this case the
algorithm is already registered, so a TFM may arrive, while the latest
probing device is added to the list, but not kpp registered. In case this
fails and this last device is going to be removed again from the list, this
leaves a window where the TFM might obtain a pointer to the - now deleted -
i2c client, which opens a UAF risk. Furthermore, there will happen atempts
to multiple registering the same driver to the same type of algorithm.
Note, a simple reverting of the order: first register kpp, second add the
i2c client to the i2c_client_list - is not possible here, since the kpp
registration immediately triggers the self tests, which then will allocate
and require an i2c client.
2. The critical race condition problem: It exists when an Atmel device
instance is rapidly removed and immediately re-probed, before the global
resources are fully cleaned up. In this scenario, the asynchronous
unregistration sequence in the remove() lags behind the incoming probe()
function. Because of the global algorithm structure being not yet
completely cleaned up, the newly re-probed device incorrectly intercepts
the static, partially-dismantled global context. It then overwrites active
pointers and re-acquires the global instance prematurely. In this way, when
the deregistration sequence finally completes its execution, under the
newly initialized device, it may lose the tracking references, leaking the
older driver memory blocks, and introducing an immediate UAF risk.
3. The removal race problem, when a call to remove() starts removing the
device, but another thread executing a TFM, a severe Time-of-Check to
Time-of-Use (TOCTOU) race condition exists in the teardown path between the
asynchronous remove() sequence and completing TFMs. When the device is
unbound, the remove() function evaluates the active tfm_count and decides
whether to wait or proceed with resource deallocation. However, if the
final active TFM finishes its crypto operation and invokes the client free
function immediately after remove() performs its reference check but before
it can sleep, the completion signal is fired into a clearing state. The
unbind thread then misinterprets the zeroed counter, skips the
synchronization barrier entirely, and instantly deallocates the per-device
private structures. This leaves the final TFM worker thread executing code
inside a completely freed memory area, triggering an immediate UAF kernel
panic. Note, simply calling the kpp unregister here won't clean up the
situation in the context of having a setup with external hardware on a slow
bus.
Address this by implementing an independent subsystem reference counter
kpp refcnt protected by a dedicated mutex to ensure the static global kpp
algorithm structure is registered exactly once by the first probing device
instance. In multi-device scenarios, or when extending the resource
management support of the i2c_client_list to all atmel-i2c based device
drivers, such scenarios can become realistic. The particular algorithm is
registered only once. Each i2c client (i.e. each probing device driver) is
added as client to the i2c_client_list. This guarantee that only the first
probe will register the algorithm. The list is populated for further calls
to probe, and subsequent calls to the client alloc function.
Concurrently, decouple list mutations from registration by moving the
global list eviction to the absolute top of the remove lifecycle. This
keeps the quick execution of the list allocation loop intact, ensures that
unbinding hardware is instantly blind to the rest of the system, and
completely bypasses the recursive deadlock condition previously triggered
by synchronous crypto API self-tests.
Fixes: 11105693fa05 ("crypto: atmel-ecc - introduce Microchip / Atmel ECC driver")
Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
v4 -> v5:
- sashiko warning: revert wait_for_completion_timeout() by
wait_for_completion() when former instance still active at probe()
- change return type of atmel_ecc_wait_for_tfms() to void
v3 -> v4:
- sashiko warning: replace wait_for_completion() by
wait_for_completion_timeout() in remove; decision is a kind of dilemma
- move redundant code of this fix out into a separate function
- make also use of the wait_for_completion_timeout() function at probe for
convenience
v2 -> v3:
- sashiko warning: fix missing init_completion() for remove_done
- add comment naming all three related main problem situations
v1 -> v2:
- remove the initial approach with "ready" state bool, replace it by
this be a more comprehensive approach
drivers/crypto/atmel-ecc.c | 122 ++++++++++++++++++++++++++++---------
drivers/crypto/atmel-i2c.h | 3 +
2 files changed, 97 insertions(+), 28 deletions(-)
diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index 0ca02995a1de..be956508edcc 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -23,6 +23,11 @@
#include <crypto/kpp.h>
#include "atmel-i2c.h"
+static DEFINE_MUTEX(atmel_ecc_kpp_lock);
+static int atmel_ecc_kpp_refcnt;
+DECLARE_COMPLETION(atmel_ecc_unreg_done);
+static bool atmel_ecc_unreg_active;
+
static struct atmel_ecc_driver_data driver_data;
/**
@@ -241,7 +246,10 @@ static void atmel_ecc_i2c_client_free(struct i2c_client *client)
{
struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client);
- atomic_dec(&i2c_priv->tfm_count);
+ spin_lock(&driver_data.i2c_list_lock);
+ if (atomic_dec_and_test(&i2c_priv->tfm_count) && i2c_priv->unbinding)
+ complete(&i2c_priv->remove_done);
+ spin_unlock(&driver_data.i2c_list_lock);
}
static int atmel_ecdh_init_tfm(struct crypto_kpp *tfm)
@@ -276,7 +284,8 @@ static void atmel_ecdh_exit_tfm(struct crypto_kpp *tfm)
struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm);
kfree(ctx->public_key);
- crypto_free_kpp(ctx->fallback);
+ if (ctx->fallback)
+ crypto_free_kpp(ctx->fallback);
atmel_ecc_i2c_client_free(ctx->client);
}
@@ -295,6 +304,21 @@ static unsigned int atmel_ecdh_max_size(struct crypto_kpp *tfm)
return ATMEL_ECC_PUBKEY_SIZE;
}
+static void atmel_ecc_wait_for_tfms(struct atmel_i2c_client_priv *i2c_priv)
+{
+ spin_lock(&driver_data.i2c_list_lock);
+ list_del(&i2c_priv->i2c_client_list_node);
+ i2c_priv->unbinding = true;
+ reinit_completion(&i2c_priv->remove_done);
+ if (!atomic_read(&i2c_priv->tfm_count)) {
+ spin_unlock(&driver_data.i2c_list_lock);
+ return;
+ }
+ spin_unlock(&driver_data.i2c_list_lock);
+
+ wait_for_completion(&i2c_priv->remove_done);
+}
+
static struct kpp_alg atmel_ecdh_nist_p256 = {
.set_secret = atmel_ecdh_set_secret,
.generate_public_key = atmel_ecdh_generate_public_key,
@@ -315,6 +339,7 @@ static struct kpp_alg atmel_ecdh_nist_p256 = {
static int atmel_ecc_probe(struct i2c_client *client)
{
struct atmel_i2c_client_priv *i2c_priv;
+ unsigned long timeout;
int ret;
ret = atmel_i2c_probe(client);
@@ -323,49 +348,90 @@ static int atmel_ecc_probe(struct i2c_client *client)
i2c_priv = i2c_get_clientdata(client);
+ init_completion(&i2c_priv->remove_done);
+ i2c_priv->unbinding = false;
+
spin_lock(&driver_data.i2c_list_lock);
list_add_tail(&i2c_priv->i2c_client_list_node,
&driver_data.i2c_client_list);
spin_unlock(&driver_data.i2c_list_lock);
- ret = crypto_register_kpp(&atmel_ecdh_nist_p256);
- if (ret) {
- spin_lock(&driver_data.i2c_list_lock);
- list_del(&i2c_priv->i2c_client_list_node);
- spin_unlock(&driver_data.i2c_list_lock);
-
- dev_err(&client->dev, "%s alg registration failed\n",
- atmel_ecdh_nist_p256.base.cra_driver_name);
- } else {
- dev_info(&client->dev, "atmel ecc algorithms registered in /proc/crypto\n");
+ mutex_lock(&atmel_ecc_kpp_lock);
+ /*
+ * For cases where the same/last such device is still in unregistering,
+ * and now re-registering (refcnt is 0, but completion still exists).
+ * Safely capture the pointer, drop the lock and sleep until it
+ * terminates upon completion or retry limit reached.
+ */
+ while (atmel_ecc_unreg_active) {
+ mutex_unlock(&atmel_ecc_kpp_lock);
+ timeout = wait_for_completion_timeout(&atmel_ecc_unreg_done,
+ msecs_to_jiffies(2000));
+ mutex_lock(&atmel_ecc_kpp_lock);
+ if (timeout == 0) {
+ mutex_unlock(&atmel_ecc_kpp_lock);
+
+ atmel_ecc_wait_for_tfms(i2c_priv);
+ dev_err(&client->dev,
+ "probe timed out, former instance active\n");
+ return -ETIMEDOUT;
+ }
+ }
+ if (atmel_ecc_kpp_refcnt == 0) {
+ ret = crypto_register_kpp(&atmel_ecdh_nist_p256);
+ if (ret) {
+ mutex_unlock(&atmel_ecc_kpp_lock);
+
+ atmel_ecc_wait_for_tfms(i2c_priv);
+ dev_err(&client->dev, "%s alg registration failed\n",
+ atmel_ecdh_nist_p256.base.cra_driver_name);
+ return ret;
+ }
}
+ atmel_ecc_kpp_refcnt++;
+ mutex_unlock(&atmel_ecc_kpp_lock);
+ dev_info(&client->dev, "atmel ecc algorithms registered in /proc/crypto\n");
return ret;
}
static void atmel_ecc_remove(struct i2c_client *client)
{
struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client);
-
- /* Return EBUSY if i2c client already allocated. */
- if (atomic_read(&i2c_priv->tfm_count)) {
- /*
- * After we return here, the memory backing the device is freed.
- * That happens no matter what the return value of this function
- * is because in the Linux device model there is no error
- * handling for unbinding a driver.
- * If there is still some action pending, it probably involves
- * accessing the freed memory.
- */
- dev_emerg(&client->dev, "Device is busy, expect memory corruption.\n");
- return;
- }
-
- crypto_unregister_kpp(&atmel_ecdh_nist_p256);
+ bool trigger_unreg = false;
+ bool wait_needed = false;
+ unsigned long timeout;
spin_lock(&driver_data.i2c_list_lock);
list_del(&i2c_priv->i2c_client_list_node);
+ i2c_priv->unbinding = true;
+ reinit_completion(&i2c_priv->remove_done);
+ if (atomic_read(&i2c_priv->tfm_count) > 0)
+ wait_needed = true;
spin_unlock(&driver_data.i2c_list_lock);
+ if (wait_needed) {
+ timeout = wait_for_completion_timeout(&i2c_priv->remove_done,
+ msecs_to_jiffies(5000));
+ if (timeout == 0)
+ dev_emerg(&client->dev, "Teardown timed out! Active TFMs leaked, memory corruption imminent.\n");
+ }
+
+ mutex_lock(&atmel_ecc_kpp_lock);
+ atmel_ecc_kpp_refcnt--;
+ if (atmel_ecc_kpp_refcnt == 0) {
+ trigger_unreg = true;
+ atmel_ecc_unreg_active = true;
+ reinit_completion(&atmel_ecc_unreg_done);
+ }
+ mutex_unlock(&atmel_ecc_kpp_lock);
+
+ if (trigger_unreg) {
+ crypto_unregister_kpp(&atmel_ecdh_nist_p256);
+ mutex_lock(&atmel_ecc_kpp_lock);
+ atmel_ecc_unreg_active = false;
+ complete_all(&atmel_ecc_unreg_done);
+ mutex_unlock(&atmel_ecc_kpp_lock);
+ }
}
static const struct of_device_id atmel_ecc_dt_ids[] = {
diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h
index 72f04c15682f..8e6617422191 100644
--- a/drivers/crypto/atmel-i2c.h
+++ b/drivers/crypto/atmel-i2c.h
@@ -129,6 +129,7 @@ struct atmel_ecc_driver_data {
* @wake_token_sz : size in bytes of the wake_token
* @tfm_count : number of active crypto transformations on i2c client
* @hwrng : hold the hardware generated rng
+ * @unbinding : unbinding handshake
*
* Reads and writes from/to the i2c client are sequential. The first byte
* transmitted to the device is treated as the byte size. Any attempt to send
@@ -145,6 +146,8 @@ struct atmel_i2c_client_priv {
size_t wake_token_sz;
atomic_t tfm_count ____cacheline_aligned;
struct hwrng hwrng;
+ struct completion remove_done;
+ bool unbinding;
};
/**
base-commit: 79bbe453e5bfa6e1c6aa2e8329bfc8f152b81c9b
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v2 49/78] drm/mediatek: dp: Switch to atomic_create_state
From: AngeloGioacchino Del Regno @ 2026-06-08 15:32 UTC (permalink / raw)
To: Maxime Ripard, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter
Cc: Dmitry Baryshkov, dri-devel, Chun-Kuang Hu, Philipp Zabel,
Matthias Brugger, linux-mediatek, linux-kernel, linux-arm-kernel
In-Reply-To: <20260608-drm-no-more-bridge-reset-v2-49-0a91018bf886@kernel.org>
On 6/8/26 16:36, Maxime Ripard wrote:
> The drm_bridge_funcs.atomic_reset callback and its
> drm_atomic_helper_bridge_reset() helper are deprecated.
>
> Switch to the atomic_create_state callback and its
> drm_atomic_helper_bridge_create_state() counterpart.
>
> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
> Signed-off-by: Maxime Ripard <mripard@kernel.org>
> ---
> To: Chun-Kuang Hu <chunkuang.hu@kernel.org>
> To: Philipp Zabel <p.zabel@pengutronix.de>
> To: Matthias Brugger <matthias.bgg@gmail.com>
> To: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> Cc: dri-devel@lists.freedesktop.org
> Cc: linux-mediatek@lists.infradead.org
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
^ permalink raw reply
* Re: [PATCH] ARM: footbridge: convert to sparse IRQs
From: Dmitry Torokhov @ 2026-06-08 16:56 UTC (permalink / raw)
To: Ethan Nelson-Moore
Cc: linux-arm-kernel, linux-input, linux-serial, Russell King,
Arnd Bergmann, Greg Kroah-Hartman, Jiri Slaby,
Russell King (Oracle), Linus Walleij, Kees Cook,
Nathan Chancellor, Sebastian Andrzej Siewior, Steven Rostedt,
Thomas Weissschuh, Peter Zijlstra
In-Reply-To: <20260510052107.555825-1-enelsonmoore@gmail.com>
Hi Ethan,
On Sat, May 09, 2026 at 10:20:49PM -0700, Ethan Nelson-Moore wrote:
> diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
> index a8f4b2d70e59..cea72bd888af 100644
> --- a/drivers/input/serio/i8042-io.h
> +++ b/drivers/input/serio/i8042-io.h
> @@ -15,9 +15,9 @@
> * IRQs.
> */
>
> -#if defined(__arm__)
> -/* defined in include/asm-arm/arch-xxx/irqs.h */
> -#include <asm/irq.h>
> +#ifdef CONFIG_ARCH_FOOTBRIDGE
> +/* defined in arch/arm/mach-footbridge/include/mach/irqs.h */
> +#include <mach/irqs.h>
> #elif defined(CONFIG_PPC)
> extern int of_i8042_kbd_irq;
> extern int of_i8042_aux_irq;
This does not look right. Did you mean to drop inclusion of asm/irq.h
for all other arms?
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH v2 7/7] KVM: arm64: Support FFA_NOTIFICATION_INFO_GET in host handler
From: Sebastian Ene @ 2026-06-08 16:55 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
In-Reply-To: <20260608165549.1479409-1-sebastianene@google.com>
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 28b6cb0e14c4..463a845557f9 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -689,8 +689,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 */
@@ -1003,6 +1001,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);
+}
+
bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
{
struct arm_smccc_1_2_regs res;
@@ -1079,6 +1091,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.1064.gd145956f57-goog
^ permalink raw reply related
* [PATCH v2 6/7] KVM: arm64: Support FFA_NOTIFICATION_GET in host handler
From: Sebastian Ene @ 2026-06-08 16:55 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
In-Reply-To: <20260608165549.1479409-1-sebastianene@google.com>
Allow FF-A notification GET messages to be proxied from the pKVM
hypervisor to Trustzone and enforce MBZ/SBZ fields.
Signed-off-by: Sebastian Ene <sebastianene@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 3270381679b4..28b6cb0e14c4 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -690,7 +690,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_GET:
case FFA_NOTIFICATION_INFO_GET:
/* Optional interfaces added in FF-A 1.2 */
case FFA_MSG_SEND_DIRECT_REQ2: /* Optional per 7.5.1 */
@@ -984,6 +983,26 @@ static void do_ffa_notif_set(struct arm_smccc_1_2_regs *res,
arm_smccc_1_2_smc(args, res);
}
+static void do_ffa_notif_get(struct arm_smccc_1_2_regs *res,
+ struct kvm_cpu_context *ctxt)
+{
+ DECLARE_REG(u32, flags, ctxt, 2);
+ 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 (flags & GENMASK(31, 4)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ args = (void *)&ctxt->regs.regs[0];
+ arm_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;
@@ -1057,6 +1076,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
case FFA_NOTIFICATION_SET:
do_ffa_notif_set(&res, host_ctxt);
goto out_handled;
+ case FFA_NOTIFICATION_GET:
+ do_ffa_notif_get(&res, host_ctxt);
+ goto out_handled;
}
if (ffa_call_supported(func_id))
--
2.54.0.1064.gd145956f57-goog
^ permalink raw reply related
* [PATCH v2 2/7] KVM: arm64: Support FFA_NOTIFICATION_BITMAP_DESTROY in host handler
From: Sebastian Ene @ 2026-06-08 16:55 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
In-Reply-To: <20260608165549.1479409-1-sebastianene@google.com>
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 | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index c20d45191085..91e89d889c44 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:
@@ -893,6 +892,26 @@ static void do_ffa_notif_bitmap_create(struct arm_smccc_1_2_regs *res,
arm_smccc_1_2_smc(args, res);
}
+static void do_ffa_notif_bitmap_destroy(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, 2)) {
+ 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];
+ arm_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;
@@ -954,6 +973,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
case FFA_NOTIFICATION_BITMAP_CREATE:
do_ffa_notif_bitmap_create(&res, host_ctxt);
goto out_handled;
+ case FFA_NOTIFICATION_BITMAP_DESTROY:
+ do_ffa_notif_bitmap_destroy(&res, host_ctxt);
+ goto out_handled;
}
if (ffa_call_supported(func_id))
--
2.54.0.1064.gd145956f57-goog
^ permalink raw reply related
* [PATCH v2 4/7] KVM: arm64: Support FFA_NOTIFICATION_UNBIND in host handler
From: Sebastian Ene @ 2026-06-08 16:55 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
In-Reply-To: <20260608165549.1479409-1-sebastianene@google.com>
Verify the arguments of the FF-A notification unbind call and forward
the message to Trustzone.
Signed-off-by: Sebastian Ene <sebastianene@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index eedb01955a45..ca285e89516e 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -690,7 +690,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_UNBIND:
case FFA_NOTIFICATION_SET:
case FFA_NOTIFICATION_GET:
case FFA_NOTIFICATION_INFO_GET:
@@ -939,6 +938,27 @@ static void do_ffa_notif_bind(struct arm_smccc_1_2_regs *res,
arm_smccc_1_2_smc(args, res);
}
+static void do_ffa_notif_unbind(struct arm_smccc_1_2_regs *res,
+ struct kvm_cpu_context *ctxt)
+{
+ DECLARE_REG(u32, endp_id, ctxt, 1);
+ DECLARE_REG(u32, reserved, ctxt, 2);
+ struct arm_smccc_1_2_regs *args;
+
+ if (ffa_check_unused_args_sbz(ctxt, 5) || reserved) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ if (FIELD_GET(FFA_NOTIF_SENDER_ENDP_MASK, endp_id) != HOST_FFA_ID) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ args = (void *)&ctxt->regs.regs[0];
+ arm_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;
@@ -1006,6 +1026,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
case FFA_NOTIFICATION_BIND:
do_ffa_notif_bind(&res, host_ctxt);
goto out_handled;
+ case FFA_NOTIFICATION_UNBIND:
+ do_ffa_notif_unbind(&res, host_ctxt);
+ goto out_handled;
}
if (ffa_call_supported(func_id))
--
2.54.0.1064.gd145956f57-goog
^ permalink raw reply related
* [PATCH v2 3/7] KVM: arm64: Support FFA_NOTIFICATION_BIND in host handler
From: Sebastian Ene @ 2026-06-08 16:55 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
In-Reply-To: <20260608165549.1479409-1-sebastianene@google.com>
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 91e89d889c44..eedb01955a45 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
@@ -688,7 +690,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:
@@ -912,6 +913,32 @@ static void do_ffa_notif_bitmap_destroy(struct arm_smccc_1_2_regs *res,
arm_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) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ if (flags & GENMASK(31, 1)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ args = (void *)&ctxt->regs.regs[0];
+ arm_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;
@@ -976,6 +1003,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
case FFA_NOTIFICATION_BITMAP_DESTROY:
do_ffa_notif_bitmap_destroy(&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.1064.gd145956f57-goog
^ permalink raw reply related
* [PATCH v2 5/7] KVM: arm64: Support FFA_NOTIFICATION_SET in host handler
From: Sebastian Ene @ 2026-06-08 16:55 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
In-Reply-To: <20260608165549.1479409-1-sebastianene@google.com>
Allow FF-A notification SET messages to be proxied from the pKVM
hypervisor to Trustzone and enforce MBZ/SBZ fields.
Signed-off-by: Sebastian Ene <sebastianene@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index ca285e89516e..3270381679b4 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -690,7 +690,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_SET:
case FFA_NOTIFICATION_GET:
case FFA_NOTIFICATION_INFO_GET:
/* Optional interfaces added in FF-A 1.2 */
@@ -959,6 +958,32 @@ static void do_ffa_notif_unbind(struct arm_smccc_1_2_regs *res,
arm_smccc_1_2_smc(args, res);
}
+static void do_ffa_notif_set(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 (FIELD_GET(FFA_NOTIF_SENDER_ENDP_MASK, endp_id) != HOST_FFA_ID) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ if (ffa_check_unused_args_sbz(ctxt, 5)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ if (flags & GENMASK(15, 2)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ args = (void *)&ctxt->regs.regs[0];
+ arm_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;
@@ -1029,6 +1054,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
case FFA_NOTIFICATION_UNBIND:
do_ffa_notif_unbind(&res, host_ctxt);
goto out_handled;
+ case FFA_NOTIFICATION_SET:
+ do_ffa_notif_set(&res, host_ctxt);
+ goto out_handled;
}
if (ffa_call_supported(func_id))
--
2.54.0.1064.gd145956f57-goog
^ 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