[PATCH net] can: xilinx_can: set CAN FD flags on received frames

From: Maximilian Zimmermann

Date: Mon Sep 21 2026 - 02:09:23 EST


The Xilinx CAN FD controller reports the bit rate switch (BRS) and error
state indicator (ESI) in the receive buffer DLC register. The receive
path currently uses this register to determine frame format and payload
length, but does not set BRS and ESI in struct canfd_frame::flags.

This results in applications being unable to receive the BRS and ESI
flags, even when the controller correctly received them.

Add the ESI register mask and copy the controller flags to the
corresponding SocketCAN canfd_frame struct.

Fixes: c223da689324 ("can: xilinx_can: Add support for CANFD FD frames")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Maximilian Zimmermann <maxz@xxxxxxxxxxxxxxx>
---
Tested building against net/main and backported
linux-xlnx (31626ef92ff1).

Also tested runtime on the backported linux-xlnx kernel with
QEMU Xilinx CAN FD 2.0 connected through host SocketCAN to a
physical board via candump. Verified reception with and without BRS
using frames transmitted by the board. Send an ESI frame using
cansend on the host and verified that both QEMU and board
reported ESI.
---
drivers/net/can/xilinx_can.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 43d7f22820b8..52661e088205 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -157,6 +157,7 @@ enum xcan_reg {
#define XCAN_2_FSR_RI_MASK 0x0000003F /* RX Read Index */
#define XCAN_DLCR_EDL_MASK 0x08000000 /* EDL Mask in DLC */
#define XCAN_DLCR_BRS_MASK 0x04000000 /* BRS Mask in DLC */
+#define XCAN_DLCR_ESI_MASK 0x02000000 /* ESI Mask in DLC */
#define XCAN_ECC_CFG_REECRX_MASK BIT(2) /* Reset RX FIFO ECC error counters */
#define XCAN_ECC_CFG_REECTXOL_MASK BIT(1) /* Reset TXOL FIFO ECC error counters */
#define XCAN_ECC_CFG_REECTXTL_MASK BIT(0) /* Reset TXTL FIFO ECC error counters */
@@ -959,6 +960,11 @@ static int xcanfd_rx(struct net_device *ndev, int frame_base)

/* Check the frame received is FD or not*/
if (dlc & XCAN_DLCR_EDL_MASK) {
+ if (dlc & XCAN_DLCR_BRS_MASK)
+ cf->flags |= CANFD_BRS;
+ if (dlc & XCAN_DLCR_ESI_MASK)
+ cf->flags |= CANFD_ESI;
+
for (i = 0; i < cf->len; i += 4) {
dw_offset = XCANFD_FRAME_DW_OFFSET(frame_base) +
(dwindex * XCANFD_DW_BYTES);

---
base-commit: 1e24c4f2ee44be0eee94092b5d13cbdb4bdf0d60
change-id: 20260921-fix-xilinx-canfd-flags-1b4d517ffa8e

Best regards,
--
Maximilian Zimmermann <maxz@xxxxxxxxxxxxxxx>