frank-zago/ch341-i2c-spi-gpio

[q] what is max SPI transfer size ?

Sfinx opened this issue · 4 comments

Sfinx commented

while trying to send 256 bytes I'm seeing the corruption/driver freeze after size of 121. Is this is limitation of the driver or ch341 chip itself ?

The max size is set to 124 in the driver (cha341_spi_max_tx_size). I've tested large transfer talking to some SPI displays, but maybe linux never reached that size???

Sfinx commented

Seems like there is no size error check somewhere as trying to send 128 bytes with SPI_IOC_MESSAGE will hang the driver - no further interactions possible, only rmmod/insmod ch341_buses.ko will bring it to live again.

Will something like this work for increasing transfer size ?

diff --git a/ch341-spi.c b/ch341-spi.c
index 432b9b5..19f8751 100644
--- a/ch341-spi.c
+++ b/ch341-spi.c
@@ -48,7 +48,7 @@ static const struct spi_gpio spi_gpio_cs[CH341_SPI_MAX_NUM_DEVICES] = {
 
 static size_t cha341_spi_max_tx_size(struct spi_device *spi)
 {
-       return CH341_SPI_NSEGS * (SEG_SIZE - 1);
+       return CH341_SPI_NSEGS * (CH341_SPI_SEG_SIZE - 1);
 }
 
 /* Send a command and get a reply if requested */
@@ -69,7 +69,7 @@ static int spi_transfer(struct ch341_device *dev, u8 *buf, int len, int nsegs)
        do {
                rc = usb_bulk_msg(dev->usb_dev,
                                  usb_rcvbulkpipe(dev->usb_dev, dev->ep_in),
-                                 &buf[sz_read], SEG_SIZE, &actual, DEFAULT_TIMEOUT);
+                                 &buf[sz_read], CH341_SPI_SEG_SIZE, &actual, DEFAULT_TIMEOUT);
 
                if (rc == 0)
                        sz_read += actual;
@@ -102,12 +102,12 @@ static unsigned int copy_to_device(u8 *buf, unsigned int buf_idx,
        int to_copy;
 
        while (len) {
-               if (buf_idx % SEG_SIZE == 0) {
+               if (buf_idx % CH341_SPI_SEG_SIZE == 0) {
                        buf[buf_idx] = CH341_CMD_SPI_STREAM;
                        buf_idx++;
                }
 
-               to_copy = min(len, SEG_SIZE - (buf_idx % SEG_SIZE));
+               to_copy = min(len, CH341_SPI_SEG_SIZE - (buf_idx % CH341_SPI_SEG_SIZE));
 
                if (tx_buf) {
                        if (lsb)
diff --git a/ch341.h b/ch341.h
index 56488df..5e24efe 100644
--- a/ch341.h
+++ b/ch341.h
@@ -25,6 +25,7 @@
  * crash if more than 4.
  */
 #define CH341_SPI_NSEGS 4
+#define CH341_SPI_SEG_SIZE 64
 
 #define CH341_USB_MAX_INTR_SIZE 8
 
@@ -74,7 +75,7 @@ struct ch341_device {
        struct spi_client {
                struct spi_device *slave;
                struct gpio_desc *gpio;
-               u8 buf[CH341_SPI_NSEGS * SEG_SIZE];
+               u8 buf[CH341_SPI_NSEGS * CH341_SPI_SEG_SIZE];
        } spi_clients[CH341_SPI_MAX_NUM_DEVICES];
 };

That's not correct. The chip is using 32-bytes segments, not 64.

I tested again with an eeprom using the spi-nor driver. I saw no issue, and the max transfer size was always 128 bytes.

What are you doing to see corruption?

Sfinx commented

I needed 256 bytes, 128 is not enough. The driver module just hangs if transfer size is bigger 128. I see, seems like 128b is somewhat unknown limit.