xref: /linux/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
4 //
5 // Copyright (c) 2019, 2020, 2021, 2023 Pengutronix,
6 //               Marc Kleine-Budde <kernel@pengutronix.de>
7 //
8 // Based on:
9 //
10 // CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
11 //
12 // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org>
13 //
14 
15 #include <linux/bitfield.h>
16 
17 #include "mcp251xfd.h"
18 
mcp251xfd_tx_fifo_sta_full(u32 fifo_sta)19 static inline bool mcp251xfd_tx_fifo_sta_full(u32 fifo_sta)
20 {
21 	return !(fifo_sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF);
22 }
23 
24 static inline int
mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv * priv,u8 * tef_tail)25 mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv,
26 				 u8 *tef_tail)
27 {
28 	u32 tef_ua;
29 	int err;
30 
31 	err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFUA, &tef_ua);
32 	if (err)
33 		return err;
34 
35 	*tef_tail = tef_ua / sizeof(struct mcp251xfd_hw_tef_obj);
36 
37 	return 0;
38 }
39 
mcp251xfd_check_tef_tail(const struct mcp251xfd_priv * priv)40 static int mcp251xfd_check_tef_tail(const struct mcp251xfd_priv *priv)
41 {
42 	u8 tef_tail_chip, tef_tail;
43 	int err;
44 
45 	if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY))
46 		return 0;
47 
48 	err = mcp251xfd_tef_tail_get_from_chip(priv, &tef_tail_chip);
49 	if (err)
50 		return err;
51 
52 	tef_tail = mcp251xfd_get_tef_tail(priv);
53 	if (tef_tail_chip != tef_tail) {
54 		netdev_err(priv->ndev,
55 			   "TEF tail of chip (0x%02x) and ours (0x%08x) inconsistent.\n",
56 			   tef_tail_chip, tef_tail);
57 		return -EILSEQ;
58 	}
59 
60 	return 0;
61 }
62 
63 static int
mcp251xfd_handle_tefif_one(struct mcp251xfd_priv * priv,const struct mcp251xfd_hw_tef_obj * hw_tef_obj,unsigned int * frame_len_ptr)64 mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
65 			   const struct mcp251xfd_hw_tef_obj *hw_tef_obj,
66 			   unsigned int *frame_len_ptr)
67 {
68 	struct net_device_stats *stats = &priv->ndev->stats;
69 	u32 seq, tef_tail_masked, tef_tail;
70 	struct sk_buff *skb;
71 
72 	 /* Use the MCP2517FD mask on the MCP2518FD, too. We only
73 	  * compare 7 bits, this is enough to detect old TEF objects.
74 	  */
75 	seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK,
76 			hw_tef_obj->flags);
77 	tef_tail_masked = priv->tef->tail &
78 		field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
79 
80 	/* According to mcp2518fd erratum DS80000789E 6. the FIFOCI
81 	 * bits of a FIFOSTA register, here the TX FIFO tail index
82 	 * might be corrupted and we might process past the TEF FIFO's
83 	 * head into old CAN frames.
84 	 *
85 	 * Compare the sequence number of the currently processed CAN
86 	 * frame with the expected sequence number. Abort with
87 	 * -EBADMSG if an old CAN frame is detected.
88 	 */
89 	if (seq != tef_tail_masked) {
90 		netdev_dbg(priv->ndev, "%s: chip=0x%02x ring=0x%02x\n", __func__,
91 			   seq, tef_tail_masked);
92 		stats->tx_fifo_errors++;
93 
94 		return -EBADMSG;
95 	}
96 
97 	tef_tail = mcp251xfd_get_tef_tail(priv);
98 	skb = priv->can.echo_skb[tef_tail];
99 	if (skb)
100 		mcp251xfd_skb_set_timestamp_raw(priv, skb, hw_tef_obj->ts);
101 	stats->tx_bytes +=
102 		can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload,
103 							    tef_tail, hw_tef_obj->ts,
104 							    frame_len_ptr);
105 	stats->tx_packets++;
106 	priv->tef->tail++;
107 
108 	return 0;
109 }
110 
111 static int
mcp251xfd_get_tef_len(struct mcp251xfd_priv * priv,u8 * len_p)112 mcp251xfd_get_tef_len(struct mcp251xfd_priv *priv, u8 *len_p)
113 {
114 	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
115 	const u8 shift = tx_ring->obj_num_shift_to_u8;
116 	u8 chip_tx_tail, tail, len;
117 	u32 fifo_sta;
118 	int err;
119 
120 	err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOSTA(priv->tx->fifo_nr),
121 			  &fifo_sta);
122 	if (err)
123 		return err;
124 
125 	if (mcp251xfd_tx_fifo_sta_full(fifo_sta)) {
126 		*len_p = tx_ring->obj_num;
127 		return 0;
128 	}
129 
130 	chip_tx_tail = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta);
131 
132 	err =  mcp251xfd_check_tef_tail(priv);
133 	if (err)
134 		return err;
135 	tail = mcp251xfd_get_tef_tail(priv);
136 
137 	/* First shift to full u8. The subtraction works on signed
138 	 * values, that keeps the difference steady around the u8
139 	 * overflow. The right shift acts on len, which is an u8.
140 	 */
141 	BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(chip_tx_tail));
142 	BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(tail));
143 	BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(len));
144 
145 	len = (chip_tx_tail << shift) - (tail << shift);
146 	*len_p = len >> shift;
147 
148 	return 0;
149 }
150 
151 static inline int
mcp251xfd_tef_obj_read(const struct mcp251xfd_priv * priv,struct mcp251xfd_hw_tef_obj * hw_tef_obj,const u8 offset,const u8 len)152 mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv,
153 		       struct mcp251xfd_hw_tef_obj *hw_tef_obj,
154 		       const u8 offset, const u8 len)
155 {
156 	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
157 	const int val_bytes = regmap_get_val_bytes(priv->map_rx);
158 
159 	if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
160 	    (offset > tx_ring->obj_num ||
161 	     len > tx_ring->obj_num ||
162 	     offset + len > tx_ring->obj_num)) {
163 		netdev_err(priv->ndev,
164 			   "Trying to read too many TEF objects (max=%d, offset=%d, len=%d).\n",
165 			   tx_ring->obj_num, offset, len);
166 		return -ERANGE;
167 	}
168 
169 	return regmap_bulk_read(priv->map_rx,
170 				mcp251xfd_get_tef_obj_addr(offset),
171 				hw_tef_obj,
172 				sizeof(*hw_tef_obj) / val_bytes * len);
173 }
174 
mcp251xfd_ecc_tefif_successful(struct mcp251xfd_priv * priv)175 static inline void mcp251xfd_ecc_tefif_successful(struct mcp251xfd_priv *priv)
176 {
177 	struct mcp251xfd_ecc *ecc = &priv->ecc;
178 
179 	ecc->ecc_stat = 0;
180 }
181 
mcp251xfd_handle_tefif(struct mcp251xfd_priv * priv)182 int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
183 {
184 	struct mcp251xfd_hw_tef_obj hw_tef_obj[MCP251XFD_TX_OBJ_NUM_MAX];
185 	unsigned int total_frame_len = 0;
186 	u8 tef_tail, len, l;
187 	int err, i;
188 
189 	err = mcp251xfd_get_tef_len(priv, &len);
190 	if (err)
191 		return err;
192 
193 	tef_tail = mcp251xfd_get_tef_tail(priv);
194 	l = mcp251xfd_get_tef_linear_len(priv, len);
195 	err = mcp251xfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l);
196 	if (err)
197 		return err;
198 
199 	if (l < len) {
200 		err = mcp251xfd_tef_obj_read(priv, &hw_tef_obj[l], 0, len - l);
201 		if (err)
202 			return err;
203 	}
204 
205 	for (i = 0; i < len; i++) {
206 		unsigned int frame_len = 0;
207 
208 		err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len);
209 		/* -EBADMSG means we're affected by mcp2518fd erratum
210 		 * DS80000789E 6., i.e. the Sequence Number in the TEF
211 		 * doesn't match our tef_tail. Don't process any
212 		 * further and mark processed frames as good.
213 		 */
214 		if (err == -EBADMSG)
215 			goto out_netif_wake_queue;
216 		if (err)
217 			return err;
218 
219 		total_frame_len += frame_len;
220 	}
221 
222 out_netif_wake_queue:
223 	len = i;	/* number of handled goods TEFs */
224 	if (len) {
225 		struct mcp251xfd_tef_ring *ring = priv->tef;
226 		struct mcp251xfd_tx_ring *tx_ring = priv->tx;
227 		int offset;
228 
229 		ring->head += len;
230 
231 		/* Increment the TEF FIFO tail pointer 'len' times in
232 		 * a single SPI message.
233 		 *
234 		 * Note:
235 		 * Calculate offset, so that the SPI transfer ends on
236 		 * the last message of the uinc_xfer array, which has
237 		 * "cs_change == 0", to properly deactivate the chip
238 		 * select.
239 		 */
240 		offset = ARRAY_SIZE(ring->uinc_xfer) - len;
241 		err = spi_sync_transfer(priv->spi,
242 					ring->uinc_xfer + offset, len);
243 		if (err)
244 			return err;
245 
246 		tx_ring->tail += len;
247 		netdev_completed_queue(priv->ndev, len, total_frame_len);
248 
249 		err = mcp251xfd_check_tef_tail(priv);
250 		if (err)
251 			return err;
252 	}
253 
254 	mcp251xfd_ecc_tefif_successful(priv);
255 
256 	if (mcp251xfd_get_tx_free(priv->tx)) {
257 		/* Make sure that anybody stopping the queue after
258 		 * this sees the new tx_ring->tail.
259 		 */
260 		smp_mb();
261 		netif_wake_queue(priv->ndev);
262 	}
263 
264 	if (priv->tx_coalesce_usecs_irq)
265 		hrtimer_start(&priv->tx_irq_timer,
266 			      ns_to_ktime(priv->tx_coalesce_usecs_irq *
267 					  NSEC_PER_USEC),
268 			      HRTIMER_MODE_REL);
269 
270 	return 0;
271 }
272