Re: [BUG] spi/spi-atmel: DMA rx buffer corruption with SPI_IOC_MESSAGE

From: Richard Genoud
Date: Tue Oct 08 2013 - 08:34:36 EST


2013/10/8 Mark Brown <broonie@xxxxxxxxxx>:
> On Tue, Oct 08, 2013 at 12:44:16PM +0200, Richard Genoud wrote:
>
>> I'm attaching the test software that I used ( ./spi_test /dev/spidevx.x )
>
> Looks like the attachment got forgotten?
arg !!!

thanks !
here it is.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>


#define SMALL 2
#define BIG 120
#define NB 3

const int FILL_BYTE = 0xaa;
const int RX_BYTE = 0xFF;
const unsigned int MAX_LOOPS = 50;

struct spi_ioc_transfer xfer[NB];
char rx_header[SMALL];
char rx_buffer[BIG];
char rx_footer[SMALL];
char tx_header[SMALL];
char tx_buffer[BIG];
char tx_footer[SMALL];

void dump(char *buf, unsigned int len)
{
unsigned int i;

for (i = 0; i < len; i++) {
printf("%2.2x ", buf[i]);
if (((i + 1) % 16) == 0)
printf("\n");
}
printf("\n");
}

/*
* Checks if the buffer buf is filled with val bytes
* return 0 if it is, 1 if a byte is != val
*/
int check_buf(char *buf, unsigned int len, unsigned int val)
{
while (len--)
if (buf[len] != RX_BYTE)
return 1;
return 0;
}

void usage(const char *progname)
{
printf("Usage: %s spidev\n", progname);
}

int main(int argc, char **argv)
{
const char *spi_dev_name;
int err = 0;
int fd;
unsigned int i;
unsigned int loops = MAX_LOOPS;

if (argc < 2) {
usage(argv[0]);
err = -1;
goto out;
}

spi_dev_name = argv[1];

fd = open(spi_dev_name, O_RDWR);
if (fd < 0) {
perror("open");
err = -1;
goto out;
}

xfer[0].tx_buf = (unsigned long)tx_header;
xfer[0].rx_buf = (unsigned long)rx_header;
xfer[0].len = SMALL;
xfer[1].tx_buf = (unsigned long)tx_buffer;
xfer[1].rx_buf = (unsigned long)rx_buffer;
xfer[1].len = BIG;
xfer[2].tx_buf = (unsigned long)tx_footer;
xfer[2].rx_buf = (unsigned long)rx_footer;
xfer[2].len = SMALL;

while (loops--) {
for (i = 0; i < NB; i++) {
memset((void *)xfer[i].tx_buf, FILL_BYTE, xfer[i].len);
memset((void *)xfer[i].rx_buf, FILL_BYTE, xfer[i].len);
}

err = ioctl(fd, SPI_IOC_MESSAGE(NB), xfer);
if (err < 0) {
perror("ioctl");
break;
}
if (err != (sizeof(rx_buffer) + sizeof(rx_footer)
+ sizeof(rx_header))) {
printf("message too short: %d bytes\n", err);
break;
}
for (i = 0; i < NB; i++) {
err = check_buf((char *)(xfer[i].rx_buf), xfer[i].len, RX_BYTE);
if (err)
dump((char *)(xfer[i].rx_buf), xfer[i].len);
}
}

(void) close(fd);
out:
return err;
}