* [PATCH v7 0/6] can: flexcan: Add NXP S32N79 SoC support
@ 2026-08-31 14:34 Ciprian Costea
2026-08-31 14:34 ` [PATCH v7 1/6] can: flexcan: use dedicated IRQ handlers for multi-IRQ platforms Ciprian Costea
` (5 more replies)
0 siblings, 6 replies; 14+ messages in thread
From: Ciprian Costea @ 2026-08-31 14:34 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Angelo Dureghello, Frank Li
Cc: linux-can, devicetree, linux-kernel, NXP S32 Linux Team, imx,
Christophe Lizzi, Alberto Ruiz, Enric Balletbo, Eric Chanudet,
Ciprian Marian Costea
From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
This patch series adds FlexCAN support for the NXP S32N79 SoC.
The S32N79 is an automotive-grade processor from NXP with multiple
FlexCAN instances. The FlexCAN IP integration on S32N79 differs from
other SoCs in the interrupt routing - it uses two separate interrupt
lines:
- one interrupt for mailboxes 0-127
- one interrupt for bus error detection and device state changes
The CAN controllers are connected through an irqsteer interrupt
controller in the RCU (Resource Control Unit) domain.
This series:
1. Splits flexcan_irq() into dedicated handlers for multi-IRQ platforms
2. Adds dt-bindings documentation for S32N79 FlexCAN
3. Introduces FLEXCAN_QUIRK_IRQ_BERR to handle the two-interrupt
configuration
4. Adds S32N79 device data and compatible string to the driver
5. Adds FlexCAN device tree nodes for S32N79 SoC
6. Enables FlexCAN devices on the S32N79-RDB board
Tested on S32N79-RDB board with CAN and CAN FD communication.
v7 -> v6
- Fixed an issue reported by 'sashiko-bot'regarding the
'FLEXCAN_QUIRK_BROKEN_PERR_STATE' quirk, caused by irq handlers refactor
in this patchset
v6 -> v5
- Addressed a couple of cosmetic issues on patches 3 and 5 .
- Removed dts related changes as they should be sent on different review
list
v5 -> v4
- Simplified splitting rx/tx masks per mailbox IRQ line
v4 -> v3
- flexcan_chip_interrupts_enable(): disable/enable all IRQ lines
(not just dev->irq) during IMASK register writes
- Split rx/tx masks per mailbox IRQ line (struct flexcan_mb_irq) so
each handler on S32G2 only processes its own MB range
- Added received Acked-by tag on DT bindings patch
v3 -> v2
- Split flexcan_irq() into dedicated handlers (flexcan_irq_mb,
flexcan_irq_boff, flexcan_irq_berr) to fix duplicate event
processing when multiple IRQ lines run concurrently (new patch).
- Added flexcan_irq_esr() handler composing state + berr for S32N79
- Ordered quirks used by s32n devtype data by value.
v2 -> v1
- Renamed FLEXCAN_QUIRK_NR_IRQ_2 to FLEXCAN_QUIRK_IRQ_BERR to better
describe the actual hardware feature
- Appended new quirk at the end
- Switched from platform_get_irq to platform_get_irq_byname usage
- Updated interrupt description in dt-bindings
Ciprian Marian Costea (6):
can: flexcan: use dedicated IRQ handlers for multi-IRQ platforms
can: flexcan: disable all IRQ lines in
flexcan_chip_interrupts_enable()
can: flexcan: split rx/tx masks per mailbox IRQ line
dt-bindings: can: fsl,flexcan: add NXP S32N79 SoC support
can: flexcan: add FLEXCAN_QUIRK_IRQ_BERR quirk
can: flexcan: add NXP S32N79 SoC support
.../bindings/net/can/fsl,flexcan.yaml | 30 ++-
drivers/net/can/flexcan/flexcan-core.c | 229 +++++++++++++++---
drivers/net/can/flexcan/flexcan.h | 2 +
3 files changed, 232 insertions(+), 29 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v7 1/6] can: flexcan: use dedicated IRQ handlers for multi-IRQ platforms
2026-08-31 14:34 [PATCH v7 0/6] can: flexcan: Add NXP S32N79 SoC support Ciprian Costea
@ 2026-08-31 14:34 ` Ciprian Costea
2026-08-31 18:01 ` sashiko-bot
2026-08-31 14:34 ` [PATCH v7 2/6] can: flexcan: disable all IRQ lines in flexcan_chip_interrupts_enable() Ciprian Costea
` (4 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Ciprian Costea @ 2026-08-31 14:34 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Angelo Dureghello, Frank Li
Cc: linux-can, devicetree, linux-kernel, NXP S32 Linux Team, imx,
Christophe Lizzi, Alberto Ruiz, Enric Balletbo, Eric Chanudet,
Ciprian Marian Costea, Haibo Chen
From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
On platforms with multiple IRQ lines (S32G2, MCF5441X), all lines are
registered to the same flexcan_irq() handler. Since these are distinct IRQ
numbers, they can be dispatched concurrently on different CPUs. Both
instances then read the same iflag and ESR registers unconditionally,
leading to duplicate frame processing.
Fix this by splitting the monolithic handler into focused parts:
- flexcan_do_mb(): processes mailbox events
- flexcan_do_state(): processes device state change events
- flexcan_do_berr(): processes bus error events
Introduce dedicated IRQ handlers for multi-IRQ platforms:
- flexcan_irq_mb(): mailbox-only, used for mb-0, mb-1 IRQ lines
- flexcan_irq_boff(): state-change-only, used for boff/state IRQ line
- flexcan_irq_berr(): bus-error-only, used for berr IRQ line
The FLEXCAN_QUIRK_BROKEN_PERR_STATE workaround re-enables the error
interrupt (FLEXCAN_CTRL_ERR_MSK) while the controller is in the
error-warning window so that state transitions keep being reported.
The combined flexcan_irq() handler is preserved for single-IRQ
platforms with no functional change.
Fixes: d9cead75b1c6 ("can: flexcan: add mcf5441x support")
Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
Reviewed-by: Vincent Mailhol <mailhol@kernel.org>
Reviewed-and-tested-by: Haibo Chen <haibo.chen@nxp.com>
Tested-by: Enric Balletbo i Serra <eballetb@redhat.com>
---
drivers/net/can/flexcan/flexcan-core.c | 131 +++++++++++++++++++++----
1 file changed, 114 insertions(+), 17 deletions(-)
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index f5d22c61503f..2e9df2d14b34 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -1070,16 +1070,14 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
return skb;
}
-static irqreturn_t flexcan_irq(int irq, void *dev_id)
+/* Process mailbox (RX + TX) events */
+static irqreturn_t flexcan_do_mb(struct net_device *dev)
{
- struct net_device *dev = dev_id;
struct net_device_stats *stats = &dev->stats;
struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->regs;
irqreturn_t handled = IRQ_NONE;
u64 reg_iflag_tx;
- u32 reg_esr;
- enum can_state last_state = priv->can.state;
/* reception interrupt */
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX) {
@@ -1131,25 +1129,57 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
netif_wake_queue(dev);
}
+ return handled;
+}
+
+/* Process bus error events */
+static irqreturn_t flexcan_do_berr(struct net_device *dev)
+{
+ struct flexcan_priv *priv = netdev_priv(dev);
+ struct flexcan_regs __iomem *regs = priv->regs;
+ irqreturn_t handled = IRQ_NONE;
+ u32 reg_esr;
+
reg_esr = priv->read(®s->esr);
- /* ACK all bus error, state change and wake IRQ sources */
- if (reg_esr & (FLEXCAN_ESR_ALL_INT | FLEXCAN_ESR_WAK_INT)) {
+ /* ACK bus error interrupt source */
+ if (reg_esr & FLEXCAN_ESR_ERR_INT) {
handled = IRQ_HANDLED;
- priv->write(reg_esr & (FLEXCAN_ESR_ALL_INT | FLEXCAN_ESR_WAK_INT), ®s->esr);
+ priv->write(FLEXCAN_ESR_ERR_INT, ®s->esr);
}
- /* state change interrupt or broken error state quirk fix is enabled */
- if ((reg_esr & FLEXCAN_ESR_ERR_STATE) ||
- (priv->devtype_data.quirks & (FLEXCAN_QUIRK_BROKEN_WERR_STATE |
- FLEXCAN_QUIRK_BROKEN_PERR_STATE)))
- flexcan_irq_state(dev, reg_esr);
-
/* bus error IRQ - handle if bus error reporting is activated */
if ((reg_esr & FLEXCAN_ESR_ERR_BUS) &&
(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
flexcan_irq_bus_err(dev, reg_esr);
+ return handled;
+}
+
+/* Process device state change events */
+static irqreturn_t flexcan_do_state(struct net_device *dev)
+{
+ struct flexcan_priv *priv = netdev_priv(dev);
+ struct flexcan_regs __iomem *regs = priv->regs;
+ irqreturn_t handled = IRQ_NONE;
+ u32 reg_esr;
+ enum can_state last_state = priv->can.state;
+
+ reg_esr = priv->read(®s->esr);
+
+ /* ACK state change and wake IRQ sources */
+ if (reg_esr & (FLEXCAN_ESR_ERR_STATE | FLEXCAN_ESR_WAK_INT)) {
+ handled = IRQ_HANDLED;
+ priv->write(reg_esr & (FLEXCAN_ESR_ERR_STATE | FLEXCAN_ESR_WAK_INT),
+ ®s->esr);
+ }
+
+ /* state change interrupt or broken error state quirk fix is enabled */
+ if ((reg_esr & FLEXCAN_ESR_ERR_STATE) ||
+ (priv->devtype_data.quirks &
+ (FLEXCAN_QUIRK_BROKEN_WERR_STATE | FLEXCAN_QUIRK_BROKEN_PERR_STATE)))
+ flexcan_irq_state(dev, reg_esr);
+
/* availability of error interrupt among state transitions in case
* bus error reporting is de-activated and
* FLEXCAN_QUIRK_BROKEN_PERR_STATE is enabled:
@@ -1188,6 +1218,68 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
}
}
+ return handled;
+}
+
+/* Combined IRQ handler for single-IRQ platforms */
+static irqreturn_t flexcan_irq(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct flexcan_priv *priv = netdev_priv(dev);
+ irqreturn_t handled;
+
+ handled = flexcan_do_mb(dev);
+ handled |= flexcan_do_state(dev);
+ handled |= flexcan_do_berr(dev);
+
+ if (handled)
+ can_rx_offload_irq_finish(&priv->offload);
+
+ return handled;
+}
+
+/* Mailbox IRQ handler for multi-IRQ platforms */
+static irqreturn_t flexcan_irq_mb(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct flexcan_priv *priv = netdev_priv(dev);
+ irqreturn_t handled;
+
+ handled = flexcan_do_mb(dev);
+
+ if (handled)
+ can_rx_offload_irq_finish(&priv->offload);
+
+ return handled;
+}
+
+/* Bus error IRQ handler for multi-IRQ platforms */
+static irqreturn_t flexcan_irq_berr(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct flexcan_priv *priv = netdev_priv(dev);
+ irqreturn_t handled;
+
+ handled = flexcan_do_berr(dev);
+
+ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_BROKEN_PERR_STATE)
+ handled |= flexcan_do_state(dev);
+
+ if (handled)
+ can_rx_offload_irq_finish(&priv->offload);
+
+ return handled;
+}
+
+/* Device state change IRQ handler for multi-IRQ platforms */
+static irqreturn_t flexcan_irq_boff(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct flexcan_priv *priv = netdev_priv(dev);
+ irqreturn_t handled;
+
+ handled = flexcan_do_state(dev);
+
if (handled)
can_rx_offload_irq_finish(&priv->offload);
@@ -1761,25 +1853,30 @@ static int flexcan_open(struct net_device *dev)
can_rx_offload_enable(&priv->offload);
- err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
+ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3)
+ err = request_irq(dev->irq, flexcan_irq_mb,
+ IRQF_SHARED, dev->name, dev);
+ else
+ err = request_irq(dev->irq, flexcan_irq,
+ IRQF_SHARED, dev->name, dev);
if (err)
goto out_can_rx_offload_disable;
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
err = request_irq(priv->irq_boff,
- flexcan_irq, IRQF_SHARED, dev->name, dev);
+ flexcan_irq_boff, IRQF_SHARED, dev->name, dev);
if (err)
goto out_free_irq;
err = request_irq(priv->irq_err,
- flexcan_irq, IRQF_SHARED, dev->name, dev);
+ flexcan_irq_berr, IRQF_SHARED, dev->name, dev);
if (err)
goto out_free_irq_boff;
}
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ) {
err = request_irq(priv->irq_secondary_mb,
- flexcan_irq, IRQF_SHARED, dev->name, dev);
+ flexcan_irq_mb, IRQF_SHARED, dev->name, dev);
if (err)
goto out_free_irq_err;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v7 2/6] can: flexcan: disable all IRQ lines in flexcan_chip_interrupts_enable()
2026-08-31 14:34 [PATCH v7 0/6] can: flexcan: Add NXP S32N79 SoC support Ciprian Costea
2026-08-31 14:34 ` [PATCH v7 1/6] can: flexcan: use dedicated IRQ handlers for multi-IRQ platforms Ciprian Costea
@ 2026-08-31 14:34 ` Ciprian Costea
2026-08-31 18:15 ` sashiko-bot
2026-08-31 14:34 ` [PATCH v7 3/6] can: flexcan: split rx/tx masks per mailbox IRQ line Ciprian Costea
` (3 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Ciprian Costea @ 2026-08-31 14:34 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Angelo Dureghello, Frank Li
Cc: linux-can, devicetree, linux-kernel, NXP S32 Linux Team, imx,
Christophe Lizzi, Alberto Ruiz, Enric Balletbo, Eric Chanudet,
Ciprian Marian Costea, Haibo Chen
From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
flexcan_chip_interrupts_enable() disables only the primary IRQ line while
writing to the IMASK and CTRL registers.
On multi-IRQ platforms (S32G2, MCF5441X), the additional IRQ lines (boff,
err, secondary-mb) remain active so their handlers can fire while
registers are inconsistent.
Disable all registered IRQ lines around the IMASK/CTRL writes. This
also fixes the resume path, which calls this function.
Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
Reviewed-by: Vincent Mailhol <mailhol@kernel.org>
Reviewed-and-tested-by: Haibo Chen <haibo.chen@nxp.com>
Tested-by: Enric Balletbo i Serra <eballetb@redhat.com>
---
drivers/net/can/flexcan/flexcan-core.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index 2e9df2d14b34..4eda54d2169e 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -1522,14 +1522,28 @@ static void flexcan_chip_interrupts_enable(const struct net_device *dev)
{
const struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->regs;
+ u32 quirks = priv->devtype_data.quirks;
u64 reg_imask;
disable_irq(dev->irq);
+ if (quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
+ disable_irq(priv->irq_boff);
+ disable_irq(priv->irq_err);
+ }
+ if (quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ)
+ disable_irq(priv->irq_secondary_mb);
+
priv->write(priv->reg_ctrl_default, ®s->ctrl);
reg_imask = priv->rx_mask | priv->tx_mask;
priv->write(upper_32_bits(reg_imask), ®s->imask2);
priv->write(lower_32_bits(reg_imask), ®s->imask1);
enable_irq(dev->irq);
+ if (quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ)
+ enable_irq(priv->irq_secondary_mb);
+ if (quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
+ enable_irq(priv->irq_boff);
+ enable_irq(priv->irq_err);
+ }
}
static void flexcan_chip_interrupts_disable(const struct net_device *dev)
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v7 3/6] can: flexcan: split rx/tx masks per mailbox IRQ line
2026-08-31 14:34 [PATCH v7 0/6] can: flexcan: Add NXP S32N79 SoC support Ciprian Costea
2026-08-31 14:34 ` [PATCH v7 1/6] can: flexcan: use dedicated IRQ handlers for multi-IRQ platforms Ciprian Costea
2026-08-31 14:34 ` [PATCH v7 2/6] can: flexcan: disable all IRQ lines in flexcan_chip_interrupts_enable() Ciprian Costea
@ 2026-08-31 14:34 ` Ciprian Costea
2026-08-31 18:27 ` sashiko-bot
2026-08-31 14:34 ` [PATCH v7 4/6] dt-bindings: can: fsl,flexcan: add NXP S32N79 SoC support Ciprian Costea
` (2 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Ciprian Costea @ 2026-08-31 14:34 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Angelo Dureghello, Frank Li
Cc: linux-can, devicetree, linux-kernel, NXP S32 Linux Team, imx,
Christophe Lizzi, Alberto Ruiz, Enric Balletbo, Eric Chanudet,
Ciprian Marian Costea, Haibo Chen
From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
On S32G2, which has two mailbox IRQ lines (mb-0 for MBs 0-7, mb-1
for MBs 8-63), both handlers currently process the full rx_mask/tx_mask
range.
Introduce FLEXCAN_SECONDARY_MB_IRQ_MB0_MASK and
FLEXCAN_SECONDARY_MB_IRQ_MB1_MASK to describe the split, and pass
the selected mask to flexcan_do_mb() via a new mb_mask parameter.
In flexcan_irq_mb(), the irq argument selects the correct mask: the
primary MB IRQ uses MB0_MASK and the secondary uses MB1_MASK.
For single-IRQ platforms, mb_mask is ~0ULL with no functional change.
Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
Reviewed-by: Vincent Mailhol <mailhol@kernel.org>
Reviewed-and-tested-by: Haibo Chen <haibo.chen@nxp.com>
Tested-by: Enric Balletbo i Serra <eballetb@redhat.com>
---
drivers/net/can/flexcan/flexcan-core.c | 39 ++++++++++++++++++--------
1 file changed, 28 insertions(+), 11 deletions(-)
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index 4eda54d2169e..f28ff0e95b74 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -182,6 +182,12 @@
#define FLEXCAN_IFLAG_RX_FIFO_WARN BIT(6)
#define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE BIT(5)
+/* On platforms with FLEXCAN_QUIRK_SECONDARY_MB_IRQ, the MB IRQ lines are
+ * split.
+ */
+#define FLEXCAN_SECONDARY_MB_IRQ_MB0_MASK GENMASK_U64(7, 0)
+#define FLEXCAN_SECONDARY_MB_IRQ_MB1_MASK GENMASK_U64(63, 8)
+
/* FLEXCAN message buffers */
#define FLEXCAN_MB_CODE_MASK (0xf << 24)
#define FLEXCAN_MB_CODE_RX_BUSY_BIT (0x1 << 24)
@@ -957,14 +963,16 @@ static inline void flexcan_write64(struct flexcan_priv *priv, u64 val, void __io
priv->write(lower_32_bits(val), addr);
}
-static inline u64 flexcan_read_reg_iflag_rx(struct flexcan_priv *priv)
+static inline u64 flexcan_read_reg_iflag_rx(struct flexcan_priv *priv,
+ u64 rx_mask)
{
- return flexcan_read64_mask(priv, &priv->regs->iflag1, priv->rx_mask);
+ return flexcan_read64_mask(priv, &priv->regs->iflag1, rx_mask);
}
-static inline u64 flexcan_read_reg_iflag_tx(struct flexcan_priv *priv)
+static inline u64 flexcan_read_reg_iflag_tx(struct flexcan_priv *priv,
+ u64 tx_mask)
{
- return flexcan_read64_mask(priv, &priv->regs->iflag1, priv->tx_mask);
+ return flexcan_read64_mask(priv, &priv->regs->iflag1, tx_mask);
}
static inline struct flexcan_priv *rx_offload_to_priv(struct can_rx_offload *offload)
@@ -1071,12 +1079,14 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
}
/* Process mailbox (RX + TX) events */
-static irqreturn_t flexcan_do_mb(struct net_device *dev)
+static irqreturn_t flexcan_do_mb(struct net_device *dev, u64 mb_mask)
{
struct net_device_stats *stats = &dev->stats;
struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->regs;
irqreturn_t handled = IRQ_NONE;
+ u64 rx_mask = priv->rx_mask & mb_mask;
+ u64 tx_mask = priv->tx_mask & mb_mask;
u64 reg_iflag_tx;
/* reception interrupt */
@@ -1084,7 +1094,8 @@ static irqreturn_t flexcan_do_mb(struct net_device *dev)
u64 reg_iflag_rx;
int ret;
- while ((reg_iflag_rx = flexcan_read_reg_iflag_rx(priv))) {
+ while ((reg_iflag_rx = flexcan_read_reg_iflag_rx(priv,
+ rx_mask))) {
handled = IRQ_HANDLED;
ret = can_rx_offload_irq_offload_timestamp(&priv->offload,
reg_iflag_rx);
@@ -1110,10 +1121,10 @@ static irqreturn_t flexcan_do_mb(struct net_device *dev)
}
}
- reg_iflag_tx = flexcan_read_reg_iflag_tx(priv);
+ reg_iflag_tx = flexcan_read_reg_iflag_tx(priv, tx_mask);
/* transmission complete interrupt */
- if (reg_iflag_tx & priv->tx_mask) {
+ if (reg_iflag_tx & tx_mask) {
u32 reg_ctrl = priv->read(&priv->tx_mb->can_ctrl);
handled = IRQ_HANDLED;
@@ -1125,7 +1136,7 @@ static irqreturn_t flexcan_do_mb(struct net_device *dev)
/* after sending a RTR frame MB is in RX mode */
priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
&priv->tx_mb->can_ctrl);
- flexcan_write64(priv, priv->tx_mask, ®s->iflag1);
+ flexcan_write64(priv, tx_mask, ®s->iflag1);
netif_wake_queue(dev);
}
@@ -1228,7 +1239,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
struct flexcan_priv *priv = netdev_priv(dev);
irqreturn_t handled;
- handled = flexcan_do_mb(dev);
+ handled = flexcan_do_mb(dev, ~0ULL);
handled |= flexcan_do_state(dev);
handled |= flexcan_do_berr(dev);
@@ -1244,8 +1255,14 @@ static irqreturn_t flexcan_irq_mb(int irq, void *dev_id)
struct net_device *dev = dev_id;
struct flexcan_priv *priv = netdev_priv(dev);
irqreturn_t handled;
+ u64 mb_mask = ~0ULL;
+
+ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ)
+ mb_mask = (irq == priv->irq_secondary_mb) ?
+ FLEXCAN_SECONDARY_MB_IRQ_MB1_MASK :
+ FLEXCAN_SECONDARY_MB_IRQ_MB0_MASK;
- handled = flexcan_do_mb(dev);
+ handled = flexcan_do_mb(dev, mb_mask);
if (handled)
can_rx_offload_irq_finish(&priv->offload);
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v7 4/6] dt-bindings: can: fsl,flexcan: add NXP S32N79 SoC support
2026-08-31 14:34 [PATCH v7 0/6] can: flexcan: Add NXP S32N79 SoC support Ciprian Costea
` (2 preceding siblings ...)
2026-08-31 14:34 ` [PATCH v7 3/6] can: flexcan: split rx/tx masks per mailbox IRQ line Ciprian Costea
@ 2026-08-31 14:34 ` Ciprian Costea
2026-08-31 18:37 ` sashiko-bot
2026-08-31 14:34 ` [PATCH v7 5/6] can: flexcan: add FLEXCAN_QUIRK_IRQ_BERR quirk Ciprian Costea
2026-08-31 14:34 ` [PATCH v7 6/6] can: flexcan: add NXP S32N79 SoC support Ciprian Costea
5 siblings, 1 reply; 14+ messages in thread
From: Ciprian Costea @ 2026-08-31 14:34 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Angelo Dureghello, Frank Li
Cc: linux-can, devicetree, linux-kernel, NXP S32 Linux Team, imx,
Christophe Lizzi, Alberto Ruiz, Enric Balletbo, Eric Chanudet,
Ciprian Marian Costea, Andra-Teodora Ilie, Larisa Grigore,
Conor Dooley, Haibo Chen
From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
Add NXP S32N79 SoC compatible string and interrupt properties.
On S32N79, FlexCAN IP is integrated with two interrupt lines:
one for the mailbox interrupts (0-127) and one for signaling
bus errors and device state changes.
Co-developed-by: Andra-Teodora Ilie <andra.ilie@nxp.com>
Signed-off-by: Andra-Teodora Ilie <andra.ilie@nxp.com>
Co-developed-by: Larisa Grigore <larisa.grigore@nxp.com>
Signed-off-by: Larisa Grigore <larisa.grigore@nxp.com>
Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-and-tested-by: Haibo Chen <haibo.chen@nxp.com>
---
.../bindings/net/can/fsl,flexcan.yaml | 30 ++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml b/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml
index f81d56f7c12a..d098a44c2b9c 100644
--- a/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml
+++ b/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml
@@ -26,6 +26,7 @@ properties:
- fsl,ls1021ar2-flexcan
- fsl,lx2160ar1-flexcan
- nxp,s32g2-flexcan
+ - nxp,s32n79-flexcan
- items:
- enum:
- fsl,imx53-flexcan
@@ -173,11 +174,38 @@ allOf:
- const: mb-1
required:
- interrupt-names
- else:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: nxp,s32n79-flexcan
+ then:
+ properties:
+ interrupts:
+ items:
+ - description: Message Buffer interrupt for mailboxes 0-127
+ - description: Bus Error and Device state change interrupt
+ interrupt-names:
+ items:
+ - const: mb-0
+ - const: berr
+ required:
+ - interrupt-names
+
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nxp,s32g2-flexcan
+ - nxp,s32n79-flexcan
+ then:
properties:
interrupts:
maxItems: 1
interrupt-names: false
+
- if:
required:
- xceiver-supply
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v7 5/6] can: flexcan: add FLEXCAN_QUIRK_IRQ_BERR quirk
2026-08-31 14:34 [PATCH v7 0/6] can: flexcan: Add NXP S32N79 SoC support Ciprian Costea
` (3 preceding siblings ...)
2026-08-31 14:34 ` [PATCH v7 4/6] dt-bindings: can: fsl,flexcan: add NXP S32N79 SoC support Ciprian Costea
@ 2026-08-31 14:34 ` Ciprian Costea
2026-08-31 18:51 ` sashiko-bot
2026-08-31 14:34 ` [PATCH v7 6/6] can: flexcan: add NXP S32N79 SoC support Ciprian Costea
5 siblings, 1 reply; 14+ messages in thread
From: Ciprian Costea @ 2026-08-31 14:34 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Angelo Dureghello, Frank Li
Cc: linux-can, devicetree, linux-kernel, NXP S32 Linux Team, imx,
Christophe Lizzi, Alberto Ruiz, Enric Balletbo, Eric Chanudet,
Ciprian Marian Costea, Larisa Grigore, Haibo Chen
From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
Introduce FLEXCAN_QUIRK_IRQ_BERR quirk to handle hardware integration
where the FlexCAN module has a dedicated interrupt line for signaling
bus errors and device state changes.
This adds the flexcan_irq_esr() handler which composes
flexcan_do_state() and flexcan_do_berr() to handle platforms where
these events share a single IRQ line.
Also extend flexcan_chip_interrupts_enable() to disable/enable the
new IRQ line during IMASK register writes.
This is required for NXP S32N79 SoC support.
Co-developed-by: Larisa Grigore <larisa.grigore@nxp.com>
Signed-off-by: Larisa Grigore <larisa.grigore@nxp.com>
Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
Reviewed-by: Vincent Mailhol <mailhol@kernel.org>
Reviewed-and-tested-by: Haibo Chen <haibo.chen@nxp.com>
Tested-by: Enric Balletbo i Serra <eballetb@redhat.com>
---
drivers/net/can/flexcan/flexcan-core.c | 53 +++++++++++++++++++++-----
drivers/net/can/flexcan/flexcan.h | 2 +
2 files changed, 46 insertions(+), 9 deletions(-)
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index f28ff0e95b74..601d88bfcfeb 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -1303,6 +1303,22 @@ static irqreturn_t flexcan_irq_boff(int irq, void *dev_id)
return handled;
}
+/* Combined bus error and state change IRQ handler */
+static irqreturn_t flexcan_irq_esr(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct flexcan_priv *priv = netdev_priv(dev);
+ irqreturn_t handled;
+
+ handled = flexcan_do_state(dev);
+ handled |= flexcan_do_berr(dev);
+
+ if (handled)
+ can_rx_offload_irq_finish(&priv->offload);
+
+ return handled;
+}
+
static void flexcan_set_bittiming_ctrl(const struct net_device *dev)
{
const struct flexcan_priv *priv = netdev_priv(dev);
@@ -1543,10 +1559,10 @@ static void flexcan_chip_interrupts_enable(const struct net_device *dev)
u64 reg_imask;
disable_irq(dev->irq);
- if (quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
+ if (quirks & FLEXCAN_QUIRK_NR_IRQ_3)
disable_irq(priv->irq_boff);
+ if (quirks & (FLEXCAN_QUIRK_NR_IRQ_3 | FLEXCAN_QUIRK_IRQ_BERR))
disable_irq(priv->irq_err);
- }
if (quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ)
disable_irq(priv->irq_secondary_mb);
@@ -1557,10 +1573,10 @@ static void flexcan_chip_interrupts_enable(const struct net_device *dev)
enable_irq(dev->irq);
if (quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ)
enable_irq(priv->irq_secondary_mb);
- if (quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
- enable_irq(priv->irq_boff);
+ if (quirks & (FLEXCAN_QUIRK_NR_IRQ_3 | FLEXCAN_QUIRK_IRQ_BERR))
enable_irq(priv->irq_err);
- }
+ if (quirks & FLEXCAN_QUIRK_NR_IRQ_3)
+ enable_irq(priv->irq_boff);
}
static void flexcan_chip_interrupts_disable(const struct net_device *dev)
@@ -1884,7 +1900,8 @@ static int flexcan_open(struct net_device *dev)
can_rx_offload_enable(&priv->offload);
- if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3)
+ if (priv->devtype_data.quirks &
+ (FLEXCAN_QUIRK_NR_IRQ_3 | FLEXCAN_QUIRK_IRQ_BERR))
err = request_irq(dev->irq, flexcan_irq_mb,
IRQF_SHARED, dev->name, dev);
else
@@ -1905,6 +1922,13 @@ static int flexcan_open(struct net_device *dev)
goto out_free_irq_boff;
}
+ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_IRQ_BERR) {
+ err = request_irq(priv->irq_err,
+ flexcan_irq_esr, IRQF_SHARED, dev->name, dev);
+ if (err)
+ goto out_free_irq_boff;
+ }
+
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ) {
err = request_irq(priv->irq_secondary_mb,
flexcan_irq_mb, IRQF_SHARED, dev->name, dev);
@@ -1919,7 +1943,8 @@ static int flexcan_open(struct net_device *dev)
return 0;
out_free_irq_err:
- if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3)
+ if (priv->devtype_data.quirks &
+ (FLEXCAN_QUIRK_IRQ_BERR | FLEXCAN_QUIRK_NR_IRQ_3))
free_irq(priv->irq_err, dev);
out_free_irq_boff:
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3)
@@ -1951,10 +1976,12 @@ static int flexcan_close(struct net_device *dev)
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ)
free_irq(priv->irq_secondary_mb, dev);
- if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
+ if (priv->devtype_data.quirks &
+ (FLEXCAN_QUIRK_IRQ_BERR | FLEXCAN_QUIRK_NR_IRQ_3))
free_irq(priv->irq_err, dev);
+
+ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3)
free_irq(priv->irq_boff, dev);
- }
free_irq(dev->irq, dev);
can_rx_offload_disable(&priv->offload);
@@ -2341,6 +2368,14 @@ static int flexcan_probe(struct platform_device *pdev)
if (transceiver)
priv->can.bitrate_max = transceiver->attrs.max_link_rate;
+ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_IRQ_BERR) {
+ priv->irq_err = platform_get_irq_byname(pdev, "berr");
+ if (priv->irq_err < 0) {
+ err = priv->irq_err;
+ goto failed_platform_get_irq;
+ }
+ }
+
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
priv->irq_boff = platform_get_irq(pdev, 1);
if (priv->irq_boff < 0) {
diff --git a/drivers/net/can/flexcan/flexcan.h b/drivers/net/can/flexcan/flexcan.h
index 16692a2502eb..bbb1a8dd4777 100644
--- a/drivers/net/can/flexcan/flexcan.h
+++ b/drivers/net/can/flexcan/flexcan.h
@@ -74,6 +74,8 @@
* both need to have an interrupt handler registered.
*/
#define FLEXCAN_QUIRK_SECONDARY_MB_IRQ BIT(18)
+/* Setup dedicated bus error and state change IRQ */
+#define FLEXCAN_QUIRK_IRQ_BERR BIT(19)
struct flexcan_devtype_data {
u32 quirks; /* quirks needed for different IP cores */
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v7 6/6] can: flexcan: add NXP S32N79 SoC support
2026-08-31 14:34 [PATCH v7 0/6] can: flexcan: Add NXP S32N79 SoC support Ciprian Costea
` (4 preceding siblings ...)
2026-08-31 14:34 ` [PATCH v7 5/6] can: flexcan: add FLEXCAN_QUIRK_IRQ_BERR quirk Ciprian Costea
@ 2026-08-31 14:34 ` Ciprian Costea
2026-08-31 19:01 ` sashiko-bot
5 siblings, 1 reply; 14+ messages in thread
From: Ciprian Costea @ 2026-08-31 14:34 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Angelo Dureghello, Frank Li
Cc: linux-can, devicetree, linux-kernel, NXP S32 Linux Team, imx,
Christophe Lizzi, Alberto Ruiz, Enric Balletbo, Eric Chanudet,
Ciprian Marian Costea, Andra-Teodora Ilie, Larisa Grigore,
Haibo Chen
From: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
Add device data and compatible string for NXP S32N79 SoC.
FlexCAN IP integration on S32N79 SoC uses two interrupts:
- one for mailboxes 0-127
- one for signaling bus errors and device state changes
Co-developed-by: Andra-Teodora Ilie <andra.ilie@nxp.com>
Signed-off-by: Andra-Teodora Ilie <andra.ilie@nxp.com>
Co-developed-by: Larisa Grigore <larisa.grigore@nxp.com>
Signed-off-by: Larisa Grigore <larisa.grigore@nxp.com>
Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
Reviewed-by: Vincent Mailhol <mailhol@kernel.org>
Reviewed-and-tested-by: Haibo Chen <haibo.chen@nxp.com>
Tested-by: Enric Balletbo i Serra <eballetb@redhat.com>
---
drivers/net/can/flexcan/flexcan-core.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index 601d88bfcfeb..0533cdf969b2 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -403,6 +403,15 @@ static const struct flexcan_devtype_data nxp_s32g2_devtype_data = {
FLEXCAN_QUIRK_SECONDARY_MB_IRQ,
};
+static const struct flexcan_devtype_data nxp_s32n_devtype_data = {
+ .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
+ FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX |
+ FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_SUPPORT_FD |
+ FLEXCAN_QUIRK_SUPPORT_ECC | FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
+ FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR |
+ FLEXCAN_QUIRK_IRQ_BERR,
+};
+
static const struct can_bittiming_const flexcan_bittiming_const = {
.name = DRV_NAME,
.tseg1_min = 4,
@@ -2225,6 +2234,7 @@ static const struct of_device_id flexcan_of_match[] = {
{ .compatible = "fsl,ls1021ar2-flexcan", .data = &fsl_ls1021a_r2_devtype_data, },
{ .compatible = "fsl,lx2160ar1-flexcan", .data = &fsl_lx2160a_r1_devtype_data, },
{ .compatible = "nxp,s32g2-flexcan", .data = &nxp_s32g2_devtype_data, },
+ { .compatible = "nxp,s32n79-flexcan", .data = &nxp_s32n_devtype_data, },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, flexcan_of_match);
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v7 1/6] can: flexcan: use dedicated IRQ handlers for multi-IRQ platforms
2026-08-31 14:34 ` [PATCH v7 1/6] can: flexcan: use dedicated IRQ handlers for multi-IRQ platforms Ciprian Costea
@ 2026-08-31 18:01 ` sashiko-bot
2026-09-01 14:44 ` Ciprian Marian Costea
0 siblings, 1 reply; 14+ messages in thread
From: sashiko-bot @ 2026-08-31 18:01 UTC (permalink / raw)
To: Ciprian Costea
Cc: devicetree, robh, conor+dt, Marc Kleine-Budde, Oliver Hartkopp,
linux-can, Vincent Mailhol, imx, Frank.Li, Oleksij Rempel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] The split IRQ handlers fail to resolve multi-IRQ concurrency for device state processing, leading to lockless list corruption.
--
commit f3f261bafd25e44254ad99cda953074bc68ed987
Author: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
can: flexcan: use dedicated IRQ handlers for multi-IRQ platforms
This commit splits the monolithic flexcan_irq handler into dedicated
functions for mailbox, device state, and bus error processing. The split
handlers are then registered to specific multi-IRQ lines depending on the
platform quirks.
> diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
> index f5d22c61503fa..2e9df2d14b341 100644
> --- a/drivers/net/can/flexcan/flexcan-core.c
> +++ b/drivers/net/can/flexcan/flexcan-core.c
[ ... ]
> +/* Process device state change events */
> +static irqreturn_t flexcan_do_state(struct net_device *dev)
> +{
[ ... ]
> + /* state change interrupt or broken error state quirk fix is enabled */
> + if ((reg_esr & FLEXCAN_ESR_ERR_STATE) ||
> + (priv->devtype_data.quirks &
> + (FLEXCAN_QUIRK_BROKEN_WERR_STATE | FLEXCAN_QUIRK_BROKEN_PERR_STATE)))
> + flexcan_irq_state(dev, reg_esr);
[Severity: High]
This is a pre-existing issue, but does calling flexcan_irq_state()
concurrently corrupt the lockless SKB queue?
If the boff and err handlers execute flexcan_do_state() concurrently,
they will both allocate error SKBs and insert them into
offload->skb_irq_queue using the lockless __skb_queue_add_sort().
Can this concurrent insertion corrupt the list pointers (skb->next and
skb->prev), potentially causing infinite loops or use-after-free
conditions?
[ ... ]
> +/* Bus error IRQ handler for multi-IRQ platforms */
> +static irqreturn_t flexcan_irq_berr(int irq, void *dev_id)
> +{
> + struct net_device *dev = dev_id;
> + struct flexcan_priv *priv = netdev_priv(dev);
> + irqreturn_t handled;
> +
> + handled = flexcan_do_berr(dev);
> +
> + if (priv->devtype_data.quirks & FLEXCAN_QUIRK_BROKEN_PERR_STATE)
> + handled |= flexcan_do_state(dev);
[Severity: High]
This isn't a bug introduced by this patch, but could this multi-IRQ
setup lead to concurrent device state mutations?
On platforms like s32g2 and mcf5441x with FLEXCAN_QUIRK_NR_IRQ_3 and
FLEXCAN_QUIRK_BROKEN_PERR_STATE, a hardware bus error or state change
can trigger both the boff and berr interrupts on distinct IRQ lines.
Since flexcan_irq_berr() and flexcan_irq_boff() execute on different
CPUs, couldn't they both call flexcan_do_state(dev) at the same time?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831143449.12828-1-ciprianmarian.costea@oss.nxp.com?part=1
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v7 2/6] can: flexcan: disable all IRQ lines in flexcan_chip_interrupts_enable()
2026-08-31 14:34 ` [PATCH v7 2/6] can: flexcan: disable all IRQ lines in flexcan_chip_interrupts_enable() Ciprian Costea
@ 2026-08-31 18:15 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-08-31 18:15 UTC (permalink / raw)
To: Ciprian Costea
Cc: Frank.Li, Oleksij Rempel, linux-can, Marc Kleine-Budde, conor+dt,
imx, robh, Vincent Mailhol, Oliver Hartkopp, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Missing synchronization in `flexcan_chip_interrupts_disable()` leads to a race with interrupt handlers, which can leave hardware interrupts enabled after `free_irq()`.
--
commit 199c16c8ec6245fdb40faa9ca7c9456354adfb8c
Author: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
can: flexcan: disable all IRQ lines in flexcan_chip_interrupts_enable()
This commit disables all registered IRQ lines around IMASK/CTRL register
writes in flexcan_chip_interrupts_enable to prevent handlers from firing
while registers are inconsistent on multi-IRQ platforms.
> diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
> index 2e9df2d14b341..4eda54d2169e7 100644
> --- a/drivers/net/can/flexcan/flexcan-core.c
> +++ b/drivers/net/can/flexcan/flexcan-core.c
[ ... ]
> @@ -1522,14 +1522,28 @@ static void flexcan_chip_interrupts_enable(const struct net_device *dev)
> {
[ ... ]
> priv->write(upper_32_bits(reg_imask), ®s->imask2);
> priv->write(lower_32_bits(reg_imask), ®s->imask1);
> enable_irq(dev->irq);
> + if (quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ)
> + enable_irq(priv->irq_secondary_mb);
> + if (quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
> + enable_irq(priv->irq_boff);
> + enable_irq(priv->irq_err);
> + }
> }
>
> static void flexcan_chip_interrupts_disable(const struct net_device *dev)
[Severity: High]
This is a pre-existing issue, but does flexcan_chip_interrupts_disable also
need this same fix pattern applied?
Currently, flexcan_chip_interrupts_disable modifies the ctrl register
without first masking the IRQ lines via disable_irq.
If flexcan_close calls flexcan_chip_interrupts_disable while the hardware
is still running, could a concurrent state-change interrupt on another CPU
invoke flexcan_do_state? That handler calls flexcan_error_irq_enable,
which might overwrite regs->ctrl and inadvertently re-enable hardware error
interrupts.
Since flexcan_close immediately proceeds to call free_irq while the
hardware might still be active due to this race, does this expose a time
window where an unhandled interrupt storm can trigger?
If an interrupt storm occurs without a registered handler, it could force
the kernel to permanently disable the IRQ line. On platforms where IRQs are
shared (requested by IRQF_SHARED in flexcan_open), this could break other
devices sharing the line.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831143449.12828-1-ciprianmarian.costea@oss.nxp.com?part=2
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v7 3/6] can: flexcan: split rx/tx masks per mailbox IRQ line
2026-08-31 14:34 ` [PATCH v7 3/6] can: flexcan: split rx/tx masks per mailbox IRQ line Ciprian Costea
@ 2026-08-31 18:27 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-08-31 18:27 UTC (permalink / raw)
To: Ciprian Costea
Cc: robh, Marc Kleine-Budde, conor+dt, Frank.Li, imx, Oliver Hartkopp,
devicetree, linux-can, Vincent Mailhol, Oleksij Rempel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Concurrent execution of mailbox IRQ handlers causes `skb_irq_queue` list corruption.
--
commit 03c6b5c54e432135868db888c97ca8c2b9bc7225
Author: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
can: flexcan: split rx/tx masks per mailbox IRQ line
On S32G2 with two mailbox IRQ lines, handlers process the full rx_mask/tx_mask
range. This patch introduces masks to split the range between the MB0 and MB1
IRQ lines.
> diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
> index 4eda54d2169e7..f28ff0e95b74f 100644
> --- a/drivers/net/can/flexcan/flexcan-core.c
> +++ b/drivers/net/can/flexcan/flexcan-core.c
[ ... ]
> @@ -1244,8 +1255,14 @@ static irqreturn_t flexcan_irq_mb(int irq, void *dev_id)
> struct net_device *dev = dev_id;
> struct flexcan_priv *priv = netdev_priv(dev);
> irqreturn_t handled;
> + u64 mb_mask = ~0ULL;
> +
> + if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ)
> + mb_mask = (irq == priv->irq_secondary_mb) ?
> + FLEXCAN_SECONDARY_MB_IRQ_MB1_MASK :
> + FLEXCAN_SECONDARY_MB_IRQ_MB0_MASK;
>
> - handled = flexcan_do_mb(dev);
> + handled = flexcan_do_mb(dev, mb_mask);
>
> if (handled)
> can_rx_offload_irq_finish(&priv->offload);
[Severity: Critical]
This is a pre-existing issue, but does concurrent execution of mailbox IRQ
handlers cause skb_irq_queue list corruption?
On multi-IRQ platforms like S32G2, CAN packets arriving concurrently on both
mailbox ranges (MB 0-7 and MB 8-63) will trigger both mb-0 and mb-1
interrupts. If these are routed to different CPUs, flexcan_irq_mb() runs
concurrently on both CPUs.
Both contexts then invoke can_rx_offload_irq_offload_timestamp() (inside
flexcan_do_mb()) and can_rx_offload_irq_finish(), which modify the shared
lockless list offload->skb_irq_queue without synchronization:
drivers/net/can/dev/rx-offload.c:can_rx_offload_irq_offload_timestamp() {
...
__skb_queue_add_sort(&offload->skb_irq_queue, skb,
can_rx_offload_compare);
...
}
drivers/net/can/dev/rx-offload.c:can_rx_offload_irq_finish() {
...
skb_queue_splice_tail_init(&offload->skb_irq_queue, &offload->skb_queue);
...
}
Can this lead to memory corruption (corrupted sk_buff_head list pointers)
and an immediate kernel panic in hardirq context when the list is accessed
or modified?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831143449.12828-1-ciprianmarian.costea@oss.nxp.com?part=3
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v7 4/6] dt-bindings: can: fsl,flexcan: add NXP S32N79 SoC support
2026-08-31 14:34 ` [PATCH v7 4/6] dt-bindings: can: fsl,flexcan: add NXP S32N79 SoC support Ciprian Costea
@ 2026-08-31 18:37 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-08-31 18:37 UTC (permalink / raw)
To: Ciprian Costea
Cc: Oliver Hartkopp, conor+dt, Frank.Li, imx, linux-can,
Marc Kleine-Budde, Vincent Mailhol, robh, devicetree,
Oleksij Rempel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Concurrent execution of split IRQ handlers corrupts rx-offload skb_irq_queue and CAN state.
--
commit c8453ab295dd4a8e4e7831e7734d0b2de7b63259
Author: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
dt-bindings: can: fsl,flexcan: add NXP S32N79 SoC support
Add NXP S32N79 SoC compatible string and interrupt properties.
On S32N79, FlexCAN IP is integrated with two interrupt lines:
one for the mailbox interrupts (0-127) and one for signaling
bus errors and device state changes.
> diff --git a/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml b/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml
> index f81d56f7c12a5..d098a44c2b9c2 100644
> --- a/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml
> +++ b/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml
[ ... ]
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: nxp,s32n79-flexcan
> + then:
> + properties:
> + interrupts:
> + items:
> + - description: Message Buffer interrupt for mailboxes 0-127
> + - description: Bus Error and Device state change interrupt
[Severity: High]
This is a pre-existing issue, but this multi-IRQ configuration exposes a
concurrent execution bug in the split IRQ handlers.
When multiple interrupt events (e.g., mailbox processing and bus error) fire
simultaneously, the handlers mapped to different IRQ numbers on multi-IRQ
platforms (like S32G2 or S32N79) can be dispatched concurrently on different
CPU cores.
For example, in drivers/net/can/flexcan/flexcan-core.c, flexcan_irq_mb()
calls flexcan_do_mb():
handled = flexcan_do_mb(dev, mb_mask);
if (handled)
can_rx_offload_irq_finish(&priv->offload);
This can run concurrently with the state change interrupt in flexcan_do_state():
/* state change interrupt or broken error state quirk fix is enabled */
if ((reg_esr & FLEXCAN_ESR_ERR_STATE) ||
(priv->devtype_data.quirks &
(FLEXCAN_QUIRK_BROKEN_WERR_STATE | FLEXCAN_QUIRK_BROKEN_PERR_STATE)))
flexcan_irq_state(dev, reg_esr);
These concurrent handlers invoke can_rx_offload_irq_offload_timestamp() and
can_rx_offload_queue_timestamp(), which use the lockless
__skb_queue_add_sort() API to insert SKBs into offload->skb_irq_queue.
Since these list insertion APIs omit locking (relying on a single-IRQ
execution context), can this concurrent execution corrupt the doubly-linked
list pointers and lead to a kernel panic during normal CAN traffic?
Additionally, with the FLEXCAN_QUIRK_BROKEN_PERR_STATE quirk, both
flexcan_irq_berr() and flexcan_irq_boff() can concurrently execute
flexcan_do_state(), causing data races in can_change_state().
This issue was introduced by the earlier commit "can: flexcan: use dedicated
IRQ handlers for multi-IRQ platforms" in this patchset, and it was not
resolved by the end of the series. Should locking be introduced to protect
the CAN state and offload queues?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831143449.12828-1-ciprianmarian.costea@oss.nxp.com?part=4
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v7 5/6] can: flexcan: add FLEXCAN_QUIRK_IRQ_BERR quirk
2026-08-31 14:34 ` [PATCH v7 5/6] can: flexcan: add FLEXCAN_QUIRK_IRQ_BERR quirk Ciprian Costea
@ 2026-08-31 18:51 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-08-31 18:51 UTC (permalink / raw)
To: Ciprian Costea
Cc: Marc Kleine-Budde, Vincent Mailhol, Frank.Li, imx, robh, conor+dt,
devicetree, Oliver Hartkopp, linux-can, Oleksij Rempel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [Medium] Wakeup interrupt is not configured for the new dedicated ESR IRQ during suspend.
Pre-existing issues:
- [Critical] Concurrent execution of separate IRQ handlers corrupts the lockless rx-offload SKB queue.
--
commit 53e92dd64634f7bc681782eddd379791f6533960
Author: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
can: flexcan: add FLEXCAN_QUIRK_IRQ_BERR quirk
This commit introduces the FLEXCAN_QUIRK_IRQ_BERR quirk for platforms where bus
errors and state changes share a dedicated IRQ line. It adds a combined IRQ
handler flexcan_irq_esr() and updates interrupt setup and teardown to manage
the new line.
> diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
> index f28ff0e95b74f..601d88bfcfeb2 100644
> --- a/drivers/net/can/flexcan/flexcan-core.c
> +++ b/drivers/net/can/flexcan/flexcan-core.c
[ ... ]
> @@ -1303,6 +1303,22 @@ static irqreturn_t flexcan_irq_boff(int irq, void *dev_id)
> return handled;
> }
>
> +/* Combined bus error and state change IRQ handler */
> +static irqreturn_t flexcan_irq_esr(int irq, void *dev_id)
> +{
> + struct net_device *dev = dev_id;
> + struct flexcan_priv *priv = netdev_priv(dev);
> + irqreturn_t handled;
> +
> + handled = flexcan_do_state(dev);
> + handled |= flexcan_do_berr(dev);
> +
> + if (handled)
> + can_rx_offload_irq_finish(&priv->offload);
> +
> + return handled;
> +}
[Severity: Critical]
This is a pre-existing issue, but adding this separate IRQ handler highlights
a race condition. Can this new handler and the main mailbox IRQ handler
execute concurrently on different CPUs?
If dev->irq and priv->irq_err are dispatched to different CPUs simultaneously,
both handlers can call into the Rx offload functions in rx-offload.c. For
example:
CPU1 (in flexcan_irq_mb):
can_rx_offload_irq_offload_timestamp()
__skb_queue_add_sort(&offload->skb_irq_queue, ...)
CPU2 (in flexcan_irq_esr):
handled |= flexcan_do_berr(dev);
flexcan_irq_bus_err()
can_rx_offload_queue_timestamp()
__skb_queue_add_sort(&offload->skb_irq_queue, ...)
Since the Rx offload queue manipulation in __skb_queue_add_sort() is lockless,
could this concurrent execution corrupt the skb_irq_queue list and crash the
kernel? Similarly, both paths call can_rx_offload_irq_finish() which splices
the queue locklessly from the IRQ queue side without adequate mutual exclusion
against other HardIRQs.
[ ... ]
> @@ -1905,6 +1922,13 @@ static int flexcan_open(struct net_device *dev)
> goto out_free_irq_boff;
> }
>
> + if (priv->devtype_data.quirks & FLEXCAN_QUIRK_IRQ_BERR) {
> + err = request_irq(priv->irq_err,
> + flexcan_irq_esr, IRQF_SHARED, dev->name, dev);
> + if (err)
> + goto out_free_irq_boff;
> + }
> +
[Severity: Medium]
Since this quirk routes the wakeup event (WAK_INT) to this new dedicated ESR
IRQ line, should priv->irq_err be configured for wakeup during suspend?
Currently, flexcan_suspend() calls enable_irq_wake(dev->irq), but it does
not arm priv->irq_err. Will the system fail to wake up from sleep upon CAN
activity on platforms using this quirk because the interrupt controller isn't
armed for the correct line?
Should flexcan_suspend() and flexcan_resume() be updated to handle
priv->irq_err as well?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831143449.12828-1-ciprianmarian.costea@oss.nxp.com?part=5
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v7 6/6] can: flexcan: add NXP S32N79 SoC support
2026-08-31 14:34 ` [PATCH v7 6/6] can: flexcan: add NXP S32N79 SoC support Ciprian Costea
@ 2026-08-31 19:01 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-08-31 19:01 UTC (permalink / raw)
To: Ciprian Costea
Cc: Oliver Hartkopp, Oleksij Rempel, Frank.Li, conor+dt, robh, imx,
Marc Kleine-Budde, Vincent Mailhol, linux-can, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Incorrect interrupt line enabled for system wakeup in flexcan_suspend() on multi-IRQ platforms.
--
commit cee5e83ffcddcb89ac8051e51286d9d24014fc17
Author: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
can: flexcan: add NXP S32N79 SoC support
This commit adds device data and compatible strings for the NXP S32N79 SoC
to the flexcan driver.
> diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
> index 601d88bfcfeb2..0533cdf969b2c 100644
> --- a/drivers/net/can/flexcan/flexcan-core.c
> +++ b/drivers/net/can/flexcan/flexcan-core.c
> @@ -403,6 +403,15 @@ static const struct flexcan_devtype_data nxp_s32g2_devtype_data = {
> FLEXCAN_QUIRK_SECONDARY_MB_IRQ,
> };
>
> +static const struct flexcan_devtype_data nxp_s32n_devtype_data = {
> + .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
> + FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX |
> + FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_SUPPORT_FD |
> + FLEXCAN_QUIRK_SUPPORT_ECC | FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
> + FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR |
> + FLEXCAN_QUIRK_IRQ_BERR,
[Severity: High]
This is a pre-existing issue, but adding FLEXCAN_QUIRK_IRQ_BERR for the new
S32N79 SoC exposes an existing problem with system wakeup.
On multi-IRQ platforms that use FLEXCAN_QUIRK_IRQ_BERR or
FLEXCAN_QUIRK_NR_IRQ_3, dev->irq is dedicated exclusively to mailbox events.
The FlexCAN Wake-Up Interrupt (FLEXCAN_ESR_WAK_INT) triggers a state change
event, which is routed to the dedicated state change interrupt line
(priv->irq_err or priv->irq_boff).
However, when the system goes to sleep with Wake-on-CAN enabled, does
flexcan_suspend() enable the wrong interrupt line for wakeup?
drivers/net/can/flexcan/flexcan-core.c:flexcan_suspend() {
...
if (device_may_wakeup(device)) {
...
enable_irq_wake(dev->irq);
...
}
...
}
Since enable_irq_wake() configures the irqchip to listen to the mailbox
interrupt instead of the state change interrupt, will the system fail to wake
up from suspend on CAN network activity?
The same incorrectly assigned wakeup interrupt is subsequently disabled in
flexcan_resume() by calling disable_irq_wake(dev->irq).
> +};
> +
> static const struct can_bittiming_const flexcan_bittiming_const = {
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831143449.12828-1-ciprianmarian.costea@oss.nxp.com?part=6
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v7 1/6] can: flexcan: use dedicated IRQ handlers for multi-IRQ platforms
2026-08-31 18:01 ` sashiko-bot
@ 2026-09-01 14:44 ` Ciprian Marian Costea
0 siblings, 0 replies; 14+ messages in thread
From: Ciprian Marian Costea @ 2026-09-01 14:44 UTC (permalink / raw)
To: sashiko-reviews
Cc: devicetree, robh, conor+dt, Marc Kleine-Budde, Oliver Hartkopp,
linux-can, Vincent Mailhol, imx, Frank.Li, Oleksij Rempel, s32,
imx
On 8/31/2026 9:01 PM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [High] The split IRQ handlers fail to resolve multi-IRQ concurrency for device state processing, leading to lockless list corruption.
> --
>
> commit f3f261bafd25e44254ad99cda953074bc68ed987
> Author: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
>
> can: flexcan: use dedicated IRQ handlers for multi-IRQ platforms
>
> This commit splits the monolithic flexcan_irq handler into dedicated
> functions for mailbox, device state, and bus error processing. The split
> handlers are then registered to specific multi-IRQ lines depending on the
> platform quirks.
>
>> diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
>> index f5d22c61503fa..2e9df2d14b341 100644
>> --- a/drivers/net/can/flexcan/flexcan-core.c
>> +++ b/drivers/net/can/flexcan/flexcan-core.c
> [ ... ]
>> +/* Process device state change events */
>> +static irqreturn_t flexcan_do_state(struct net_device *dev)
>> +{
> [ ... ]
>> + /* state change interrupt or broken error state quirk fix is enabled */
>> + if ((reg_esr & FLEXCAN_ESR_ERR_STATE) ||
>> + (priv->devtype_data.quirks &
>> + (FLEXCAN_QUIRK_BROKEN_WERR_STATE | FLEXCAN_QUIRK_BROKEN_PERR_STATE)))
>> + flexcan_irq_state(dev, reg_esr);
>
> [Severity: High]
> This is a pre-existing issue, but does calling flexcan_irq_state()
> concurrently corrupt the lockless SKB queue?
>
> If the boff and err handlers execute flexcan_do_state() concurrently,
> they will both allocate error SKBs and insert them into
> offload->skb_irq_queue using the lockless __skb_queue_add_sort().
>
> Can this concurrent insertion corrupt the list pointers (skb->next and
> skb->prev), potentially causing infinite loops or use-after-free
> conditions?
>
> [ ... ]
>> +/* Bus error IRQ handler for multi-IRQ platforms */
>> +static irqreturn_t flexcan_irq_berr(int irq, void *dev_id)
>> +{
>> + struct net_device *dev = dev_id;
>> + struct flexcan_priv *priv = netdev_priv(dev);
>> + irqreturn_t handled;
>> +
>> + handled = flexcan_do_berr(dev);
>> +
>> + if (priv->devtype_data.quirks & FLEXCAN_QUIRK_BROKEN_PERR_STATE)
>> + handled |= flexcan_do_state(dev);
>
> [Severity: High]
> This isn't a bug introduced by this patch, but could this multi-IRQ
> setup lead to concurrent device state mutations?
>
> On platforms like s32g2 and mcf5441x with FLEXCAN_QUIRK_NR_IRQ_3 and
> FLEXCAN_QUIRK_BROKEN_PERR_STATE, a hardware bus error or state change
> can trigger both the boff and berr interrupts on distinct IRQ lines.
>
> Since flexcan_irq_berr() and flexcan_irq_boff() execute on different
> CPUs, couldn't they both call flexcan_do_state(dev) at the same time?
>
multi-IRQ concurrency findings in this series should be covered by the
following patchset [1]
[1]
https://lore.kernel.org/all/20260901114848.500591-1-ciprianmarian.costea@oss.nxp.com/T/#t
Regards,
Ciprian
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-09-01 14:44 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-31 14:34 [PATCH v7 0/6] can: flexcan: Add NXP S32N79 SoC support Ciprian Costea
2026-08-31 14:34 ` [PATCH v7 1/6] can: flexcan: use dedicated IRQ handlers for multi-IRQ platforms Ciprian Costea
2026-08-31 18:01 ` sashiko-bot
2026-09-01 14:44 ` Ciprian Marian Costea
2026-08-31 14:34 ` [PATCH v7 2/6] can: flexcan: disable all IRQ lines in flexcan_chip_interrupts_enable() Ciprian Costea
2026-08-31 18:15 ` sashiko-bot
2026-08-31 14:34 ` [PATCH v7 3/6] can: flexcan: split rx/tx masks per mailbox IRQ line Ciprian Costea
2026-08-31 18:27 ` sashiko-bot
2026-08-31 14:34 ` [PATCH v7 4/6] dt-bindings: can: fsl,flexcan: add NXP S32N79 SoC support Ciprian Costea
2026-08-31 18:37 ` sashiko-bot
2026-08-31 14:34 ` [PATCH v7 5/6] can: flexcan: add FLEXCAN_QUIRK_IRQ_BERR quirk Ciprian Costea
2026-08-31 18:51 ` sashiko-bot
2026-08-31 14:34 ` [PATCH v7 6/6] can: flexcan: add NXP S32N79 SoC support Ciprian Costea
2026-08-31 19:01 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox