Message ID | 20210520211657.3451036-2-olteanv@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Commit | ca021f0dd85140bc96f1381700bbcab753b74658 |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Adapt the sja1105 DSA driver to the SPI controller's transfer limits | expand |
Context | Check | Description |
---|---|---|
netdev/cover_letter | success | Link |
netdev/fixes_present | success | Link |
netdev/patch_count | success | Link |
netdev/tree_selection | success | Clearly marked for net-next |
netdev/subject_prefix | success | Link |
netdev/cc_maintainers | warning | 9 maintainers not CCed: yhs@fb.com kpsingh@kernel.org daniel@iogearbox.net andrii@kernel.org bpf@vger.kernel.org kafai@fb.com ast@kernel.org john.fastabend@gmail.com songliubraving@fb.com |
netdev/source_inline | success | Was 0 now: 0 |
netdev/verify_signedoff | success | Link |
netdev/module_param | success | Was 0 now: 0 |
netdev/build_32bit | success | Errors and warnings before: 0 this patch: 0 |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/verify_fixes | success | Link |
netdev/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 85 lines checked |
netdev/build_allmodconfig_warn | success | Errors and warnings before: 0 this patch: 0 |
netdev/header_inline | success | Link |
On Fri, May 21, 2021 at 12:16:56AM +0300, Vladimir Oltean wrote: > The fact of the matter is that spi_max_message_size() has an ambiguous > meaning if any non-final transfer has cs_change = true. This is not the case, spi_message_max_size() is a limit on the size of a spi_message.
On Mon, May 24, 2021 at 09:35:29AM +0100, Mark Brown wrote: > On Fri, May 21, 2021 at 12:16:56AM +0300, Vladimir Oltean wrote: > > > The fact of the matter is that spi_max_message_size() has an ambiguous > > meaning if any non-final transfer has cs_change = true. > > This is not the case, spi_message_max_size() is a limit on the size of a > spi_message. That is true, although it doesn't mean much, since in the presence of cs_change, a spi_message has no correspondent in the physical world (i.e. you can't look at a logic analyzer dump and say "this spi_message was from this to this point"), and that is the problem really. Describing the controller's inability to send more than N SPI words with continuous chip select using spi_message_max_size() is what seems flawed to me, but it's what we have, and what I've adapted to.
On Mon, May 24, 2021 at 04:02:12PM +0300, Vladimir Oltean wrote: > On Mon, May 24, 2021 at 09:35:29AM +0100, Mark Brown wrote: > > This is not the case, spi_message_max_size() is a limit on the size of a > > spi_message. > That is true, although it doesn't mean much, since in the presence of > cs_change, a spi_message has no correspondent in the physical world > (i.e. you can't look at a logic analyzer dump and say "this spi_message > was from this to this point"), and that is the problem really. It may affect how things are implemented by the driver, for example if the driver can send a command stream to the hardware the limit might be due to that command stream. There is no need or expectation for drivers to pattern match what the're being asked to do and parse out something that should be a string of messages from the spi_message they get, it is expected that client drivers should split things up naturally. > Describing the controller's inability to send more than N SPI words with > continuous chip select using spi_message_max_size() is what seems flawed > to me, but it's what we have, and what I've adapted to. I can't entirely parse that but the limit here isn't to do with how long chip select is asserted for.
diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index f7a1514f81e8..8746e3f158a0 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -29,13 +29,6 @@ sja1105_spi_message_pack(void *buf, const struct sja1105_spi_message *msg) sja1105_pack(buf, &msg->address, 24, 4, size); } -#define sja1105_hdr_xfer(xfers, chunk) \ - ((xfers) + 2 * (chunk)) -#define sja1105_chunk_xfer(xfers, chunk) \ - ((xfers) + 2 * (chunk) + 1) -#define sja1105_hdr_buf(hdr_bufs, chunk) \ - ((hdr_bufs) + (chunk) * SJA1105_SIZE_SPI_MSG_HEADER) - /* If @rw is: * - SPI_WRITE: creates and sends an SPI write message at absolute * address reg_addr, taking @len bytes from *buf @@ -46,41 +39,25 @@ 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) { + u8 hdr_buf[SJA1105_SIZE_SPI_MSG_HEADER] = {0}; 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; + struct spi_transfer xfers[2] = {0}; + struct spi_transfer *chunk_xfer; + struct spi_transfer *hdr_xfer; int num_chunks; int rc, i = 0; - u8 *hdr_bufs; num_chunks = DIV_ROUND_UP(len, SJA1105_SIZE_SPI_MSG_MAXLEN); - /* One transfer for each message header, one for each message - * payload (chunk). - */ - xfers = kcalloc(2 * num_chunks, sizeof(struct spi_transfer), - GFP_KERNEL); - if (!xfers) - return -ENOMEM; - - /* Packed buffers for the num_chunks SPI message headers, - * stored as a contiguous array - */ - hdr_bufs = kcalloc(num_chunks, SJA1105_SIZE_SPI_MSG_HEADER, - GFP_KERNEL); - if (!hdr_bufs) { - kfree(xfers); - return -ENOMEM; - } + hdr_xfer = &xfers[0]; + chunk_xfer = &xfers[1]; for (i = 0; i < num_chunks; i++) { - struct spi_transfer *chunk_xfer = sja1105_chunk_xfer(xfers, i); - struct spi_transfer *hdr_xfer = sja1105_hdr_xfer(xfers, i); - u8 *hdr_buf = sja1105_hdr_buf(hdr_bufs, i); struct spi_transfer *ptp_sts_xfer; struct sja1105_spi_message msg; @@ -129,19 +106,14 @@ static int sja1105_xfer(const struct sja1105_private *priv, chunk.len = min_t(size_t, (ptrdiff_t)(buf + len - chunk.buf), SJA1105_SIZE_SPI_MSG_MAXLEN); - /* De-assert the chip select after each chunk. */ - if (chunk.len) - chunk_xfer->cs_change = 1; + rc = spi_sync_transfer(spi, xfers, 2); + if (rc < 0) { + dev_err(&spi->dev, "SPI transfer failed: %d\n", rc); + return rc; + } } - rc = spi_sync_transfer(spi, xfers, 2 * num_chunks); - if (rc < 0) - dev_err(&spi->dev, "SPI transfer failed: %d\n", rc); - - kfree(hdr_bufs); - kfree(xfers); - - return rc; + return 0; } int sja1105_xfer_buf(const struct sja1105_private *priv,