File Index
Files and directories
Sign in
FILE

mcp251xfd-tef.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c C
  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
 19static inline bool mcp251xfd_tx_fifo_sta_empty(u32 fifo_sta)
 20{
 21	return fifo_sta & MCP251XFD_REG_FIFOSTA_TFERFFIF;
 22}
 23
 24static inline bool mcp251xfd_tx_fifo_sta_less_than_half_full(u32 fifo_sta)
 25{
 26	return fifo_sta & MCP251XFD_REG_FIFOSTA_TFHRFHIF;
 27}
 28
 29static inline int
 30mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv,
 31				 u8 *tef_tail)
 32{
 33	u32 tef_ua;
 34	int err;
 35
 36	err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFUA, &tef_ua);
 37	if (err)
 38		return err;
 39
 40	*tef_tail = tef_ua / sizeof(struct mcp251xfd_hw_tef_obj);
 41
 42	return 0;
 43}
 44
 45static int mcp251xfd_check_tef_tail(const struct mcp251xfd_priv *priv)
 46{
 47	u8 tef_tail_chip, tef_tail;
 48	int err;
 49
 50	if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY))
 51		return 0;
 52
 53	err = mcp251xfd_tef_tail_get_from_chip(priv, &tef_tail_chip);
 54	if (err)
 55		return err;
 56
 57	tef_tail = mcp251xfd_get_tef_tail(priv);
 58	if (tef_tail_chip != tef_tail) {
 59		netdev_err(priv->ndev,
 60			   "TEF tail of chip (0x%02x) and ours (0x%08x) inconsistent.\n",
 61			   tef_tail_chip, tef_tail);
 62		return -EILSEQ;
 63	}
 64
 65	return 0;
 66}
 67
 68static int
 69mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
 70			   const struct mcp251xfd_hw_tef_obj *hw_tef_obj,
 71			   unsigned int *frame_len_ptr)
 72{
 73	struct net_device_stats *stats = &priv->ndev->stats;
 74	u32 seq, tef_tail_masked, tef_tail;
 75	struct sk_buff *skb;
 76
 77	 /* Use the MCP2517FD mask on the MCP2518FD, too. We only
 78	  * compare 7 bits, this is enough to detect old TEF objects.
 79	  */
 80	seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK,
 81			hw_tef_obj->flags);
 82	tef_tail_masked = priv->tef->tail &
 83		field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
 84
 85	/* According to mcp2518fd erratum DS80000789E 6. the FIFOCI
 86	 * bits of a FIFOSTA register, here the TX FIFO tail index
 87	 * might be corrupted and we might process past the TEF FIFO's
 88	 * head into old CAN frames.
 89	 *
 90	 * Compare the sequence number of the currently processed CAN
 91	 * frame with the expected sequence number. Abort with
 92	 * -EBADMSG if an old CAN frame is detected.
 93	 */
 94	if (seq != tef_tail_masked) {
 95		netdev_dbg(priv->ndev, "%s: chip=0x%02x ring=0x%02x\n", __func__,
 96			   seq, tef_tail_masked);
 97		stats->tx_fifo_errors++;
 98
 99		return -EBADMSG;
100	}
101
102	tef_tail = mcp251xfd_get_tef_tail(priv);
103	skb = priv->can.echo_skb[tef_tail];
104	if (skb)
105		mcp251xfd_skb_set_timestamp_raw(priv, skb, hw_tef_obj->ts);
106	stats->tx_bytes +=
107		can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload,
108							    tef_tail, hw_tef_obj->ts,
109							    frame_len_ptr);
110	stats->tx_packets++;
111	priv->tef->tail++;
112
113	return 0;
114}
115
116static int
117mcp251xfd_get_tef_len(struct mcp251xfd_priv *priv, u8 *len_p)
118{
119	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
120	const u8 shift = tx_ring->obj_num_shift_to_u8;
121	u8 chip_tx_tail, tail, len;
122	u32 fifo_sta;
123	int err;
124
125	err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOSTA(priv->tx->fifo_nr),
126			  &fifo_sta);
127	if (err)
128		return err;
129
130	/* If the chip says the TX-FIFO is empty, but there are no TX
131	 * buffers free in the ring, we assume all have been sent.
132	 */
133	if (mcp251xfd_tx_fifo_sta_empty(fifo_sta) &&
134	    mcp251xfd_get_tx_free(tx_ring) == 0) {
135		*len_p = tx_ring->obj_num;
136		return 0;
137	}
138
139	chip_tx_tail = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta);
140
141	err =  mcp251xfd_check_tef_tail(priv);
142	if (err)
143		return err;
144	tail = mcp251xfd_get_tef_tail(priv);
145
146	/* First shift to full u8. The subtraction works on signed
147	 * values, that keeps the difference steady around the u8
148	 * overflow. The right shift acts on len, which is an u8.
149	 */
150	BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(chip_tx_tail));
151	BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(tail));
152	BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(len));
153
154	len = (chip_tx_tail << shift) - (tail << shift);
155	len >>= shift;
156
157	/* According to mcp2518fd erratum DS80000789E 6. the FIFOCI
158	 * bits of a FIFOSTA register, here the TX-FIFO tail index
159	 * might be corrupted.
160	 *
161	 * However here it seems the bit indicating that the TX-FIFO
162	 * is empty (MCP251XFD_REG_FIFOSTA_TFERFFIF) is not correct
163	 * while the TX-FIFO tail index is.
164	 *
165	 * We assume the TX-FIFO is empty, i.e. all pending CAN frames
166	 * haven been send, if:
167	 * - Chip's head and tail index are equal (len == 0).
168	 * - The TX-FIFO is less than half full.
169	 *   (The TX-FIFO empty case has already been checked at the
170	 *    beginning of this function.)
171	 * - No free buffers in the TX ring.
172	 */
173	if (len == 0 && mcp251xfd_tx_fifo_sta_less_than_half_full(fifo_sta) &&
174	    mcp251xfd_get_tx_free(tx_ring) == 0)
175		len = tx_ring->obj_num;
176
177	*len_p = len;
178
179	return 0;
180}
181
182static inline int
183mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv,
184		       struct mcp251xfd_hw_tef_obj *hw_tef_obj,
185		       const u8 offset, const u8 len)
186{
187	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
188	const int val_bytes = regmap_get_val_bytes(priv->map_rx);
189
190	if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
191	    (offset > tx_ring->obj_num ||
192	     len > tx_ring->obj_num ||
193	     offset + len > tx_ring->obj_num)) {
194		netdev_err(priv->ndev,
195			   "Trying to read too many TEF objects (max=%d, offset=%d, len=%d).\n",
196			   tx_ring->obj_num, offset, len);
197		return -ERANGE;
198	}
199
200	return regmap_bulk_read(priv->map_rx,
201				mcp251xfd_get_tef_obj_addr(offset),
202				hw_tef_obj,
203				sizeof(*hw_tef_obj) / val_bytes * len);
204}
205
206static inline void mcp251xfd_ecc_tefif_successful(struct mcp251xfd_priv *priv)
207{
208	struct mcp251xfd_ecc *ecc = &priv->ecc;
209
210	ecc->ecc_stat = 0;
211}
212
213int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
214{
215	struct mcp251xfd_hw_tef_obj hw_tef_obj[MCP251XFD_TX_OBJ_NUM_MAX];
216	unsigned int total_frame_len = 0;
217	u8 tef_tail, len, l;
218	int err, i;
219
220	err = mcp251xfd_get_tef_len(priv, &len);
221	if (err)
222		return err;
223
224	tef_tail = mcp251xfd_get_tef_tail(priv);
225	l = mcp251xfd_get_tef_linear_len(priv, len);
226	err = mcp251xfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l);
227	if (err)
228		return err;
229
230	if (l < len) {
231		err = mcp251xfd_tef_obj_read(priv, &hw_tef_obj[l], 0, len - l);
232		if (err)
233			return err;
234	}
235
236	for (i = 0; i < len; i++) {
237		unsigned int frame_len = 0;
238
239		err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len);
240		/* -EBADMSG means we're affected by mcp2518fd erratum
241		 * DS80000789E 6., i.e. the Sequence Number in the TEF
242		 * doesn't match our tef_tail. Don't process any
243		 * further and mark processed frames as good.
244		 */
245		if (err == -EBADMSG)
246			goto out_netif_wake_queue;
247		if (err)
248			return err;
249
250		total_frame_len += frame_len;
251	}
252
253out_netif_wake_queue:
254	len = i;	/* number of handled goods TEFs */
255	if (len) {
256		struct mcp251xfd_tef_ring *ring = priv->tef;
257		struct mcp251xfd_tx_ring *tx_ring = priv->tx;
258		int offset;
259
260		ring->head += len;
261
262		/* Increment the TEF FIFO tail pointer 'len' times in
263		 * a single SPI message.
264		 *
265		 * Note:
266		 * Calculate offset, so that the SPI transfer ends on
267		 * the last message of the uinc_xfer array, which has
268		 * "cs_change == 0", to properly deactivate the chip
269		 * select.
270		 */
271		offset = ARRAY_SIZE(ring->uinc_xfer) - len;
272		err = spi_sync_transfer(priv->spi,
273					ring->uinc_xfer + offset, len);
274		if (err)
275			return err;
276
277		tx_ring->tail += len;
278		netdev_completed_queue(priv->ndev, len, total_frame_len);
279
280		err = mcp251xfd_check_tef_tail(priv);
281		if (err)
282			return err;
283	}
284
285	mcp251xfd_ecc_tefif_successful(priv);
286
287	if (mcp251xfd_get_tx_free(priv->tx)) {
288		/* Make sure that anybody stopping the queue after
289		 * this sees the new tx_ring->tail.
290		 */
291		smp_mb();
292		netif_wake_queue(priv->ndev);
293	}
294
295	if (priv->tx_coalesce_usecs_irq)
296		hrtimer_start(&priv->tx_irq_timer,
297			      ns_to_ktime(priv->tx_coalesce_usecs_irq *
298					  NSEC_PER_USEC),
299			      HRTIMER_MODE_REL);
300
301	return 0;
302}
~/ Read-only file preview.