* [PATCH v2 3/4] arm64: dts: rockchip: add CAN-FD nodes for RK3588
From: 1579567540 @ 2026-07-02 14:06 UTC (permalink / raw)
To: Marc Kleine-Budde, linux-can
Cc: Vincent Mailhol, Rob Herring, Krzysztof Kozlowski, kernel,
Conor Dooley, Heiko Stuebner, Dmitry Torokhov, Shengjiu Wang,
Pengpeng Hou, Russell King, Eric Biggers, Mario Limonciello,
Karl Mehltretter, Yixun Lan, Stephen Boyd, devicetree,
linux-arm-kernel, linux-rockchip, linux-kernel, Cunhao Lu
In-Reply-To: <20260702140654.2961561-1-1579567540@qq.com>
From: Cunhao Lu <1579567540@qq.com>
Describe the three CAN-FD controllers integrated in RK3588 in the base
SoC .dtsi.
Add CAN0, CAN1 and CAN2 nodes with their register ranges, interrupts,
clocks and resets, and keep them disabled by default so board DTS files
can enable them as needed.
Signed-off-by: Cunhao Lu <1579567540@qq.com>
---
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 39 +++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
index fc1fdbfd3162..b340973775c5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
@@ -2648,6 +2648,45 @@ dmac1: dma-controller@fea30000 {
#dma-cells = <1>;
};
+ can0: can@fea50000 {
+ compatible = "rockchip,rk3588-canfd";
+ reg = <0x0 0xfea50000 0x0 0x1000>;
+ interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru CLK_CAN0>, <&cru PCLK_CAN0>;
+ clock-names = "baud", "pclk";
+ resets = <&cru SRST_CAN0>, <&cru SRST_P_CAN0>;
+ reset-names = "core", "apb";
+ pinctrl-names = "default";
+ pinctrl-0 = <&can0m0_pins>;
+ status = "disabled";
+ };
+
+ can1: can@fea60000 {
+ compatible = "rockchip,rk3588-canfd";
+ reg = <0x0 0xfea60000 0x0 0x1000>;
+ interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru CLK_CAN1>, <&cru PCLK_CAN1>;
+ clock-names = "baud", "pclk";
+ resets = <&cru SRST_CAN1>, <&cru SRST_P_CAN1>;
+ reset-names = "core", "apb";
+ pinctrl-names = "default";
+ pinctrl-0 = <&can1m0_pins>;
+ status = "disabled";
+ };
+
+ can2: can@fea70000 {
+ compatible = "rockchip,rk3588-canfd";
+ reg = <0x0 0xfea70000 0x0 0x1000>;
+ interrupts = <GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru CLK_CAN2>, <&cru PCLK_CAN2>;
+ clock-names = "baud", "pclk";
+ resets = <&cru SRST_CAN2>, <&cru SRST_P_CAN2>;
+ reset-names = "core", "apb";
+ pinctrl-names = "default";
+ pinctrl-0 = <&can2m0_pins>;
+ status = "disabled";
+ };
+
i2c1: i2c@fea90000 {
compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
reg = <0x0 0xfea90000 0x0 0x1000>;
--
2.34.1
^ permalink raw reply related
* [PATCH v2 2/4] can: rockchip: add RK3588 CAN support
From: 1579567540 @ 2026-07-02 14:06 UTC (permalink / raw)
To: Marc Kleine-Budde, linux-can
Cc: Vincent Mailhol, Rob Herring, Krzysztof Kozlowski, kernel,
Conor Dooley, Heiko Stuebner, Dmitry Torokhov, Shengjiu Wang,
Pengpeng Hou, Russell King, Eric Biggers, Mario Limonciello,
Karl Mehltretter, Yixun Lan, Stephen Boyd, devicetree,
linux-arm-kernel, linux-rockchip, linux-kernel, Cunhao Lu,
Heiko Stuebner
In-Reply-To: <20260702140654.2961561-1-1579567540@qq.com>
From: Cunhao Lu <1579567540@qq.com>
Add support for the RK3588 CAN controller by introducing a dedicated
model ID and OF match entry.
The block is closely related to the existing RK3568 variants, but it
cannot reuse their match data unchanged. In particular, RK3588
encodes RX_FIFO_CNT in bits 7:5 instead of 6:4, so the RX path needs
SoC-specific handling.
The RX FIFO count bitfield difference was found by comparing Rockchip's
vendor kernel 6.1 CAN support for RK3568 and RK3588. Runtime testing on
RK3588 also confirms that bits 7:5 are needed.
Enable the existing erratum 5 empty-FIFO workaround for RK3588.
Heiko reproduced erratum 6 on RK3588, so enable that workaround as
well.
Keep RKCANFD_QUIRK_CANFD_BROKEN enabled for RK3588, so CAN-FD stays
disabled for now. Local testing did not reproduce the two known CAN-FD
trigger frames that cause Error Interrupts on RK3568 variants. Instead,
RK3588 shows a different CAN-FD failure mode: CAN-FD frames without BRS
work in this setup, but BRS with a data bitrate different from the
nominal bitrate immediately drives the controller bus-off.
Reported-by: Heiko Stuebner <heiko.stuebner@cherry.de>
Link: https://lore.kernel.org/lkml/20260630164336.3444550-4-heiko@sntech.de/
Signed-off-by: Cunhao Lu <1579567540@qq.com>
---
.../net/can/rockchip/rockchip_canfd-core.c | 12 +++++++++
drivers/net/can/rockchip/rockchip_canfd-rx.c | 5 +++-
drivers/net/can/rockchip/rockchip_canfd.h | 26 ++++++++++++++++++-
3 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/can/rockchip/rockchip_canfd-core.c
index 29de0c01e4ed..178d69edf1bb 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-core.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-core.c
@@ -50,6 +50,13 @@ static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3568v3 = {
RKCANFD_QUIRK_CANFD_BROKEN,
};
+static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3588 = {
+ .model = RKCANFD_MODEL_RK3588,
+ .quirks = RKCANFD_QUIRK_RK3568_ERRATUM_5 |
+ RKCANFD_QUIRK_RK3568_ERRATUM_6 |
+ RKCANFD_QUIRK_CANFD_BROKEN,
+};
+
static const char *__rkcanfd_get_model_str(enum rkcanfd_model model)
{
switch (model) {
@@ -57,6 +64,8 @@ static const char *__rkcanfd_get_model_str(enum rkcanfd_model model)
return "rk3568v2";
case RKCANFD_MODEL_RK3568V3:
return "rk3568v3";
+ case RKCANFD_MODEL_RK3588:
+ return "rk3588";
}
return "<unknown>";
@@ -846,6 +855,9 @@ static const struct of_device_id rkcanfd_of_match[] = {
}, {
.compatible = "rockchip,rk3568v3-canfd",
.data = &rkcanfd_devtype_data_rk3568v3,
+ }, {
+ .compatible = "rockchip,rk3588-canfd",
+ .data = &rkcanfd_devtype_data_rk3588,
}, {
/* sentinel */
},
diff --git a/drivers/net/can/rockchip/rockchip_canfd-rx.c b/drivers/net/can/rockchip/rockchip_canfd-rx.c
index 475c0409e215..24e87daa1df0 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-rx.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-rx.c
@@ -281,7 +281,10 @@ rkcanfd_rx_fifo_get_len(const struct rkcanfd_priv *priv)
{
const u32 reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL);
- return FIELD_GET(RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT, reg);
+ if (priv->devtype_data.model == RKCANFD_MODEL_RK3588)
+ return FIELD_GET(RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT_RK3588, reg);
+
+ return FIELD_GET(RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT_RK3568, reg);
}
int rkcanfd_handle_rx_int(struct rkcanfd_priv *priv)
diff --git a/drivers/net/can/rockchip/rockchip_canfd.h b/drivers/net/can/rockchip/rockchip_canfd.h
index 93131c7d7f54..82a617e4ca66 100644
--- a/drivers/net/can/rockchip/rockchip_canfd.h
+++ b/drivers/net/can/rockchip/rockchip_canfd.h
@@ -214,7 +214,8 @@
#define RKCANFD_REG_TXEVENT_FIFO_CTRL_TXE_FIFO_ENABLE BIT(0)
#define RKCANFD_REG_RX_FIFO_CTRL 0x118
-#define RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT GENMASK(6, 4)
+#define RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT_RK3568 GENMASK(6, 4)
+#define RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT_RK3588 GENMASK(7, 5)
#define RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_FULL_WATERMARK GENMASK(3, 1)
#define RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_ENABLE BIT(0)
@@ -331,6 +332,11 @@
* rarely with the standard clock of 300 MHz, but almost immediately
* at 80 MHz.
*
+ * Tests on the rk3588 show the same empty FIFO condition.
+ * In that setup rx_fifo_empty_errors increments when the bus
+ * transitions from idle to high CAN-FD load and stops growing once
+ * the bus reaches a steady state.
+ *
* To workaround this problem, check for empty FIFO with
* rkcanfd_fifo_header_empty() in rkcanfd_handle_rx_int_one() and exit
* early.
@@ -344,6 +350,8 @@
/* Erratum 6: The CAN controller's transmission of extended frames may
* intermittently change into standard frames
*
+ * Tests on the rk3588 show the same problem.
+ *
* Work around this issue by activating self reception (RXSTX). If we
* have pending TX CAN frames, check all RX'ed CAN frames in
* rkcanfd_rxstx_filter().
@@ -408,6 +416,18 @@
* cansend can0 002##07217010000000000
* DUT:
* candump any,0:0,#FFFFFFFF -cexdHtA
+ *
+ * Tests on the rk3588 show a different CAN-FD failure mode: these two
+ * CAN-FD frames do not trigger Error Interrupt or Error-Warning. CAN-FD
+ * frames without bitrate switching work in this setup, but BRS with a
+ * data bitrate different from the nominal bitrate drives the controller
+ * bus-off immediately.
+ *
+ * To reproduce:
+ * host:
+ * cangen can0 -I 2 -Li -Di -p 10 -f -g 1 -c32 -b
+ * DUT:
+ * cansequence -rv can1 -f
*/
#define RKCANFD_QUIRK_CANFD_BROKEN BIT(12)
@@ -424,6 +444,9 @@
* cansequence -rv -i 1
*
* - TX starvation after repeated Bus-Off
+ * Tests on the rk3588 show the same problem. In a
+ * 10-cycle Bus-Off recovery test, 9 cycles failed to send after the
+ * controller restarted.
* To reproduce:
* host:
* sleep 3 && cangen can0 -I2 -Li -Di -p10 -g 0.0
@@ -434,6 +457,7 @@
enum rkcanfd_model {
RKCANFD_MODEL_RK3568V2 = 0x35682,
RKCANFD_MODEL_RK3568V3 = 0x35683,
+ RKCANFD_MODEL_RK3588 = 0x3588,
};
struct rkcanfd_devtype_data {
--
2.34.1
^ permalink raw reply related
* [PATCH v2 1/4] dt-bindings: can: rockchip: add rk3588 CAN-FD compatible
From: 1579567540 @ 2026-07-02 14:06 UTC (permalink / raw)
To: Marc Kleine-Budde, linux-can
Cc: Vincent Mailhol, Rob Herring, Krzysztof Kozlowski, kernel,
Conor Dooley, Heiko Stuebner, Dmitry Torokhov, Shengjiu Wang,
Pengpeng Hou, Russell King, Eric Biggers, Mario Limonciello,
Karl Mehltretter, Yixun Lan, Stephen Boyd, devicetree,
linux-arm-kernel, linux-rockchip, linux-kernel, Cunhao Lu
In-Reply-To: <20260702140654.2961561-1-1579567540@qq.com>
From: Cunhao Lu <1579567540@qq.com>
RK3588 integrates a Rockchip CAN-FD controller variant that is not
fully compatible with RK3568v2. The RX FIFO count register field is
encoded in bits 7:5 on RK3588, while RK3568v2 uses bits 6:4.
Add a dedicated rockchip,rk3588-canfd compatible to describe this
variant. Do not use rockchip,rk3568v2-canfd as a fallback, because that
would describe a register layout that does not match the hardware.
Changes in v2:
- Use enum for the single-compatible entries, as suggested by Krzysztof.
- Reword the commit message to explain the hardware difference instead
of referring to Linux driver match data.
Signed-off-by: Cunhao Lu <1579567540@qq.com>
---
.../devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml b/Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml
index a077c0330013..81e2b6dfeb02 100644
--- a/Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml
+++ b/Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml
@@ -16,7 +16,9 @@ allOf:
properties:
compatible:
oneOf:
- - const: rockchip,rk3568v2-canfd
+ - enum:
+ - rockchip,rk3568v2-canfd
+ - rockchip,rk3588-canfd
- items:
- const: rockchip,rk3568v3-canfd
- const: rockchip,rk3568v2-canfd
--
2.34.1
^ permalink raw reply related
* [PATCH v2 0/4] can: rockchip: add RK3588 CAN support
From: 1579567540 @ 2026-07-02 14:06 UTC (permalink / raw)
To: Marc Kleine-Budde, linux-can
Cc: Vincent Mailhol, Rob Herring, Krzysztof Kozlowski, kernel,
Conor Dooley, Heiko Stuebner, Dmitry Torokhov, Shengjiu Wang,
Pengpeng Hou, Russell King, Eric Biggers, Mario Limonciello,
Karl Mehltretter, Yixun Lan, Stephen Boyd, devicetree,
linux-arm-kernel, linux-rockchip, linux-kernel, Cunhao Lu
From: Cunhao Lu <1579567540@qq.com>
Add support for the RK3588 CAN controller.
RK3588 integrates three CAN-FD controllers that are closely related to
the existing Rockchip CAN-FD IP already supported in the kernel. The
RK3588 variant is not fully compatible with RK3568v2 because the RX
FIFO count register field has a different layout.
This series therefore:
- extends the existing Rockchip CAN-FD binding with the
rockchip,rk3588-canfd compatible
- adds a dedicated RK3588 match entry and devtype in the driver
- describes the three CAN controller nodes in rk3588-base.dtsi
- enables CAN on the RK3588 Tiger Haikou board
RK3588 encodes RX_FIFO_CNT in bits 7:5 instead of 6:4. This
difference was found by comparing Rockchip's vendor kernel 6.1 CAN
support for RK3568 and RK3588, and was also confirmed by runtime
testing.
RK3588 uses the existing erratum 5 empty-FIFO workaround. Based on
Heiko's testing, v2 also enables the erratum 6 workaround for extended
frames being transmitted as standard frames.
RKCANFD_QUIRK_CANFD_BROKEN remains enabled for RK3588, so CAN-FD stays
disabled for now. Local testing did not reproduce the two known CAN-FD
trigger frames that cause Error Interrupts on RK3568 variants. Instead,
RK3588 shows a different CAN-FD failure mode: CAN-FD frames without BRS
work in this setup, but BRS with a data bitrate different from the
nominal bitrate immediately drives the controller bus-off.
Tested on an embedfire,rk3588-lubancat-5io board with can0/can1
directly connected. Runtime testing used a 200 MHz CAN clock, nominal
bitrate 500 kbit/s, data bitrate 500 kbit/s and 1 Mbit/s, and included stress and
error-path coverage for the existing Rockchip errata handling.
Changes in v2:
- use real author name
- fold the single-compatible entries into an enum, as suggested by Krzysztof
- enable the erratum 6 workaround for RK3588 based on Heiko's testing
- add Heiko's RK3588 Tiger Haikou CAN enablement patch
- keep RKCANFD_QUIRK_CANFD_BROKEN enabled for RK3588 so CAN-FD stays disabled
- document the RK3588 CAN-FD/BRS bus-off failure mode
Cunhao Lu (3):
dt-bindings: can: rockchip: add rk3588 CAN-FD compatible
can: rockchip: add RK3588 CAN support
arm64: dts: rockchip: add CAN-FD nodes for RK3588
Heiko Stuebner (1):
arm64: dts: rockchip: Enable CAN controller on RK3588-Tiger-Haikou
.../net/can/rockchip,rk3568v2-canfd.yaml | 4 +-
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 39 +++++++++++++++++++
.../boot/dts/rockchip/rk3588-tiger-haikou.dts | 6 +++
.../net/can/rockchip/rockchip_canfd-core.c | 12 ++++++
drivers/net/can/rockchip/rockchip_canfd-rx.c | 5 ++-
drivers/net/can/rockchip/rockchip_canfd.h | 26 ++++++++++++-
6 files changed, 89 insertions(+), 3 deletions(-)
--
2.34.1
^ permalink raw reply
* Re: [PATCH net-next v7 3/3] net: airoha: defer GDM3/GDM4 WAN mode and GDM2 loopback to QoS offload
From: Lorenzo Bianconi @ 2026-07-02 14:02 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Simon Horman, Alexander Lobakin, linux-arm-kernel, linux-mediatek,
netdev, Madhur Agrawal
In-Reply-To: <20260701-airoha-ethtool-priv_flags-v7-3-b4153bd44428@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 12784 bytes --]
On Jul 01, Lorenzo Bianconi wrote:
> 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(). Add the capability to configure
> GDM3/GDM4 as WAN/LAN on demand when QoS offload is created or destroyed.
> 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. Introduce the
> AIROHA_DEV_F_QOS flag to track whether a device has an active HTB
> qdisc; clear it on TC_HTB_DESTROY. The device keeps its WAN role after
> qdisc teardown so that its configuration is preserved until another
> device explicitly needs the WAN role for QoS offload.
> If another GDM3/GDM4 device already holds the WAN role without an active
> QoS qdisc, demote it to LAN before promoting the requesting device. Skip
> the demotion when the requesting device is itself already the WAN device.
> Since airoha_dev_set_qdma() can now be called on a running device to
> migrate between QDMA blocks, make dev->qdma an RCU pointer so the TX
> path can safely dereference it without holding RTNL.
> Hold flow_offload_mutex in airoha_enable_qos_for_gdm34() and
> airoha_disable_qos_for_gdm34() around the dev->flags update,
> airoha_dev_set_qdma() and GDM2 loopback configuration, serializing
> against concurrent airoha_ppe_hw_init() in the TC_SETUP_CLSFLOWER
> offload path.
> Introduce airoha_qdma_deref() helper that wraps rcu_dereference_protected()
> with a lockdep condition accepting either rtnl_lock or flow_offload_mutex,
> and use it across all control-path dereferences of the RCU-protected
> dev->qdma pointer.
> Add airoha_disable_gdm2_loopback() to disable GDM2 hw loopback.
>
> Tested-by: Madhur Agrawal <madhur.agrawal@airoha.com>
> Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
> Reviewed-by: Simon Horman <horms@kernel.org>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Commenting on Sashiko's report:
https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260701-airoha-ethtool-priv_flags-v7-0-b4153bd44428%40kernel.org
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 219 ++++++++++++++++++++++++++----
> drivers/net/ethernet/airoha/airoha_eth.h | 13 +-
> drivers/net/ethernet/airoha/airoha_ppe.c | 9 +-
> drivers/net/ethernet/airoha/airoha_regs.h | 1 +
> 4 files changed, 214 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 2c9ceb9f16f8..609a5ea67fb7 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
[...]
> +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;
> +
> + err = airoha_disable_gdm2_loopback(dev);
> + if (err)
> + netdev_warn(netdev,
> + "failed disabling GDM2 loopback: %d\n", err);
> +
> + dev->flags &= ~AIROHA_DEV_F_WAN;
> + airoha_dev_set_qdma(dev);
> +
> + airoha_set_macaddr(dev, netdev->dev_addr);
- Should the return value of airoha_set_macaddr() be checked here?
airoha_set_macaddr() can return -EINVAL when the device MAC MSBs do
not match other same-role sibling devices:
if (!is_zero_ether_addr(ref_addr) && memcmp(ref_addr, addr, 3)) {
...
return -EINVAL;
}
Since AIROHA_DEV_F_WAN has just been cleared and dev->qdma has been
switched to QDMA0, the scan now iterates LAN-role peers. If the
ex-WAN MAC's top three bytes disagree with the LAN peers, the call
returns -EINVAL and the HW MAC registers are left unwritten while
the software state has already been flipped to LAN.
- The asymmetry is intentional. airoha_disable_qos_for_gdm34() is a
teardown path that returns void, the demotion has to happen regardless.
Moreover, airoha_set_macaddr() can fail just if the device is
misconfigured.
> + if (netif_running(netdev))
> + airoha_set_gdm_port_fwd_cfg(dev->eth,
> + REG_GDM_FWD_CFG(port->id),
> + FE_PSE_PORT_PPE1);
> +}
> +
> +static int airoha_enable_qos_for_gdm34(struct net_device *netdev,
> + struct netlink_ext_ack *extack)
> +{
> + struct airoha_gdm_dev *wan_dev, *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> + struct airoha_eth *eth = dev->eth;
> + int err = -EBUSY;
> +
> + 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;
> +
> + mutex_lock(&flow_offload_mutex);
> +
> + wan_dev = airoha_get_wan_gdm_dev(eth);
> + if (wan_dev) {
> + if ((wan_dev->flags & AIROHA_DEV_F_QOS) ||
> + wan_dev->port->id == AIROHA_GDM2_IDX) {
> + NL_SET_ERR_MSG_MOD(extack,
> + "QoS configured for WAN device");
> + goto error_unlock;
> + }
> + airoha_disable_qos_for_gdm34(netdev_from_priv(wan_dev));
> + }
> +
> + dev->flags |= AIROHA_DEV_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;
> +
> + if (netif_running(netdev)) {
> + u32 pse_port;
> +
> + 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(port->id),
> + pse_port);
> + }
> +
> + mutex_unlock(&flow_offload_mutex);
> +
> + return 0;
> +
> +error_disable_loopback:
> + airoha_disable_gdm2_loopback(dev);
> +error_disable_wan:
> + dev->flags &= ~AIROHA_DEV_F_WAN;
> + airoha_dev_set_qdma(dev);
> +error_unlock:
> + mutex_unlock(&flow_offload_mutex);
> +
> + return err;
- Does this failure path fully implement the "proper rollback on failure"
described in the commit message?
Earlier in the function, if a peer wan_dev exists it is demoted via:
airoha_disable_qos_for_gdm34(netdev_from_priv(wan_dev));
That helper clears AIROHA_DEV_F_WAN on wan_dev, swaps its RCU qdma
pointer to QDMA0, disables GDM2 loopback, rewrites its MAC to the LAN
registers, and (if wan_dev was running) sets its REG_GDM_FWD_CFG to
FE_PSE_PORT_PPE1.
If a later step for the requesting device fails, the error labels
error_disable_loopback / error_disable_wan / error_unlock only unwind
the requesting device. The demoted wan_dev is never re-promoted.
For example, airoha_set_macaddr(dev, netdev->dev_addr) can return
-EINVAL when the requesting device's MAC MSBs disagree with the other
WAN-role peers:
if (!is_zero_ether_addr(ref_addr) && memcmp(ref_addr, addr, 3)) {
...
return -EINVAL;
}
In that case the failed tc qdisc add returns to userspace, the
requesting device is rolled back to LAN, and no GDM3/GDM4 device holds
the WAN role anymore. The previously working WAN device silently loses
its WAN role and QDMA1 binding.
Should the error paths re-promote wan_dev, or should the preconditions
that can fail (MAC MSB check, GDM2 loopback setup) be validated before
mutating the peer's state?
- This issue has been already reported in the past. If the configuration
fails, I think there is no point to move back the previous device as WAN.
The user will be able to log again and re-apply the configuration.
Moreover, airoha_enable_qos_for_gdm34() can fail just if the device is
misconfigured (failures in airoha_enable_gdm2_loopback() or
airoha_set_macaddr()).
Regards,
Lorenzo
> +}
> +
> static int airoha_tc_htb_destroy(struct net_device *netdev)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> @@ -3057,6 +3217,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);
>
> + dev->flags &= ~AIROHA_DEV_F_QOS;
> +
> return 0;
> }
>
> @@ -3076,24 +3238,33 @@ static int airoha_tc_get_htb_get_leaf_queue(struct net_device *netdev,
> return 0;
> }
>
> -static int airoha_tc_setup_qdisc_htb(struct net_device *dev,
> +static int airoha_tc_setup_qdisc_htb(struct net_device *netdev,
> struct tc_htb_qopt_offload *opt)
> {
> switch (opt->command) {
> - case TC_HTB_CREATE:
> + case TC_HTB_CREATE: {
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + int err;
> +
> + err = airoha_enable_qos_for_gdm34(netdev, opt->extack);
> + if (err)
> + return err;
> +
> + dev->flags |= AIROHA_DEV_F_QOS;
> break;
> + }
> case TC_HTB_DESTROY:
> - return airoha_tc_htb_destroy(dev);
> + return airoha_tc_htb_destroy(netdev);
> case TC_HTB_NODE_MODIFY:
> - return airoha_tc_htb_modify_queue(dev, opt);
> + return airoha_tc_htb_modify_queue(netdev, opt);
> case TC_HTB_LEAF_ALLOC_QUEUE:
> - return airoha_tc_htb_alloc_leaf_queue(dev, opt);
> + return airoha_tc_htb_alloc_leaf_queue(netdev, opt);
> case TC_HTB_LEAF_DEL:
> case TC_HTB_LEAF_DEL_LAST:
> case TC_HTB_LEAF_DEL_LAST_FORCE:
> - return airoha_tc_htb_delete_leaf_queue(dev, opt);
> + return airoha_tc_htb_delete_leaf_queue(netdev, opt);
> case TC_HTB_LEAF_QUERY_QUEUE:
> - return airoha_tc_get_htb_get_leaf_queue(dev, opt);
> + return airoha_tc_get_htb_get_leaf_queue(netdev, opt);
> default:
> return -EOPNOTSUPP;
> }
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index ac5f571f3e53..a314330fcd48 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -537,11 +537,12 @@ struct airoha_qdma {
>
> enum airoha_dev_flags {
> AIROHA_DEV_F_WAN = BIT(0),
> + AIROHA_DEV_F_QOS = BIT(1),
> };
>
> struct airoha_gdm_dev {
> + struct airoha_qdma __rcu *qdma;
> struct airoha_gdm_port *port;
> - struct airoha_qdma *qdma;
> struct airoha_eth *eth;
>
> DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);
> @@ -677,6 +678,16 @@ int airoha_get_fe_port(struct airoha_gdm_dev *dev);
> bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
> struct airoha_gdm_dev *dev);
>
> +extern struct mutex flow_offload_mutex;
> +
> +static inline struct airoha_qdma *
> +airoha_qdma_deref(struct airoha_gdm_dev *dev)
> +{
> + return rcu_dereference_protected(dev->qdma,
> + lockdep_rtnl_is_held() ||
> + lockdep_is_held(&flow_offload_mutex));
> +}
> +
> void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport);
> bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index);
> void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
> diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> index 42f4b0f21d17..0f260c50ac3c 100644
> --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> @@ -15,7 +15,10 @@
> #include "airoha_regs.h"
> #include "airoha_eth.h"
>
> -static DEFINE_MUTEX(flow_offload_mutex);
> +/* Serialize airoha_gdm_dev flags, QDMA pointer and PPE CPU port
> + * configuration.
> + */
> +DEFINE_MUTEX(flow_offload_mutex);
> static DEFINE_SPINLOCK(ppe_lock);
>
> static const struct rhashtable_params airoha_flow_table_params = {
> @@ -86,8 +89,8 @@ static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe)
>
> void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport)
> {
> - struct airoha_qdma *qdma = dev->qdma;
> - struct airoha_eth *eth = qdma->eth;
> + struct airoha_qdma *qdma = airoha_qdma_deref(dev);
> + struct airoha_eth *eth = dev->eth;
> u8 qdma_id = qdma - ð->qdma[0];
> u32 fe_cpu_port;
>
> 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
>
>
> --
> 2.54.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v4 0/4] arm64: cross-CPU NMI via SDEI
From: Kiryl Shutsemau @ 2026-07-02 13:57 UTC (permalink / raw)
To: Catalin Marinas
Cc: Will Deacon, James Morse, Mark Rutland, Marc Zyngier,
Doug Anderson, Petr Mladek, Thomas Gleixner, Andrew Morton,
Baoquan He, Puranjay Mohan, Usama Arif, Breno Leitao,
Julien Thierry, Lecopzer Chen, Sumit Garg, kernel-team, kexec,
linux-arm-kernel, linux-kernel
In-Reply-To: <akOT3yaYVM6BTm_4@thinkstation>
On Tue, Jun 30, 2026 at 11:04:14AM +0100, Kiryl Shutsemau wrote:
> On Mon, Jun 29, 2026 at 05:53:57PM +0100, Kiryl Shutsemau wrote:
> > On Mon, Jun 29, 2026 at 04:54:18PM +0100, Catalin Marinas wrote:
> > > Have you tried SDEI_EVENT_COMPLETE_AND_RESUME instead? Just COMPLETE
> > > won't return to the kernel. We have sdei_handler_abort() to complete the
> > > event and, hopefully, you can continue with the CPU_OFF. It's a work
> > > around the TF-A non-compliance but I think this is useful even if you
> > > don't issue the CPU_OFF (e.g. no CPU hotplug, just the park loop).
> >
> > Tried it. The result is the opposite of what I expected, and it argues
> > against doing the complete at all under QEMU's TF-A.
>
> I have to walk back on this. My test setup was broken. I will be back to
> you with proper data.
Back with proper data. Short version: CPU_OFF from the SDEI stop does not
work on Grace, whether or not the event is completed first, so the series
stays with the park. Details below.
What was broken before
======================
My QEMU kdump harness had three faults that together made CPU_OFF look
like it broke the capture kernel:
- a race between the sysrq-c crash and the buddy detector -- the script
that wedges the CPU wasn't pinned off it, so which crash path ran (and
thus the outcome) was random;
- the capture kernel's console went quiet at the boot-console handover,
so "nothing after Bye!" was mostly lost output, not a hang (keep_bootcon
shows it booting on);
- the one genuine early stall was the capture kernel's CFI probe of the
secure NOR flash -- it reproduces with the whole series compiled out
(CONFIG_ARM_SDEI_NMI=n) and disappears with
initcall_blacklist=physmap_init, i.e. nothing to do with SDEI.
With those fixed, QEMU/TF-A boots the capture kernel to userspace for both
park and raw CPU_OFF, and CPU_OFF really powers the PE off. But QEMU can't
decide the question that matters: its post-kexec hold-pen can't revive any
CPU_OFF'd core (even a cleanly hotplug-offlined one), so re-onlining is
undecidable there. Hence Grace.
Grace (Neoverse V2, EL3 TF-A)
=============================
- Series as posted (park): the SDEI rung stops the wedged CPU, its
context lands in the vmcore, the capture kernel boots. Works.
Bringing up secondary CPUs complains that it cannot get the CPU up,
but proceeds.
- raw CPU_OFF from the uncompleted SDEI event: the capture kernel boots
but hangs at "smp: Bringing up secondary CPUs ..." -- it cannot
re-online the CPU that was CPU_OFF'd. This is exactly the TF-A point
you raised: the SDEI dispatch is left dangling on CPU_OFF and the PE
won't come back cleanly.
- complete-then-CPU_OFF: same hang at secondary bring-up. Completing the
event first does not help.
For that last one I did not use sdei_handler_abort(): it can't express
"complete, then CPU_OFF" from the handler, because its COMPLETE_AND_RESUME
lands on the "1: ret" trampoline, which resumes the *interrupted* (wedged)
context -- so nothing after it runs. I used a COMPLETE_AND_RESUME whose
resume PC is a PSCI CPU_OFF stub, so the event is genuinely completed and
then the PE powers off. It still can't be re-onlined. (I suspect the
"complete-then-CPU_OFF wedged EL3" I mentioned earlier was in fact the
sdei_handler_abort() path resuming the wedged loop, i.e. never doing the
CPU_OFF at all.)
Conclusion
==========
CPU_OFF from the SDEI stop is unusable on current TF-A, with or without
completing the event first -- a concrete real-HW consequence of the
non-compliance you flagged (TF-A subscribes SDEI to PSCI CPU_ON and
suspend-wakeup, but not CPU_OFF). So the series keeps the park: the dump
is complete either way, and only re-onlining the SDEI-stopped CPU in an
SMP capture kernel is lost -- the same fallback the shared stop path
already takes when CPU_OFF is unavailable. Powering the PE off for reuse
is a firmware follow-up (TF-A completing or tearing down the SDEI dispatch
on PSCI CPU_OFF), not something the kernel can paper over.
Please consider applying v5.
--
Kiryl Shutsemau / Kirill A. Shutemov
^ permalink raw reply
* [PATCH 1/2] ARM: dts: ti/omap: embt2ws: use mulit-led for RGB LED
From: Andreas Kemnade @ 2026-07-02 13:52 UTC (permalink / raw)
To: Aaro Koskinen, Kevin Hilman, Roger Quadros, Tony Lindgren,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Russell King
Cc: linux-omap, devicetree, linux-kernel, linux-arm-kernel,
Andreas Kemnade, Pavel Machek
In-Reply-To: <20260702-b200multiled-v1-0-c1799ad45c96@kemnade.info>
The device has one single RGB LED. Explicitly declare it as such
by combing the LEDs into one.
Suggested-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts b/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts
index e253e0775ea9..e11d1931c42a 100644
--- a/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts
+++ b/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts
@@ -64,6 +64,13 @@ key-lock {
};
};
+ multi-led {
+ compatible = "leds-group-multicolor";
+ color = <LED_COLOR_ID_RGB>;
+ function = LED_FUNCTION_STATUS;
+ leds = <&led_r>, <&led_g>, <&led_b>;
+ };
+
cb_v18: regulator-cb-v18 {
pinctrl-names = "default";
pinctrl-0 = <&cb_v18_pins>;
@@ -368,19 +375,19 @@ led-controller@66 {
#address-cells = <1>;
#size-cells = <0>;
- led@0 {
+ led_g: led@0 {
reg = <0>;
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_STATUS;
};
- led@2 {
+ led_b: led@2 {
reg = <2>;
color = <LED_COLOR_ID_BLUE>;
function = LED_FUNCTION_STATUS;
};
- led@4 {
+ led_r: led@4 {
reg = <4>;
color = <LED_COLOR_ID_RED>;
function = LED_FUNCTION_STATUS;
--
2.47.3
^ permalink raw reply related
* [PATCH 0/2] ARM: dts: ti/omap: embt2ws: define RGB LED
From: Andreas Kemnade @ 2026-07-02 13:52 UTC (permalink / raw)
To: Aaro Koskinen, Kevin Hilman, Roger Quadros, Tony Lindgren,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Russell King
Cc: linux-omap, devicetree, linux-kernel, linux-arm-kernel,
Andreas Kemnade, Pavel Machek
Combine the LED definitions into an RGB LED and add the drivers into
defconfig.
This has already been suggested a long time ago.
Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
Andreas Kemnade (2):
ARM: dts: ti/omap: embt2ws: use mulit-led for RGB LED
arm: omap2plus_defconfig: Enable multi-LED
arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts | 13 ++++++++++---
arch/arm/configs/omap2plus_defconfig | 2 ++
2 files changed, 12 insertions(+), 3 deletions(-)
---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20260702-b200multiled-ce27e3f3a5f6
Best regards,
--
Andreas Kemnade <andreas@kemnade.info>
^ permalink raw reply
* [PATCH 2/2] arm: omap2plus_defconfig: Enable multi-LED
From: Andreas Kemnade @ 2026-07-02 13:52 UTC (permalink / raw)
To: Aaro Koskinen, Kevin Hilman, Roger Quadros, Tony Lindgren,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Russell King
Cc: linux-omap, devicetree, linux-kernel, linux-arm-kernel,
Andreas Kemnade
In-Reply-To: <20260702-b200multiled-v1-0-c1799ad45c96@kemnade.info>
Enable drivers needed to use RGB LEDs composed of multiple monochromatic
LEDs.
Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
arch/arm/configs/omap2plus_defconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index ad5ae1636dee..3a4fb59d3fad 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -602,6 +602,7 @@ CONFIG_MMC_OMAP_HS=y
CONFIG_MMC_SDHCI_OMAP=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=m
+CONFIG_LEDS_CLASS_MULTICOLOR=m
CONFIG_LEDS_CPCAP=m
CONFIG_LEDS_LM3532=m
CONFIG_LEDS_GPIO=m
@@ -611,6 +612,7 @@ CONFIG_LEDS_PCA963X=m
CONFIG_LEDS_PWM=m
CONFIG_LEDS_BD2606MVV=m
CONFIG_LEDS_TCA6507=m
+CONFIG_LEDS_GROUP_MULTICOLOR=m
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_ONESHOT=m
--
2.47.3
^ permalink raw reply related
* Re: [PATCH net-next v7 3/3] net: airoha: defer GDM3/GDM4 WAN mode and GDM2 loopback to QoS offload
From: Lorenzo Bianconi @ 2026-07-02 13:51 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Simon Horman, Alexander Lobakin, linux-arm-kernel, linux-mediatek,
netdev, Madhur Agrawal
In-Reply-To: <20260701-airoha-ethtool-priv_flags-v7-3-b4153bd44428@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 21222 bytes --]
> 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(). Add the capability to configure
> GDM3/GDM4 as WAN/LAN on demand when QoS offload is created or destroyed.
> 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. Introduce the
> AIROHA_DEV_F_QOS flag to track whether a device has an active HTB
> qdisc; clear it on TC_HTB_DESTROY. The device keeps its WAN role after
> qdisc teardown so that its configuration is preserved until another
> device explicitly needs the WAN role for QoS offload.
> If another GDM3/GDM4 device already holds the WAN role without an active
> QoS qdisc, demote it to LAN before promoting the requesting device. Skip
> the demotion when the requesting device is itself already the WAN device.
> Since airoha_dev_set_qdma() can now be called on a running device to
> migrate between QDMA blocks, make dev->qdma an RCU pointer so the TX
> path can safely dereference it without holding RTNL.
> Hold flow_offload_mutex in airoha_enable_qos_for_gdm34() and
> airoha_disable_qos_for_gdm34() around the dev->flags update,
> airoha_dev_set_qdma() and GDM2 loopback configuration, serializing
> against concurrent airoha_ppe_hw_init() in the TC_SETUP_CLSFLOWER
> offload path.
> Introduce airoha_qdma_deref() helper that wraps rcu_dereference_protected()
> with a lockdep condition accepting either rtnl_lock or flow_offload_mutex,
> and use it across all control-path dereferences of the RCU-protected
> dev->qdma pointer.
> Add airoha_disable_gdm2_loopback() to disable GDM2 hw loopback.
>
> Tested-by: Madhur Agrawal <madhur.agrawal@airoha.com>
> Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
> Reviewed-by: Simon Horman <horms@kernel.org>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
commenting on Sashiko's report:
https://sashiko.dev/#/patchset/20260701-airoha-ethtool-priv_flags-v7-0-b4153bd44428%40kernel.org
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 219 ++++++++++++++++++++++++++----
> drivers/net/ethernet/airoha/airoha_eth.h | 13 +-
> drivers/net/ethernet/airoha/airoha_ppe.c | 9 +-
> drivers/net/ethernet/airoha/airoha_regs.h | 1 +
> 4 files changed, 214 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 2c9ceb9f16f8..609a5ea67fb7 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -929,7 +929,7 @@ static void airoha_qdma_wake_netdev_txqs(struct airoha_queue *q)
> if (!dev)
> continue;
>
> - if (dev->qdma != qdma)
> + if (rcu_access_pointer(dev->qdma) != qdma)
> continue;
>
> netdev = netdev_from_priv(dev);
> @@ -1837,13 +1837,14 @@ static int airoha_dev_open(struct net_device *netdev)
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> struct airoha_gdm_port *port = dev->port;
> u32 cur_len, pse_port = FE_PSE_PORT_PPE1;
> - struct airoha_qdma *qdma = dev->qdma;
> + struct airoha_qdma *qdma;
>
> netif_tx_start_all_queues(netdev);
> err = airoha_set_vip_for_gdm_port(dev, true);
> if (err)
> return err;
>
> + qdma = airoha_qdma_deref(dev);
> if (netdev_uses_dsa(netdev))
> airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
> GDM_STAG_EN_MASK);
> @@ -1903,7 +1904,6 @@ static int airoha_dev_stop(struct net_device *netdev)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> struct airoha_gdm_port *port = dev->port;
> - struct airoha_qdma *qdma = dev->qdma;
>
> netif_tx_disable(netdev);
> airoha_set_vip_for_gdm_port(dev, false);
> @@ -1911,7 +1911,7 @@ static int airoha_dev_stop(struct net_device *netdev)
> if (--port->users)
> airoha_set_port_mtu(dev->eth, port);
> else
> - airoha_set_gdm_port_fwd_cfg(qdma->eth,
> + airoha_set_gdm_port_fwd_cfg(dev->eth,
> REG_GDM_FWD_CFG(port->id),
> FE_PSE_PORT_DROP);
> return 0;
> @@ -1998,6 +1998,53 @@ 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)) {
> + u32 mask = FC_ID_OF_SRC_PORT_MASK(dev->nbq);
> +
> + airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, mask,
> + FC_MAP6_DEF_VALUE & mask);
> + }
> +
> + return 0;
> +}
> +
> static struct airoha_gdm_dev *
> airoha_get_wan_gdm_dev(struct airoha_eth *eth)
> {
> @@ -2024,15 +2071,26 @@ airoha_get_wan_gdm_dev(struct airoha_eth *eth)
> static void airoha_dev_set_qdma(struct airoha_gdm_dev *dev)
> {
> struct net_device *netdev = netdev_from_priv(dev);
> + struct airoha_qdma *cur_qdma, *qdma;
> struct airoha_eth *eth = dev->eth;
> int ppe_id;
>
> /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */
> - dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)];
> - netdev->irq = dev->qdma->irq_banks[0].irq;
> + qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)];
> + cur_qdma = airoha_qdma_deref(dev);
> +
> + rcu_assign_pointer(dev->qdma, qdma);
> + netdev->irq = qdma->irq_banks[0].irq;
>
> ppe_id = !airoha_is_lan_gdm_dev(dev) && airoha_ppe_is_enabled(eth, 1);
> airoha_ppe_set_cpu_port(dev, ppe_id, airoha_get_fe_port(dev));
> +
> + if (!cur_qdma)
> + return;
> +
> + memset(dev->qos_stats, 0, sizeof(dev->qos_stats));
- Will zeroing dev->qos_stats without resetting the free-running hardware counters
cause a massive artificial spike in reported QoS statistics?
- I do not think this issue can occur since we can't enable hw ETS QoS for
GDM3 and GDM4 at the same time. Moreover, this would be just a 'cosmetic'
issue since in the next iteration the driver properly takes care of the
delta.
> + synchronize_rcu();
> + netif_tx_wake_all_queues(netdev);
> }
>
> static int airoha_dev_init(struct net_device *netdev)
> @@ -2187,9 +2245,9 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> struct net_device *netdev)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_qdma *qdma = dev->qdma;
> u32 nr_frags, tag, msg0, msg1, len;
> struct airoha_queue_entry *e;
> + struct airoha_qdma *qdma;
> struct netdev_queue *txq;
> struct airoha_queue *q;
> LIST_HEAD(tx_list);
> @@ -2198,6 +2256,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> u16 index;
> u8 fport;
- This is a pre-existing issue, but does this function have an out-of-bounds
write to the TCP header for GSO packets?
- This issue has been already reported in the past and we already decided it
can't occur.
>
> + rcu_read_lock();
> + qdma = rcu_dereference(dev->qdma);
> qid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb));
> tag = airoha_get_dsa_tag(skb, netdev);
- This isn't a bug introduced by this patch, but does the hardware QoS offload
use the wrong channel due to incorrect queue ID mapping?
- This issue has been already reported in the past but it can't occur since
the driver implement ndo_select_queue() callback setting skb queue in the range [0,32[.
Regards,
Lorenzo
>
> @@ -2247,6 +2307,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> netif_tx_stop_queue(txq);
> q->txq_stopped = true;
> spin_unlock_bh(&q->lock);
> + rcu_read_unlock();
> +
> return NETDEV_TX_BUSY;
> }
>
> @@ -2309,6 +2371,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> FIELD_PREP(TX_RING_CPU_IDX_MASK, index));
>
> spin_unlock_bh(&q->lock);
> + rcu_read_unlock();
>
> return NETDEV_TX_OK;
>
> @@ -2324,6 +2387,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> error:
> dev_kfree_skb_any(skb);
> netdev->stats.tx_dropped++;
> + rcu_read_unlock();
>
> return NETDEV_TX_OK;
> }
> @@ -2403,17 +2467,19 @@ static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
> const u16 *weights, u8 n_weights)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_qdma *qdma;
> int i;
>
> + qdma = airoha_qdma_deref(dev);
> for (i = 0; i < AIROHA_NUM_QOS_QUEUES; i++)
> - airoha_qdma_clear(dev->qdma, REG_QUEUE_CLOSE_CFG(channel),
> + airoha_qdma_clear(qdma, REG_QUEUE_CLOSE_CFG(channel),
> TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i));
>
> for (i = 0; i < n_weights; i++) {
> u32 status;
> int err;
>
> - airoha_qdma_wr(dev->qdma, REG_TXWRR_WEIGHT_CFG,
> + airoha_qdma_wr(qdma, REG_TXWRR_WEIGHT_CFG,
> TWRR_RW_CMD_MASK |
> FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) |
> FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) |
> @@ -2421,12 +2487,12 @@ static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
> err = read_poll_timeout(airoha_qdma_rr, status,
> status & TWRR_RW_CMD_DONE,
> USEC_PER_MSEC, 10 * USEC_PER_MSEC,
> - true, dev->qdma, REG_TXWRR_WEIGHT_CFG);
> + true, qdma, REG_TXWRR_WEIGHT_CFG);
> if (err)
> return err;
> }
>
> - airoha_qdma_rmw(dev->qdma, REG_CHAN_QOS_MODE(channel >> 3),
> + airoha_qdma_rmw(qdma, REG_CHAN_QOS_MODE(channel >> 3),
> CHAN_QOS_MODE_MASK(channel),
> __field_prep(CHAN_QOS_MODE_MASK(channel), mode));
>
> @@ -2490,10 +2556,11 @@ static int airoha_qdma_get_tx_ets_stats(struct net_device *netdev, int channel,
> struct tc_ets_qopt_offload *opt)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_qdma *qdma = dev->qdma;
> u32 cpu_tx_packets, fwd_tx_packets;
> + struct airoha_qdma *qdma;
> u64 tx_packets;
>
> + qdma = airoha_qdma_deref(dev);
> cpu_tx_packets = airoha_qdma_rr(qdma, REG_CNTR_VAL(channel << 1));
> fwd_tx_packets = airoha_qdma_rr(qdma,
> REG_CNTR_VAL((channel << 1) + 1));
> @@ -2760,16 +2827,18 @@ static int airoha_qdma_set_tx_rate_limit(struct net_device *netdev,
> u32 bucket_size)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_qdma *qdma;
> int i, err;
>
> + qdma = airoha_qdma_deref(dev);
> for (i = 0; i <= TRTCM_PEAK_MODE; i++) {
> - err = airoha_qdma_set_trtcm_config(dev->qdma, channel,
> + err = airoha_qdma_set_trtcm_config(qdma, channel,
> REG_EGRESS_TRTCM_CFG, i,
> !!rate, TRTCM_METER_MODE);
> if (err)
> return err;
>
> - err = airoha_qdma_set_trtcm_token_bucket(dev->qdma, channel,
> + err = airoha_qdma_set_trtcm_token_bucket(qdma, channel,
> REG_EGRESS_TRTCM_CFG,
> i, rate, bucket_size);
> if (err)
> @@ -2805,11 +2874,12 @@ static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev,
> u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
> int err, num_tx_queues = AIROHA_NUM_TX_RING + channel + 1;
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_qdma *qdma = dev->qdma;
> + struct airoha_qdma *qdma;
>
> /* Here we need to check the requested QDMA channel is not already
> * in use by another net_device running on the same QDMA block.
> */
> + qdma = airoha_qdma_deref(dev);
> if (test_and_set_bit(channel, qdma->qos_channel_map)) {
> NL_SET_ERR_MSG_MOD(opt->extack,
> "qdma qos channel already in use");
> @@ -2845,7 +2915,7 @@ static int airoha_qdma_set_rx_meter(struct airoha_gdm_dev *dev,
> u32 rate, u32 bucket_size,
> enum trtcm_unit_type unit_type)
> {
> - struct airoha_qdma *qdma = dev->qdma;
> + struct airoha_qdma *qdma = airoha_qdma_deref(dev);
> int i;
>
> for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
> @@ -3020,10 +3090,11 @@ static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> int num_tx_queues = AIROHA_NUM_TX_RING;
> - struct airoha_qdma *qdma = dev->qdma;
> + struct airoha_qdma *qdma;
>
> airoha_qdma_set_tx_rate_limit(netdev, queue, 0, 0);
>
> + qdma = airoha_qdma_deref(dev);
> clear_bit(queue, qdma->qos_channel_map);
> clear_bit(queue, dev->qos_sq_bmap);
>
> @@ -3049,6 +3120,95 @@ static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev,
> return 0;
> }
>
> +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;
> +
> + err = airoha_disable_gdm2_loopback(dev);
> + if (err)
> + netdev_warn(netdev,
> + "failed disabling GDM2 loopback: %d\n", err);
> +
> + dev->flags &= ~AIROHA_DEV_F_WAN;
> + airoha_dev_set_qdma(dev);
> +
> + airoha_set_macaddr(dev, netdev->dev_addr);
> + if (netif_running(netdev))
> + airoha_set_gdm_port_fwd_cfg(dev->eth,
> + REG_GDM_FWD_CFG(port->id),
> + FE_PSE_PORT_PPE1);
> +}
> +
> +static int airoha_enable_qos_for_gdm34(struct net_device *netdev,
> + struct netlink_ext_ack *extack)
> +{
> + struct airoha_gdm_dev *wan_dev, *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> + struct airoha_eth *eth = dev->eth;
> + int err = -EBUSY;
> +
> + 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;
> +
> + mutex_lock(&flow_offload_mutex);
> +
> + wan_dev = airoha_get_wan_gdm_dev(eth);
> + if (wan_dev) {
> + if ((wan_dev->flags & AIROHA_DEV_F_QOS) ||
> + wan_dev->port->id == AIROHA_GDM2_IDX) {
> + NL_SET_ERR_MSG_MOD(extack,
> + "QoS configured for WAN device");
> + goto error_unlock;
> + }
> + airoha_disable_qos_for_gdm34(netdev_from_priv(wan_dev));
> + }
> +
> + dev->flags |= AIROHA_DEV_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;
> +
> + if (netif_running(netdev)) {
> + u32 pse_port;
> +
> + 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(port->id),
> + pse_port);
> + }
> +
> + mutex_unlock(&flow_offload_mutex);
> +
> + return 0;
> +
> +error_disable_loopback:
> + airoha_disable_gdm2_loopback(dev);
> +error_disable_wan:
> + dev->flags &= ~AIROHA_DEV_F_WAN;
> + airoha_dev_set_qdma(dev);
> +error_unlock:
> + mutex_unlock(&flow_offload_mutex);
> +
> + return err;
> +}
> +
> static int airoha_tc_htb_destroy(struct net_device *netdev)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> @@ -3057,6 +3217,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);
>
> + dev->flags &= ~AIROHA_DEV_F_QOS;
> +
> return 0;
> }
>
> @@ -3076,24 +3238,33 @@ static int airoha_tc_get_htb_get_leaf_queue(struct net_device *netdev,
> return 0;
> }
>
> -static int airoha_tc_setup_qdisc_htb(struct net_device *dev,
> +static int airoha_tc_setup_qdisc_htb(struct net_device *netdev,
> struct tc_htb_qopt_offload *opt)
> {
> switch (opt->command) {
> - case TC_HTB_CREATE:
> + case TC_HTB_CREATE: {
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + int err;
> +
> + err = airoha_enable_qos_for_gdm34(netdev, opt->extack);
> + if (err)
> + return err;
> +
> + dev->flags |= AIROHA_DEV_F_QOS;
> break;
> + }
> case TC_HTB_DESTROY:
> - return airoha_tc_htb_destroy(dev);
> + return airoha_tc_htb_destroy(netdev);
> case TC_HTB_NODE_MODIFY:
> - return airoha_tc_htb_modify_queue(dev, opt);
> + return airoha_tc_htb_modify_queue(netdev, opt);
> case TC_HTB_LEAF_ALLOC_QUEUE:
> - return airoha_tc_htb_alloc_leaf_queue(dev, opt);
> + return airoha_tc_htb_alloc_leaf_queue(netdev, opt);
> case TC_HTB_LEAF_DEL:
> case TC_HTB_LEAF_DEL_LAST:
> case TC_HTB_LEAF_DEL_LAST_FORCE:
> - return airoha_tc_htb_delete_leaf_queue(dev, opt);
> + return airoha_tc_htb_delete_leaf_queue(netdev, opt);
> case TC_HTB_LEAF_QUERY_QUEUE:
> - return airoha_tc_get_htb_get_leaf_queue(dev, opt);
> + return airoha_tc_get_htb_get_leaf_queue(netdev, opt);
> default:
> return -EOPNOTSUPP;
> }
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index ac5f571f3e53..a314330fcd48 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -537,11 +537,12 @@ struct airoha_qdma {
>
> enum airoha_dev_flags {
> AIROHA_DEV_F_WAN = BIT(0),
> + AIROHA_DEV_F_QOS = BIT(1),
> };
>
> struct airoha_gdm_dev {
> + struct airoha_qdma __rcu *qdma;
> struct airoha_gdm_port *port;
> - struct airoha_qdma *qdma;
> struct airoha_eth *eth;
>
> DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);
> @@ -677,6 +678,16 @@ int airoha_get_fe_port(struct airoha_gdm_dev *dev);
> bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
> struct airoha_gdm_dev *dev);
>
> +extern struct mutex flow_offload_mutex;
> +
> +static inline struct airoha_qdma *
> +airoha_qdma_deref(struct airoha_gdm_dev *dev)
> +{
> + return rcu_dereference_protected(dev->qdma,
> + lockdep_rtnl_is_held() ||
> + lockdep_is_held(&flow_offload_mutex));
> +}
> +
> void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport);
> bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index);
> void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
> diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> index 42f4b0f21d17..0f260c50ac3c 100644
> --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> @@ -15,7 +15,10 @@
> #include "airoha_regs.h"
> #include "airoha_eth.h"
>
> -static DEFINE_MUTEX(flow_offload_mutex);
> +/* Serialize airoha_gdm_dev flags, QDMA pointer and PPE CPU port
> + * configuration.
> + */
> +DEFINE_MUTEX(flow_offload_mutex);
> static DEFINE_SPINLOCK(ppe_lock);
>
> static const struct rhashtable_params airoha_flow_table_params = {
> @@ -86,8 +89,8 @@ static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe)
>
> void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport)
> {
> - struct airoha_qdma *qdma = dev->qdma;
> - struct airoha_eth *eth = qdma->eth;
> + struct airoha_qdma *qdma = airoha_qdma_deref(dev);
> + struct airoha_eth *eth = dev->eth;
> u8 qdma_id = qdma - ð->qdma[0];
> u32 fe_cpu_port;
>
> 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
>
>
> --
> 2.54.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v2 13/19] ARM: orion5x: mark all board files as deprecated
From: Arnd Bergmann @ 2026-07-02 13:50 UTC (permalink / raw)
To: Arnd Bergmann, linux-arm-kernel, soc
Cc: linux-kernel, Aaro Koskinen, A. Sverdlin, Alexandre Belloni,
Alexandre Torgue, Andrew Lunn, Ard Biesheuvel, Claudiu Beznea,
Daniel Mack, Ethan Nelson-Moore, Frank Li, Gregory Clement,
Haojian Zhuang, Jeremy J. Peper, Kristoffer Ericson,
Krzysztof Kozlowski, Linus Walleij, Mark Brown, Marc Zyngier,
Mike Rapoport, Nicolas Ferre, Patrice Chotard, Ralph Siemsen,
Robert Jarzmik, Russell King, Sascha Hauer, Sebastian Hesselbarth,
Stefan Agner, Stefan Wiehler, Tony Lindgren, Vladimir Zapolskiy,
Will Deacon
In-Reply-To: <20260701212353.2196041-14-arnd@kernel.org>
On Wed, Jul 1, 2026, at 23:23, Arnd Bergmann wrote:
> Debian has previously removed the orion/kirkwood kernel
> binary from the armel distro, but building custom kernels
> from the Debian source code should keep working, so
> removing the board files after the 6.12 release ensures
> that this remains possible for the Debian Trixie release,
> assuming this will use the 6.12 LTS kernel.
I noticed this paragraph is outdated and have now replaced
it with
| Debian and OpenWRT no longer support orion5x, and buildroot
| could keep using linux-7.3-LTS for a few more years.
Arnd
^ permalink raw reply
* Re: [PATCH v14 00/44] arm64: Support for Arm CCA in KVM
From: Kohei Enju @ 2026-07-02 13:49 UTC (permalink / raw)
To: Steven Price
Cc: kvm, kvmarm, Catalin Marinas, Marc Zyngier, Will Deacon,
James Morse, Oliver Upton, Suzuki K Poulose, Zenghui Yu,
linux-arm-kernel, linux-kernel, Joey Gouly, Alexandru Elisei,
Christoffer Dall, Fuad Tabba, linux-coco, Ganapatrao Kulkarni,
Gavin Shan, Shanker Donthineni, Alper Gun, Aneesh Kumar K . V,
Emi Kisanuki, Vishal Annapurve, WeiLin.Chang, Lorenzo.Pieralisi2
In-Reply-To: <8c0e6a32-2de2-4b94-9fe2-e32f5e9bcc4a@arm.com>
On 07/01 11:53, Steven Price wrote:
> On 01/07/2026 03:15, Kohei Enju wrote:
> > On 05/13 14:17, Steven Price wrote:
> >> This series adds support for running protected VMs using KVM under the
> >> Arm Confidential Compute Architecture (CCA).
> >>
> >> This is rebased on v7.1-rc1, but still targets RMM v2.0-bet1[1].
> >>
> >> The major updates from v13 remain but have been more fully implemented:
> >> the RMM uses the host's page size, range based RMI APIs mean we don't
> >> have to break everything down to base page sizes, the GIC state is
> >> passed via system registers, and the uAPI has been simplified.
> >>
> >> The main changes since v13 are:
> >>
> >> * The RMI definitions and wrappers have been fully updated for RMM
> >> v2.0-bet1. In particular the temporary RMM v1.0 SMC compatibility
> >> patch has been dropped.
> >>
> >> * The PSCI completion ioctl has been removed. RMM v2.0-bet1 still
> >> requires the host to provide the target REC for PSCI calls which
> >> name another vCPU, but KVM now performs the RMI PSCI completion
> >> automatically before entering the REC again. Userspace no longer
> >> needs to issue KVM_ARM_VCPU_RMI_PSCI_COMPLETE. A future spec should
> >> remove the need for the host to provide the MPIDR mapping.
> >>
> >> * The generic RMI init, RMM configuration, GPT setup,
> >> delegate/undelegate helpers and SRO infrastructure have moved out of
> >> KVM into arch/arm64/kernel/rmi.c. RMI is expected to be used by
> >> features outside KVM, so this code should be available even when KVM
> >> is not built.
> >>
> >> * RMI_GRANULE_TRACKING_GET has been updated to work on a range, this
> >> allows it to work when the region is not aligned to the tracking
> >> size. Solves the problem reported by Mathieu[2].
> >>
> >> * SRO support has been moved earlier in the series and improved. It
> >> provides a cleaner way for the host to provide the RMM with the extra
> >> memory it requires. However support is still incomplete where the
> >> TF-RMM code does not yet implement it. This is noted by FIXMEs in the
> >> code.
> >>
> >> * The ARM VM type encoding has been reworked to coexist with the
> >> upstream pKVM KVM_VM_TYPE_ARM_PROTECTED bit.
> >>
> >> * The private-memory documentation now notes that arm64 uses
> >> KVM_CAP_MEMORY_ATTRIBUTES.
> >>
> >> * PMU support is dropped for now. It will be added later in a separate
> >> series. Similarly for selecting the hash algorithm and RPV.
> >
> > Hi Steven,
>
> Hi,
>
> > Is there any plan to add support for selecting the MEC policy (shared or
> > private)? We have been working on adding support for this on top of your
> > series. If this is not already in the works, we may upstream our
> > implementation later.
>
> I've been trying to focus on getting the minimum useful series
> upstreamed before looking at additional features (such as hash
> algorithm, MEC policy etc). If you've already got support then yes
> please do upstream it later when we've got this series landed.
Thank you for the clarification. That makes sense.
I agree that the non-RFC patch should wait until your series has landed.
Before that, however, I'd like to send an RFC patch to gather feedback
on the design from the community while your series is still under
review. I don't expect the RFC to interfere with the upstreaming of your
series.
Thanks,
Kohei.
>
> Thanks,
> Steve
>
> > Thanks,
> > Kohei
> >
> >>
> >> There are also the usual rebase updates and smaller fixes, including
> >> changes to the RMM v2.0-bet1 range APIs, removal of REC auxiliary
> >> granule handling, fixes to the address range descriptor encoding, and
> >> cleanups around realm stage-2 teardown.
> >>
> >> Stateful RMI Operations
> >> -----------------------
> >>
> >> The RMM v2.0 spec introduces Stateful RMI Operations (SROs), which allow
> >> the RMM to complete an operation over several SMC calls while requesting
> >> or returning memory to the host. This allows interrupts to be handled in
> >> the middle of an operation and lets the RMM dynamically allocate memory
> >> for internal tracking purposes. For example, RMI_REC_CREATE no longer
> >> needs auxiliary granules to be provided up front, and can instead
> >> request memory during the operation.
> >>
> >> This series includes the generic SRO infrastructure in
> >> arch/arm64/kernel/rmi.c and uses it for REC create/destroy. The other
> >> cases are not yet used by TF-RMM and a future revision will be needed to
> >> finish those paths in Linux.
> >>
> >> This series is based on v7.1-rc1. It is also available as a git
> >> repository:
> >>
> >> https://gitlab.arm.com/linux-arm/linux-cca cca-host/v14
> >>
> >> Work in progress changes for kvmtool are available from the git
> >> repository below:
> >>
> >> https://gitlab.arm.com/linux-arm/kvmtool-cca cca/v12
> >>
> >> The TF-RMM has not yet merged the RMM v2.0 support, so you will need to
> >> use a branch with RMM v2.0-bet1 support. At the time of writing the
> >> following branch is being used:
> >>
> >> https://git.trustedfirmware.org/TF-RMM/tf-rmm.git topics/rmm-v2.0-poc_2
> >> (tested on commit 3340667a291a)
> >>
> >> There is a kvm-unit-test branch which has been updated to support the
> >> attestation used in RMMv2.0 available here:
> >>
> >> https://gitlab.arm.com/linux-arm/kvm-unit-tests-cca cca/v4
> >>
> >> [1] https://developer.arm.com/documentation/den0137/2-0bet1/
> >> [2] https://lore.kernel.org/all/acrj-cKphy4hJsEG@p14s/
>
>
^ permalink raw reply
* Re: [PATCH v2 03/19] ARM: rework ARM11 CPU selection logic
From: Arnd Bergmann @ 2026-07-02 13:49 UTC (permalink / raw)
To: Alexandre Belloni, Arnd Bergmann
Cc: linux-arm-kernel, soc, linux-kernel, Aaro Koskinen, A. Sverdlin,
Alexandre Torgue, Andrew Lunn, Ard Biesheuvel, Claudiu Beznea,
Daniel Mack, Ethan Nelson-Moore, Frank Li, Gregory Clement,
Haojian Zhuang, Jeremy J. Peper, Kristoffer Ericson,
Krzysztof Kozlowski, Linus Walleij, Mark Brown, Marc Zyngier,
Mike Rapoport, Nicolas Ferre, Patrice Chotard, Ralph Siemsen,
Robert Jarzmik, Russell King, Sascha Hauer, Sebastian Hesselbarth,
Stefan Agner, Stefan Wiehler, Tony Lindgren, Vladimir Zapolskiy,
Will Deacon, Linus Walleij
In-Reply-To: <202607021346368633bfa6@mail.local>
On Thu, Jul 2, 2026, at 15:46, Alexandre Belloni wrote:
> On 01/07/2026 23:23:37+0200, Arnd Bergmann wrote:
>>
>> To my knowledge, none of these have any actual users aside from
>> reference boards being used more easily test the platforms.
>
> There is a missing "to" in this sentence ;)
Fixed, thanks!
Arnd
^ permalink raw reply
* Re: [PATCH v2 03/19] ARM: rework ARM11 CPU selection logic
From: Alexandre Belloni @ 2026-07-02 13:46 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-arm-kernel, soc, linux-kernel, Arnd Bergmann, Aaro Koskinen,
Alexander Sverdlin, Alexandre Torgue, Andrew Lunn, Ard Biesheuvel,
Claudiu Beznea, Daniel Mack, Ethan Nelson-Moore, Frank Li,
Gregory Clement, Haojian Zhuang, Jeremy J. Peper,
Kristoffer Ericson, Krzysztof Kozlowski, Linus Walleij,
Mark Brown, Marc Zyngier, Mike Rapoport, Nicolas Ferre,
Patrice Chotard, Ralph Siemsen, Robert Jarzmik, Russell King,
Sascha Hauer, Sebastian Hesselbarth, Stefan Agner, Stefan Wiehler,
Tony Lindgren, Vladimir Zapolskiy, Will Deacon, Linus Walleij
In-Reply-To: <20260701212353.2196041-4-arnd@kernel.org>
On 01/07/2026 23:23:37+0200, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> Support for SMP on ARM1136r0 has been broken for a while, and nobody
> is working on fixing it. I had a plan to change ARMv6 support to no
> longer coexist in a common kernel with ARMv7 CPUs but instead ARMv5 and
> below. This would have addressed the problem, but after a recent mailing
> list discussion, we concluded that an easier approach is to just forbid
> ARM1136r0 CPU support on SMP-enabled kernels.
>
> This mainly affects users of the Nokia N800/N810 tablets using an
> OMAP2420 SoC, which is the only commercial product with an ARM1136r0
> that is still supported by the kernel.
>
> The other machines that are still in the same hardware catogory are:
>
> - TI OMAP2420 H4 reference board
> - TI OMAP2430 SDP software development platform
> - Freescale/NXP i.MX31 Lite Development Kit
> - Buglabs i.MX31 Bug 1.x prototype
> - Arm Integrator/AP with CM1136JF-S core module
>
> To my knowledge, none of these have any actual users aside from
> reference boards being used more easily test the platforms.
There is a missing "to" in this sentence ;)
>
> There are also a few ARM1136r1 machines, which implement the
> ARMv6K SMP support (barriers, atomics and TLS):
>
> - Eukrea CPUIMX35 reference platform
> - Freescale/NXP i.MX35 Product Development Kit
> - ARM Integrator/CP/IM-LT3 with ARM1136J Core Tile
> - ARM Realview/EB with ARM1136J Core Tile
>
> Again, these are mainly reference implementations rather than
> actual products, but since they support ARMv6K, they should
> continue to work correctly in SMP-enabled kernels. For the
> ARM Core Tile, I have not found a datasheet but instead use
> the revision based on what the respective virtual models
> report.
>
> All the other ARMv6 platforms use an ARM1176 with ARMv6K,
> VMSAv7 and Trustzone support.
>
> To avoid the broken configuration, annotate the ARM1136 based
> machines with specific CPU_ARM1136R0 or CPU_ARM1136R2 symbols
> in Kconfig and make the r0 variants depend on !SMP.
>
> Link: https://lore.kernel.org/linux-arm-kernel/2831c5a6-cfbf-4fe0-b51c-0396e5b0aeb7@app.fastmail.com/T/
> Acked-by: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> arch/arm/Kconfig.platforms | 2 +-
> arch/arm/mach-imx/Kconfig | 4 +++-
> arch/arm/mach-omap2/Kconfig | 3 ++-
> arch/arm/mach-versatile/Kconfig | 10 +++++-----
> arch/arm/mm/Kconfig | 24 +++++++++++++++++++++++-
> 5 files changed, 34 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm/Kconfig.platforms b/arch/arm/Kconfig.platforms
> index 386eccc81868..2e118b65f93b 100644
> --- a/arch/arm/Kconfig.platforms
> +++ b/arch/arm/Kconfig.platforms
> @@ -33,7 +33,7 @@ config ARCH_MULTI_V4_V5
> config ARCH_MULTI_V6
> bool "ARMv6 based platforms (ARM11)"
> select ARCH_MULTI_V6_V7
> - select CPU_V6K
> + select CPU_ARM1176
>
> config ARCH_MULTI_V7
> bool "ARMv7 based platforms (Cortex-A, PJ4, Scorpion, Krait)"
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index a361840d7a04..041e73ad203a 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -41,13 +41,15 @@ comment "ARM1136 platforms"
>
> config SOC_IMX31
> bool "i.MX31 support"
> - select CPU_V6
> + depends on !SMP
> + select CPU_ARM1136R0
> select MXC_AVIC
> help
> This enables support for Freescale i.MX31 processor
>
> config SOC_IMX35
> bool "i.MX35 support"
> + select CPU_ARM1136R1
> select MXC_AVIC
> help
> This enables support for Freescale i.MX35 processor
> diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
> index f3f19bcfca2c..13987ffbba00 100644
> --- a/arch/arm/mach-omap2/Kconfig
> +++ b/arch/arm/mach-omap2/Kconfig
> @@ -8,8 +8,9 @@ config OMAP_HWMOD
> config ARCH_OMAP2
> bool "TI OMAP2"
> depends on ARCH_MULTI_V6
> + depends on !SMP
> select ARCH_OMAP2PLUS
> - select CPU_V6
> + select CPU_ARM1136R0
> select OMAP_HWMOD
> select SOC_HAS_OMAP2_SDRC
>
> diff --git a/arch/arm/mach-versatile/Kconfig b/arch/arm/mach-versatile/Kconfig
> index 513618078440..de42da7de8c8 100644
> --- a/arch/arm/mach-versatile/Kconfig
> +++ b/arch/arm/mach-versatile/Kconfig
> @@ -113,7 +113,8 @@ config INTEGRATOR_CM1136JFS
> bool "Integrator/CM1136JF-S core module"
> depends on ARCH_INTEGRATOR_AP
> depends on ARCH_MULTI_V6
> - select CPU_V6
> + depends on !SMP
> + select CPU_ARM1136R0
>
> config ARCH_INTEGRATOR_CP
> bool "Support Integrator/CP platform"
> @@ -135,7 +136,7 @@ config INTEGRATOR_CTB36
> bool "Integrator/CTB36 (ARM1136JF-S) core tile"
> depends on ARCH_INTEGRATOR_CP
> depends on ARCH_MULTI_V6
> - select CPU_V6
> + select CPU_ARM1136R1
>
> config ARCH_CINTEGRATOR
> depends on ARCH_INTEGRATOR_CP
> @@ -182,7 +183,7 @@ config MACH_REALVIEW_EB
> config REALVIEW_EB_ARM1136
> bool "Support ARM1136J(F)-S Tile"
> depends on MACH_REALVIEW_EB && ARCH_MULTI_V6
> - select CPU_V6
> + select CPU_ARM1136R1
> help
> Enable support for the ARM1136 tile fitted to the
> Realview(R) Emulation Baseboard platform.
> @@ -201,11 +202,10 @@ config REALVIEW_EB_A9MP
> Enable support for the Cortex-A9MPCore tile fitted to the
> Realview(R) Emulation Baseboard platform.
>
> -# ARMv6 CPU without K extensions, but does have the new exclusive ops
> config MACH_REALVIEW_PB1176
> bool "Support RealView(R) Platform Baseboard for ARM1176JZF-S"
> depends on ARCH_MULTI_V6
> - select CPU_V6
> + select CPU_ARM1176
> select HAVE_TCM
> help
> Include support for the ARM(R) RealView(R) Platform Baseboard for
> diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
> index 871bd58d2ccc..f3d71e89a31f 100644
> --- a/arch/arm/mm/Kconfig
> +++ b/arch/arm/mm/Kconfig
> @@ -376,6 +376,7 @@ config CPU_PJ4B
> # ARMv6
> config CPU_V6
> bool
> + depends on !SMP
> select CPU_32v6
> select CPU_ABRT_EV6
> select CPU_CACHE_V6
> @@ -386,7 +387,6 @@ config CPU_V6
> select CPU_PABRT_V6
> select CPU_THUMB_CAPABLE
> select CPU_TLB_V6 if MMU
> - select SMP_ON_UP if SMP
>
> # ARMv6k
> config CPU_V6K
> @@ -403,6 +403,28 @@ config CPU_V6K
> select CPU_THUMB_CAPABLE
> select CPU_TLB_V6 if MMU
>
> +config CPU_ARM1136R0
> + bool
> + select CPU_V6
> + depends on !SMP
> + help
> + These early revisions of ARM1136 lack support for the
> + ARMv6k extensions for multiprocessing.
> +
> +config CPU_ARM1136R1
> + bool
> + select CPU_V6K
> + help
> + Later revisions of ARM1136 add ARMv6k (atomics, barriers
> + and TLS register) in addition to the features from r0.
> +
> +config CPU_ARM1176
> + bool
> + select CPU_V6K
> + help
> + ARM1176 implements ARMv6k, VMSAv7 and Trustzone in
> + addition to the ARMv6 baseline.
> +
> # ARMv7 and ARMv8 architectures
> config CPU_V7
> bool
> --
> 2.39.5
>
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH v2 02/19] ARM: limit OABI support to StrongARM CPUs
From: Arnd Bergmann @ 2026-07-02 13:40 UTC (permalink / raw)
To: Alexandre Belloni, Arnd Bergmann
Cc: linux-arm-kernel, soc, linux-kernel, Aaro Koskinen, A. Sverdlin,
Alexandre Torgue, Andrew Lunn, Ard Biesheuvel, Claudiu Beznea,
Daniel Mack, Ethan Nelson-Moore, Frank Li, Gregory Clement,
Haojian Zhuang, Jeremy J. Peper, Kristoffer Ericson,
Krzysztof Kozlowski, Linus Walleij, Mark Brown, Marc Zyngier,
Mike Rapoport, Nicolas Ferre, Patrice Chotard, Ralph Siemsen,
Robert Jarzmik, Russell King, Sascha Hauer, Sebastian Hesselbarth,
Stefan Agner, Stefan Wiehler, Tony Lindgren, Vladimir Zapolskiy,
Will Deacon, Linus Walleij
In-Reply-To: <20260702133626d12c29ad@mail.local>
On Thu, Jul 2, 2026, at 15:36, Alexandre Belloni wrote:
> On 01/07/2026 23:23:36+0200, Arnd Bergmann wrote:
>> @@ -9,9 +9,9 @@ CONFIG_ARCH_MULTI_V4=y
>> CONFIG_ARCH_FOOTBRIDGE=y
>> CONFIG_ARCH_EBSA285_HOST=y
>> CONFIG_ARCH_NETWINDER=y
>> +# CONFIG_AEABI is not set
>> CONFIG_FPE_NWFPE=y
>> CONFIG_FPE_NWFPE_XP=y
>> -# CONFIG_AEABI is not set
>
> I'm not objecting to the change this reordering is not directly related
> to the current patch, maybe this should be squashed in 1/19
>
I've dropped these changes now, I don't think they were
intentional at the time.
Arnd
^ permalink raw reply
* Re: [PATCH v2 02/19] ARM: limit OABI support to StrongARM CPUs
From: Alexandre Belloni @ 2026-07-02 13:36 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-arm-kernel, soc, linux-kernel, Arnd Bergmann, Aaro Koskinen,
Alexander Sverdlin, Alexandre Torgue, Andrew Lunn, Ard Biesheuvel,
Claudiu Beznea, Daniel Mack, Ethan Nelson-Moore, Frank Li,
Gregory Clement, Haojian Zhuang, Jeremy J. Peper,
Kristoffer Ericson, Krzysztof Kozlowski, Linus Walleij,
Mark Brown, Marc Zyngier, Mike Rapoport, Nicolas Ferre,
Patrice Chotard, Ralph Siemsen, Robert Jarzmik, Russell King,
Sascha Hauer, Sebastian Hesselbarth, Stefan Agner, Stefan Wiehler,
Tony Lindgren, Vladimir Zapolskiy, Will Deacon, Linus Walleij
In-Reply-To: <20260701212353.2196041-3-arnd@kernel.org>
On 01/07/2026 23:23:36+0200, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> As discussed on the mailing lists, there is no way to build OABI userspace
> binaries any more since gcc-4.8, and now support is also getting dropped in
> binutils, which will make it impossible to build pure OABI kernels at some
> point in the future.
>
> I found no evidence of anyone still sing OABI userspace on embedded systems
> that keep getting kernel updates, but there are a few desktop-class machines
> that date back to the 1990s using Intel StrongARM processors that were
> supported by old versions of Debian, Red Hat or the official Corel
> Netwinder distribution.
>
> Add a much stricter Kconfig dependency for both native OABI and OABI_COMPAT
> enabled kernels, only allowing either of them to be selected when building
> a kernel that targets a StrongARM based machine.
>
> Link: https://lore.kernel.org/lkml/2831c5a6-cfbf-4fe0-b51c-0396e5b0aeb7@app.fastmail.com/
> Acked-by: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> arch/arm/Kconfig | 14 +++++++-------
> arch/arm/configs/am200epdkit_defconfig | 1 -
> arch/arm/configs/axm55xx_defconfig | 1 -
> arch/arm/configs/footbridge_defconfig | 2 +-
> arch/arm/configs/neponset_defconfig | 2 +-
> arch/arm/configs/versatile_defconfig | 1 -
> 6 files changed, 9 insertions(+), 12 deletions(-)
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index ccc0114d30de..3b2316dc9d13 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1151,8 +1151,7 @@ config ARM_PATCH_IDIV
> code to do integer division.
>
> config AEABI
> - bool "Use the ARM EABI to compile the kernel" if !CPU_V7 && \
> - !CPU_V7M && !CPU_V6 && !CPU_V6K && !CC_IS_CLANG
> + bool "Use the ARM EABI to compile the kernel" if CPU_SA110 || CPU_SA1100
> default y
> help
> The Arm EABI is the default ABI on all modern Linux
> @@ -1162,9 +1161,13 @@ config AEABI
> Everyone should enable this, as support for OABI user space
> was dropped in gcc-4.8 and most distributions after ca. 2013.
>
> + Support for OABI mode will be removed from the kernel
> + once Intel StrongARM CPUs are phased out.
> +
> config OABI_COMPAT
> bool "Allow old ABI binaries to run with this kernel (EXPERIMENTAL)"
> depends on AEABI && !THUMB2_KERNEL
> + depends on CPU_SA110 || CPU_SA1100
> help
> This option preserves the old syscall interface along with the
> new (ARM EABI) one. It also provides a compatibility layer to
> @@ -1177,11 +1180,8 @@ config OABI_COMPAT
> selected, since there is no way yet to sensibly distinguish
> between calling conventions during filtering.
>
> - If you know you'll be using only pure EABI user space then you
> - can say N here. If this option is not selected and you attempt
> - to execute a legacy ABI binary then the result will be
> - UNPREDICTABLE (in fact it can be predicted that it won't work
> - at all). If in doubt say N.
> + Support for OABI_COMPAT will be removed from the kernel
> + once Intel StrongARM CPUs are phased out.
>
> config ARCH_SELECT_MEMORY_MODEL
> def_bool y
> diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
> index b3f81237c6e1..d4745b0f3dcb 100644
> --- a/arch/arm/configs/am200epdkit_defconfig
> +++ b/arch/arm/configs/am200epdkit_defconfig
> @@ -7,7 +7,6 @@ CONFIG_EXPERT=y
> # CONFIG_ARCH_MULTI_V7 is not set
> CONFIG_ARCH_PXA=y
> CONFIG_ARCH_GUMSTIX=y
> -# CONFIG_OABI_COMPAT is not set
> CONFIG_CMDLINE="console=ttyS0,115200n8 root=1f01 rootfstype=jffs2"
> CONFIG_MODULES=y
> CONFIG_MODULE_UNLOAD=y
> diff --git a/arch/arm/configs/axm55xx_defconfig b/arch/arm/configs/axm55xx_defconfig
> index 12c59a4ee504..541e38e2205b 100644
> --- a/arch/arm/configs/axm55xx_defconfig
> +++ b/arch/arm/configs/axm55xx_defconfig
> @@ -38,7 +38,6 @@ CONFIG_PCIE_AXXIA=y
> CONFIG_SMP=y
> CONFIG_NR_CPUS=16
> CONFIG_HOTPLUG_CPU=y
> -CONFIG_OABI_COMPAT=y
> CONFIG_HIGHMEM=y
> CONFIG_ARM_APPENDED_DTB=y
> CONFIG_ARM_ATAG_DTB_COMPAT=y
> diff --git a/arch/arm/configs/footbridge_defconfig b/arch/arm/configs/footbridge_defconfig
> index 589b7b1df8c6..e8bf9847d35d 100644
> --- a/arch/arm/configs/footbridge_defconfig
> +++ b/arch/arm/configs/footbridge_defconfig
> @@ -9,9 +9,9 @@ CONFIG_ARCH_MULTI_V4=y
> CONFIG_ARCH_FOOTBRIDGE=y
> CONFIG_ARCH_EBSA285_HOST=y
> CONFIG_ARCH_NETWINDER=y
> +# CONFIG_AEABI is not set
> CONFIG_FPE_NWFPE=y
> CONFIG_FPE_NWFPE_XP=y
> -# CONFIG_AEABI is not set
I'm not objecting to the change this reordering is not directly related
to the current patch, maybe this should be squashed in 1/19
> CONFIG_MODULES=y
> CONFIG_PARTITION_ADVANCED=y
> CONFIG_ACORN_PARTITION=y
> diff --git a/arch/arm/configs/neponset_defconfig b/arch/arm/configs/neponset_defconfig
> index c3010a4d93a8..16f0afd770c1 100644
> --- a/arch/arm/configs/neponset_defconfig
> +++ b/arch/arm/configs/neponset_defconfig
> @@ -6,12 +6,12 @@ CONFIG_ARCH_MULTI_V4=y
> CONFIG_ARCH_SA1100=y
> CONFIG_SA1100_ASSABET=y
> CONFIG_ASSABET_NEPONSET=y
> +# CONFIG_AEABI is not set
> CONFIG_ZBOOT_ROM_TEXT=0x80000
> CONFIG_ZBOOT_ROM_BSS=0xc1000000
> CONFIG_ZBOOT_ROM=y
> CONFIG_CMDLINE="console=ttySA0,38400n8 cpufreq=221200 rw root=/dev/mtdblock2 mtdparts=sa1100:512K(boot),1M(kernel),2560K(initrd),4M(root) mem=32M noinitrd initrd=0xc0800000,3M"
> CONFIG_FPE_NWFPE=y
> -# CONFIG_AEABI is not set
Ditto
> CONFIG_PM=y
> CONFIG_MODULES=y
> CONFIG_MODULE_UNLOAD=y
> diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig
> index 8e89debb5a5b..bb9eb9ccbbde 100644
> --- a/arch/arm/configs/versatile_defconfig
> +++ b/arch/arm/configs/versatile_defconfig
> @@ -6,7 +6,6 @@ CONFIG_LOG_BUF_SHIFT=14
> CONFIG_BLK_DEV_INITRD=y
> # CONFIG_ARCH_MULTI_V7 is not set
> CONFIG_ARCH_VERSATILE=y
> -CONFIG_OABI_COMPAT=y
> CONFIG_CMDLINE="root=1f03 mem=32M"
> CONFIG_FPE_NWFPE=y
> CONFIG_VFP=y
> --
> 2.39.5
>
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH net-next v7 2/3] net: airoha: fix ETS QoS stats counter underflow and cross-channel corruption
From: Lorenzo Bianconi @ 2026-07-02 13:31 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Simon Horman, Alexander Lobakin, linux-arm-kernel, linux-mediatek,
netdev
In-Reply-To: <20260701-airoha-ethtool-priv_flags-v7-2-b4153bd44428@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 4323 bytes --]
> airoha_qdma_get_tx_ets_stats() has two bugs:
> - The hardware counters read via airoha_qdma_rr() are 32-bit values
> but are stored in u64 locals and subtracted from u64 baselines. When
> a 32-bit hardware counter wraps around, the subtraction produces a
> large underflow value passed to _bstats_update().
> - The baseline counters (cpu_tx_packets, fwd_tx_packets) are stored as
> single per-device fields, but airoha_qdma_get_tx_ets_stats() is
> called with different channel values (0-3). Each call reads a
> different channel's hardware counter but overwrites the same
> baseline, corrupting the delta computation for other channels.
>
> Fix both by:
> - Narrowing the counter locals and baselines to u32 so that 32-bit
> unsigned subtraction handles wrap-around naturally.
> - Grouping the baselines into a per-channel qos_stats array so each
> channel tracks its own previous counter value independently.
>
> Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support")
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
commenting on sashiko's report:
https://sashiko.dev/#/patchset/20260701-airoha-ethtool-priv_flags-v7-0-b4153bd44428%40kernel.org
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 18 +++++++++++-------
> drivers/net/ethernet/airoha/airoha_eth.h | 7 ++++---
> 2 files changed, 15 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 8bba54ebcf07..2c9ceb9f16f8 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -2491,16 +2491,20 @@ static int airoha_qdma_get_tx_ets_stats(struct net_device *netdev, int channel,
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> struct airoha_qdma *qdma = dev->qdma;
> + u32 cpu_tx_packets, fwd_tx_packets;
> + u64 tx_packets;
>
> - u64 cpu_tx_packets = airoha_qdma_rr(qdma, REG_CNTR_VAL(channel << 1));
> - u64 fwd_tx_packets = airoha_qdma_rr(qdma,
> - REG_CNTR_VAL((channel << 1) + 1));
> - u64 tx_packets = (cpu_tx_packets - dev->cpu_tx_packets) +
> - (fwd_tx_packets - dev->fwd_tx_packets);
> + cpu_tx_packets = airoha_qdma_rr(qdma, REG_CNTR_VAL(channel << 1));
> + fwd_tx_packets = airoha_qdma_rr(qdma,
> + REG_CNTR_VAL((channel << 1) + 1));
> + tx_packets = (u32)(cpu_tx_packets -
> + dev->qos_stats[channel].cpu_tx_packets) +
> + (u32)(fwd_tx_packets -
> + dev->qos_stats[channel].fwd_tx_packets);
- Will this addition overflow in 32-bit space before the result is assigned to
the 64-bit tx_packets?
- I do not think this is a problem since we are just considering the delta
betwen cpu_tx_packets/fwd_tx_packets and the previous value. Moreover, the
u32 cast will take care of possible wrap-around.
>
> _bstats_update(opt->stats.bstats, 0, tx_packets);
- This isn't a bug introduced by this patch, but does calling _bstats_update()
here directly from process context race with the software datapath?
- Sashiko is right here. This is a pre-existing (theoretical) issue not
introduced by this patch. However, since the Airoha EN7581/EN7583 is
ARM64-only, u64_stats_update_begin/end are NOPs on this platform and
there is no actual race. IIUC the seqcount corruption scenario only
applies to 32-bit architectures. I guess we can
Regards,
Lorenzo
> - dev->cpu_tx_packets = cpu_tx_packets;
> - dev->fwd_tx_packets = fwd_tx_packets;
> + dev->qos_stats[channel].cpu_tx_packets = cpu_tx_packets;
> + dev->qos_stats[channel].fwd_tx_packets = fwd_tx_packets;
>
> return 0;
> }
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index 87ab3ea10664..ac5f571f3e53 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -545,9 +545,10 @@ struct airoha_gdm_dev {
> struct airoha_eth *eth;
>
> DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);
> - /* qos stats counters */
> - u64 cpu_tx_packets;
> - u64 fwd_tx_packets;
> + struct {
> + u32 cpu_tx_packets;
> + u32 fwd_tx_packets;
> + } qos_stats[AIROHA_NUM_QOS_CHANNELS];
>
> u32 flags;
> int nbq;
>
> --
> 2.54.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH] soc: renesas: Expand MFIS acronym in RCAR_MFIS help description
From: Geert Uytterhoeven @ 2026-07-02 13:27 UTC (permalink / raw)
To: Kuninori Morimoto, Wolfram Sang
Cc: linux-renesas-soc, linux-arm-kernel, Geert Uytterhoeven
People not very familiar with Renesas R-Car SoCs may not know the
meaning of the MFIS acronym. Hence expand it in the help text.
While at it, drop "core driver", as there is only a single driver,
unlike early development revisions.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/soc/renesas/Kconfig | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig
index 2f2251d06457c9e3..8a625bc17091773f 100644
--- a/drivers/soc/renesas/Kconfig
+++ b/drivers/soc/renesas/Kconfig
@@ -490,9 +490,9 @@ config RCAR_MFIS
depends on ARCH_RENESAS || COMPILE_TEST
depends on MAILBOX
help
- Select this option to enable the Renesas R-Car MFIS core driver for
- the MFIS device found on SoCs like R-Car. On families like Gen5, this
- is needed to communicate with the SCP.
+ Select this option to enable support for the Renesas R-Car
+ Multifunctional Interface (MFIS) device found on SoCs like R-Car.
+ On families like Gen5, this is needed to communicate with the SCP.
config PWC_RZV2M
bool "Renesas RZ/V2M PWC support" if COMPILE_TEST
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v3 1/8] dt-bindings: rtc: sun6i: no clock-output-names on h616/r329
From: Chen-Yu Tsai @ 2026-07-02 13:23 UTC (permalink / raw)
To: Jerome Brunet
Cc: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jernej Skrabec, Samuel Holland, Michael Turquette,
Stephen Boyd, Maxime Ripard, linux-rtc, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel, linux-clk, Sashiko
In-Reply-To: <20260702-a733-rtc-v3-1-eb2580374de6@baylibre.com>
On Thu, Jul 2, 2026 at 4:10 PM Jerome Brunet <jbrunet@baylibre.com> wrote:
>
> On h616 and r329 chips, clock output names are never defined through DT and
> are not meant to be. Just disallow the property for those chips.
>
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Closes: http://lore.kernel.org/r/20260629125305.0DF981F000E9@smtp.kernel.org
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Reviewed-by: Chen-Yu Tsai <wens@kernel.org>
^ permalink raw reply
* Re: [PATCH v3 3/8] clk: sunxi-ng: fix ccu probe clock unregister on error
From: Chen-Yu Tsai @ 2026-07-02 13:23 UTC (permalink / raw)
To: Jerome Brunet
Cc: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jernej Skrabec, Samuel Holland, Michael Turquette,
Stephen Boyd, Maxime Ripard, linux-rtc, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel, linux-clk, Sashiko
In-Reply-To: <20260702-a733-rtc-v3-3-eb2580374de6@baylibre.com>
On Thu, Jul 2, 2026 at 4:10 PM Jerome Brunet <jbrunet@baylibre.com> wrote:
>
> When registering clocks with sunxi_ccu_probe(), the number of ccu_clocks
> and the number of hw clocks might be different, eventhough they usually are
> the same.
>
> If they are different, it could lead to out-of-bound access or registered
> clock left behind on error.
>
> Use a different variable when iterating on hw clocks so every registered
> clock, and only those, gets unregistered on error.
>
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Closes: https://lore.kernel.org/r/20260629131254.7E34C1F00A3A@smtp.kernel.org
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Reviewed-by: Chen-Yu Tsai <wens@kernel.org>
^ permalink raw reply
* Re: [External Mail] Re: [PATCH v3 2/7] net: wwan: t9xx: Add control plane transaction layer
From: Andrew Lunn @ 2026-07-02 13:17 UTC (permalink / raw)
To: Wu. JackBB (GSM)
Cc: Loic Poulain, Sergey Ryazanov, Johannes Berg, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Wen-Zhi Huang, Shi-Wei Yeh, Minano Tseng, Matthias Brugger,
AngeloGioacchino Del Regno, Simon Horman, Jonathan Corbet,
Shuah Khan, linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org, linux-doc@vger.kernel.org
In-Reply-To: <4ec081f8df234cc584702abc67213965@compal.com>
> We will also remove all unnecessary devm_kfree() calls from probe
> error paths and remove paths, keeping them only where resources
> are freed and re-allocated at runtime (e.g., CLDMA queue lifecycle
> during modem reset cycles).
There is no point using devm_ if you are going to manually manage
their release. Anything which has a shorter lifetime than the device
should use kzalloc()/kfree().
Andrew
^ permalink raw reply
* Re: [PATCH v2 16/19] ARM: mark footbridge as deprecated
From: Ralph Siemsen @ 2026-07-02 13:08 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-arm-kernel, soc, linux-kernel, Arnd Bergmann, Aaro Koskinen,
Alexander Sverdlin, Alexandre Belloni, Alexandre Torgue,
Andrew Lunn, Ard Biesheuvel, Claudiu Beznea, Daniel Mack,
Ethan Nelson-Moore, Frank Li, Gregory Clement, Haojian Zhuang,
Jeremy J. Peper, Kristoffer Ericson, Krzysztof Kozlowski,
Linus Walleij, Mark Brown, Marc Zyngier, Mike Rapoport,
Nicolas Ferre, Patrice Chotard, Ralph Siemsen, Robert Jarzmik,
Russell King, Sascha Hauer, Sebastian Hesselbarth, Stefan Agner,
Stefan Wiehler, Tony Lindgren, Vladimir Zapolskiy, Will Deacon,
Linus Walleij
In-Reply-To: <20260701212353.2196041-17-arnd@kernel.org>
On Wed, Jul 01, 2026 at 11:23:50PM +0200, Arnd Bergmann wrote:
>
>Along with RiscPC and SA1100, these are the last remaining Intel StrongARM
>machines. The Corel NetWinder used to be particular popular in the late
>1990s, but was discontinued during the bankruptcy of rebel.com in 2001.
>The other machine is the DEC (later Intel) EBSA285 evaluation board that
>was made in small numbers in 1997 for software developers.
>
>The footbridge/netwinder platform was the main target for the first Debian
>2.0 "Hamm" release on the Arm architecture back in 1998, but was dropped
>in Debian 6.0 "Squeeze" in 2011, which only supported ARMv4T and higher
>with the EABI based ports as ARMv4 hardware had fallen already out of
>use by that time.
>
>Link: http://netwinder.org/
>Cc: Linus Walleij <linus.walleij@linaro.org>
>Cc: Russell King <linux@armlinux.org.uk>
>Cc: Ralph Siemsen <ralph.siemsen@linaro.org>
>Acked-by: Linus Walleij <linus.walleij@linaro.org>
>Acked-by: Marc Zyngier <maz@kernel.org>
>Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>---
> arch/arm/mach-footbridge/Kconfig | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
>diff --git a/arch/arm/mach-footbridge/Kconfig b/arch/arm/mach-footbridge/Kconfig
>index 78189997caa1..96a74d447028 100644
>--- a/arch/arm/mach-footbridge/Kconfig
>+++ b/arch/arm/mach-footbridge/Kconfig
>@@ -1,6 +1,6 @@
> # SPDX-License-Identifier: GPL-2.0-only
> menuconfig ARCH_FOOTBRIDGE
>- bool "FootBridge Implementations"
>+ bool "FootBridge Implementations (DEPRECATED)"
> depends on ARCH_MULTI_V4 && !(ARCH_MULTI_V4T || ARCH_MULTI_V5)
> depends on !(ARCH_MOXART || ARCH_GEMINI || ARCH_SA1100)
> depends on ATAGS
>@@ -12,7 +12,10 @@ menuconfig ARCH_FOOTBRIDGE
> select NEED_MACH_MEMORY_H
> help
> Support for systems based on the DC21285 companion chip
>- ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
>+ ("FootBridge"), used in the EBSA285 and the Rebel NetWinder.
>+
>+ Support for these machines will go away in 2027,
>+ unless there are any remaining users that speak up.
>
> if ARCH_FOOTBRIDGE
>
Speaking for NetWinder, although it is sad to let it go, the reality is
there have been no active users in years. This is based on the mailing
list being silent (other than spam). And the trickle of emails I used to
get about netwinder has also ended for many years. So with that:
Acked-by: Ralph Siemsen <ralphs@netwinder.org>
Regards,
Ralph
^ permalink raw reply
* Re: [PATCH v2 2/2] cache: add SMCCC-backed cache invalidate provider
From: Bence Csókás @ 2026-07-02 13:04 UTC (permalink / raw)
To: Srirangan Madhavan, Mark Rutland, Lorenzo Pieralisi, Sudeep Holla,
Conor Dooley, Jonathan Cameron
Cc: Catalin Marinas, Will Deacon, Dan Williams, Thierry Reding,
Jonathan Hunter, Souvik Chakravarty, linux-arm-kernel,
linux-kernel, linux-tegra
In-Reply-To: <20260608220709.1300245-3-smadhavan@nvidia.com>
Hi,
I'm reading the 1.7 H BET0 [1] version of the spec (released
2026-04-20), and I see some discrepancies. Not sure if I'm the one
reading it wrong, or if you had a different version than me.
[1] https://developer.arm.com/documentation/den0028/h/?lang=en
Either way, thanks for posting this patch, I'm also looking forward to
seeing it get merged!
On 2026. 06. 09. 0:07, Srirangan Madhavan wrote:
> Add a cache maintenance provider for the Arm SMCCC cache clean+invalidate
> interface.
>
> The provider discovers SMCCC support and attributes at init time,
> serializes firmware calls, handles transient BUSY and RATE_LIMITED
> responses with bounded retries, and registers with the generic cache
> coherency framework used by memregion callers.
>
> Signed-off-by: Srirangan Madhavan <smadhavan@nvidia.com>
> Reviewed-by: Jonathan Cameron <jic23@kernel.org>
> ---
> drivers/cache/Kconfig | 11 +++
> drivers/cache/Makefile | 2 +
> drivers/cache/arm_smccc_cache.c | 157 ++++++++++++++++++++++++++++++++
> 3 files changed, 170 insertions(+)
> create mode 100644 drivers/cache/arm_smccc_cache.c
>
> diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig
> index 1518449d47b5..57fd1823dec5 100644
> --- a/drivers/cache/Kconfig
> +++ b/drivers/cache/Kconfig
> @@ -42,6 +42,17 @@ menuconfig CACHEMAINT_FOR_HOTPLUG
>
> if CACHEMAINT_FOR_HOTPLUG
>
> +config ARM_SMCCC_CACHE
> + bool "Arm SMCCC cache maintenance provider"
> + depends on ARM64 && HAVE_ARM_SMCCC_DISCOVERY
> + help
> + Enable support for the Arm SMCCC cache clean+invalidate
> + interface as a provider for memory hotplug-like cache
> + maintenance operations.
> + The provider registers only when firmware advertises the
> + SMCCC calls and attributes, so systems without firmware support
> + continue without this registered provider.
> +
> config HISI_SOC_HHA
> tristate "HiSilicon Hydra Home Agent (HHA) device driver"
> depends on (ARM64 && ACPI) || COMPILE_TEST
> diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile
> index b3362b15d6c1..55736a032d6f 100644
> --- a/drivers/cache/Makefile
> +++ b/drivers/cache/Makefile
> @@ -4,4 +4,6 @@ obj-$(CONFIG_AX45MP_L2_CACHE) += ax45mp_cache.o
> obj-$(CONFIG_SIFIVE_CCACHE) += sifive_ccache.o
> obj-$(CONFIG_STARFIVE_STARLINK_CACHE) += starfive_starlink_cache.o
>
> +# Providers below depend on CACHEMAINT_FOR_HOTPLUG.
> +obj-$(CONFIG_ARM_SMCCC_CACHE) += arm_smccc_cache.o
> obj-$(CONFIG_HISI_SOC_HHA) += hisi_soc_hha.o
> diff --git a/drivers/cache/arm_smccc_cache.c b/drivers/cache/arm_smccc_cache.c
> new file mode 100644
> index 000000000000..82b9efdb190b
> --- /dev/null
> +++ b/drivers/cache/arm_smccc_cache.c
> @@ -0,0 +1,157 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2026 NVIDIA Corporation
> + *
> + * Arm SMCCC cache maintenance provider using cache clean+invalidate calls.
> + */
> +
> +#include <linux/arm-smccc.h>
> +#include <linux/cache_coherency.h>
> +#include <linux/cleanup.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/mutex.h>
> +#include <linux/nmi.h>
> +
> +#define SMCCC_CACHE_MAX_RETRIES 5
Indentation seems off here.
> +#define SMCCC_CACHE_DEFAULT_DELAY_US 1000UL
> +#define SMCCC_CACHE_MAX_DELAY_US 20000UL
> +
> +struct smccc_cache {
> + /* Must be first member */
> + struct cache_coherency_ops_inst cci;
> + struct mutex lock; /* Serializes SMCCC cache maintenance calls. */
> + u32 latency_us;
> + u32 rate_limit;
> +};
> +
> +static int smccc_cache_status_to_errno(s32 status)
I could see this being useful in the common smccc.c, not just here.
> +{
> + switch (status) {
> + case SMCCC_RET_SUCCESS:
> + return 0;
> + case SMCCC_RET_NOT_SUPPORTED:
> + return -EOPNOTSUPP;
> + case SMCCC_RET_INVALID_PARAMETER:
> + return -EINVAL;
> + case SMCCC_RET_RATE_LIMITED:
> + return -EAGAIN;
> + case SMCCC_RET_BUSY:
> + return -EBUSY;
> + default:
> + return -EIO;
> + }
> +}
> +
> +static unsigned long smccc_cache_delay_us(const struct smccc_cache *cache)
> +{
> + unsigned long delay_us = 0;
> +
> + if (cache->rate_limit)
> + delay_us = DIV_ROUND_UP_ULL(USEC_PER_SEC, cache->rate_limit);
> +
> + if (cache->latency_us)
> + delay_us = max(delay_us, (unsigned long)cache->latency_us);
> +
> + /*
> + * Firmware may advertise neither a rate limit nor a latency hint; use
> + * a small bounded backoff instead of retrying in a tight loop.
> + */
> + if (!delay_us)
> + delay_us = SMCCC_CACHE_DEFAULT_DELAY_US;
> +
> + return min(delay_us, SMCCC_CACHE_MAX_DELAY_US);
> +}
> +
> +static int smccc_cache_wbinv(struct cache_coherency_ops_inst *cci,
> + struct cc_inval_params *invp)
> +{
> + struct smccc_cache *cache = container_of(cci, struct smccc_cache, cci);
> + struct arm_smccc_res res = {};
I would move this down one, for aesthetics (reverse fir tree).
> + unsigned long delay_us = smccc_cache_delay_us(cache);
> + int ret;
> +
> + if (!invp->size)
> + return -EINVAL;
> +
> + /*
> + * Serialize the full retry sequence. With the default bounds, a caller
> + * may hold the mutex across up to five 20ms backoff sleeps.
> + */
> + guard(mutex)(&cache->lock);
> +
> + for (unsigned int i = 0; i < SMCCC_CACHE_MAX_RETRIES; i++) {
> + /* Long firmware operations can trigger watchdog checks. */
> + touch_nmi_watchdog();
> +
> + arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_CLEAN_INV_MEMREGION,
> + invp->addr, invp->size, 0UL, &res);
> +
> + ret = smccc_cache_status_to_errno((s32)res.a0);
> + if (!ret)
> + return 0;
> +
> + if (ret != -EBUSY && ret != -EAGAIN)
> + return ret;
> +
> + fsleep(delay_us);
> + }
> +
> + return -EBUSY;
Minor: I would do `return ret;` so that we get the last error message,
which could be either EBUSY or EAGAIN (depending on if FW responded BUSY
or RATE_LIMITED).
> +}
> +
> +static const struct cache_coherency_ops smccc_cache_ops = {
> + .wbinv = smccc_cache_wbinv,
> +};
> +
> +static int __init smccc_cache_init(void)
> +{
> + struct smccc_cache *cache;
Again, I would move this line down one.
> + struct arm_smccc_res res = {};
> + int ret;
> +
> + if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_1)
> + return -ENODEV;
> +
> + if (arm_smccc_1_1_get_conduit() == SMCCC_CONDUIT_NONE)
> + return -ENODEV;
> +
> + arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
> + ARM_SMCCC_ARCH_CLEAN_INV_MEMREGION, &res);
> + if ((s32)res.a0 < 0)
> + return -ENODEV;
> +
> + arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
> + ARM_SMCCC_ARCH_CLEAN_INV_MEMREGION_ATTRIBUTES,
> + &res);
> + if ((s32)res.a0 < 0)
> + return -ENODEV;
7.11.2 states (top of page 47):
This function must be implemented if SMCCC_ARCH_CLEAN_INV_MEMREGION
is implemented.
Therefore, this check can be dropped, just checking for INV_MEMREGION's
existence should be enough.
> + arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_CLEAN_INV_MEMREGION_ATTRIBUTES,
> + &res);
> + if ((s32)res.a0)
> + return -ENODEV;
> +
> + cache = cache_coherency_ops_instance_alloc(&smccc_cache_ops,
> + struct smccc_cache, cci);
> + if (!cache)
> + return -ENOMEM;
> +
> + mutex_init(&cache->lock);
> + cache->latency_us = lower_32_bits(res.a2);
> + cache->rate_limit = lower_32_bits(res.a3);
The spec only says to truncate X2 to 32 bits, not X3 (chapter 7.11, page
46).
> + ret = cache_coherency_ops_instance_register(&cache->cci);
> + if (ret) {
> + mutex_destroy(&cache->lock);
> + cache_coherency_ops_instance_put(&cache->cci);
> + return ret;
> + }
> +
> + pr_info("SMCCC cache clean+invalidate provider registered\n");
Is this log line useful for _production_ environments?
> + return 0;
> +}
> +arch_initcall(smccc_cache_init);
Bence
^ permalink raw reply
* Re: [PATCH v2] ACPI: APEI: Handle repeated SEA error storms
From: Rafael J. Wysocki (Intel) @ 2026-07-02 13:01 UTC (permalink / raw)
To: hejunhao
Cc: rafael, tony.luck, guohanjun, mchehab, xueshuai, jarkko,
yazen.ghannam, jane.chu, lenb, linmiaohe, bp, linux-acpi,
linux-arm-kernel, linux-kernel, linux-edac, tanxiaofei,
liuyonglong, mawupeng1
In-Reply-To: <6ebea989-81c7-6237-1a31-8d6975796680@h-partners.com>
On Thu, Jul 2, 2026 at 2:50 PM hejunhao <hejunhao3@h-partners.com> wrote:
>
> Gentle ping for this one, and it's ready.
So it requires at least one ACK from a person listed as APEI reviewers
in MAINTAINERS.
> On 2026/5/27 16:27, Junhao He wrote:
> > When hardware memory corruption occurs and a user process accesses the
> > corrupted page, the CPU triggers a Synchronous External Abort (SEA).
> > The kernel invokes do_sea() to handle the exception, which calls
> > memory_failure() to handle the faulty page.
> >
> > Scenario 1: Memory Error Interrupt First, then SEA
> > The page is already poisoned by the memory error interrupt path. The
> > subsequent SEA handler sends a SIGBUS to the task, which accesses the
> > poisoned page. This flow is correct.
> >
> > Scenario 2: SEA first, then memory error interrupt (problematic scenario)
> > If a user task directly accesses corrupted memory through a PFNMAP-style
> > mapping (e.g., devmem), the page may still be in the free-buddy state when
> > SEA is handled. In this case, memory_failure() will poison the page without
> > invoking kill_accessing_process(), and then takes the free-buddy recovery
> > path.
> >
> > After the CPU returns to the task context, the task re-enters the SEA
> > handler due to the same access. However, ghes_estatus_cached() suppresses
> > all subsequent entries during the 10-second window, preventing
> > ghes_do_proc() from being called. This suppression blocks the
> > MF_ACTION_REQUIRED-based SIGBUS delivery, causing the kernel to fail to
> > kill the task immediately. Consequently, the process keeps re-entering
> > the SEA handler, leading to an SEA storm. Later, the memory error
> > interrupt path also cannot kill the task, leaving the system stuck in
> > this repeated loop.
> >
> > The following error logs are explained using the devmem process:
> > NOTICE: SEA Handle
> > [Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 9
> > [Hardware Error]: event severity: recoverable
> > [Hardware Error]: section_type: ARM processor error
> > [Hardware Error]: physical fault address: 0x0000001000093c00
> > [T54990] Memory failure: 0x1000093: recovery action for free buddy page: Recovered
> > [ T9955] EDAC MC0: 1 UE Multi-bit ECC on unknown memory
> > (page:0x1000093 offset:0xc00 grain:1 - APEI location: ...)
> > NOTICE: SEA Handle
> > NOTICE: SEA Handle
> > ...
> > ... ---> SEA storm
> > ...
> > NOTICE: SEA Handle
> > [ T9955] Memory failure: 0x1000093: already hardware poisoned
> > ghes_print_estatus: 1 callbacks suppressed
> > [Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 9
> > [Hardware Error]: event severity: recoverable
> > [Hardware Error]: section_type: ARM processor error
> > [Hardware Error]: physical fault address: 0x0000001000093c00
> > [T54990] Memory failure: 0x1000093: already hardware poisoned
> > [T54990] 0x1000093: Sending SIGBUS to devmem:54990 due to hardware memory corruption
> >
> > To resolve this, return an error when encountering the same SEA again.
> > The subsequent SEA handler invocation uses arm64_notify_die() to send a
> > SIGBUS signal to the task, which terminates the process and prevents it
> > from re-entering the handler loop.
> >
> > Signed-off-by: Junhao He <hejunhao3@h-partners.com>
> > ---
> > drivers/acpi/apei/ghes.c | 10 +++++++++-
> > 1 file changed, 9 insertions(+), 1 deletion(-)
> >
> > Changes in V2:
> > 1. update the commit message per suggestion from Xueshuai
> > 2. Add a check to only return failure on the ghes_notify_sea() path,
> > avoiding impact on other NMI-type GHES handlers.
> > Link to V1 - https://lore.kernel.org/all/20251030071321.2763224-1-hejunhao3@h-partners.com/
> >
> > diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
> > index 3236a3ce79d6..787664740150 100644
> > --- a/drivers/acpi/apei/ghes.c
> > +++ b/drivers/acpi/apei/ghes.c
> > @@ -1383,8 +1383,16 @@ static int ghes_in_nmi_queue_one_entry(struct ghes *ghes,
> > ghes_clear_estatus(ghes, &tmp_header, buf_paddr, fixmap_idx);
> >
> > /* This error has been reported before, don't process it again. */
> > - if (ghes_estatus_cached(estatus))
> > + if (ghes_estatus_cached(estatus)) {
> > + /*
> > + * Return failure on duplicate SEA entries so that the
> > + * subsequent SEA handler invocation sends a SIGBUS signal to
> > + * the task to prevent it from re-entering the handler loop.
> > + */
> > + if (is_hest_sync_notify(ghes))
> > + rc = -ECANCELED;
> > goto no_work;
> > + }
> >
> > llist_add(&estatus_node->llnode, &ghes_estatus_llist);
> >
>
^ permalink raw reply
* Re: [RESEND PATCH v2 5/5] drm/tidss: Fix sampling edge configuration
From: Leonardo Costa @ 2026-07-02 12:59 UTC (permalink / raw)
To: s-jain1
Cc: airlied, aradhya.bhatia, conor+dt, devarsht, devicetree,
dri-devel, h-shenoy, jyri.sarha, kristo, krzk+dt, lee,
linux-arm-kernel, linux-kernel, louis.chauvet, maarten.lankhorst,
mripard, nm, praneeth, robh, simona, tomi.valkeinen, tzimmermann,
vigneshr, leonardo.costa
In-Reply-To: <20251106141227.899054-6-s-jain1@ti.com>
Hello,
We tested this patch and it introduces a regression on our panel.
On our board, a Toshiba TC358768 DPI-to-DSI bridge is connected to the parallel
RGB output. The bridge requires data to be driven on the negative edge, and
this is also reflected by the `ipc` variable in `dispc_vp_enable()`, which is
set to `1`.
With this patch applied, however, data is driven on the positive edge instead.
According to SPRUIV7C, both `MAIN_CTRL_MMR_CFG0_DPI0_CLK_CTRL[8]` and
`DSS_VP1_POL_FREQ[14] IPC` should be programmed consistently. However, if we
follow the actual bit descriptions, and ignore the sentence saying that the two
programmed values should be the same, the data is driven on the requested edge.
From SPRUIV7C (https://www.ti.com/lit/ug/spruiv7b/spruiv7c.pdf):
MAIN_CTRL_MMR_CFG0_DPI0_CLK_CTRL[8] (DPI0_CLK_CTRL_DATA_CLK_INVDIS):
Clock edge select for DPI0 data outputs
Note that this value should be the same as the programmed value of
DSS_POL_FREQ[14] IPC.
Reset Source: mod_por_rst_n
0 DATA and DE are driven on the falling edge of clk
1 DATA and DE are driven on the rising edge of clk
DSS_VP1_POL_FREQ[14] (IPC)
Invert pixel clock
To set data to pixel clock relationship, CTRL_MMR_DPI0_CLK_CTRL[8]
DPI0_CLK_CTRL_DATA_CLK_INVDIS setting should be the same as the [14]
IPC setting.
0 Data is driven on the LCD data lines on the rising-edge of the pixel clock
1 Data is driven on the LCD data lines on the falling-edge of the pixel clock
So, the proposed fix to this patch is:
```diff
- regmap_update_bits(dispc->clk_ctrl, 0, 0x100, ipc ? 0x100 : 0x000);
+ regmap_update_bits(dispc->clk_ctrl, 0, 0x100, ipc ? 0x000 : 0x100);
```
Reverting the patch also makes the Toshiba bridge work correctly again.
However, we can confirm that the patch is needed, otherwise only the
positive-edge case (our case) works correctly.
In other words, the two registers need to match semantically, not numerically.
Please ignore the previous email I sent:
https://lore.kernel.org/all/20260702104817.1219078-1-leoreis.costa@gmail.com/
I hadn't seen this more recent thread at the time.
^ permalink raw reply
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