1 // SPDX-License-Identifier: GPL-2.0
3 // Copyright (c) 2023, 2024 Pengutronix,
4 // Marc Kleine-Budde <kernel@pengutronix.de>
7 #include <net/netdev_queues.h>
9 #include "rockchip_canfd.h"
11 static bool rkcanfd_can_frame_header_equal(const struct canfd_frame
*const cfd1
,
12 const struct canfd_frame
*const cfd2
,
15 const u8 mask_flags
= CANFD_BRS
| CANFD_ESI
| CANFD_FDF
;
16 canid_t mask
= CAN_EFF_FLAG
;
18 if (canfd_sanitize_len(cfd1
->len
) != canfd_sanitize_len(cfd2
->len
))
24 if (cfd1
->can_id
& CAN_EFF_FLAG
)
29 if ((cfd1
->can_id
& mask
) != (cfd2
->can_id
& mask
))
33 (cfd1
->flags
& mask_flags
) != (cfd2
->flags
& mask_flags
))
39 static bool rkcanfd_can_frame_data_equal(const struct canfd_frame
*cfd1
,
40 const struct canfd_frame
*cfd2
,
45 if (!is_canfd
&& (cfd1
->can_id
& CAN_RTR_FLAG
))
48 len
= canfd_sanitize_len(cfd1
->len
);
50 return !memcmp(cfd1
->data
, cfd2
->data
, len
);
54 rkcanfd_fifo_header_to_cfd_header(const struct rkcanfd_priv
*priv
,
55 const struct rkcanfd_fifo_header
*header
,
56 struct canfd_frame
*cfd
)
58 unsigned int len
= sizeof(*cfd
) - sizeof(cfd
->data
);
61 if (header
->frameinfo
& RKCANFD_REG_FD_FRAMEINFO_FRAME_FORMAT
)
62 cfd
->can_id
= FIELD_GET(RKCANFD_REG_FD_ID_EFF
, header
->id
) |
65 cfd
->can_id
= FIELD_GET(RKCANFD_REG_FD_ID_SFF
, header
->id
);
67 dlc
= FIELD_GET(RKCANFD_REG_FD_FRAMEINFO_DATA_LENGTH
,
71 if (header
->frameinfo
& RKCANFD_REG_FD_FRAMEINFO_FDF
) {
72 cfd
->len
= can_fd_dlc2len(dlc
);
74 /* The cfd is not allocated by alloc_canfd_skb(), so
77 cfd
->flags
|= CANFD_FDF
;
79 if (header
->frameinfo
& RKCANFD_REG_FD_FRAMEINFO_BRS
)
80 cfd
->flags
|= CANFD_BRS
;
82 cfd
->len
= can_cc_dlc2len(dlc
);
84 if (header
->frameinfo
& RKCANFD_REG_FD_FRAMEINFO_RTR
) {
85 cfd
->can_id
|= CAN_RTR_FLAG
;
91 return len
+ cfd
->len
;
94 static int rkcanfd_rxstx_filter(struct rkcanfd_priv
*priv
,
95 const struct canfd_frame
*cfd_rx
, const u32 ts
,
98 struct net_device_stats
*stats
= &priv
->ndev
->stats
;
99 struct rkcanfd_stats
*rkcanfd_stats
= &priv
->stats
;
100 const struct canfd_frame
*cfd_nominal
;
101 const struct sk_buff
*skb
;
102 unsigned int tx_tail
;
104 tx_tail
= rkcanfd_get_tx_tail(priv
);
105 skb
= priv
->can
.echo_skb
[tx_tail
];
107 netdev_err(priv
->ndev
,
108 "%s: echo_skb[%u]=NULL tx_head=0x%08x tx_tail=0x%08x\n",
110 priv
->tx_head
, priv
->tx_tail
);
114 cfd_nominal
= (struct canfd_frame
*)skb
->data
;
116 /* We RX'ed a frame identical to our pending TX frame. */
117 if (rkcanfd_can_frame_header_equal(cfd_rx
, cfd_nominal
,
118 cfd_rx
->flags
& CANFD_FDF
) &&
119 rkcanfd_can_frame_data_equal(cfd_rx
, cfd_nominal
,
120 cfd_rx
->flags
& CANFD_FDF
)) {
121 unsigned int frame_len
;
123 rkcanfd_handle_tx_done_one(priv
, ts
, &frame_len
);
125 WRITE_ONCE(priv
->tx_tail
, priv
->tx_tail
+ 1);
126 netif_subqueue_completed_wake(priv
->ndev
, 0, 1, frame_len
,
127 rkcanfd_get_effective_tx_free(priv
),
128 RKCANFD_TX_START_THRESHOLD
);
135 if (!(priv
->devtype_data
.quirks
& RKCANFD_QUIRK_RK3568_ERRATUM_6
))
138 /* Erratum 6: Extended frames may be send as standard frames.
141 * - TX'ed a standard frame -or-
142 * - RX'ed an extended frame
144 if (!(cfd_nominal
->can_id
& CAN_EFF_FLAG
) ||
145 (cfd_rx
->can_id
& CAN_EFF_FLAG
))
149 * - standard part and RTR flag of the TX'ed frame
150 * is not equal the CAN-ID and RTR flag of the RX'ed frame.
152 if ((cfd_nominal
->can_id
& (CAN_RTR_FLAG
| CAN_SFF_MASK
)) !=
153 (cfd_rx
->can_id
& (CAN_RTR_FLAG
| CAN_SFF_MASK
)))
157 * - length is not the same
159 if (cfd_nominal
->len
!= cfd_rx
->len
)
163 * - the data of non RTR frames is different
165 if (!(cfd_nominal
->can_id
& CAN_RTR_FLAG
) &&
166 memcmp(cfd_nominal
->data
, cfd_rx
->data
, cfd_nominal
->len
))
169 /* Affected by Erratum 6 */
170 u64_stats_update_begin(&rkcanfd_stats
->syncp
);
171 u64_stats_inc(&rkcanfd_stats
->tx_extended_as_standard_errors
);
172 u64_stats_update_end(&rkcanfd_stats
->syncp
);
174 /* Manual handling of CAN Bus Error counters. See
175 * rkcanfd_get_corrected_berr_counter() for detailed
186 rkcanfd_xmit_retry(priv
);
192 rkcanfd_fifo_header_empty(const struct rkcanfd_fifo_header
*header
)
194 /* Erratum 5: If the FIFO is empty, we read the same value for
197 return header
->frameinfo
== header
->id
&&
198 header
->frameinfo
== header
->ts
;
201 static int rkcanfd_handle_rx_int_one(struct rkcanfd_priv
*priv
)
203 struct net_device_stats
*stats
= &priv
->ndev
->stats
;
204 struct canfd_frame cfd
[1] = { }, *skb_cfd
;
205 struct rkcanfd_fifo_header header
[1] = { };
210 /* read header into separate struct and convert it later */
211 rkcanfd_read_rep(priv
, RKCANFD_REG_RX_FIFO_RDATA
,
212 header
, sizeof(*header
));
213 /* read data directly into cfd */
214 rkcanfd_read_rep(priv
, RKCANFD_REG_RX_FIFO_RDATA
,
215 cfd
->data
, sizeof(cfd
->data
));
217 /* Erratum 5: Counters for TXEFIFO and RXFIFO may be wrong */
218 if (rkcanfd_fifo_header_empty(header
)) {
219 struct rkcanfd_stats
*rkcanfd_stats
= &priv
->stats
;
221 u64_stats_update_begin(&rkcanfd_stats
->syncp
);
222 u64_stats_inc(&rkcanfd_stats
->rx_fifo_empty_errors
);
223 u64_stats_update_end(&rkcanfd_stats
->syncp
);
228 len
= rkcanfd_fifo_header_to_cfd_header(priv
, header
, cfd
);
230 /* Drop any received CAN-FD frames if CAN-FD mode is not
233 if (header
->frameinfo
& RKCANFD_REG_FD_FRAMEINFO_FDF
&&
234 !(priv
->can
.ctrlmode
& CAN_CTRLMODE_FD
)) {
240 if (rkcanfd_get_tx_pending(priv
)) {
241 bool tx_done
= false;
243 err
= rkcanfd_rxstx_filter(priv
, cfd
, header
->ts
, &tx_done
);
246 if (tx_done
&& !(priv
->can
.ctrlmode
& CAN_CTRLMODE_LOOPBACK
))
250 /* Manual handling of CAN Bus Error counters. See
251 * rkcanfd_get_corrected_berr_counter() for detailed
255 priv
->bec
.rxerr
= min(CAN_ERROR_PASSIVE_THRESHOLD
,
256 priv
->bec
.rxerr
) - 1;
258 if (header
->frameinfo
& RKCANFD_REG_FD_FRAMEINFO_FDF
)
259 skb
= alloc_canfd_skb(priv
->ndev
, &skb_cfd
);
261 skb
= alloc_can_skb(priv
->ndev
, (struct can_frame
**)&skb_cfd
);
269 memcpy(skb_cfd
, cfd
, len
);
270 rkcanfd_skb_set_timestamp(priv
, skb
, header
->ts
);
272 err
= can_rx_offload_queue_timestamp(&priv
->offload
, skb
, header
->ts
);
274 stats
->rx_fifo_errors
++;
279 static inline unsigned int
280 rkcanfd_rx_fifo_get_len(const struct rkcanfd_priv
*priv
)
282 const u32 reg
= rkcanfd_read(priv
, RKCANFD_REG_RX_FIFO_CTRL
);
284 return FIELD_GET(RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT
, reg
);
287 int rkcanfd_handle_rx_int(struct rkcanfd_priv
*priv
)
292 while ((len
= rkcanfd_rx_fifo_get_len(priv
))) {
293 err
= rkcanfd_handle_rx_int_one(priv
);