netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next] net: dsa: sja1105: adapt to a SPI controller with a limited max transfer size
@ 2021-05-20 13:50 Vladimir Oltean
  2021-05-20 13:56 ` Mark Brown
  0 siblings, 1 reply; 6+ messages in thread
From: Vladimir Oltean @ 2021-05-20 13:50 UTC (permalink / raw)
  To: Jakub Kicinski, David S. Miller, netdev
  Cc: Florian Fainelli, Andrew Lunn, Vivien Didelot, Mark Brown,
	linux-spi, Guenter Roeck, Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

The static config of the sja1105 switch is a long stream of bytes which
is programmed to the hardware in chunks (portions with the chip select
continuously asserted) of max 256 bytes each.

Only that certain SPI controllers, such as the spi-sc18is602 I2C-to-SPI
bridge, cannot keep the chip select asserted for that long.
The spi_max_transfer_size() and spi_max_message_size() functions are how
the controller can impose its hardware limitations upon the SPI
peripheral driver.

The sja1105 sends its static config to the SPI master as a huge
scatter/gather spi_message - commit 08839c06e96f ("net: dsa: sja1105:
Switch to scatter/gather API for SPI") contains a description of that.
That spi_message contains the following list of spi_transfers:

                |                         |      cs_change
 spi_transfer # |       Contents          | (deassert chip select)
 ---------------|-------------------------|-----------------------
       1        |   SPI message header 1  |         no
       2        |  Static config chunk 1  |         yes
       3        |   SPI message header 2  |         no
       4        |  Static config chunk 2  |         yes
      ...       |           ...           |         ...

Since what the SPI master does not support is keeping the CS asserted
for more than, say, 200 bytes, we must limit the summed length of the
spi_transfers with cs_change deasserted (1+2, 3+4 etc) lower than 200.

This is a bit fuzzy, but I think the proper way to handle this is to
just look at the spi_max_transfer_size() reported by the master, and
adapt to that. We can disregard the spi_max_message_size() limit since I
suppose that assumes no cs_change - but then again, spi_max_transfer_size
is itself capped by spi_max_message_size, which makes sense.

Regression-tested on a switch connected to a controller with no
limitations (spi-fsl-dspi) as well as with one with caps for both
max_transfer_size and max_message_size (spi-sc18is602).

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/sja1105/sja1105_spi.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c
index f7a1514f81e8..ac766def45c8 100644
--- a/drivers/net/dsa/sja1105/sja1105_spi.c
+++ b/drivers/net/dsa/sja1105/sja1105_spi.c
@@ -46,18 +46,22 @@ static int sja1105_xfer(const struct sja1105_private *priv,
 			sja1105_spi_rw_mode_t rw, u64 reg_addr, u8 *buf,
 			size_t len, struct ptp_system_timestamp *ptp_sts)
 {
+	struct spi_device *spi = priv->spidev;
 	struct sja1105_chunk chunk = {
-		.len = min_t(size_t, len, SJA1105_SIZE_SPI_MSG_MAXLEN),
 		.reg_addr = reg_addr,
 		.buf = buf,
 	};
-	struct spi_device *spi = priv->spidev;
 	struct spi_transfer *xfers;
+	size_t xfer_len;
 	int num_chunks;
 	int rc, i = 0;
 	u8 *hdr_bufs;
 
-	num_chunks = DIV_ROUND_UP(len, SJA1105_SIZE_SPI_MSG_MAXLEN);
+	xfer_len = min_t(size_t, SJA1105_SIZE_SPI_MSG_MAXLEN,
+			 spi_max_transfer_size(spi) - SJA1105_SIZE_SPI_MSG_HEADER);
+
+	num_chunks = DIV_ROUND_UP(len, xfer_len);
+	chunk.len = min(len, xfer_len);
 
 	/* One transfer for each message header, one for each message
 	 * payload (chunk).
@@ -127,7 +131,7 @@ static int sja1105_xfer(const struct sja1105_private *priv,
 		chunk.buf += chunk.len;
 		chunk.reg_addr += chunk.len / 4;
 		chunk.len = min_t(size_t, (ptrdiff_t)(buf + len - chunk.buf),
-				  SJA1105_SIZE_SPI_MSG_MAXLEN);
+				  xfer_len);
 
 		/* De-assert the chip select after each chunk. */
 		if (chunk.len)
-- 
2.25.1


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

end of thread, other threads:[~2021-05-20 16:54 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-05-20 13:50 [PATCH net-next] net: dsa: sja1105: adapt to a SPI controller with a limited max transfer size Vladimir Oltean
2021-05-20 13:56 ` Mark Brown
2021-05-20 14:06   ` Vladimir Oltean
2021-05-20 14:29     ` Mark Brown
2021-05-20 14:54       ` Vladimir Oltean
2021-05-20 16:54         ` Mark Brown

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).