DPDK patches and discussions
 help / color / mirror / Atom feed
From: "Xu, Rosen" <rosen.xu@intel.com>
To: "Huang, Wei" <wei.huang@intel.com>, "dev@dpdk.org" <dev@dpdk.org>,
	"Zhang,  Qi Z" <qi.z.zhang@intel.com>
Cc: "stable@dpdk.org" <stable@dpdk.org>,
	"Zhang, Tianfei" <tianfei.zhang@intel.com>,
	"Yigit, Ferruh" <ferruh.yigit@intel.com>
Subject: RE: [PATCH v1] raw/ifpga/base: fix SPI transaction
Date: Wed, 19 Jan 2022 10:50:49 +0000	[thread overview]
Message-ID: <DM6PR11MB4252282C2670CE945A29918189599@DM6PR11MB4252.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20220119014459.3904-1-wei.huang@intel.com>

Hi,

> -----Original Message-----
> From: Huang, Wei <wei.huang@intel.com>
> Sent: Wednesday, January 19, 2022 9:45
> To: dev@dpdk.org; Xu, Rosen <rosen.xu@intel.com>; Zhang, Qi Z
> <qi.z.zhang@intel.com>
> Cc: stable@dpdk.org; Zhang, Tianfei <tianfei.zhang@intel.com>; Yigit, Ferruh
> <ferruh.yigit@intel.com>
> Subject: [PATCH v1] raw/ifpga/base: fix SPI transaction
> 
> From: Tianfei Zhang <tianfei.zhang@intel.com>
> 
> When EOP is detected, 2 more bytes should be received (may be a
> SPI_PACKET_ESC before last valid byte) then rx should be finished.
> 
> Fixes: 96ebfcf8 ("raw/ifpga/base: add SPI and MAX10 device driver")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
> ---
>  drivers/raw/ifpga/base/opae_spi.c             |  12 ++
>  drivers/raw/ifpga/base/opae_spi.h             |   4 +
>  drivers/raw/ifpga/base/opae_spi_transaction.c | 215 +++++++++++++++------
> -----
>  3 files changed, 140 insertions(+), 91 deletions(-)
> 
> diff --git a/drivers/raw/ifpga/base/opae_spi.c
> b/drivers/raw/ifpga/base/opae_spi.c
> index 9efeecb..ca3d41f 100644
> --- a/drivers/raw/ifpga/base/opae_spi.c
> +++ b/drivers/raw/ifpga/base/opae_spi.c
> @@ -239,6 +239,18 @@ int spi_command(struct altera_spi_device *dev,
> unsigned int chip_select,
>  	return 0;
>  }
> 
> +int spi_write(struct altera_spi_device *dev, unsigned int chip_select,
> +		unsigned int wlen, void *wdata)
> +{
> +	return spi_command(dev, chip_select, wlen, wdata, 0, NULL); }
> +
> +int spi_read(struct altera_spi_device *dev, unsigned int chip_select,
> +		unsigned int rlen, void *rdata)
> +{
> +	return spi_command(dev, chip_select, 0, NULL, rlen, rdata); }
> +
>  struct altera_spi_device *altera_spi_alloc(void *base, int type)  {
>  	struct altera_spi_device *spi_dev =
> diff --git a/drivers/raw/ifpga/base/opae_spi.h
> b/drivers/raw/ifpga/base/opae_spi.h
> index af11656..bcff67d 100644
> --- a/drivers/raw/ifpga/base/opae_spi.h
> +++ b/drivers/raw/ifpga/base/opae_spi.h
> @@ -117,6 +117,10 @@ struct spi_tran_header {
>  	u32 addr;
>  };
> 
> +int spi_read(struct altera_spi_device *dev, unsigned int chip_select,
> +		unsigned int rlen, void *rdata);
> +int spi_write(struct altera_spi_device *dev, unsigned int chip_select,
> +		unsigned int wlen, void *wdata);
>  int spi_command(struct altera_spi_device *dev, unsigned int chip_select,
>  		unsigned int wlen, void *wdata, unsigned int rlen, void
> *rdata);  void spi_cs_deactivate(struct altera_spi_device *dev); diff --git
> a/drivers/raw/ifpga/base/opae_spi_transaction.c
> b/drivers/raw/ifpga/base/opae_spi_transaction.c
> index 006cdb4..cd50d40 100644
> --- a/drivers/raw/ifpga/base/opae_spi_transaction.c
> +++ b/drivers/raw/ifpga/base/opae_spi_transaction.c
> @@ -40,7 +40,7 @@ static void print_buffer(const char *string, void *buffer,
> int len)
>  	printf("%s print buffer, len=%d\n", string, len);
> 
>  	for (i = 0; i < len; i++)
> -		printf("%x ", *(p+i));
> +		printf("%02x ", *(p+i));
>  	printf("\n");
>  }
>  #else
> @@ -72,43 +72,6 @@ static void reorder_phy_data(u8 bits_per_word,
>  	}
>  }
> 
> -enum {
> -	SPI_FOUND_SOP,
> -	SPI_FOUND_EOP,
> -	SPI_NOT_FOUND,
> -};
> -
> -static int resp_find_sop_eop(unsigned char *resp, unsigned int len,
> -		int flags)
> -{
> -	int ret = SPI_NOT_FOUND;
> -
> -	unsigned char *b = resp;
> -
> -	/* find SOP */
> -	if (flags != SPI_FOUND_SOP) {
> -		while (b < resp + len && *b != SPI_PACKET_SOP)
> -			b++;
> -
> -		if (*b != SPI_PACKET_SOP)
> -			goto done;
> -
> -		ret = SPI_FOUND_SOP;
> -	}
> -
> -	/* find EOP */
> -	while (b < resp + len && *b != SPI_PACKET_EOP)
> -		b++;
> -
> -	if (*b != SPI_PACKET_EOP)
> -		goto done;
> -
> -	ret = SPI_FOUND_EOP;
> -
> -done:
> -	return ret;
> -}
> -
>  static void phy_tx_pad(unsigned char *phy_buf, unsigned int phy_buf_len,
>  		unsigned int *aligned_len)
>  {
> @@ -137,6 +100,104 @@ static void phy_tx_pad(unsigned char *phy_buf,
> unsigned int phy_buf_len,
>  		*p++ = SPI_BYTE_IDLE;
>  }
> 
> +#define RX_ALL_IDLE_DATA (SPI_BYTE_IDLE << 24 | SPI_BYTE_IDLE << 16 |
> 	\
> +			 SPI_BYTE_IDLE << 8 | SPI_BYTE_IDLE)
> +
> +static bool all_idle_data(u8 *rxbuf)
> +{
> +	return *(u32 *)rxbuf == RX_ALL_IDLE_DATA; }
> +
> +static unsigned char *find_eop(u8 *rxbuf, u32 BPW) {
> +	return memchr(rxbuf, SPI_PACKET_EOP, BPW); }
> +
> +static int do_spi_txrx(struct spi_transaction_dev *dev,
> +		unsigned char *tx_buffer,
> +		unsigned int tx_len, unsigned char *rx_buffer,
> +		unsigned int rx_len,
> +		unsigned int *actual_rx)
> +{
> +	unsigned int rx_cnt = 0;
> +	int ret = 0;
> +	unsigned int BPW = 4;
> +	bool eop_found = false;
> +	unsigned char *eop;
> +	unsigned char *ptr;
> +	unsigned char *rxbuf = rx_buffer;
> +	int add_byte = 0;
> +	unsigned long ticks;
> +	unsigned long timeout;
> +
> +	/* send command */
> +	ret = spi_write(dev->dev, dev->chipselect, tx_len, tx_buffer);
> +	if (ret)
> +		return -EBUSY;
> +
> +	timeout = rte_get_timer_cycles() +
> +				msecs_to_timer_cycles(2000);
> +
> +	/* read out data */
> +	while (rx_cnt < rx_len) {
> +		ret = spi_read(dev->dev, dev->chipselect, BPW, rxbuf);
> +		if (ret)
> +			return -EBUSY;
> +
> +		/* skip all of invalid data */
> +		if (!eop_found && all_idle_data(rxbuf)) {
> +			ticks = rte_get_timer_cycles();
> +			if (!time_after(ticks, timeout)) {
> +				continue;
> +			} else {
> +				dev_err(dev, "read spi data timeout\n");
> +				return -ETIMEDOUT;
> +			}
> +		}
> +
> +		rx_cnt += BPW;
> +		if (!eop_found) {
> +			/* EOP is found, we read 2 more bytes and exit. */
> +			eop = find_eop(rxbuf, BPW);
> +			if (eop) {
> +				if ((BPW + rxbuf - eop) > 2) {
> +					/*
> +					 * check if the last 2 bytes are already
> +					 * received in current word.
> +					 */
> +					break;
> +				} else if ((BPW + rxbuf - eop) == 2) {
> +					/*
> +					 * skip if last byte is not SPI_BYTE_ESC
> +					 * or SPI_PACKET_ESC. this is the valid
> +					 * end of a response too.
> +					 */
> +					ptr = eop + 1;
> +
> +					if (*ptr != SPI_BYTE_ESC &&
> +							*ptr !=
> SPI_PACKET_ESC)
> +						break;
> +
> +					add_byte = 1;
> +				} else {
> +					add_byte = 2;
> +				}
> +
> +				rx_len = min(rx_len,
> +						IFPGA_ALIGN(rx_cnt +
> +							add_byte, BPW));
> +				eop_found = true;
> +			}
> +		}
> +		rxbuf += BPW;
> +	}
> +
> +	*actual_rx = rx_cnt;
> +	print_buffer("found valid data:", rx_buffer, rx_cnt);
> +
> +	return ret;
> +}
> +
>  static int byte_to_core_convert(struct spi_transaction_dev *dev,
>  		unsigned int send_len, unsigned char *send_data,
>  		unsigned int resp_len, unsigned char *resp_data, @@ -
> 148,15 +209,9 @@ static int byte_to_core_convert(struct
> spi_transaction_dev *dev,
>  	unsigned char *resp_packet = dev->buffer->bytes_resp;
>  	unsigned char *p;
>  	unsigned char current_byte;
> -	unsigned char *tx_buffer;
>  	unsigned int tx_len = 0;
> -	unsigned char *rx_buffer;
> -	unsigned int rx_len = 0;
> -	int retry = 0;
> -	int spi_flags;
> -	unsigned long timeout = msecs_to_timer_cycles(1000);
> -	unsigned long ticks;
>  	unsigned int resp_max_len = 2 * resp_len;
> +	unsigned int actual_rx;
> 
>  	print_buffer("before bytes:", send_data, send_len);
> 
> @@ -190,48 +245,15 @@ static int byte_to_core_convert(struct
> spi_transaction_dev *dev,
> 
>  	print_buffer("after order to spi:", send_packet, tx_len);
> 
> -	/* call spi */
> -	tx_buffer = send_packet;
> -	rx_buffer = resp_packet;
> -	rx_len = resp_max_len;
> -	spi_flags = SPI_NOT_FOUND;
> -
> -read_again:
> -	ret = spi_command(dev->dev, dev->chipselect, tx_len, tx_buffer,
> -			rx_len, rx_buffer);
> +	ret = do_spi_txrx(dev, send_packet, tx_len, resp_packet,
> +			resp_max_len, &actual_rx);
>  	if (ret)
> -		return -EBUSY;
> -
> -	print_buffer("read from spi:", rx_buffer, rx_len);
> -
> -	/* look for SOP firstly*/
> -	ret = resp_find_sop_eop(rx_buffer, rx_len - 1, spi_flags);
> -	if (ret != SPI_FOUND_EOP) {
> -		tx_buffer = NULL;
> -		tx_len = 0;
> -		ticks = rte_get_timer_cycles();
> -		if (time_after(ticks, timeout) &&
> -				retry++ > SPI_MAX_RETRY) {
> -			dev_err(NULL, "Have retry %d, found invalid packet
> data\n",
> -				retry);
> -			return -EBUSY;
> -		}
> -
> -		if (ret == SPI_FOUND_SOP) {
> -			rx_buffer += rx_len;
> -			resp_max_len += rx_len;
> -		}
> -
> -		spi_flags = ret;
> -		goto read_again;
> -	}
> -
> -	print_buffer("found valid data:", resp_packet, resp_max_len);
> +		return ret;
> 
>  	/* analyze response packet */
>  	i = 0;
>  	p = resp_data;
> -	while (i < resp_max_len) {
> +	while (i < actual_rx) {
>  		current_byte = resp_packet[i];
>  		switch (current_byte) {
>  		case SPI_BYTE_IDLE:
> @@ -337,9 +359,13 @@ static int packet_to_byte_conver(struct
> spi_transaction_dev *dev,
>  		current_byte = resp_packet[i];
> 
>  		switch (current_byte) {
> -		case SPI_PACKET_ESC:
> -		case SPI_PACKET_CHANNEL:
>  		case SPI_PACKET_SOP:
> +			dev_err(dev, "error on get SOP after SOP\n");
> +			return -EINVAL;
> +		case SPI_PACKET_CHANNEL:
> +			i += 2;
> +			break;
> +		case SPI_PACKET_ESC:
>  			i++;
>  			current_byte = resp_packet[i];
>  			*p++ = xor_20(current_byte);
> @@ -348,23 +374,30 @@ static int packet_to_byte_conver(struct
> spi_transaction_dev *dev,
>  		case SPI_PACKET_EOP:
>  			i++;
>  			current_byte = resp_packet[i];
> -			if (current_byte == SPI_PACKET_ESC ||
> -					current_byte ==
> SPI_PACKET_CHANNEL ||
> -					current_byte == SPI_PACKET_SOP) {
> +			switch (current_byte) {
> +			case SPI_PACKET_ESC:
>  				i++;
>  				current_byte = resp_packet[i];
>  				*p++ = xor_20(current_byte);
> -			} else
> +				break;
> +			case SPI_PACKET_CHANNEL:
> +			case SPI_PACKET_SOP:
> +			case SPI_PACKET_EOP:
> +				dev_err(dev, "error get SOP/EOP after
> EOP\n");
> +				return -EINVAL;
> +			default:
>  				*p++ = current_byte;
> -			i = valid_resp_len;
> -			break;
> +				break;
> +			}
> +			goto done;
> +
>  		default:
>  			*p++ = current_byte;
>  			i++;
>  		}
> -
>  	}
> 
> +done:
>  	*valid = p - resp_buf;
> 
>  	print_buffer("after packet:", resp_buf, *valid);
> --
> 1.8.3.1

Acked-by: Rosen Xu <rosen.xu@intel.com>

  reply	other threads:[~2022-01-19 10:50 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-19  1:44 Wei Huang
2022-01-19 10:50 ` Xu, Rosen [this message]
2022-01-25  0:40   ` Zhang, Qi Z

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=DM6PR11MB4252282C2670CE945A29918189599@DM6PR11MB4252.namprd11.prod.outlook.com \
    --to=rosen.xu@intel.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@intel.com \
    --cc=qi.z.zhang@intel.com \
    --cc=stable@dpdk.org \
    --cc=tianfei.zhang@intel.com \
    --cc=wei.huang@intel.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).