From patchwork Tue Jan 18 03:17:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wei Huang X-Patchwork-Id: 105985 X-Patchwork-Delegate: qi.z.zhang@intel.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id D9F5DA00C3; Tue, 18 Jan 2022 04:21:00 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 781A4426DC; Tue, 18 Jan 2022 04:20:57 +0100 (CET) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mails.dpdk.org (Postfix) with ESMTP id C8F62426DC; Tue, 18 Jan 2022 04:20:54 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1642476055; x=1674012055; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=m6uXnOd8btdxVPCNwl+4PJgv0K68JznsKpsWez+BFfE=; b=KSt9RzoS56rPzCvTpRTKLSH/afpB8p4ST/uUPdHccGU3mmwg2u6BF18b jC9yZwqgGD2imCsWwstnVrmiqmrpgP4zt4oOmb/vd1raTmxeiiTM1JmH6 DnsA/2XHTl3RwC1O1MUTHF7BCYCx29jAW1xB899FS22qdRVPuwtrpCp3X 8NA4FSaUqI7Ck5fMwh5FlPzFpnxTqQa8dgiNosQSMRs1o55BwpiY/BqHt aN8Fs96tKcNMhJGSmEltQfpLUQChPCLqkOakorEEKf9XZEV9+vj2OfisG +IWS/eJb0RtDEFCrt0k9xYY2Rh1Iga4jmh1B6RAEwevODJpUcCz1PxZhM w==; X-IronPort-AV: E=McAfee;i="6200,9189,10230"; a="331079641" X-IronPort-AV: E=Sophos;i="5.88,296,1635231600"; d="scan'208";a="331079641" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jan 2022 19:20:53 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,296,1635231600"; d="scan'208";a="625372005" Received: from unknown (HELO localhost.localdomain.sh.intel.com) ([10.238.175.107]) by orsmga004.jf.intel.com with ESMTP; 17 Jan 2022 19:20:51 -0800 From: Wei Huang To: dev@dpdk.org, rosen.xu@intel.com, qi.z.zhang@intel.com Cc: stable@dpdk.org, tianfei.zhang@intel.com, ferruh.yigit@intel.com Subject: [PATCH v1 1/4] raw/ifpga/base: fix SPI transaction Date: Mon, 17 Jan 2022 22:17:35 -0500 Message-Id: <20220118031738.2059-2-wei.huang@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20220118031738.2059-1-wei.huang@intel.com> References: <20220118031738.2059-1-wei.huang@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Tianfei Zhang 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 --- 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);