From: Jiawen Wu <jiawenwu@trustnetic.com>
To: dev@dpdk.org
Cc: Jiawen Wu <jiawenwu@trustnetic.com>
Subject: [dpdk-dev] [PATCH v8 06/19] net/ngbe: init and validate EEPROM
Date: Thu, 8 Jul 2021 17:32:26 +0800 [thread overview]
Message-ID: <20210708093239.13896-7-jiawenwu@trustnetic.com> (raw)
In-Reply-To: <20210708093239.13896-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 2d19dea8da..34f7556e3e 100644
--- a/drivers/net/ngbe/base/meson.build
+++ b/drivers/net/ngbe/base/meson.build
@@ -2,7 +2,9 @@
# Copyright(c) 2018-2021 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 ce6156b697..c9c17dcad8 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..3dcd5c2f6c
--- /dev/null
+++ b/drivers/net/ngbe/base/ngbe_eeprom.c
@@ -0,0 +1,203 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2021 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..b433077629
--- /dev/null
+++ b/drivers/net/ngbe/base/ngbe_eeprom.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2021 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 c40215e43e..a9819e4a84 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 a33776552b..a7b80f8200 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..6ad2838ea7
--- /dev/null
+++ b/drivers/net/ngbe/base/ngbe_mng.c
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2021 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..e86893101b
--- /dev/null
+++ b/drivers/net/ngbe/base/ngbe_mng.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2021 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 1d11045a6c..689184b368 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 f94c5d9306..4548ddd1c4 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
next prev parent reply other threads:[~2021-07-08 9:34 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-08 9:32 [dpdk-dev] [PATCH v8 00/19] net: ngbe PMD Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 01/19] net/ngbe: add build and doc infrastructure Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 02/19] net/ngbe: support probe and remove Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 03/19] net/ngbe: add log type and error type Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 04/19] net/ngbe: define registers Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 05/19] net/ngbe: set MAC type and LAN ID with device initialization Jiawen Wu
2021-07-08 9:32 ` Jiawen Wu [this message]
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 07/19] net/ngbe: add HW initialization Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 08/19] net/ngbe: identify PHY and reset PHY Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 09/19] net/ngbe: store MAC address Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 10/19] net/ngbe: support link update Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 11/19] net/ngbe: setup the check PHY link Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 12/19] net/ngbe: add Rx queue setup and release Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 13/19] net/ngbe: add Tx " Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 14/19] net/ngbe: add device start and stop operations Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 15/19] net/ngbe: add Tx queue start and stop Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 16/19] net/ngbe: add Rx " Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 17/19] net/ngbe: add simple Rx flow Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 18/19] net/ngbe: add simple Tx flow Jiawen Wu
2021-07-08 9:32 ` [dpdk-dev] [PATCH v8 19/19] net/ngbe: support to close and reset device Jiawen Wu
2021-07-08 10:12 ` [dpdk-dev] [PATCH v8 00/19] net: ngbe PMD Andrew Rybchenko
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=20210708093239.13896-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 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).