Add firmware version get operation.

Signed-off-by: Jiawen Wu <jiawe...@trustnetic.com>
---
 doc/guides/nics/features/ngbe.ini   |  1 +
 doc/guides/nics/ngbe.rst            |  1 +
 drivers/net/ngbe/base/ngbe_dummy.h  |  6 ++++
 drivers/net/ngbe/base/ngbe_eeprom.c | 56 +++++++++++++++++++++++++++++
 drivers/net/ngbe/base/ngbe_eeprom.h |  5 +++
 drivers/net/ngbe/base/ngbe_hw.c     |  3 ++
 drivers/net/ngbe/base/ngbe_mng.c    | 44 +++++++++++++++++++++++
 drivers/net/ngbe/base/ngbe_mng.h    |  5 +++
 drivers/net/ngbe/base/ngbe_type.h   |  2 ++
 drivers/net/ngbe/ngbe_ethdev.c      | 21 +++++++++++
 10 files changed, 144 insertions(+)

diff --git a/doc/guides/nics/features/ngbe.ini 
b/doc/guides/nics/features/ngbe.ini
index 2f38f1e843..1006c3935b 100644
--- a/doc/guides/nics/features/ngbe.ini
+++ b/doc/guides/nics/features/ngbe.ini
@@ -25,6 +25,7 @@ Packet type parsing  = Y
 Basic stats          = Y
 Extended stats       = Y
 Stats per queue      = Y
+FW version           = Y
 Multiprocess aware   = Y
 Linux                = Y
 ARMv8                = Y
diff --git a/doc/guides/nics/ngbe.rst b/doc/guides/nics/ngbe.rst
index 8333fba9cd..50a6e85c49 100644
--- a/doc/guides/nics/ngbe.rst
+++ b/doc/guides/nics/ngbe.rst
@@ -21,6 +21,7 @@ Features
 - Jumbo frames
 - Link state information
 - Scattered and gather for TX and RX
+- FW version
 
 
 Prerequisites
diff --git a/drivers/net/ngbe/base/ngbe_dummy.h 
b/drivers/net/ngbe/base/ngbe_dummy.h
index 0def116c53..689480cc9a 100644
--- a/drivers/net/ngbe/base/ngbe_dummy.h
+++ b/drivers/net/ngbe/base/ngbe_dummy.h
@@ -33,6 +33,11 @@ static inline s32 ngbe_rom_init_params_dummy(struct ngbe_hw 
*TUP0)
 {
        return NGBE_ERR_OPS_DUMMY;
 }
+static inline s32 ngbe_rom_read32_dummy(struct ngbe_hw *TUP0, u32 TUP1,
+                                       u32 *TUP2)
+{
+       return NGBE_ERR_OPS_DUMMY;
+}
 static inline s32 ngbe_rom_validate_checksum_dummy(struct ngbe_hw *TUP0,
                                        u16 *TUP1)
 {
@@ -177,6 +182,7 @@ 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.read32 = ngbe_rom_read32_dummy;
        hw->rom.validate_checksum = ngbe_rom_validate_checksum_dummy;
        hw->mac.init_hw = ngbe_mac_init_hw_dummy;
        hw->mac.reset_hw = ngbe_mac_reset_hw_dummy;
diff --git a/drivers/net/ngbe/base/ngbe_eeprom.c 
b/drivers/net/ngbe/base/ngbe_eeprom.c
index 3dcd5c2f6c..9ae2f0badb 100644
--- a/drivers/net/ngbe/base/ngbe_eeprom.c
+++ b/drivers/net/ngbe/base/ngbe_eeprom.c
@@ -161,6 +161,30 @@ void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw)
        ngbe_flush(hw);
 }
 
+/**
+ *  ngbe_ee_read32 - Read EEPROM word using a host interface cmd
+ *  @hw: pointer to hardware structure
+ *  @offset: offset of  word in the EEPROM to read
+ *  @data: word read from the EEPROM
+ *
+ *  Reads a 32 bit word from the EEPROM using the hostif.
+ **/
+s32 ngbe_ee_read32(struct ngbe_hw *hw, u32 addr, u32 *data)
+{
+       const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH;
+       int err;
+
+       err = hw->mac.acquire_swfw_sync(hw, mask);
+       if (err)
+               return err;
+
+       err = ngbe_hic_sr_read(hw, addr, (u8 *)data, 4);
+
+       hw->mac.release_swfw_sync(hw, mask);
+
+       return err;
+}
+
 /**
  *  ngbe_validate_eeprom_checksum_em - Validate EEPROM checksum
  *  @hw: pointer to hardware structure
@@ -201,3 +225,35 @@ s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw,
        return err;
 }
 
+/**
+ * ngbe_save_eeprom_version
+ * @hw: pointer to hardware structure
+ *
+ * Save off EEPROM version number and Option Rom version which
+ * together make a unique identify for the eeprom
+ */
+s32 ngbe_save_eeprom_version(struct ngbe_hw *hw)
+{
+       u32 eeprom_verl = 0;
+       u32 etrack_id = 0;
+       u32 offset = (hw->rom.sw_addr + NGBE_EEPROM_VERSION_L) << 1;
+
+       DEBUGFUNC("ngbe_save_eeprom_version");
+
+       if (hw->bus.lan_id == 0) {
+               hw->rom.read32(hw, offset, &eeprom_verl);
+               etrack_id = eeprom_verl;
+               wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, etrack_id);
+               wr32(hw, NGBE_CALSUM_CAP_STATUS,
+                       hw->rom.cksum_devcap | 0x10000);
+       } else if (hw->rom.cksum_devcap) {
+               etrack_id = hw->rom.saved_version;
+       } else {
+               hw->rom.read32(hw, offset, &eeprom_verl);
+               etrack_id = eeprom_verl;
+       }
+
+       hw->eeprom_id = etrack_id;
+
+       return 0;
+}
diff --git a/drivers/net/ngbe/base/ngbe_eeprom.h 
b/drivers/net/ngbe/base/ngbe_eeprom.h
index b433077629..5f27425913 100644
--- a/drivers/net/ngbe/base/ngbe_eeprom.h
+++ b/drivers/net/ngbe/base/ngbe_eeprom.h
@@ -6,6 +6,8 @@
 #ifndef _NGBE_EEPROM_H_
 #define _NGBE_EEPROM_H_
 
+#define NGBE_EEPROM_VERSION_L          0x1D
+#define NGBE_EEPROM_VERSION_H          0x1E
 #define NGBE_CALSUM_CAP_STATUS         0x10224
 #define NGBE_EEPROM_VERSION_STORE_REG  0x1022C
 
@@ -13,5 +15,8 @@ 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);
+s32 ngbe_save_eeprom_version(struct ngbe_hw *hw);
+
+s32 ngbe_ee_read32(struct ngbe_hw *hw, u32 addr, u32 *data);
 
 #endif /* _NGBE_EEPROM_H_ */
diff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c
index f302df5d9d..0dabb6c1c7 100644
--- a/drivers/net/ngbe/base/ngbe_hw.c
+++ b/drivers/net/ngbe/base/ngbe_hw.c
@@ -44,6 +44,8 @@ s32 ngbe_init_hw(struct ngbe_hw *hw)
 
        DEBUGFUNC("ngbe_init_hw");
 
+       ngbe_save_eeprom_version(hw);
+
        /* Reset the hardware */
        status = hw->mac.reset_hw(hw);
        if (status == 0) {
@@ -1115,6 +1117,7 @@ s32 ngbe_init_ops_pf(struct ngbe_hw *hw)
 
        /* EEPROM */
        rom->init_params = ngbe_init_eeprom_params;
+       rom->read32 = ngbe_ee_read32;
        rom->validate_checksum = ngbe_validate_eeprom_checksum_em;
 
        mac->mcft_size          = NGBE_EM_MC_TBL_SIZE;
diff --git a/drivers/net/ngbe/base/ngbe_mng.c b/drivers/net/ngbe/base/ngbe_mng.c
index 6ad2838ea7..9416ea4c8d 100644
--- a/drivers/net/ngbe/base/ngbe_mng.c
+++ b/drivers/net/ngbe/base/ngbe_mng.c
@@ -158,6 +158,50 @@ ngbe_host_interface_command(struct ngbe_hw *hw, u32 
*buffer,
        return err;
 }
 
+/**
+ *  ngbe_hic_sr_read - Read EEPROM word using a host interface cmd
+ *  assuming that the semaphore is already obtained.
+ *  @hw: pointer to hardware structure
+ *  @offset: offset of  word in the EEPROM to read
+ *  @data: word read from the EEPROM
+ *
+ *  Reads a 16 bit word from the EEPROM using the hostif.
+ **/
+s32 ngbe_hic_sr_read(struct ngbe_hw *hw, u32 addr, u8 *buf, int len)
+{
+       struct ngbe_hic_read_shadow_ram command;
+       u32 value;
+       int err, i = 0, j = 0;
+
+       if (len > NGBE_PMMBX_DATA_SIZE)
+               return NGBE_ERR_HOST_INTERFACE_COMMAND;
+
+       memset(&command, 0, sizeof(command));
+       command.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
+       command.hdr.req.buf_lenh = 0;
+       command.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
+       command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
+       command.address = cpu_to_be32(addr);
+       command.length = cpu_to_be16(len);
+
+       err = ngbe_hic_unlocked(hw, (u32 *)&command,
+                       sizeof(command), NGBE_HI_COMMAND_TIMEOUT);
+       if (err)
+               return err;
+
+       while (i < (len >> 2)) {
+               value = rd32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i);
+               ((u32 *)buf)[i] = value;
+               i++;
+       }
+
+       value = rd32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i);
+       for (i <<= 2; i < len; i++)
+               ((u8 *)buf)[i] = ((u8 *)&value)[j++];
+
+       return 0;
+}
+
 s32 ngbe_hic_check_cap(struct ngbe_hw *hw)
 {
        struct ngbe_hic_read_shadow_ram command;
diff --git a/drivers/net/ngbe/base/ngbe_mng.h b/drivers/net/ngbe/base/ngbe_mng.h
index e86893101b..6f368b028f 100644
--- a/drivers/net/ngbe/base/ngbe_mng.h
+++ b/drivers/net/ngbe/base/ngbe_mng.h
@@ -10,12 +10,16 @@
 
 #define NGBE_PMMBX_QSIZE       64 /* Num of dwords in range */
 #define NGBE_PMMBX_BSIZE       (NGBE_PMMBX_QSIZE * 4)
+#define NGBE_PMMBX_DATA_SIZE   (NGBE_PMMBX_BSIZE - FW_NVM_DATA_OFFSET * 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_READ_SHADOW_RAM_CMD          0x31
+#define FW_READ_SHADOW_RAM_LEN          0x6
 #define FW_DEFAULT_CHECKSUM             0xFF /* checksum always 0xFF */
+#define FW_NVM_DATA_OFFSET              3
 #define FW_EEPROM_CHECK_STATUS         0xE9
 
 #define FW_CHECKSUM_CAP_ST_PASS        0x80658383
@@ -61,5 +65,6 @@ struct ngbe_hic_read_shadow_ram {
        u16 pad3;
 };
 
+s32 ngbe_hic_sr_read(struct ngbe_hw *hw, u32 addr, u8 *buf, int len);
 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 78fb0da7fa..2586eaf36a 100644
--- a/drivers/net/ngbe/base/ngbe_type.h
+++ b/drivers/net/ngbe/base/ngbe_type.h
@@ -202,6 +202,7 @@ struct ngbe_hw_stats {
 
 struct ngbe_rom_info {
        s32 (*init_params)(struct ngbe_hw *hw);
+       s32 (*read32)(struct ngbe_hw *hw, u32 addr, u32 *data);
        s32 (*validate_checksum)(struct ngbe_hw *hw, u16 *checksum_val);
 
        enum ngbe_eeprom_type type;
@@ -310,6 +311,7 @@ struct ngbe_hw {
        u16 vendor_id;
        u16 sub_device_id;
        u16 sub_system_id;
+       u32 eeprom_id;
        bool adapter_stopped;
 
        uint64_t isb_dma;
diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c
index ce71edd6d8..5566bf26a9 100644
--- a/drivers/net/ngbe/ngbe_ethdev.c
+++ b/drivers/net/ngbe/ngbe_ethdev.c
@@ -1524,6 +1524,26 @@ ngbe_dev_xstats_reset(struct rte_eth_dev *dev)
        return 0;
 }
 
+static int
+ngbe_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
+{
+       struct ngbe_hw *hw = ngbe_dev_hw(dev);
+       int ret;
+
+       ret = snprintf(fw_version, fw_size, "0x%08x", hw->eeprom_id);
+
+       if (ret < 0)
+               return -EINVAL;
+
+       ret += 1; /* add the size of '\0' */
+       if (fw_size < (size_t)ret)
+               return ret;
+       else
+               return 0;
+
+       return 0;
+}
+
 static int
 ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
@@ -2181,6 +2201,7 @@ static const struct eth_dev_ops ngbe_eth_dev_ops = {
        .xstats_get_names           = ngbe_dev_xstats_get_names,
        .xstats_get_names_by_id     = ngbe_dev_xstats_get_names_by_id,
        .queue_stats_mapping_set    = ngbe_dev_queue_stats_mapping_set,
+       .fw_version_get             = ngbe_fw_version_get,
        .mtu_set                    = ngbe_dev_mtu_set,
        .vlan_offload_set           = ngbe_vlan_offload_set,
        .rx_queue_start             = ngbe_dev_rx_queue_start,
-- 
2.21.0.windows.1



Reply via email to