From: Slawomir Mrozowicz <slawomirx.mrozow...@intel.com>

Add functions reading the netlist version info and use them
as a part of the setting NVM info procedure.

Reviewed-by: Mateusz Polchlopek <mateusz.polchlo...@intel.com>
Signed-off-by: Slawomir Mrozowicz <slawomirx.mrozow...@intel.com>
Co-developed-by: Piotr Kwapulinski <piotr.kwapulin...@intel.com>
Signed-off-by: Piotr Kwapulinski <piotr.kwapulin...@intel.com>
Signed-off-by: Jedrzej Jagielski <jedrzej.jagiel...@intel.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c | 112 ++++++++++++++++++
 .../ethernet/intel/ixgbe/ixgbe_type_e610.h    |  33 ++++++
 2 files changed, 145 insertions(+)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c 
b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c
index bad4bc04bb66..b34570b244d9 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c
@@ -2582,6 +2582,33 @@ static int ixgbe_read_nvm_module(struct ixgbe_hw *hw,
        return err;
 }
 
+/**
+ * ixgbe_read_netlist_module - Read data from the netlist module area
+ * @hw: pointer to the HW structure
+ * @bank: whether to read from the active or inactive module
+ * @offset: offset into the netlist to read from
+ * @data: storage for returned word value
+ *
+ * Read a word from the specified netlist bank.
+ *
+ * Return: the exit code of the operation.
+ */
+static int ixgbe_read_netlist_module(struct ixgbe_hw *hw,
+                                    enum ixgbe_bank_select bank,
+                                    u32 offset, u16 *data)
+{
+       __le16 data_local;
+       int err;
+
+       err = ixgbe_read_flash_module(hw, bank, IXGBE_E610_SR_NETLIST_BANK_PTR,
+                                     offset * sizeof(data_local),
+                                     (u8 *)&data_local, sizeof(data_local));
+       if (!err)
+               *data = le16_to_cpu(data_local);
+
+       return err;
+}
+
 /**
  * ixgbe_read_orom_module - Read from the active Option ROM module
  * @hw: pointer to the HW structure
@@ -2887,6 +2914,86 @@ static int ixgbe_get_nvm_ver_info(struct ixgbe_hw *hw,
        return 0;
 }
 
+/**
+ * ixgbe_get_netlist_info - Read the netlist version information
+ * @hw: pointer to the HW struct
+ * @bank: whether to read from the active or inactive flash bank
+ * @netlist: pointer to netlist version info structure
+ *
+ * Get the netlist version information from the requested bank. Reads the Link
+ * Topology section to find the Netlist ID block and extract the relevant
+ * information into the netlist version structure.
+ *
+ * Return: the exit code of the operation.
+ */
+static int ixgbe_get_netlist_info(struct ixgbe_hw *hw,
+                                 enum ixgbe_bank_select bank,
+                                 struct ixgbe_netlist_info *netlist)
+{
+       u16 module_id, length, node_count, i;
+       u16 *id_blk;
+       int err;
+
+       err = ixgbe_read_netlist_module(hw, bank, IXGBE_NETLIST_TYPE_OFFSET,
+                                       &module_id);
+       if (err)
+               return err;
+
+       if (module_id != IXGBE_NETLIST_LINK_TOPO_MOD_ID)
+               return -EIO;
+
+       err = ixgbe_read_netlist_module(hw, bank, IXGBE_LINK_TOPO_MODULE_LEN,
+                                       &length);
+       if (err)
+               return err;
+
+       /* Sanity check that we have at least enough words to store the
+        * netlist ID block.
+        */
+       if (length < IXGBE_NETLIST_ID_BLK_SIZE)
+               return -EIO;
+
+       err = ixgbe_read_netlist_module(hw, bank, IXGBE_LINK_TOPO_NODE_COUNT,
+                                       &node_count);
+       if (err)
+               return err;
+
+       node_count &= IXGBE_LINK_TOPO_NODE_COUNT_M;
+
+       id_blk = kcalloc(IXGBE_NETLIST_ID_BLK_SIZE, sizeof(*id_blk), 
GFP_KERNEL);
+       if (!id_blk)
+               return -ENOMEM;
+
+       /* Read out the entire Netlist ID Block at once. */
+       err = ixgbe_read_flash_module(hw, bank, IXGBE_E610_SR_NETLIST_BANK_PTR,
+                                     IXGBE_NETLIST_ID_BLK_OFFSET(node_count) *
+                                     sizeof(*id_blk), (u8 *)id_blk,
+                                     IXGBE_NETLIST_ID_BLK_SIZE *
+                                     sizeof(*id_blk));
+       if (err)
+               goto free_id_blk;
+
+       for (i = 0; i < IXGBE_NETLIST_ID_BLK_SIZE; i++)
+               id_blk[i] = le16_to_cpu(((__le16 *)id_blk)[i]);
+
+       netlist->major = id_blk[IXGBE_NETLIST_ID_BLK_MAJOR_VER_HIGH] << 16 |
+                        id_blk[IXGBE_NETLIST_ID_BLK_MAJOR_VER_LOW];
+       netlist->minor = id_blk[IXGBE_NETLIST_ID_BLK_MINOR_VER_HIGH] << 16 |
+                        id_blk[IXGBE_NETLIST_ID_BLK_MINOR_VER_LOW];
+       netlist->type = id_blk[IXGBE_NETLIST_ID_BLK_TYPE_HIGH] << 16 |
+                       id_blk[IXGBE_NETLIST_ID_BLK_TYPE_LOW];
+       netlist->rev = id_blk[IXGBE_NETLIST_ID_BLK_REV_HIGH] << 16 |
+                      id_blk[IXGBE_NETLIST_ID_BLK_REV_LOW];
+       netlist->cust_ver = id_blk[IXGBE_NETLIST_ID_BLK_CUST_VER];
+       /* Read the left most 4 bytes of SHA */
+       netlist->hash = id_blk[IXGBE_NETLIST_ID_BLK_SHA_HASH_WORD(15)] << 16 |
+                       id_blk[IXGBE_NETLIST_ID_BLK_SHA_HASH_WORD(14)];
+
+free_id_blk:
+       kfree(id_blk);
+       return err;
+}
+
 /**
  * ixgbe_get_flash_data - get flash data
  * @hw: pointer to the HW struct
@@ -2939,6 +3046,11 @@ int ixgbe_get_flash_data(struct ixgbe_hw *hw)
 
        err = ixgbe_get_orom_ver_info(hw, IXGBE_ACTIVE_FLASH_BANK,
                                      &flash->orom);
+       if (err)
+               return err;
+
+       err = ixgbe_get_netlist_info(hw, IXGBE_ACTIVE_FLASH_BANK,
+                                    &flash->netlist);
 
        return err;
 }
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h 
b/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h
index 9b04075edd4a..a1c963cf7127 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h
@@ -45,6 +45,39 @@
 /* Shadow RAM related */
 #define IXGBE_SR_WORDS_IN_1KB  512
 
+/* The Netlist ID Block is located after all of the Link Topology nodes. */
+#define IXGBE_NETLIST_ID_BLK_SIZE              0x30
+#define IXGBE_NETLIST_ID_BLK_OFFSET(n)         
IXGBE_NETLIST_LINK_TOPO_OFFSET(0x0004 + 2 * (n))
+
+/* netlist ID block field offsets (word offsets) */
+#define IXGBE_NETLIST_ID_BLK_MAJOR_VER_LOW     0x02
+#define IXGBE_NETLIST_ID_BLK_MAJOR_VER_HIGH    0x03
+#define IXGBE_NETLIST_ID_BLK_MINOR_VER_LOW     0x04
+#define IXGBE_NETLIST_ID_BLK_MINOR_VER_HIGH    0x05
+#define IXGBE_NETLIST_ID_BLK_TYPE_LOW          0x06
+#define IXGBE_NETLIST_ID_BLK_TYPE_HIGH         0x07
+#define IXGBE_NETLIST_ID_BLK_REV_LOW           0x08
+#define IXGBE_NETLIST_ID_BLK_REV_HIGH          0x09
+#define IXGBE_NETLIST_ID_BLK_SHA_HASH_WORD(n)  (0x0A + (n))
+#define IXGBE_NETLIST_ID_BLK_CUST_VER          0x2F
+
+/* The Link Topology Netlist section is stored as a series of words. It is
+ * stored in the NVM as a TLV, with the first two words containing the type
+ * and length.
+ */
+#define IXGBE_NETLIST_LINK_TOPO_MOD_ID         0x011B
+#define IXGBE_NETLIST_TYPE_OFFSET              0x0000
+#define IXGBE_NETLIST_LEN_OFFSET               0x0001
+
+/* The Link Topology section follows the TLV header. When reading the netlist
+ * using ixgbe_read_netlist_module, we need to account for the 2-word TLV
+ * header.
+ */
+#define IXGBE_NETLIST_LINK_TOPO_OFFSET(n)      ((n) + 2)
+#define IXGBE_LINK_TOPO_MODULE_LEN     IXGBE_NETLIST_LINK_TOPO_OFFSET(0x0000)
+#define IXGBE_LINK_TOPO_NODE_COUNT     IXGBE_NETLIST_LINK_TOPO_OFFSET(0x0001)
+#define IXGBE_LINK_TOPO_NODE_COUNT_M           GENMASK_ULL(9, 0)
+
 /* Firmware Status Register (GL_FWSTS) */
 #define GL_FWSTS               0x00083048 /* Reset Source: POR */
 #define GL_FWSTS_EP_PF0                BIT(24)
-- 
2.31.1

Reply via email to