All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiawen Wu <jiawenwu@trustnetic.com>
To: dev@dpdk.org
Cc: Jiawen Wu <jiawenwu@trustnetic.com>
Subject: [dpdk-dev] [PATCH v6 06/19] net/ngbe: init and validate EEPROM
Date: Thu, 17 Jun 2021 18:59:52 +0800	[thread overview]
Message-ID: <20210617110005.4132926-7-jiawenwu@trustnetic.com> (raw)
In-Reply-To: <20210617110005.4132926-1-jiawenwu@trustnetic.com>

Reset swfw lock before NVM access, init EEPROM and validate the
checksum.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/ngbe/base/meson.build   |   2 +
 drivers/net/ngbe/base/ngbe_dummy.h  |  23 ++++
 drivers/net/ngbe/base/ngbe_eeprom.c | 203 ++++++++++++++++++++++++++++
 drivers/net/ngbe/base/ngbe_eeprom.h |  17 +++
 drivers/net/ngbe/base/ngbe_hw.c     |  83 ++++++++++++
 drivers/net/ngbe/base/ngbe_hw.h     |   3 +
 drivers/net/ngbe/base/ngbe_mng.c    | 198 +++++++++++++++++++++++++++
 drivers/net/ngbe/base/ngbe_mng.h    |  65 +++++++++
 drivers/net/ngbe/base/ngbe_type.h   |  24 ++++
 drivers/net/ngbe/ngbe_ethdev.c      |  39 ++++++
 10 files changed, 657 insertions(+)
 create mode 100644 drivers/net/ngbe/base/ngbe_eeprom.c
 create mode 100644 drivers/net/ngbe/base/ngbe_eeprom.h
 create mode 100644 drivers/net/ngbe/base/ngbe_mng.c
 create mode 100644 drivers/net/ngbe/base/ngbe_mng.h

diff --git a/drivers/net/ngbe/base/meson.build b/drivers/net/ngbe/base/meson.build
index fdbfa99916..ddd122ec45 100644
--- a/drivers/net/ngbe/base/meson.build
+++ b/drivers/net/ngbe/base/meson.build
@@ -2,7 +2,9 @@
 # Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd.
 
 sources = [
+	'ngbe_eeprom.c',
 	'ngbe_hw.c',
+	'ngbe_mng.c',
 ]
 
 error_cflags = []
diff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h
index 75b4e50bca..ade03eae81 100644
--- a/drivers/net/ngbe/base/ngbe_dummy.h
+++ b/drivers/net/ngbe/base/ngbe_dummy.h
@@ -28,9 +28,32 @@
 static inline void ngbe_bus_set_lan_id_dummy(struct ngbe_hw *TUP0)
 {
 }
+/* struct ngbe_rom_operations */
+static inline s32 ngbe_rom_init_params_dummy(struct ngbe_hw *TUP0)
+{
+	return NGBE_ERR_OPS_DUMMY;
+}
+static inline s32 ngbe_rom_validate_checksum_dummy(struct ngbe_hw *TUP0,
+					u16 *TUP1)
+{
+	return NGBE_ERR_OPS_DUMMY;
+}
+static inline s32 ngbe_mac_acquire_swfw_sync_dummy(struct ngbe_hw *TUP0,
+					u32 TUP1)
+{
+	return NGBE_ERR_OPS_DUMMY;
+}
+static inline void ngbe_mac_release_swfw_sync_dummy(struct ngbe_hw *TUP0,
+					u32 TUP1)
+{
+}
 static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw)
 {
 	hw->bus.set_lan_id = ngbe_bus_set_lan_id_dummy;
+	hw->rom.init_params = ngbe_rom_init_params_dummy;
+	hw->rom.validate_checksum = ngbe_rom_validate_checksum_dummy;
+	hw->mac.acquire_swfw_sync = ngbe_mac_acquire_swfw_sync_dummy;
+	hw->mac.release_swfw_sync = ngbe_mac_release_swfw_sync_dummy;
 }
 
 #endif /* _NGBE_TYPE_DUMMY_H_ */
diff --git a/drivers/net/ngbe/base/ngbe_eeprom.c b/drivers/net/ngbe/base/ngbe_eeprom.c
new file mode 100644
index 0000000000..0ebbb7a29e
--- /dev/null
+++ b/drivers/net/ngbe/base/ngbe_eeprom.c
@@ -0,0 +1,203 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd.
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#include "ngbe_hw.h"
+#include "ngbe_mng.h"
+#include "ngbe_eeprom.h"
+
+/**
+ *  ngbe_init_eeprom_params - Initialize EEPROM params
+ *  @hw: pointer to hardware structure
+ *
+ *  Initializes the EEPROM parameters ngbe_rom_info within the
+ *  ngbe_hw struct in order to set up EEPROM access.
+ **/
+s32 ngbe_init_eeprom_params(struct ngbe_hw *hw)
+{
+	struct ngbe_rom_info *eeprom = &hw->rom;
+	u32 eec;
+	u16 eeprom_size;
+
+	DEBUGFUNC("ngbe_init_eeprom_params");
+
+	if (eeprom->type != ngbe_eeprom_unknown)
+		return 0;
+
+	eeprom->type = ngbe_eeprom_none;
+	/* Set default semaphore delay to 10ms which is a well
+	 * tested value
+	 */
+	eeprom->semaphore_delay = 10; /*ms*/
+	/* Clear EEPROM page size, it will be initialized as needed */
+	eeprom->word_page_size = 0;
+
+	/*
+	 * Check for EEPROM present first.
+	 * If not present leave as none
+	 */
+	eec = rd32(hw, NGBE_SPISTAT);
+	if (!(eec & NGBE_SPISTAT_BPFLASH)) {
+		eeprom->type = ngbe_eeprom_flash;
+
+		/*
+		 * SPI EEPROM is assumed here.  This code would need to
+		 * change if a future EEPROM is not SPI.
+		 */
+		eeprom_size = 4096;
+		eeprom->word_size = eeprom_size >> 1;
+	}
+
+	eeprom->address_bits = 16;
+	eeprom->sw_addr = 0x80;
+
+	DEBUGOUT("eeprom params: type = %d, size = %d, address bits: "
+		  "%d %d\n", eeprom->type, eeprom->word_size,
+		  eeprom->address_bits, eeprom->sw_addr);
+
+	return 0;
+}
+
+/**
+ *  ngbe_get_eeprom_semaphore - Get hardware semaphore
+ *  @hw: pointer to hardware structure
+ *
+ *  Sets the hardware semaphores so EEPROM access can occur for bit-bang method
+ **/
+s32 ngbe_get_eeprom_semaphore(struct ngbe_hw *hw)
+{
+	s32 status = NGBE_ERR_EEPROM;
+	u32 timeout = 2000;
+	u32 i;
+	u32 swsm;
+
+	DEBUGFUNC("ngbe_get_eeprom_semaphore");
+
+
+	/* Get SMBI software semaphore between device drivers first */
+	for (i = 0; i < timeout; i++) {
+		/*
+		 * If the SMBI bit is 0 when we read it, then the bit will be
+		 * set and we have the semaphore
+		 */
+		swsm = rd32(hw, NGBE_SWSEM);
+		if (!(swsm & NGBE_SWSEM_PF)) {
+			status = 0;
+			break;
+		}
+		usec_delay(50);
+	}
+
+	if (i == timeout) {
+		DEBUGOUT("Driver can't access the eeprom - SMBI Semaphore "
+			 "not granted.\n");
+		/*
+		 * this release is particularly important because our attempts
+		 * above to get the semaphore may have succeeded, and if there
+		 * was a timeout, we should unconditionally clear the semaphore
+		 * bits to free the driver to make progress
+		 */
+		ngbe_release_eeprom_semaphore(hw);
+
+		usec_delay(50);
+		/*
+		 * one last try
+		 * If the SMBI bit is 0 when we read it, then the bit will be
+		 * set and we have the semaphore
+		 */
+		swsm = rd32(hw, NGBE_SWSEM);
+		if (!(swsm & NGBE_SWSEM_PF))
+			status = 0;
+	}
+
+	/* Now get the semaphore between SW/FW through the SWESMBI bit */
+	if (status == 0) {
+		for (i = 0; i < timeout; i++) {
+			/* Set the SW EEPROM semaphore bit to request access */
+			wr32m(hw, NGBE_MNGSWSYNC,
+				NGBE_MNGSWSYNC_REQ, NGBE_MNGSWSYNC_REQ);
+
+			/*
+			 * If we set the bit successfully then we got the
+			 * semaphore.
+			 */
+			swsm = rd32(hw, NGBE_MNGSWSYNC);
+			if (swsm & NGBE_MNGSWSYNC_REQ)
+				break;
+
+			usec_delay(50);
+		}
+
+		/*
+		 * Release semaphores and return error if SW EEPROM semaphore
+		 * was not granted because we don't have access to the EEPROM
+		 */
+		if (i >= timeout) {
+			DEBUGOUT("SWESMBI Software EEPROM semaphore not granted.\n");
+			ngbe_release_eeprom_semaphore(hw);
+			status = NGBE_ERR_EEPROM;
+		}
+	} else {
+		DEBUGOUT("Software semaphore SMBI between device drivers "
+			 "not granted.\n");
+	}
+
+	return status;
+}
+
+/**
+ *  ngbe_release_eeprom_semaphore - Release hardware semaphore
+ *  @hw: pointer to hardware structure
+ *
+ *  This function clears hardware semaphore bits.
+ **/
+void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw)
+{
+	DEBUGFUNC("ngbe_release_eeprom_semaphore");
+
+	wr32m(hw, NGBE_MNGSWSYNC, NGBE_MNGSWSYNC_REQ, 0);
+	wr32m(hw, NGBE_SWSEM, NGBE_SWSEM_PF, 0);
+	ngbe_flush(hw);
+}
+
+/**
+ *  ngbe_validate_eeprom_checksum_em - Validate EEPROM checksum
+ *  @hw: pointer to hardware structure
+ *  @checksum_val: calculated checksum
+ *
+ *  Performs checksum calculation and validates the EEPROM checksum.  If the
+ *  caller does not need checksum_val, the value can be NULL.
+ **/
+s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw,
+					   u16 *checksum_val)
+{
+	u32 eeprom_cksum_devcap = 0;
+	int err = 0;
+
+	DEBUGFUNC("ngbe_validate_eeprom_checksum_em");
+	UNREFERENCED_PARAMETER(checksum_val);
+
+	/* Check EEPROM only once */
+	if (hw->bus.lan_id == 0) {
+		wr32(hw, NGBE_CALSUM_CAP_STATUS, 0x0);
+		wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, 0x0);
+	} else {
+		eeprom_cksum_devcap = rd32(hw, NGBE_CALSUM_CAP_STATUS);
+		hw->rom.saved_version = rd32(hw, NGBE_EEPROM_VERSION_STORE_REG);
+	}
+
+	if (hw->bus.lan_id == 0 || eeprom_cksum_devcap == 0) {
+		err = ngbe_hic_check_cap(hw);
+		if (err != 0) {
+			PMD_INIT_LOG(ERR,
+				"The EEPROM checksum is not valid: %d", err);
+			return -EIO;
+		}
+	}
+
+	hw->rom.cksum_devcap = eeprom_cksum_devcap & 0xffff;
+
+	return err;
+}
+
diff --git a/drivers/net/ngbe/base/ngbe_eeprom.h b/drivers/net/ngbe/base/ngbe_eeprom.h
new file mode 100644
index 0000000000..0c2819df4a
--- /dev/null
+++ b/drivers/net/ngbe/base/ngbe_eeprom.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd.
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#ifndef _NGBE_EEPROM_H_
+#define _NGBE_EEPROM_H_
+
+#define NGBE_CALSUM_CAP_STATUS         0x10224
+#define NGBE_EEPROM_VERSION_STORE_REG  0x1022C
+
+s32 ngbe_init_eeprom_params(struct ngbe_hw *hw);
+s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw, u16 *checksum_val);
+s32 ngbe_get_eeprom_semaphore(struct ngbe_hw *hw);
+void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw);
+
+#endif /* _NGBE_EEPROM_H_ */
diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c
index 014bb0faee..de6b75e1c0 100644
--- a/drivers/net/ngbe/base/ngbe_hw.c
+++ b/drivers/net/ngbe/base/ngbe_hw.c
@@ -4,6 +4,8 @@
  */
 
 #include "ngbe_type.h"
+#include "ngbe_eeprom.h"
+#include "ngbe_mng.h"
 #include "ngbe_hw.h"
 
 /**
@@ -25,6 +27,77 @@ void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw)
 	bus->func = bus->lan_id;
 }
 
+/**
+ *  ngbe_acquire_swfw_sync - Acquire SWFW semaphore
+ *  @hw: pointer to hardware structure
+ *  @mask: Mask to specify which semaphore to acquire
+ *
+ *  Acquires the SWFW semaphore through the MNGSEM register for the specified
+ *  function (CSR, PHY0, PHY1, EEPROM, Flash)
+ **/
+s32 ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask)
+{
+	u32 mngsem = 0;
+	u32 swmask = NGBE_MNGSEM_SW(mask);
+	u32 fwmask = NGBE_MNGSEM_FW(mask);
+	u32 timeout = 200;
+	u32 i;
+
+	DEBUGFUNC("ngbe_acquire_swfw_sync");
+
+	for (i = 0; i < timeout; i++) {
+		/*
+		 * SW NVM semaphore bit is used for access to all
+		 * SW_FW_SYNC bits (not just NVM)
+		 */
+		if (ngbe_get_eeprom_semaphore(hw))
+			return NGBE_ERR_SWFW_SYNC;
+
+		mngsem = rd32(hw, NGBE_MNGSEM);
+		if (mngsem & (fwmask | swmask)) {
+			/* Resource is currently in use by FW or SW */
+			ngbe_release_eeprom_semaphore(hw);
+			msec_delay(5);
+		} else {
+			mngsem |= swmask;
+			wr32(hw, NGBE_MNGSEM, mngsem);
+			ngbe_release_eeprom_semaphore(hw);
+			return 0;
+		}
+	}
+
+	/* If time expired clear the bits holding the lock and retry */
+	if (mngsem & (fwmask | swmask))
+		ngbe_release_swfw_sync(hw, mngsem & (fwmask | swmask));
+
+	msec_delay(5);
+	return NGBE_ERR_SWFW_SYNC;
+}
+
+/**
+ *  ngbe_release_swfw_sync - Release SWFW semaphore
+ *  @hw: pointer to hardware structure
+ *  @mask: Mask to specify which semaphore to release
+ *
+ *  Releases the SWFW semaphore through the MNGSEM register for the specified
+ *  function (CSR, PHY0, PHY1, EEPROM, Flash)
+ **/
+void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask)
+{
+	u32 mngsem;
+	u32 swmask = mask;
+
+	DEBUGFUNC("ngbe_release_swfw_sync");
+
+	ngbe_get_eeprom_semaphore(hw);
+
+	mngsem = rd32(hw, NGBE_MNGSEM);
+	mngsem &= ~swmask;
+	wr32(hw, NGBE_MNGSEM, mngsem);
+
+	ngbe_release_eeprom_semaphore(hw);
+}
+
 /**
  *  ngbe_set_mac_type - Sets MAC type
  *  @hw: pointer to the HW structure
@@ -134,12 +207,22 @@ void ngbe_map_device_id(struct ngbe_hw *hw)
 s32 ngbe_init_ops_pf(struct ngbe_hw *hw)
 {
 	struct ngbe_bus_info *bus = &hw->bus;
+	struct ngbe_mac_info *mac = &hw->mac;
+	struct ngbe_rom_info *rom = &hw->rom;
 
 	DEBUGFUNC("ngbe_init_ops_pf");
 
 	/* BUS */
 	bus->set_lan_id = ngbe_set_lan_id_multi_port;
 
+	/* MAC */
+	mac->acquire_swfw_sync = ngbe_acquire_swfw_sync;
+	mac->release_swfw_sync = ngbe_release_swfw_sync;
+
+	/* EEPROM */
+	rom->init_params = ngbe_init_eeprom_params;
+	rom->validate_checksum = ngbe_validate_eeprom_checksum_em;
+
 	return 0;
 }
 
diff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h
index 7d5de49248..5e508fb67f 100644
--- a/drivers/net/ngbe/base/ngbe_hw.h
+++ b/drivers/net/ngbe/base/ngbe_hw.h
@@ -10,6 +10,9 @@
 
 void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw);
 
+s32 ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask);
+void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask);
+
 s32 ngbe_init_shared_code(struct ngbe_hw *hw);
 s32 ngbe_set_mac_type(struct ngbe_hw *hw);
 s32 ngbe_init_ops_pf(struct ngbe_hw *hw);
diff --git a/drivers/net/ngbe/base/ngbe_mng.c b/drivers/net/ngbe/base/ngbe_mng.c
new file mode 100644
index 0000000000..87891a91e1
--- /dev/null
+++ b/drivers/net/ngbe/base/ngbe_mng.c
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd.
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#include "ngbe_type.h"
+#include "ngbe_mng.h"
+
+/**
+ *  ngbe_hic_unlocked - Issue command to manageability block unlocked
+ *  @hw: pointer to the HW structure
+ *  @buffer: command to write and where the return status will be placed
+ *  @length: length of buffer, must be multiple of 4 bytes
+ *  @timeout: time in ms to wait for command completion
+ *
+ *  Communicates with the manageability block. On success return 0
+ *  else returns semaphore error when encountering an error acquiring
+ *  semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ *
+ *  This function assumes that the NGBE_MNGSEM_SWMBX semaphore is held
+ *  by the caller.
+ **/
+static s32
+ngbe_hic_unlocked(struct ngbe_hw *hw, u32 *buffer, u32 length, u32 timeout)
+{
+	u32 value, loop;
+	u16 i, dword_len;
+
+	DEBUGFUNC("ngbe_hic_unlocked");
+
+	if (!length || length > NGBE_PMMBX_BSIZE) {
+		DEBUGOUT("Buffer length failure buffersize=%d.\n", length);
+		return NGBE_ERR_HOST_INTERFACE_COMMAND;
+	}
+
+	/* Calculate length in DWORDs. We must be DWORD aligned */
+	if (length % sizeof(u32)) {
+		DEBUGOUT("Buffer length failure, not aligned to dword");
+		return NGBE_ERR_INVALID_ARGUMENT;
+	}
+
+	dword_len = length >> 2;
+
+	/* The device driver writes the relevant command block
+	 * into the ram area.
+	 */
+	for (i = 0; i < dword_len; i++) {
+		wr32a(hw, NGBE_MNGMBX, i, cpu_to_le32(buffer[i]));
+		buffer[i] = rd32a(hw, NGBE_MNGMBX, i);
+	}
+	ngbe_flush(hw);
+
+	/* Setting this bit tells the ARC that a new command is pending. */
+	wr32m(hw, NGBE_MNGMBXCTL,
+	      NGBE_MNGMBXCTL_SWRDY, NGBE_MNGMBXCTL_SWRDY);
+
+	/* Check command completion */
+	loop = po32m(hw, NGBE_MNGMBXCTL,
+		NGBE_MNGMBXCTL_FWRDY, NGBE_MNGMBXCTL_FWRDY,
+		&value, timeout, 1000);
+	if (!loop || !(value & NGBE_MNGMBXCTL_FWACK)) {
+		DEBUGOUT("Command has failed with no status valid.\n");
+		return NGBE_ERR_HOST_INTERFACE_COMMAND;
+	}
+
+	return 0;
+}
+
+/**
+ *  ngbe_host_interface_command - Issue command to manageability block
+ *  @hw: pointer to the HW structure
+ *  @buffer: contains the command to write and where the return status will
+ *   be placed
+ *  @length: length of buffer, must be multiple of 4 bytes
+ *  @timeout: time in ms to wait for command completion
+ *  @return_data: read and return data from the buffer (true) or not (false)
+ *   Needed because FW structures are big endian and decoding of
+ *   these fields can be 8 bit or 16 bit based on command. Decoding
+ *   is not easily understood without making a table of commands.
+ *   So we will leave this up to the caller to read back the data
+ *   in these cases.
+ *
+ *  Communicates with the manageability block. On success return 0
+ *  else returns semaphore error when encountering an error acquiring
+ *  semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ **/
+static s32
+ngbe_host_interface_command(struct ngbe_hw *hw, u32 *buffer,
+				 u32 length, u32 timeout, bool return_data)
+{
+	u32 hdr_size = sizeof(struct ngbe_hic_hdr);
+	struct ngbe_hic_hdr *resp = (struct ngbe_hic_hdr *)buffer;
+	u16 buf_len;
+	s32 err;
+	u32 bi;
+	u32 dword_len;
+
+	DEBUGFUNC("ngbe_host_interface_command");
+
+	if (length == 0 || length > NGBE_PMMBX_BSIZE) {
+		DEBUGOUT("Buffer length failure buffersize=%d.\n", length);
+		return NGBE_ERR_HOST_INTERFACE_COMMAND;
+	}
+
+	/* Take management host interface semaphore */
+	err = hw->mac.acquire_swfw_sync(hw, NGBE_MNGSEM_SWMBX);
+	if (err)
+		return err;
+
+	err = ngbe_hic_unlocked(hw, buffer, length, timeout);
+	if (err)
+		goto rel_out;
+
+	if (!return_data)
+		goto rel_out;
+
+	/* Calculate length in DWORDs */
+	dword_len = hdr_size >> 2;
+
+	/* first pull in the header so we know the buffer length */
+	for (bi = 0; bi < dword_len; bi++)
+		buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi);
+
+	/*
+	 * If there is any thing in data position pull it in
+	 * Read Flash command requires reading buffer length from
+	 * two byes instead of one byte
+	 */
+	if (resp->cmd == 0x30) {
+		for (; bi < dword_len + 2; bi++)
+			buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi);
+
+		buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3)
+				  & 0xF00) | resp->buf_len;
+		hdr_size += (2 << 2);
+	} else {
+		buf_len = resp->buf_len;
+	}
+	if (!buf_len)
+		goto rel_out;
+
+	if (length < buf_len + hdr_size) {
+		DEBUGOUT("Buffer not large enough for reply message.\n");
+		err = NGBE_ERR_HOST_INTERFACE_COMMAND;
+		goto rel_out;
+	}
+
+	/* Calculate length in DWORDs, add 3 for odd lengths */
+	dword_len = (buf_len + 3) >> 2;
+
+	/* Pull in the rest of the buffer (bi is where we left off) */
+	for (; bi <= dword_len; bi++)
+		buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi);
+
+rel_out:
+	hw->mac.release_swfw_sync(hw, NGBE_MNGSEM_SWMBX);
+
+	return err;
+}
+
+s32 ngbe_hic_check_cap(struct ngbe_hw *hw)
+{
+	struct ngbe_hic_read_shadow_ram command;
+	s32 err;
+	int i;
+
+	DEBUGFUNC("\n");
+
+	command.hdr.req.cmd = FW_EEPROM_CHECK_STATUS;
+	command.hdr.req.buf_lenh = 0;
+	command.hdr.req.buf_lenl = 0;
+	command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
+
+	/* convert offset from words to bytes */
+	command.address = 0;
+	/* one word */
+	command.length = 0;
+
+	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
+		err = ngbe_host_interface_command(hw, (u32 *)&command,
+				sizeof(command),
+				NGBE_HI_COMMAND_TIMEOUT, true);
+		if (err)
+			continue;
+
+		command.hdr.rsp.ret_status &= 0x1F;
+		if (command.hdr.rsp.ret_status !=
+			FW_CEM_RESP_STATUS_SUCCESS)
+			err = NGBE_ERR_HOST_INTERFACE_COMMAND;
+
+		break;
+	}
+
+	if (!err && command.address != FW_CHECKSUM_CAP_ST_PASS)
+		err = NGBE_ERR_EEPROM_CHECKSUM;
+
+	return err;
+}
diff --git a/drivers/net/ngbe/base/ngbe_mng.h b/drivers/net/ngbe/base/ngbe_mng.h
new file mode 100644
index 0000000000..383e0dc0d1
--- /dev/null
+++ b/drivers/net/ngbe/base/ngbe_mng.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd.
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#ifndef _NGBE_MNG_H_
+#define _NGBE_MNG_H_
+
+#include "ngbe_type.h"
+
+#define NGBE_PMMBX_QSIZE       64 /* Num of dwords in range */
+#define NGBE_PMMBX_BSIZE       (NGBE_PMMBX_QSIZE * 4)
+#define NGBE_HI_COMMAND_TIMEOUT        5000 /* Process HI command limit */
+
+/* CEM Support */
+#define FW_CEM_MAX_RETRIES              3
+#define FW_CEM_RESP_STATUS_SUCCESS      0x1
+#define FW_DEFAULT_CHECKSUM             0xFF /* checksum always 0xFF */
+#define FW_EEPROM_CHECK_STATUS		0xE9
+
+#define FW_CHECKSUM_CAP_ST_PASS	0x80658383
+#define FW_CHECKSUM_CAP_ST_FAIL	0x70657376
+
+/* Host Interface Command Structures */
+struct ngbe_hic_hdr {
+	u8 cmd;
+	u8 buf_len;
+	union {
+		u8 cmd_resv;
+		u8 ret_status;
+	} cmd_or_resp;
+	u8 checksum;
+};
+
+struct ngbe_hic_hdr2_req {
+	u8 cmd;
+	u8 buf_lenh;
+	u8 buf_lenl;
+	u8 checksum;
+};
+
+struct ngbe_hic_hdr2_rsp {
+	u8 cmd;
+	u8 buf_lenl;
+	u8 ret_status;     /* 7-5: high bits of buf_len, 4-0: status */
+	u8 checksum;
+};
+
+union ngbe_hic_hdr2 {
+	struct ngbe_hic_hdr2_req req;
+	struct ngbe_hic_hdr2_rsp rsp;
+};
+
+/* These need to be dword aligned */
+struct ngbe_hic_read_shadow_ram {
+	union ngbe_hic_hdr2 hdr;
+	u32 address;
+	u16 length;
+	u16 pad2;
+	u16 data;
+	u16 pad3;
+};
+
+s32 ngbe_hic_check_cap(struct ngbe_hw *hw);
+#endif /* _NGBE_MNG_H_ */
diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h
index d172f2702f..c727338bd5 100644
--- a/drivers/net/ngbe/base/ngbe_type.h
+++ b/drivers/net/ngbe/base/ngbe_type.h
@@ -10,6 +10,13 @@
 #include "ngbe_osdep.h"
 #include "ngbe_devids.h"
 
+enum ngbe_eeprom_type {
+	ngbe_eeprom_unknown = 0,
+	ngbe_eeprom_spi,
+	ngbe_eeprom_flash,
+	ngbe_eeprom_none /* No NVM support */
+};
+
 enum ngbe_mac_type {
 	ngbe_mac_unknown = 0,
 	ngbe_mac_em,
@@ -49,7 +56,23 @@ struct ngbe_bus_info {
 	u8 lan_id;
 };
 
+struct ngbe_rom_info {
+	s32 (*init_params)(struct ngbe_hw *hw);
+	s32 (*validate_checksum)(struct ngbe_hw *hw, u16 *checksum_val);
+
+	enum ngbe_eeprom_type type;
+	u32 semaphore_delay;
+	u16 word_size;
+	u16 address_bits;
+	u16 word_page_size;
+	u32 sw_addr;
+	u32 saved_version;
+	u16 cksum_devcap;
+};
+
 struct ngbe_mac_info {
+	s32 (*acquire_swfw_sync)(struct ngbe_hw *hw, u32 mask);
+	void (*release_swfw_sync)(struct ngbe_hw *hw, u32 mask);
 	enum ngbe_mac_type type;
 };
 
@@ -63,6 +86,7 @@ struct ngbe_hw {
 	void *back;
 	struct ngbe_mac_info mac;
 	struct ngbe_phy_info phy;
+	struct ngbe_rom_info rom;
 	struct ngbe_bus_info bus;
 	u16 device_id;
 	u16 vendor_id;
diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c
index a355c7dc29..c779c46dd5 100644
--- a/drivers/net/ngbe/ngbe_ethdev.c
+++ b/drivers/net/ngbe/ngbe_ethdev.c
@@ -32,6 +32,29 @@ static const struct rte_pci_id pci_id_ngbe_map[] = {
 	{ .vendor_id = 0, /* sentinel */ },
 };
 
+/*
+ * Ensure that all locks are released before first NVM or PHY access
+ */
+static void
+ngbe_swfw_lock_reset(struct ngbe_hw *hw)
+{
+	uint16_t mask;
+
+	/*
+	 * These ones are more tricky since they are common to all ports; but
+	 * swfw_sync retries last long enough (1s) to be almost sure that if
+	 * lock can not be taken it is due to an improper lock of the
+	 * semaphore.
+	 */
+	mask = NGBE_MNGSEM_SWPHY |
+	       NGBE_MNGSEM_SWMBX |
+	       NGBE_MNGSEM_SWFLASH;
+	if (hw->mac.acquire_swfw_sync(hw, mask) < 0)
+		PMD_DRV_LOG(DEBUG, "SWFW common locks released");
+
+	hw->mac.release_swfw_sync(hw, mask);
+}
+
 static int
 eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 {
@@ -60,6 +83,22 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 		return -EIO;
 	}
 
+	/* Unlock any pending hardware semaphore */
+	ngbe_swfw_lock_reset(hw);
+
+	err = hw->rom.init_params(hw);
+	if (err != 0) {
+		PMD_INIT_LOG(ERR, "The EEPROM init failed: %d", err);
+		return -EIO;
+	}
+
+	/* Make sure we have a good EEPROM before we read from it */
+	err = hw->rom.validate_checksum(hw, NULL);
+	if (err != 0) {
+		PMD_INIT_LOG(ERR, "The EEPROM checksum is not valid: %d", err);
+		return -EIO;
+	}
+
 	return 0;
 }
 
-- 
2.21.0.windows.1




  parent reply	other threads:[~2021-06-17 10:58 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-17 10:59 [dpdk-dev] [PATCH v6 00/19] net: ngbe PMD Jiawen Wu
2021-06-17 10:59 ` [dpdk-dev] [PATCH v6 01/19] net/ngbe: add build and doc infrastructure Jiawen Wu
2021-07-02 13:07   ` Andrew Rybchenko
2021-07-05  2:52     ` Jiawen Wu
2021-07-05  8:54       ` Andrew Rybchenko
2021-06-17 10:59 ` [dpdk-dev] [PATCH v6 02/19] net/ngbe: support probe and remove Jiawen Wu
2021-07-02 13:22   ` Andrew Rybchenko
2021-06-17 10:59 ` [dpdk-dev] [PATCH v6 03/19] net/ngbe: add log type and error type Jiawen Wu
2021-07-02 13:22   ` Andrew Rybchenko
2021-06-17 10:59 ` [dpdk-dev] [PATCH v6 04/19] net/ngbe: define registers Jiawen Wu
2021-06-17 10:59 ` [dpdk-dev] [PATCH v6 05/19] net/ngbe: set MAC type and LAN ID with device initialization Jiawen Wu
2021-07-02 16:05   ` Andrew Rybchenko
2021-06-17 10:59 ` Jiawen Wu [this message]
2021-06-17 10:59 ` [dpdk-dev] [PATCH v6 07/19] net/ngbe: add HW initialization Jiawen Wu
2021-07-02 16:08   ` Andrew Rybchenko
2021-06-17 10:59 ` [dpdk-dev] [PATCH v6 08/19] net/ngbe: identify PHY and reset PHY Jiawen Wu
2021-06-17 10:59 ` [dpdk-dev] [PATCH v6 09/19] net/ngbe: store MAC address Jiawen Wu
2021-07-02 16:12   ` Andrew Rybchenko
2021-06-17 10:59 ` [dpdk-dev] [PATCH v6 10/19] net/ngbe: support link update Jiawen Wu
2021-07-02 16:24   ` Andrew Rybchenko
2021-07-05  7:10     ` Jiawen Wu
2021-07-05  8:58       ` Andrew Rybchenko
2021-06-17 10:59 ` [dpdk-dev] [PATCH v6 11/19] net/ngbe: setup the check PHY link Jiawen Wu
2021-06-17 10:59 ` [dpdk-dev] [PATCH v6 12/19] net/ngbe: add Rx queue setup and release Jiawen Wu
2021-07-02 16:35   ` Andrew Rybchenko
2021-07-05  8:36     ` Jiawen Wu
2021-07-05  9:08       ` Andrew Rybchenko
2021-07-06  7:53         ` Jiawen Wu
2021-07-06  8:06           ` Andrew Rybchenko
2021-07-06  8:33             ` Jiawen Wu
2021-06-17 10:59 ` [dpdk-dev] [PATCH v6 13/19] net/ngbe: add Tx " Jiawen Wu
2021-07-02 16:39   ` Andrew Rybchenko
2021-06-17 11:00 ` [dpdk-dev] [PATCH v6 14/19] net/ngbe: add simple Rx flow Jiawen Wu
2021-07-02 16:42   ` Andrew Rybchenko
2021-06-17 11:00 ` [dpdk-dev] [PATCH v6 15/19] net/ngbe: add simple Tx flow Jiawen Wu
2021-07-02 16:45   ` Andrew Rybchenko
2021-06-17 11:00 ` [dpdk-dev] [PATCH v6 16/19] net/ngbe: add device start and stop operations Jiawen Wu
2021-07-02 16:52   ` Andrew Rybchenko
2021-06-17 11:00 ` [dpdk-dev] [PATCH v6 17/19] net/ngbe: add Tx queue start and stop Jiawen Wu
2021-07-02 16:55   ` Andrew Rybchenko
2021-06-17 11:00 ` [dpdk-dev] [PATCH v6 18/19] net/ngbe: add Rx " Jiawen Wu
2021-06-17 11:00 ` [dpdk-dev] [PATCH v6 19/19] net/ngbe: support to close and reset device Jiawen Wu

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=20210617110005.4132926-7-jiawenwu@trustnetic.com \
    --to=jiawenwu@trustnetic.com \
    --cc=dev@dpdk.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.