From: Vladimir Oltean <olteanv@gmail.com>
To: Jakub Kicinski <kuba@kernel.org>,
"David S. Miller" <davem@davemloft.net>,
netdev@vger.kernel.org
Cc: Florian Fainelli <f.fainelli@gmail.com>,
Andrew Lunn <andrew@lunn.ch>,
Vivien Didelot <vivien.didelot@gmail.com>,
Mark Brown <broonie@kernel.org>,
linux-spi@vger.kernel.org, Guenter Roeck <linux@roeck-us.net>,
Vladimir Oltean <vladimir.oltean@nxp.com>
Subject: [PATCH net-next] net: dsa: sja1105: adapt to a SPI controller with a limited max transfer size
Date: Thu, 20 May 2021 16:50:31 +0300 [thread overview]
Message-ID: <20210520135031.2969183-1-olteanv@gmail.com> (raw)
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
next reply other threads:[~2021-05-20 13:50 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-20 13:50 Vladimir Oltean [this message]
2021-05-20 13:56 ` [PATCH net-next] net: dsa: sja1105: adapt to a SPI controller with a limited max transfer size 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210520135031.2969183-1-olteanv@gmail.com \
--to=olteanv@gmail.com \
--cc=andrew@lunn.ch \
--cc=broonie@kernel.org \
--cc=davem@davemloft.net \
--cc=f.fainelli@gmail.com \
--cc=kuba@kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=linux@roeck-us.net \
--cc=netdev@vger.kernel.org \
--cc=vivien.didelot@gmail.com \
--cc=vladimir.oltean@nxp.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).