linux-can.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 0/2] can: mcp251xfd: better workaround broken TX FIFO STA register read
@ 2023-01-24 15:27 Marc Kleine-Budde
  2023-01-24 15:27 ` [PATCH v1 1/2] can: mcp251xfd: tef: prepare to workaround broken RX FIFO tail index erratum Marc Kleine-Budde
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Marc Kleine-Budde @ 2023-01-24 15:27 UTC (permalink / raw)
  To: linux-can
  Cc: Manivannan Sadhasivam, Thomas Kopp, Stefan Althöfer, kernel

Hello,

this is an attempt to better workaround broken TX FIFO STA register
reads. This series implements a workaround similar to the "workaround
broken RX FIFO STA register read" [1] and should be applied to a
kernel tree containing that series.

This gets rid of the "Transmit Event FIFO buffer not empty/full", for
debugging purposes you can enable an error message by adding a
"#define DEBUG" in "drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c".

For every detected error the tx_fifo_error is increased.

[1] https://lore.kernel.org/all/20230119112842.500709-1-mkl@pengutronix.de

regards,
Marc




^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v1 1/2] can: mcp251xfd: tef: prepare to workaround broken RX FIFO tail index erratum
  2023-01-24 15:27 [PATCH v1 0/2] can: mcp251xfd: better workaround broken TX FIFO STA register read Marc Kleine-Budde
@ 2023-01-24 15:27 ` Marc Kleine-Budde
  2023-01-24 15:27 ` [PATCH v1 2/2] can: mcp251xfd: tef: use new workaround Marc Kleine-Budde
  2023-12-04  9:15 ` [PATCH v1 0/2] can: mcp251xfd: better workaround broken TX FIFO STA register read Thomas.Kopp
  2 siblings, 0 replies; 4+ messages in thread
From: Marc Kleine-Budde @ 2023-01-24 15:27 UTC (permalink / raw)
  To: linux-can
  Cc: Manivannan Sadhasivam, Thomas Kopp, Stefan Althöfer, kernel,
	Marc Kleine-Budde

Cc: Stefan Althöfer <Stefan.Althoefer@janztec.com>
Cc: Thomas Kopp <thomas.kopp@microchip.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 .../net/can/spi/mcp251xfd/mcp251xfd-ring.c    |  1 +
 drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c | 50 +++++++++++++------
 drivers/net/can/spi/mcp251xfd/mcp251xfd.h     | 13 ++---
 3 files changed, 40 insertions(+), 24 deletions(-)

diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
index f69d5fc8c9af..8ae9a3091dac 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
@@ -476,6 +476,7 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
 		clear_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags);
 	}
 
+	tx_ring->obj_num_shift_to_u8 = BITS_PER_BYTE - ilog2(tx_ring->obj_num);
 	tx_ring->obj_size = tx_obj_size;
 
 	rem = priv->rx_obj_num;
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
index 0c89e4f33976..e0c5ac943d8b 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
@@ -120,28 +120,49 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
 	return 0;
 }
 
-static int mcp251xfd_tef_ring_update(struct mcp251xfd_priv *priv)
+static inline bool mcp251xfd_tx_fifo_sta_full(u32 fifo_sta)
+{
+	return !(fifo_sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF);
+}
+
+static int
+mcp251xfd_get_tef_len(struct mcp251xfd_priv *priv, u8 *len_p)
 {
 	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
-	unsigned int new_head;
-	u8 chip_tx_tail;
+	u8 chip_tx_tail, tail, shift, len;
+	u32 fifo_sta;
 	int err;
 
-	err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail);
+	err = regmap_read(priv->map_reg,
+			  MCP251XFD_REG_FIFOSTA(priv->tx->fifo_nr),
+			  &fifo_sta);
 	if (err)
 		return err;
 
+	if (mcp251xfd_tx_fifo_sta_full(fifo_sta)) {
+		*len_p = tx_ring->obj_num;
+		return 0;
+	}
+	
 	/* chip_tx_tail, is the next TX-Object send by the HW.
-	 * The new TEF head must be >= the old head, ...
+	 * The new TEF head must be >= the old head.
 	 */
-	new_head = round_down(priv->tef->head, tx_ring->obj_num) + chip_tx_tail;
-	if (new_head <= priv->tef->head)
-		new_head += tx_ring->obj_num;
+	chip_tx_tail = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta);
 
-	/* ... but it cannot exceed the TX head. */
-	priv->tef->head = min(new_head, tx_ring->head);
+	err =  mcp251xfd_check_tef_tail(priv);
+	if (err)
+		return err;
+	tail = mcp251xfd_get_tef_tail(priv);
+
+	/* First shift to full u8. The subtraction works on singed
+	 * values, that keeps the difference steady around the u8
+	 * overflow. The right shift acts on len, which is an u8.
+	 */
+	shift = tx_ring->obj_num_shift_to_u8;
+	len = (chip_tx_tail << shift) - (tail << shift);
+	*len_p = len >> shift;
 
-	return mcp251xfd_check_tef_tail(priv);
+	return 0;
 }
 
 static inline int
@@ -182,13 +203,12 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
 	u8 tef_tail, len, l;
 	int err, i;
 
-	err = mcp251xfd_tef_ring_update(priv);
+	err = mcp251xfd_get_tef_len(priv, &len);
 	if (err)
 		return err;
 
 	tef_tail = mcp251xfd_get_tef_tail(priv);
-	len = mcp251xfd_get_tef_len(priv);
-	l = mcp251xfd_get_tef_linear_len(priv);
+	l = mcp251xfd_get_tef_linear_len(priv, len);
 	err = mcp251xfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l);
 	if (err)
 		return err;
@@ -223,6 +243,8 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
 		struct mcp251xfd_tx_ring *tx_ring = priv->tx;
 		int offset;
 
+		ring->head += len;
+
 		/* Increment the TEF FIFO tail pointer 'len' times in
 		 * a single SPI message.
 		 *
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index 6008d38810e9..66d1fcf82bfd 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -518,6 +518,7 @@ struct mcp251xfd_tef_ring {
 
 	/* u8 obj_num equals tx_ring->obj_num */
 	/* u8 obj_size equals sizeof(struct mcp251xfd_hw_tef_obj) */
+	/* u8 obj_num_shift_to_u8 equals tx_ring->obj_num_shift_to_u8 */
 
 	union mcp251xfd_write_reg_buf irq_enable_buf;
 	struct spi_transfer irq_enable_xfer;
@@ -536,6 +537,7 @@ struct mcp251xfd_tx_ring {
 	u8 nr;
 	u8 fifo_nr;
 	u8 obj_num;
+	u8 obj_num_shift_to_u8;
 	u8 obj_size;
 
 	struct mcp251xfd_tx_obj obj[MCP251XFD_TX_OBJ_NUM_MAX];
@@ -859,17 +861,8 @@ static inline u8 mcp251xfd_get_tef_tail(const struct mcp251xfd_priv *priv)
 	return priv->tef->tail & (priv->tx->obj_num - 1);
 }
 
-static inline u8 mcp251xfd_get_tef_len(const struct mcp251xfd_priv *priv)
-{
-	return priv->tef->head - priv->tef->tail;
-}
-
-static inline u8 mcp251xfd_get_tef_linear_len(const struct mcp251xfd_priv *priv)
+static inline u8 mcp251xfd_get_tef_linear_len(const struct mcp251xfd_priv *priv, u8 len)
 {
-	u8 len;
-
-	len = mcp251xfd_get_tef_len(priv);
-
 	return min_t(u8, len, priv->tx->obj_num - mcp251xfd_get_tef_tail(priv));
 }
 
-- 
2.39.0



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v1 2/2] can: mcp251xfd: tef: use new workaround
  2023-01-24 15:27 [PATCH v1 0/2] can: mcp251xfd: better workaround broken TX FIFO STA register read Marc Kleine-Budde
  2023-01-24 15:27 ` [PATCH v1 1/2] can: mcp251xfd: tef: prepare to workaround broken RX FIFO tail index erratum Marc Kleine-Budde
@ 2023-01-24 15:27 ` Marc Kleine-Budde
  2023-12-04  9:15 ` [PATCH v1 0/2] can: mcp251xfd: better workaround broken TX FIFO STA register read Thomas.Kopp
  2 siblings, 0 replies; 4+ messages in thread
From: Marc Kleine-Budde @ 2023-01-24 15:27 UTC (permalink / raw)
  To: linux-can
  Cc: Manivannan Sadhasivam, Thomas Kopp, Stefan Althöfer, kernel,
	Marc Kleine-Budde

Cc: Stefan Althöfer <Stefan.Althoefer@janztec.com>
Cc: Thomas Kopp <thomas.kopp@microchip.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c | 46 +++++--------------
 1 file changed, 11 insertions(+), 35 deletions(-)

diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
index e0c5ac943d8b..7e42c5077c8a 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
@@ -55,34 +55,6 @@ static int mcp251xfd_check_tef_tail(const struct mcp251xfd_priv *priv)
 	return 0;
 }
 
-static int
-mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq)
-{
-	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
-	u32 tef_sta;
-	int err;
-
-	err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFSTA, &tef_sta);
-	if (err)
-		return err;
-
-	if (tef_sta & MCP251XFD_REG_TEFSTA_TEFOVIF) {
-		netdev_err(priv->ndev,
-			   "Transmit Event FIFO buffer overflow.\n");
-		return -ENOBUFS;
-	}
-
-	netdev_info(priv->ndev,
-		    "Transmit Event FIFO buffer %s. (seq=0x%08x, tef_tail=0x%08x, tef_head=0x%08x, tx_head=0x%08x).\n",
-		    tef_sta & MCP251XFD_REG_TEFSTA_TEFFIF ?
-		    "full" : tef_sta & MCP251XFD_REG_TEFSTA_TEFNEIF ?
-		    "not empty" : "empty",
-		    seq, priv->tef->tail, priv->tef->head, tx_ring->head);
-
-	/* The Sequence Number in the TEF doesn't match our tef_tail. */
-	return -EAGAIN;
-}
-
 static int
 mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
 			   const struct mcp251xfd_hw_tef_obj *hw_tef_obj,
@@ -103,8 +75,13 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
 		field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
 	tef_tail_masked = priv->tef->tail &
 		field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
-	if (seq_masked != tef_tail_masked)
-		return mcp251xfd_handle_tefif_recover(priv, seq);
+	if (seq_masked != tef_tail_masked) {
+		netdev_dbg(priv->ndev, "%s: chip=0x%02x ring=0x%02x\n", __func__,
+			   seq_masked, tef_tail_masked);
+		stats->tx_fifo_errors++;
+		
+		return -EBADMSG;
+	}
 
 	tef_tail = mcp251xfd_get_tef_tail(priv);
 	skb = priv->can.echo_skb[tef_tail];
@@ -223,12 +200,11 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
 		unsigned int frame_len = 0;
 
 		err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len);
-		/* -EAGAIN means the Sequence Number in the TEF
-		 * doesn't match our tef_tail. This can happen if we
-		 * read the TEF objects too early. Leave loop let the
-		 * interrupt handler call us again.
+		/* -EBADMSG means we're affected by an erratum, the
+		 * Sequence Number in the TEF doesn't match our
+		 * tef_tail. Don't process any further.
 		 */
-		if (err == -EAGAIN)
+		if (err == -EBADMSG)
 			goto out_netif_wake_queue;
 		if (err)
 			return err;
-- 
2.39.0



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* RE: [PATCH v1 0/2] can: mcp251xfd: better workaround broken TX FIFO STA register read
  2023-01-24 15:27 [PATCH v1 0/2] can: mcp251xfd: better workaround broken TX FIFO STA register read Marc Kleine-Budde
  2023-01-24 15:27 ` [PATCH v1 1/2] can: mcp251xfd: tef: prepare to workaround broken RX FIFO tail index erratum Marc Kleine-Budde
  2023-01-24 15:27 ` [PATCH v1 2/2] can: mcp251xfd: tef: use new workaround Marc Kleine-Budde
@ 2023-12-04  9:15 ` Thomas.Kopp
  2 siblings, 0 replies; 4+ messages in thread
From: Thomas.Kopp @ 2023-12-04  9:15 UTC (permalink / raw)
  To: mkl, linux-can; +Cc: mani, Stefan.Althoefer, kernel

Hi Marc,

> Hello,
> 
> this is an attempt to better workaround broken TX FIFO STA register
> reads. This series implements a workaround similar to the "workaround
> broken RX FIFO STA register read" [1] and should be applied to a
> kernel tree containing that series.
> 
> This gets rid of the "Transmit Event FIFO buffer not empty/full", for
> debugging purposes you can enable an error message by adding a
> "#define DEBUG" in "drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c".
> 
> For every detected error the tx_fifo_error is increased.
> 
> [1] https://lore.kernel.org/all/20230119112842.500709-1-
> mkl@pengutronix.de
> 
> regards,
> Marc

The new erratasheet is finally live: https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/Errata/MCP2518FD-Errata-DS80000789.pdf

The analysis showed that this specific bug only affects that one register which is covered by the workaround. I believe the workaround worked back then on my boards. Was there any feedback that showed issues with it? Could it be merged now that we have the documentation in place?

Thomas

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-12-04  9:16 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-24 15:27 [PATCH v1 0/2] can: mcp251xfd: better workaround broken TX FIFO STA register read Marc Kleine-Budde
2023-01-24 15:27 ` [PATCH v1 1/2] can: mcp251xfd: tef: prepare to workaround broken RX FIFO tail index erratum Marc Kleine-Budde
2023-01-24 15:27 ` [PATCH v1 2/2] can: mcp251xfd: tef: use new workaround Marc Kleine-Budde
2023-12-04  9:15 ` [PATCH v1 0/2] can: mcp251xfd: better workaround broken TX FIFO STA register read Thomas.Kopp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).