From nobody Tue Feb 10 05:09:46 2026 Received: from smtp-out3.simply.com (smtp-out3.simply.com [94.231.106.210]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 47B5D42980B; Thu, 22 Jan 2026 12:10:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=94.231.106.210 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769083863; cv=none; b=imKunIrSH6ml5zmpCnYgvwnV+cfhOOkwz/qtVDtxYqPPXdiSRKSDoKy2qj/fIjmTvUWonjDrkzRwaAGNNrkG6OkfcamI62Ij8OlZS7vwP/UCXm15gPjOGh1SLxsyfTR8U3KjB8WBy0DNCzvQI8tyZvUqE6o6eCNus2XlAC/Kh8g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769083863; c=relaxed/simple; bh=PPk0WF5n99PlZvu7ZVeG5vXsJf7I/nzmRYtNPqeY/+4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gUa4P5H7jj3TYJ/VU7n3F6sQmOzhM8lSY3mR6R3P5xVVTWksv0vhSyawFOZtNB7kXfS4EzZBzRo5Of7if4CpLkl5HCT5z0n0yM5irEr7zjRLTvTbzVEuOVDJwTGf6yf/uN35Y1x7iO8lteExbKm5B8o/a0+CUrX+Ok5wKgRWWnc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gaisler.com; spf=pass smtp.mailfrom=gaisler.com; dkim=fail (0-bit key) header.d=gaisler.com header.i=@gaisler.com header.b=N9pQKyt7 reason="key not found in DNS"; arc=none smtp.client-ip=94.231.106.210 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gaisler.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gaisler.com Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=gaisler.com header.i=@gaisler.com header.b="N9pQKyt7" Received: from localhost (localhost [127.0.0.1]) by smtp.simply.com (Simply.com) with ESMTP id 4dxfzG50J3z1Fgd9; Thu, 22 Jan 2026 13:10:50 +0100 (CET) Received: from d-5xj5g74.got.gaisler.com.com (h-98-128-223-123.NA.cust.bahnhof.se [98.128.223.123]) by smtp.simply.com (Simply.com) with ESMTPA id 4dxfzG2XpPz1DDC3; Thu, 22 Jan 2026 13:10:50 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gaisler.com; s=simplycom2; t=1769083850; bh=cQecUzHZA3Ag9x7xgx5LRp21VuGFauFPBsaAtimBgwk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=N9pQKyt7wLTqxqges2RLYWUnpR2+5BG6NICOmjaBUjnKqatz+VMuj0REeDafSJJ5h xPcqQapUPjmNtrHrmoSznjVBBhCTCpn8KtkYuHC2x8yDvUAqZwQ+eiBwQEazj9yuiO 5YqY1QS6GoyVnxInF0QolPQU0k7mewZs0pF7wXBhsStsD5VeseuOdm/kYcpoET/op8 qwfx8vq5xuKdSy7axBM0UO208hwnmGMTCmKh3ZKo2oauJrDnTxjfjGTNuDlzlmoZqs T1Y4qva7jrs2IY+THg2W9dbUoHWQRf6SEDtTKruaNwVQQj7Xe7HAtxwjcWMS6dZK5j BuDAvN3P+5K4w== From: Arun Muthusamy To: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, mkl@pengutronix.de, mailhol@kernel.org Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-can@vger.kernel.org, Arun Muthusamy Subject: [PATCH v3 14/15] can: grcan: Add CANFD RX support alongside legacy CAN Date: Thu, 22 Jan 2026 13:10:37 +0100 Message-ID: <20260122121038.7910-15-arun.muthusamy@gaisler.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260122121038.7910-1-arun.muthusamy@gaisler.com> References: <20260122121038.7910-1-arun.muthusamy@gaisler.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Include CANFD RX support with the legacy CAN support, enabling support for extended data payloads to provide higher bit rates. Signed-off-by: Arun Muthusamy --- drivers/net/can/grcan.c | 98 +++++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 33 deletions(-) diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index 508ad5320cff..39afb12c50d0 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -235,6 +235,9 @@ struct grcan_registers { #define GRCAN_TX_BRS BIT(25) #define GRCAN_TX_FDF BIT(26) =20 +#define GRCAN_RX_BRS BIT(25) +#define GRCAN_RX_FDF BIT(26) + /* Hardware capabilities */ struct grcan_hwcap { /* CAN-FD capable, indicates GRCANFD IP. @@ -1235,18 +1238,22 @@ static int grcan_numbds(int len) =20 static int grcan_receive(struct net_device *dev, int budget) { + struct net_device_stats *stats =3D &dev->stats; struct grcan_priv *priv =3D netdev_priv(dev); - struct grcan_registers __iomem *regs =3D priv->regs; + struct grcan_registers __iomem *regs; struct grcan_dma *dma =3D &priv->dma; - struct net_device_stats *stats =3D &dev->stats; - struct can_frame *cf; + u32 bds, copy_len, payload_offset; + u32 wr, rd, dlc, startrd; + struct canfd_frame *cf; + int i, work_done =3D 0; struct sk_buff *skb; - u32 wr, rd, startrd; - u32 *slot; u32 rtr, eff; - int work_done =3D 0; + u32 *slot; + u8 *data; =20 + regs =3D priv->regs; rd =3D grcan_read_reg(®s->rxrd); + startrd =3D rd; for (work_done =3D 0; work_done < budget; work_done++) { /* Check for packet to receive */ @@ -1254,43 +1261,68 @@ static int grcan_receive(struct net_device *dev, in= t budget) if (rd =3D=3D wr) break; =20 - /* Take care of packet */ - skb =3D alloc_can_skb(dev, &cf); - if (skb =3D=3D NULL) { + slot =3D dma->rx.buf + rd; + + if (slot[1] & GRCAN_RX_FDF) + skb =3D alloc_canfd_skb(dev, &cf); + else + skb =3D alloc_can_skb(priv->dev, (struct can_frame **)&cf); + + if (unlikely(!skb)) { netdev_err(dev, "dropping frame: skb allocation failed\n"); stats->rx_dropped++; continue; } =20 - slot =3D dma->rx.buf + rd; - eff =3D slot[0] & GRCAN_MSG_IDE; - rtr =3D slot[0] & GRCAN_MSG_RTR; - if (eff) { - cf->can_id =3D ((slot[0] & GRCAN_MSG_EID) - >> GRCAN_MSG_EID_BIT); - cf->can_id |=3D CAN_EFF_FLAG; - } else { - cf->can_id =3D ((slot[0] & GRCAN_MSG_BID) - >> GRCAN_MSG_BID_BIT); + dlc =3D FIELD_GET(GRCAN_MSG_DLC_MASK, slot[1]); + if (slot[1] & GRCAN_RX_FDF) + cf->len =3D can_fd_dlc2len(dlc); + else + cf->len =3D can_cc_dlc2len(dlc); + + bds =3D grcan_numbds(cf->len); + payload_offset =3D 0; + data =3D cf->data; + + for (i =3D 0; i < bds; i++) { + slot =3D dma->rx.buf + rd; + + if (i =3D=3D 0) { + eff =3D slot[0] & GRCAN_MSG_IDE; + rtr =3D slot[0] & GRCAN_MSG_RTR; + if (eff) { + cf->can_id =3D FIELD_GET(GRCAN_MSG_EID_MASK, slot[0]); + cf->can_id |=3D CAN_EFF_FLAG; + } else { + cf->can_id =3D FIELD_GET(GRCAN_MSG_BID_MASK, slot[0]); + } + if (rtr) + cf->can_id |=3D CAN_RTR_FLAG; + + dlc =3D FIELD_GET(GRCAN_MSG_DLC_MASK, slot[1]); + if (slot[1] & GRCAN_RX_FDF) + cf->len =3D can_fd_dlc2len(dlc); + else + cf->len =3D can_cc_dlc2len(dlc); + + copy_len =3D min(cf->len, GRCAN_CLASSIC_DATA_SIZE); + memcpy(data, &slot[2], copy_len); + payload_offset +=3D copy_len; + } else { + copy_len =3D min(cf->len - payload_offset, GRCAN_MSG_SIZE); + memcpy(data + payload_offset, slot, copy_len); + payload_offset +=3D copy_len; + } + rd +=3D GRCAN_MSG_SIZE; + if (rd >=3D dma->rx.size) + rd -=3D dma->rx.size; } - cf->len =3D can_cc_dlc2len((slot[1] & GRCAN_MSG_DLC) - >> GRCAN_MSG_DLC_BIT); - if (rtr) { - cf->can_id |=3D CAN_RTR_FLAG; - } else { - if (cf->can_dlc > 0) - memcpy(cf->data, &slot[2], sizeof(u32)); - if (cf->can_dlc > 4) - memcpy(cf->data + 4, &slot[3], sizeof(u32)); =20 - stats->rx_bytes +=3D cf->len; - } + /* Update statistics and read pointer */ stats->rx_packets++; - + stats->rx_bytes +=3D cf->len; netif_receive_skb(skb); - - rd =3D grcan_ring_add(rd, GRCAN_MSG_SIZE, dma->rx.size); } =20 /* Make sure everything is read before allowing hardware to --=20 2.51.0