Re: [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom

2018-04-20 Thread Zijie Pan
Hi Ferruh,

I will mark the new APIs as experimental, and sent out a v4 patchset.

Thanks & Regards,
Zijie
 
 
-- Original --
From:  "Ferruh Yigit";
Date:  Thu, Apr 19, 2018 09:34 PM
To:  "Zijie Pan"; "dev"; 
Cc:  "remy.horton"; 
"john.mcnamara"; 
"marko.kovacevic"; "thomas"; 
Subject:  Re: [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom

 
On 3/21/2018 11:06 AM, Zijie Pan wrote:
> --- a/lib/librte_ether/rte_ethdev_version.map
> +++ b/lib/librte_ether/rte_ethdev_version.map
> @@ -201,6 +201,8 @@ DPDK_18.02 {
>   global:
>  
>   rte_eth_dev_filter_ctrl;
> + rte_eth_dev_get_module_info;
> + rte_eth_dev_get_module_eeprom;
>  
>  } DPDK_17.11;

New APIs needs to be experimental at least first release they are introduces,
can you please mark them as experimental?

[dpdk-dev] [PATCH v4 0/5] get the information and data of EEPROM

2018-04-24 Thread Zijie Pan
 0540  0540       .@...@..
180:          
190:          
1a0:  faff        
1b0:          
1c0:          
1d0:          
1e0:          
1f0:     0003 0100    

Both DPDK's my-module-eeprom.bin and Kernel's meeprom-kernel.bin
are the same.

v2 changes:
 - Fix typo in features.rst.
 - Fix checkpatch warnings regarding long lines.
 - Update function pcmd_module_eeprom_callback().

v3 changes:
 - fix compilation when dpdk is compiled with shared libs.

v4 changes:
 - add RTE_ prefix for the macros defined in rte_dev_info.h.
 - mark the new APIs as experimental.
 - some other minor fixes.

Zijie Pan (5):
  ethdev: add access to eeprom
  examples/ethtool: add a new command module-eeprom
  net/ixgbe: add module EEPROM callbacks for ixgbe
  net/e1000: add module EEPROM callbacks for e1000
  net/i40e: add module EEPROM callbacks for i40e

 doc/guides/nics/features.rst|   11 +++
 doc/guides/sample_app_ug/ethtool.rst|3 +
 drivers/net/e1000/base/e1000_phy.h  |8 ++
 drivers/net/e1000/igb_ethdev.c  |   86 ++
 drivers/net/i40e/i40e_ethdev.c  |  147 +++
 drivers/net/ixgbe/ixgbe_ethdev.c|   79 +
 examples/ethtool/ethtool-app/ethapp.c   |   64 ++
 examples/ethtool/lib/Makefile   |1 +
 examples/ethtool/lib/rte_ethtool.c  |   30 +++
 examples/ethtool/lib/rte_ethtool.h  |   34 +++
 lib/librte_ether/rte_dev_info.h |   18 
 lib/librte_ether/rte_ethdev.c   |   26 ++
 lib/librte_ether/rte_ethdev.h   |   43 +
 lib/librte_ether/rte_ethdev_core.h  |   12 +++
 lib/librte_ether/rte_ethdev_version.map |2 +
 15 files changed, 564 insertions(+)

-- 
1.7.10.4



[dpdk-dev] [PATCH v4 1/5] ethdev: add access to eeprom

2018-04-24 Thread Zijie Pan
add new APIs:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: john.mcnam...@intel.com
Cc: marko.kovace...@intel.com
Cc: tho...@monjalon.net

 doc/guides/nics/features.rst|   11 
 lib/librte_ether/rte_dev_info.h |   18 +
 lib/librte_ether/rte_ethdev.c   |   26 +++
 lib/librte_ether/rte_ethdev.h   |   43 +++
 lib/librte_ether/rte_ethdev_core.h  |   12 +
 lib/librte_ether/rte_ethdev_version.map |2 ++
 6 files changed, 112 insertions(+)

diff --git a/doc/guides/nics/features.rst b/doc/guides/nics/features.rst
index 1b4fb97..bb183e2 100644
--- a/doc/guides/nics/features.rst
+++ b/doc/guides/nics/features.rst
@@ -749,6 +749,17 @@ Supports getting/setting device eeprom data.
   ``rte_eth_dev_set_eeprom()``.
 
 
+.. _nic_features_module_eeprom_dump:
+
+Module EEPROM dump
+--
+
+Supports getting information and data of plugin module eeprom.
+
+* **[implements] eth_dev_ops**: ``get_module_info``, ``get_module_eeprom``.
+* **[related]API**: ``rte_eth_dev_get_module_info()``, 
``rte_eth_dev_get_module_eeprom()``.
+
+
 .. _nic_features_register_dump:
 
 Registers dump
diff --git a/lib/librte_ether/rte_dev_info.h b/lib/librte_ether/rte_dev_info.h
index 6b68584..02bdbed 100644
--- a/lib/librte_ether/rte_dev_info.h
+++ b/lib/librte_ether/rte_dev_info.h
@@ -28,4 +28,22 @@ struct rte_dev_eeprom_info {
uint32_t magic; /**< Device-specific key, such as device-id */
 };
 
+/**
+ * Placeholder for accessing plugin module eeprom
+ */
+struct rte_dev_module_info {
+   uint32_t type; /**< Type of plugin module eeprom */
+   uint32_t eeprom_len; /**< Length of plugin module eeprom */
+};
+
+/* EEPROM Standards for plug in modules */
+#define RTE_ETH_MODULE_SFF_8079 0x1
+#define RTE_ETH_MODULE_SFF_8079_LEN 256
+#define RTE_ETH_MODULE_SFF_8472 0x2
+#define RTE_ETH_MODULE_SFF_8472_LEN 512
+#define RTE_ETH_MODULE_SFF_8636 0x3
+#define RTE_ETH_MODULE_SFF_8636_LEN 256
+#define RTE_ETH_MODULE_SFF_8436 0x4
+#define RTE_ETH_MODULE_SFF_8436_LEN 256
+
 #endif /* _RTE_DEV_INFO_H_ */
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 7821a88..10bc19c 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3947,6 +3947,32 @@ int rte_eth_set_queue_rate_limit(uint16_t port_id, 
uint16_t queue_idx,
return eth_err(port_id, (*dev->dev_ops->set_eeprom)(dev, info));
 }
 
+int __rte_experimental
+rte_eth_dev_get_module_info(uint16_t port_id,
+   struct rte_dev_module_info *modinfo)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_info, -ENOTSUP);
+   return (*dev->dev_ops->get_module_info)(dev, modinfo);
+}
+
+int __rte_experimental
+rte_eth_dev_get_module_eeprom(uint16_t port_id,
+ struct rte_dev_eeprom_info *info)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_eeprom, -ENOTSUP);
+   return (*dev->dev_ops->get_module_eeprom)(dev, info);
+}
+
 int
 rte_eth_dev_get_dcb_info(uint16_t port_id,
 struct rte_eth_dcb_info *dcb_info)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 7e4e57b..b39ccc4 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -3311,6 +3311,49 @@ int rte_eth_tx_queue_info_get(uint16_t port_id, uint16_t 
queue_id,
 int rte_eth_dev_set_eeprom(uint16_t port_id, struct rte_dev_eeprom_info *info);
 
 /**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Retrieve the type and size of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param modinfo
+ *   The type and size of plugin module EEPROM.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EIO) if device is removed.
+ *   - others depends on the specific operations implementation.
+ */
+int __rte_experimental
+rte_eth_dev_get_module_info(uint16_t port_id,
+   struct rte_dev_module_info *modinfo);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Retrieve the data of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param info
+ *   The template includes the plugin module EEPROM attributes, and the
+ *   buffer for return p

[dpdk-dev] [PATCH v4 5/5] net/i40e: add module EEPROM callbacks for i40e

2018-04-24 Thread Zijie Pan
Add new callbacks for eth_dev_ops of i40e to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: beilei.x...@intel.com
Cc: qi.z.zh...@intel.com

 drivers/net/i40e/i40e_ethdev.c |  147 
 1 file changed, 147 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 180ac74..1a24cd7 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -369,6 +369,11 @@ static int i40e_get_regs(struct rte_eth_dev *dev,
 static int i40e_get_eeprom(struct rte_eth_dev *dev,
   struct rte_dev_eeprom_info *eeprom);
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo);
+static int i40e_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info);
+
 static int i40e_set_default_mac_addr(struct rte_eth_dev *dev,
  struct ether_addr *mac_addr);
 
@@ -489,6 +494,8 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
.get_reg  = i40e_get_regs,
.get_eeprom_length= i40e_get_eeprom_length,
.get_eeprom   = i40e_get_eeprom,
+   .get_module_info  = i40e_get_module_info,
+   .get_module_eeprom= i40e_get_module_eeprom,
.mac_addr_set = i40e_set_default_mac_addr,
.mtu_set  = i40e_dev_mtu_set,
.tm_ops_get   = i40e_tm_ops_get,
@@ -11327,6 +11334,146 @@ static int i40e_get_eeprom(struct rte_eth_dev *dev,
return 0;
 }
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo)
+{
+   struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t sff8472_comp = 0;
+   uint32_t sff8472_swap = 0;
+   uint32_t sff8636_rev = 0;
+   i40e_status status;
+   uint32_t type = 0;
+
+   /* Check if firmware supports reading module EEPROM. */
+   if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE)) {
+   PMD_DRV_LOG(ERR,
+   "Module EEPROM memory read not supported. "
+   "Please update the NVM image.\n");
+   return -EINVAL;
+   }
+
+   status = i40e_update_link_info(hw);
+   if (status)
+   return -EIO;
+
+   if (hw->phy.link_info.phy_type == I40E_PHY_TYPE_EMPTY) {
+   PMD_DRV_LOG(ERR,
+   "Cannot read module EEPROM memory. "
+   "No module connected.\n");
+   return -EINVAL;
+   }
+
+   type = hw->phy.link_info.module_type[0];
+
+   switch (type) {
+   case I40E_MODULE_TYPE_SFP:
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_COMP,
+   &sff8472_comp, NULL);
+   if (status)
+   return -EIO;
+
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_SWAP,
+   &sff8472_swap, NULL);
+   if (status)
+   return -EIO;
+
+   /* Check if the module requires address swap to access
+* the other EEPROM memory page.
+*/
+   if (sff8472_swap & I40E_MODULE_SFF_ADDR_MODE) {
+   PMD_DRV_LOG(WARNING,
+   "Module address swap to access "
+   "page 0xA2 is not supported.\n");
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else if (sff8472_comp == 0x00) {
+   /* Module is not SFF-8472 compliant */
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else {
+   modinfo->type = RTE_ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+   }
+   break;
+   case I40E_MODULE_TYPE_QSFP_PLUS:
+   /* Read from memory page 0. */
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+

[dpdk-dev] [PATCH v4 4/5] net/e1000: add module EEPROM callbacks for e1000

2018-04-24 Thread Zijie Pan
Add new callbacks for eth_dev_ops of e1000 to get the information and
data of plugin module EEPROM.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: wenzhuo...@intel.com

 drivers/net/e1000/base/e1000_phy.h |8 
 drivers/net/e1000/igb_ethdev.c |   86 
 2 files changed, 94 insertions(+)

diff --git a/drivers/net/e1000/base/e1000_phy.h 
b/drivers/net/e1000/base/e1000_phy.h
index 3e45a9e..2cd0e14 100644
--- a/drivers/net/e1000/base/e1000_phy.h
+++ b/drivers/net/e1000/base/e1000_phy.h
@@ -330,4 +330,12 @@ struct sfp_e1000_flags {
 #define E1000_SFF_VENDOR_OUI_AVAGO 0x00176A00
 #define E1000_SFF_VENDOR_OUI_INTEL 0x001B2100
 
+/* EEPROM byte offsets */
+#define IGB_SFF_8472_SWAP  0x5C
+#define IGB_SFF_8472_COMP  0x5E
+
+/* Bitmasks */
+#define IGB_SFF_ADDRESSING_MODE0x4
+#define IGB_SFF_8472_UNSUP 0x00
+
 #endif
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 9b808a9..4b261cc 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -223,6 +223,10 @@ static int eth_igb_get_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 static int eth_igb_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
+static int eth_igb_get_module_info(struct rte_eth_dev *dev,
+  struct rte_dev_module_info *modinfo);
+static int eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+struct rte_dev_eeprom_info *info);
 static int eth_igb_set_mc_addr_list(struct rte_eth_dev *dev,
struct ether_addr *mc_addr_set,
uint32_t nb_mc_addr);
@@ -402,6 +406,8 @@ static void eth_igb_write_ivar(struct e1000_hw *hw, uint8_t 
msix_vector,
.get_eeprom_length= eth_igb_get_eeprom_length,
.get_eeprom   = eth_igb_get_eeprom,
.set_eeprom   = eth_igb_set_eeprom,
+   .get_module_info  = eth_igb_get_module_info,
+   .get_module_eeprom= eth_igb_get_module_eeprom,
.timesync_adjust_time = igb_timesync_adjust_time,
.timesync_read_time   = igb_timesync_read_time,
.timesync_write_time  = igb_timesync_write_time,
@@ -5329,6 +5335,86 @@ static void igbvf_set_vfta_all(struct rte_eth_dev *dev, 
bool on)
 }
 
 static int
+eth_igb_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   if (hw->phy.media_type == e1000_media_type_copper ||
+   hw->phy.media_type == e1000_media_type_unknown)
+   return -EOPNOTSUPP;
+
+   /* Check whether we support SFF-8472 or not */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_COMP, &sff8472_rev);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_SWAP, &addr_mode);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   if ((addr_mode & 0xFF) & IGB_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR,
+   "Address change required to access page 0xA2, "
+   "but not supported. Please report the module "
+   "type to the driver maintainers.\n");
+   page_swap = true;
+   }
+
+   if ((sff8472_rev & 0xFF) == IGB_SFF_8472_UNSUP || page_swap) {
+   /* We have an SFP, but it does not support SFF-8472 */
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have an SFP which supports a revision of SFF-8472 */
+   modinfo->type = RTE_ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t dataword[RTE_ETH_MODULE_SFF_8472_LEN / 2 + 1];
+   u16 first_word, last_word;
+   int i = 0;
+
+   if (info->length == 0)
+   return -EINVAL;
+
+   first_word = info->offset >> 1;
+   last_word = (info->offset + info->length - 1) >> 1;
+
+   /* Read EEPROM block, SFF-8079/SFF-8472, word at a time */
+   for (i = 0; i < last_word - first_word + 1; i++) {
+   status = e1000_read_phy_reg_i2c(

[dpdk-dev] [PATCH v4 2/5] examples/ethtool: add a new command module-eeprom

2018-04-24 Thread Zijie Pan
Add a new command "module-eeprom" to get the data of plugin
module EEPROM.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: or...@mellanox.com
Cc: bruce.richard...@intel.com
Cc: pablo.de.lara.gua...@intel.com
Cc: radu.nico...@intel.com
Cc: akhil.go...@nxp.com
Cc: tomasz.kante...@intel.com
Cc: john.mcnam...@intel.com
Cc: marko.kovace...@intel.com

 doc/guides/sample_app_ug/ethtool.rst  |3 ++
 examples/ethtool/ethtool-app/ethapp.c |   64 +
 examples/ethtool/lib/Makefile |1 +
 examples/ethtool/lib/rte_ethtool.c|   30 
 examples/ethtool/lib/rte_ethtool.h|   34 ++
 5 files changed, 132 insertions(+)

diff --git a/doc/guides/sample_app_ug/ethtool.rst 
b/doc/guides/sample_app_ug/ethtool.rst
index 1b79aca..47e09f6 100644
--- a/doc/guides/sample_app_ug/ethtool.rst
+++ b/doc/guides/sample_app_ug/ethtool.rst
@@ -44,6 +44,7 @@ they do as as follows:
 
 * ``drvinfo``: Print driver info
 * ``eeprom``: Dump EEPROM to file
+* ``module-eeprom``: Dump plugin module EEPROM to file
 * ``link``: Print port link states
 * ``macaddr``: Gets/sets MAC address
 * ``mtu``: Set NIC MTU
@@ -97,6 +98,8 @@ the following functions:
 - ``rte_ethtool_get_eeprom_len()``
 - ``rte_ethtool_get_eeprom()``
 - ``rte_ethtool_set_eeprom()``
+- ``rte_ethtool_get_module_info()``
+- ``rte_ethtool_get_module_eeprom()``
 - ``rte_ethtool_get_pauseparam()``
 - ``rte_ethtool_set_pauseparam()``
 - ``rte_ethtool_net_open()``
diff --git a/examples/ethtool/ethtool-app/ethapp.c 
b/examples/ethtool/ethtool-app/ethapp.c
index 4d62f4c..a4e64b3 100644
--- a/examples/ethtool/ethtool-app/ethapp.c
+++ b/examples/ethtool/ethtool-app/ethapp.c
@@ -75,6 +75,9 @@ struct pcmd_intintint_params {
 /* Commands taking port id and string */
 cmdline_parse_token_string_t pcmd_eeprom_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "eeprom");
+cmdline_parse_token_string_t pcmd_module_eeprom_token_cmd =
+   TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd,
+"module-eeprom");
 cmdline_parse_token_string_t pcmd_mtu_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "mtu");
 cmdline_parse_token_string_t pcmd_regs_token_cmd =
@@ -298,6 +301,54 @@ struct pcmd_intintint_params {
 
 
 static void
+pcmd_module_eeprom_callback(void *ptr_params,
+   __rte_unused struct cmdline *ctx,
+   __rte_unused void *ptr_data)
+{
+   struct pcmd_intstr_params *params = ptr_params;
+   struct ethtool_eeprom info_eeprom;
+   uint32_t module_info[2];
+   int stat;
+   unsigned char bytes_eeprom[EEPROM_DUMP_CHUNKSIZE];
+   FILE *fp_eeprom;
+
+   if (!rte_eth_dev_is_valid_port(params->port)) {
+   printf("Error: Invalid port number %i\n", params->port);
+   return;
+   }
+
+   stat = rte_ethtool_get_module_info(params->port, module_info);
+   if (stat != 0) {
+   printf("Module EEPROM information read error %i\n", stat);
+   return;
+   }
+
+   info_eeprom.len = module_info[1];
+   info_eeprom.offset = 0;
+
+   stat = rte_ethtool_get_module_eeprom(params->port,
+&info_eeprom, bytes_eeprom);
+   if (stat != 0) {
+   printf("Module EEPROM read error %i\n", stat);
+   return;
+   }
+
+   fp_eeprom = fopen(params->opt, "wb");
+   if (fp_eeprom == NULL) {
+   printf("Error opening '%s' for writing\n", params->opt);
+   return;
+   }
+   printf("Total plugin module EEPROM length: %i bytes\n",
+  info_eeprom.len);
+   if (fwrite(bytes_eeprom, 1, info_eeprom.len,
+  fp_eeprom) != info_eeprom.len) {
+   printf("Error writing '%s'\n", params->opt);
+   }
+   fclose(fp_eeprom);
+}
+
+
+static void
 pcmd_pause_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
void *ptr_data)
@@ -664,6 +715,18 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
NULL
},
 };
+cmdline_parse_inst_t pcmd_module_eeprom = {
+   .f = pcmd_module_eeprom_callback,
+   .data = NULL,
+   .help_str = "module-eeprom  \n"
+   " Dump plugin module EEPROM to file",
+   .tokens = {
+   (void *)&pcmd_module_eeprom_token_cmd,
+   (void *)&pcmd_intstr_token_port,
+   (void *)&pcmd_intstr_token_opt,
+   NULL
+   },
+};
 cmdline_parse_inst_t pcmd_pause_noopt = {
.f = pcmd_pause_callback,
.data = (void *)0x01,
@@ -816,6 +879,7 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
 cmdl

[dpdk-dev] [PATCH v4 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe

2018-04-24 Thread Zijie Pan
Add new callbacks for eth_dev_ops of ixgbe to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: wenzhuo...@intel.com
Cc: konstantin.anan...@intel.com

 drivers/net/ixgbe/ixgbe_ethdev.c |   79 ++
 1 file changed, 79 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index a5e2fc0..55850df 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -327,6 +327,11 @@ static int ixgbe_get_eeprom(struct rte_eth_dev *dev,
 static int ixgbe_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 
+static int ixgbe_get_module_info(struct rte_eth_dev *dev,
+struct rte_dev_module_info *modinfo);
+static int ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+  struct rte_dev_eeprom_info *info);
+
 static int ixgbevf_get_reg_length(struct rte_eth_dev *dev);
 static int ixgbevf_get_regs(struct rte_eth_dev *dev,
struct rte_dev_reg_info *regs);
@@ -564,6 +569,8 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev 
*dev,
.get_eeprom_length= ixgbe_get_eeprom_length,
.get_eeprom   = ixgbe_get_eeprom,
.set_eeprom   = ixgbe_set_eeprom,
+   .get_module_info  = ixgbe_get_module_info,
+   .get_module_eeprom= ixgbe_get_module_eeprom,
.get_dcb_info = ixgbe_dev_get_dcb_info,
.timesync_adjust_time = ixgbe_timesync_adjust_time,
.timesync_read_time   = ixgbe_timesync_read_time,
@@ -7126,6 +7133,78 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev 
*dev, bool on)
return eeprom->ops.write_buffer(hw,  first, length, data);
 }
 
+static int
+ixgbe_get_module_info(struct rte_eth_dev *dev,
+ struct rte_dev_module_info *modinfo)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status;
+   uint8_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   /* Check whether we support SFF-8472 or not */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_COMP,
+&sff8472_rev);
+   if (status != 0)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_SWAP,
+&addr_mode);
+   if (status != 0)
+   return -EIO;
+
+   if (addr_mode & IXGBE_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR,
+   "Address change required to access page 0xA2, "
+   "but not supported. Please report the module "
+   "type to the driver maintainers.");
+   page_swap = true;
+   }
+
+   if (sff8472_rev == IXGBE_SFF_SFF_8472_UNSUP || page_swap) {
+   /* We have a SFP, but it does not support SFF-8472 */
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have a SFP which supports a revision of SFF-8472. */
+   modinfo->type = RTE_ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+   struct rte_dev_eeprom_info *info)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status = IXGBE_ERR_PHY_ADDR_INVALID;
+   uint8_t databyte = 0xFF;
+   uint8_t *data = info->data;
+   uint32_t i = 0;
+
+   if (info->length == 0)
+   return -EINVAL;
+
+   for (i = info->offset; i < info->offset + info->length; i++) {
+   if (i < RTE_ETH_MODULE_SFF_8079_LEN)
+   status = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte);
+   else
+   status = hw->phy.ops.read_i2c_sff8472(hw, i, &databyte);
+
+   if (status != 0)
+   return -EIO;
+
+   data[i - info->offset] = databyte;
+   }
+
+   return 0;
+}
+
 uint16_t
 ixgbe_reta_size_get(enum ixgbe_mac_type mac_type) {
switch (mac_type) {
-- 
1.7.10.4



Re: [dpdk-dev] [PATCH v4 1/5] ethdev: add access to eeprom

2018-04-25 Thread Zijie Pan
Hi Thomas,

> > +/**
> > + * Placeholder for accessing plugin module eeprom
> > + */
> > +struct rte_dev_module_info {
> > + uint32_t type; /**< Type of plugin module eeprom */
> > + uint32_t eeprom_len; /**< Length of plugin module eeprom */
> > +};
>
> I am not sure "plugin module" is descriptive enough.
Here is the description when "man ethtool":
-m --dump-module-eeprom --module-info
Retrieves  and if possible decodes the EEPROM from plugin modules, e.g 
SFP+, QSFP.
Is there any suggestion how to describe it?

> And I think the structure name should be rte_eth_dev_module_info
> to make clear that we are talking about NIC modules.
> Any better idea?
Yes, rte_eth_dev_module_info is better than rte_dev_module_info.
But the name of other structures should be also changed. And the file name
should be changed to rte_eth_dev_info.h.
Do we need to make a patch first to change the name of the file and structures?

> > +int __rte_experimental
> > +rte_eth_dev_get_module_eeprom(uint16_t port_id,
> > +   struct rte_dev_eeprom_info *info)
> > +{
> > + struct rte_eth_dev *dev;
> > +
> > + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +
> > + dev = &rte_eth_devices[port_id];
> > + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_eeprom, -ENOTSUP);
> > + return (*dev->dev_ops->get_module_eeprom)(dev, info);
> > +}
> > +
> >  int
> >  rte_eth_dev_get_dcb_info(uint16_t port_id,
>
> Please move this code after other EEPROM related functions.
I put the functions after rte_eth_dev_set_eeprom(). Please apply the patch and 
check it.

> > --- a/lib/librte_ether/rte_ethdev_version.map
> > +++ b/lib/librte_ether/rte_ethdev_version.map
> > @@ -229,5 +229,7 @@ EXPERIMENTAL {
> >  rte_mtr_policer_actions_update;
> >  rte_mtr_stats_read;
> >  rte_mtr_stats_update;
> > + rte_eth_dev_get_module_info;
> > + rte_eth_dev_get_module_eeprom;
>
> This must be inserted in alphabetical order.
I will update it in v5 patchset.

Thanks & Regards,
Zijie

[dpdk-dev] [PATCH v5 0/5] get the information and data of EEPROM

2018-04-25 Thread Zijie Pan
 0540  0540       .@...@..
180:          
190:          
1a0:  faff        
1b0:          
1c0:          
1d0:          
1e0:          
1f0:     0003 0100    

Both DPDK's my-module-eeprom.bin and Kernel's meeprom-kernel.bin
are the same.

v2 changes:
 - Fix typo in features.rst.
 - Fix checkpatch warnings regarding long lines.
 - Update function pcmd_module_eeprom_callback().

v3 changes:
 - fix compilation when dpdk is compiled with shared libs.

v4 changes:
 - add RTE_ prefix for the macros defined in rte_dev_info.h.
 - mark the new APIs as experimental.
 - some other minor fixes.

v5 changes:
 - insert the new APIs in alphabetical order in rte_ethdev_version.map.

Zijie Pan (5):
  ethdev: add access to eeprom
  examples/ethtool: add a new command module-eeprom
  net/ixgbe: add module EEPROM callbacks for ixgbe
  net/e1000: add module EEPROM callbacks for e1000
  net/i40e: add module EEPROM callbacks for i40e

 doc/guides/nics/features.rst|   11 +++
 doc/guides/sample_app_ug/ethtool.rst|3 +
 drivers/net/e1000/base/e1000_phy.h  |8 ++
 drivers/net/e1000/igb_ethdev.c  |   86 ++
 drivers/net/i40e/i40e_ethdev.c  |  147 +++
 drivers/net/ixgbe/ixgbe_ethdev.c|   79 +
 examples/ethtool/ethtool-app/ethapp.c   |   64 ++
 examples/ethtool/lib/Makefile   |1 +
 examples/ethtool/lib/rte_ethtool.c  |   30 +++
 examples/ethtool/lib/rte_ethtool.h  |   34 +++
 lib/librte_ether/rte_dev_info.h |   18 
 lib/librte_ether/rte_ethdev.c   |   26 ++
 lib/librte_ether/rte_ethdev.h   |   43 +
 lib/librte_ether/rte_ethdev_core.h  |   12 +++
 lib/librte_ether/rte_ethdev_version.map |2 +
 15 files changed, 564 insertions(+)

-- 
1.7.10.4



[dpdk-dev] [PATCH v5 2/5] examples/ethtool: add a new command module-eeprom

2018-04-25 Thread Zijie Pan
Add a new command "module-eeprom" to get the data of plugin
module EEPROM.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: or...@mellanox.com
Cc: bruce.richard...@intel.com
Cc: pablo.de.lara.gua...@intel.com
Cc: radu.nico...@intel.com
Cc: akhil.go...@nxp.com
Cc: tomasz.kante...@intel.com
Cc: john.mcnam...@intel.com
Cc: marko.kovace...@intel.com

 doc/guides/sample_app_ug/ethtool.rst  |3 ++
 examples/ethtool/ethtool-app/ethapp.c |   64 +
 examples/ethtool/lib/Makefile |1 +
 examples/ethtool/lib/rte_ethtool.c|   30 
 examples/ethtool/lib/rte_ethtool.h|   34 ++
 5 files changed, 132 insertions(+)

diff --git a/doc/guides/sample_app_ug/ethtool.rst 
b/doc/guides/sample_app_ug/ethtool.rst
index 1b79aca..47e09f6 100644
--- a/doc/guides/sample_app_ug/ethtool.rst
+++ b/doc/guides/sample_app_ug/ethtool.rst
@@ -44,6 +44,7 @@ they do as as follows:
 
 * ``drvinfo``: Print driver info
 * ``eeprom``: Dump EEPROM to file
+* ``module-eeprom``: Dump plugin module EEPROM to file
 * ``link``: Print port link states
 * ``macaddr``: Gets/sets MAC address
 * ``mtu``: Set NIC MTU
@@ -97,6 +98,8 @@ the following functions:
 - ``rte_ethtool_get_eeprom_len()``
 - ``rte_ethtool_get_eeprom()``
 - ``rte_ethtool_set_eeprom()``
+- ``rte_ethtool_get_module_info()``
+- ``rte_ethtool_get_module_eeprom()``
 - ``rte_ethtool_get_pauseparam()``
 - ``rte_ethtool_set_pauseparam()``
 - ``rte_ethtool_net_open()``
diff --git a/examples/ethtool/ethtool-app/ethapp.c 
b/examples/ethtool/ethtool-app/ethapp.c
index 4d62f4c..a4e64b3 100644
--- a/examples/ethtool/ethtool-app/ethapp.c
+++ b/examples/ethtool/ethtool-app/ethapp.c
@@ -75,6 +75,9 @@ struct pcmd_intintint_params {
 /* Commands taking port id and string */
 cmdline_parse_token_string_t pcmd_eeprom_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "eeprom");
+cmdline_parse_token_string_t pcmd_module_eeprom_token_cmd =
+   TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd,
+"module-eeprom");
 cmdline_parse_token_string_t pcmd_mtu_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "mtu");
 cmdline_parse_token_string_t pcmd_regs_token_cmd =
@@ -298,6 +301,54 @@ struct pcmd_intintint_params {
 
 
 static void
+pcmd_module_eeprom_callback(void *ptr_params,
+   __rte_unused struct cmdline *ctx,
+   __rte_unused void *ptr_data)
+{
+   struct pcmd_intstr_params *params = ptr_params;
+   struct ethtool_eeprom info_eeprom;
+   uint32_t module_info[2];
+   int stat;
+   unsigned char bytes_eeprom[EEPROM_DUMP_CHUNKSIZE];
+   FILE *fp_eeprom;
+
+   if (!rte_eth_dev_is_valid_port(params->port)) {
+   printf("Error: Invalid port number %i\n", params->port);
+   return;
+   }
+
+   stat = rte_ethtool_get_module_info(params->port, module_info);
+   if (stat != 0) {
+   printf("Module EEPROM information read error %i\n", stat);
+   return;
+   }
+
+   info_eeprom.len = module_info[1];
+   info_eeprom.offset = 0;
+
+   stat = rte_ethtool_get_module_eeprom(params->port,
+&info_eeprom, bytes_eeprom);
+   if (stat != 0) {
+   printf("Module EEPROM read error %i\n", stat);
+   return;
+   }
+
+   fp_eeprom = fopen(params->opt, "wb");
+   if (fp_eeprom == NULL) {
+   printf("Error opening '%s' for writing\n", params->opt);
+   return;
+   }
+   printf("Total plugin module EEPROM length: %i bytes\n",
+  info_eeprom.len);
+   if (fwrite(bytes_eeprom, 1, info_eeprom.len,
+  fp_eeprom) != info_eeprom.len) {
+   printf("Error writing '%s'\n", params->opt);
+   }
+   fclose(fp_eeprom);
+}
+
+
+static void
 pcmd_pause_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
void *ptr_data)
@@ -664,6 +715,18 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
NULL
},
 };
+cmdline_parse_inst_t pcmd_module_eeprom = {
+   .f = pcmd_module_eeprom_callback,
+   .data = NULL,
+   .help_str = "module-eeprom  \n"
+   " Dump plugin module EEPROM to file",
+   .tokens = {
+   (void *)&pcmd_module_eeprom_token_cmd,
+   (void *)&pcmd_intstr_token_port,
+   (void *)&pcmd_intstr_token_opt,
+   NULL
+   },
+};
 cmdline_parse_inst_t pcmd_pause_noopt = {
.f = pcmd_pause_callback,
.data = (void *)0x01,
@@ -816,6 +879,7 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
 cmdl

[dpdk-dev] [PATCH v5 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe

2018-04-25 Thread Zijie Pan
Add new callbacks for eth_dev_ops of ixgbe to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: wenzhuo...@intel.com
Cc: konstantin.anan...@intel.com

 drivers/net/ixgbe/ixgbe_ethdev.c |   79 ++
 1 file changed, 79 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index a5e2fc0..55850df 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -327,6 +327,11 @@ static int ixgbe_get_eeprom(struct rte_eth_dev *dev,
 static int ixgbe_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 
+static int ixgbe_get_module_info(struct rte_eth_dev *dev,
+struct rte_dev_module_info *modinfo);
+static int ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+  struct rte_dev_eeprom_info *info);
+
 static int ixgbevf_get_reg_length(struct rte_eth_dev *dev);
 static int ixgbevf_get_regs(struct rte_eth_dev *dev,
struct rte_dev_reg_info *regs);
@@ -564,6 +569,8 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev 
*dev,
.get_eeprom_length= ixgbe_get_eeprom_length,
.get_eeprom   = ixgbe_get_eeprom,
.set_eeprom   = ixgbe_set_eeprom,
+   .get_module_info  = ixgbe_get_module_info,
+   .get_module_eeprom= ixgbe_get_module_eeprom,
.get_dcb_info = ixgbe_dev_get_dcb_info,
.timesync_adjust_time = ixgbe_timesync_adjust_time,
.timesync_read_time   = ixgbe_timesync_read_time,
@@ -7126,6 +7133,78 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev 
*dev, bool on)
return eeprom->ops.write_buffer(hw,  first, length, data);
 }
 
+static int
+ixgbe_get_module_info(struct rte_eth_dev *dev,
+ struct rte_dev_module_info *modinfo)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status;
+   uint8_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   /* Check whether we support SFF-8472 or not */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_COMP,
+&sff8472_rev);
+   if (status != 0)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_SWAP,
+&addr_mode);
+   if (status != 0)
+   return -EIO;
+
+   if (addr_mode & IXGBE_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR,
+   "Address change required to access page 0xA2, "
+   "but not supported. Please report the module "
+   "type to the driver maintainers.");
+   page_swap = true;
+   }
+
+   if (sff8472_rev == IXGBE_SFF_SFF_8472_UNSUP || page_swap) {
+   /* We have a SFP, but it does not support SFF-8472 */
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have a SFP which supports a revision of SFF-8472. */
+   modinfo->type = RTE_ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+   struct rte_dev_eeprom_info *info)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status = IXGBE_ERR_PHY_ADDR_INVALID;
+   uint8_t databyte = 0xFF;
+   uint8_t *data = info->data;
+   uint32_t i = 0;
+
+   if (info->length == 0)
+   return -EINVAL;
+
+   for (i = info->offset; i < info->offset + info->length; i++) {
+   if (i < RTE_ETH_MODULE_SFF_8079_LEN)
+   status = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte);
+   else
+   status = hw->phy.ops.read_i2c_sff8472(hw, i, &databyte);
+
+   if (status != 0)
+   return -EIO;
+
+   data[i - info->offset] = databyte;
+   }
+
+   return 0;
+}
+
 uint16_t
 ixgbe_reta_size_get(enum ixgbe_mac_type mac_type) {
switch (mac_type) {
-- 
1.7.10.4



[dpdk-dev] [PATCH v5 1/5] ethdev: add access to eeprom

2018-04-25 Thread Zijie Pan
add new APIs:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: john.mcnam...@intel.com
Cc: marko.kovace...@intel.com
Cc: tho...@monjalon.net

 doc/guides/nics/features.rst|   11 
 lib/librte_ether/rte_dev_info.h |   18 +
 lib/librte_ether/rte_ethdev.c   |   26 +++
 lib/librte_ether/rte_ethdev.h   |   43 +++
 lib/librte_ether/rte_ethdev_core.h  |   12 +
 lib/librte_ether/rte_ethdev_version.map |2 ++
 6 files changed, 112 insertions(+)

diff --git a/doc/guides/nics/features.rst b/doc/guides/nics/features.rst
index 1b4fb97..bb183e2 100644
--- a/doc/guides/nics/features.rst
+++ b/doc/guides/nics/features.rst
@@ -749,6 +749,17 @@ Supports getting/setting device eeprom data.
   ``rte_eth_dev_set_eeprom()``.
 
 
+.. _nic_features_module_eeprom_dump:
+
+Module EEPROM dump
+--
+
+Supports getting information and data of plugin module eeprom.
+
+* **[implements] eth_dev_ops**: ``get_module_info``, ``get_module_eeprom``.
+* **[related]API**: ``rte_eth_dev_get_module_info()``, 
``rte_eth_dev_get_module_eeprom()``.
+
+
 .. _nic_features_register_dump:
 
 Registers dump
diff --git a/lib/librte_ether/rte_dev_info.h b/lib/librte_ether/rte_dev_info.h
index 6b68584..02bdbed 100644
--- a/lib/librte_ether/rte_dev_info.h
+++ b/lib/librte_ether/rte_dev_info.h
@@ -28,4 +28,22 @@ struct rte_dev_eeprom_info {
uint32_t magic; /**< Device-specific key, such as device-id */
 };
 
+/**
+ * Placeholder for accessing plugin module eeprom
+ */
+struct rte_dev_module_info {
+   uint32_t type; /**< Type of plugin module eeprom */
+   uint32_t eeprom_len; /**< Length of plugin module eeprom */
+};
+
+/* EEPROM Standards for plug in modules */
+#define RTE_ETH_MODULE_SFF_8079 0x1
+#define RTE_ETH_MODULE_SFF_8079_LEN 256
+#define RTE_ETH_MODULE_SFF_8472 0x2
+#define RTE_ETH_MODULE_SFF_8472_LEN 512
+#define RTE_ETH_MODULE_SFF_8636 0x3
+#define RTE_ETH_MODULE_SFF_8636_LEN 256
+#define RTE_ETH_MODULE_SFF_8436 0x4
+#define RTE_ETH_MODULE_SFF_8436_LEN 256
+
 #endif /* _RTE_DEV_INFO_H_ */
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 7821a88..10bc19c 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3947,6 +3947,32 @@ int rte_eth_set_queue_rate_limit(uint16_t port_id, 
uint16_t queue_idx,
return eth_err(port_id, (*dev->dev_ops->set_eeprom)(dev, info));
 }
 
+int __rte_experimental
+rte_eth_dev_get_module_info(uint16_t port_id,
+   struct rte_dev_module_info *modinfo)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_info, -ENOTSUP);
+   return (*dev->dev_ops->get_module_info)(dev, modinfo);
+}
+
+int __rte_experimental
+rte_eth_dev_get_module_eeprom(uint16_t port_id,
+ struct rte_dev_eeprom_info *info)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_eeprom, -ENOTSUP);
+   return (*dev->dev_ops->get_module_eeprom)(dev, info);
+}
+
 int
 rte_eth_dev_get_dcb_info(uint16_t port_id,
 struct rte_eth_dcb_info *dcb_info)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 7e4e57b..b39ccc4 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -3311,6 +3311,49 @@ int rte_eth_tx_queue_info_get(uint16_t port_id, uint16_t 
queue_id,
 int rte_eth_dev_set_eeprom(uint16_t port_id, struct rte_dev_eeprom_info *info);
 
 /**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Retrieve the type and size of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param modinfo
+ *   The type and size of plugin module EEPROM.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EIO) if device is removed.
+ *   - others depends on the specific operations implementation.
+ */
+int __rte_experimental
+rte_eth_dev_get_module_info(uint16_t port_id,
+   struct rte_dev_module_info *modinfo);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Retrieve the data of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param info
+ *   The template includes the plugin module EEPROM attributes, and the
+ *   buffer for return p

[dpdk-dev] [PATCH v5 4/5] net/e1000: add module EEPROM callbacks for e1000

2018-04-25 Thread Zijie Pan
Add new callbacks for eth_dev_ops of e1000 to get the information and
data of plugin module EEPROM.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: wenzhuo...@intel.com

 drivers/net/e1000/base/e1000_phy.h |8 
 drivers/net/e1000/igb_ethdev.c |   86 
 2 files changed, 94 insertions(+)

diff --git a/drivers/net/e1000/base/e1000_phy.h 
b/drivers/net/e1000/base/e1000_phy.h
index 3e45a9e..2cd0e14 100644
--- a/drivers/net/e1000/base/e1000_phy.h
+++ b/drivers/net/e1000/base/e1000_phy.h
@@ -330,4 +330,12 @@ struct sfp_e1000_flags {
 #define E1000_SFF_VENDOR_OUI_AVAGO 0x00176A00
 #define E1000_SFF_VENDOR_OUI_INTEL 0x001B2100
 
+/* EEPROM byte offsets */
+#define IGB_SFF_8472_SWAP  0x5C
+#define IGB_SFF_8472_COMP  0x5E
+
+/* Bitmasks */
+#define IGB_SFF_ADDRESSING_MODE0x4
+#define IGB_SFF_8472_UNSUP 0x00
+
 #endif
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 9b808a9..4b261cc 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -223,6 +223,10 @@ static int eth_igb_get_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 static int eth_igb_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
+static int eth_igb_get_module_info(struct rte_eth_dev *dev,
+  struct rte_dev_module_info *modinfo);
+static int eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+struct rte_dev_eeprom_info *info);
 static int eth_igb_set_mc_addr_list(struct rte_eth_dev *dev,
struct ether_addr *mc_addr_set,
uint32_t nb_mc_addr);
@@ -402,6 +406,8 @@ static void eth_igb_write_ivar(struct e1000_hw *hw, uint8_t 
msix_vector,
.get_eeprom_length= eth_igb_get_eeprom_length,
.get_eeprom   = eth_igb_get_eeprom,
.set_eeprom   = eth_igb_set_eeprom,
+   .get_module_info  = eth_igb_get_module_info,
+   .get_module_eeprom= eth_igb_get_module_eeprom,
.timesync_adjust_time = igb_timesync_adjust_time,
.timesync_read_time   = igb_timesync_read_time,
.timesync_write_time  = igb_timesync_write_time,
@@ -5329,6 +5335,86 @@ static void igbvf_set_vfta_all(struct rte_eth_dev *dev, 
bool on)
 }
 
 static int
+eth_igb_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   if (hw->phy.media_type == e1000_media_type_copper ||
+   hw->phy.media_type == e1000_media_type_unknown)
+   return -EOPNOTSUPP;
+
+   /* Check whether we support SFF-8472 or not */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_COMP, &sff8472_rev);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_SWAP, &addr_mode);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   if ((addr_mode & 0xFF) & IGB_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR,
+   "Address change required to access page 0xA2, "
+   "but not supported. Please report the module "
+   "type to the driver maintainers.\n");
+   page_swap = true;
+   }
+
+   if ((sff8472_rev & 0xFF) == IGB_SFF_8472_UNSUP || page_swap) {
+   /* We have an SFP, but it does not support SFF-8472 */
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have an SFP which supports a revision of SFF-8472 */
+   modinfo->type = RTE_ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t dataword[RTE_ETH_MODULE_SFF_8472_LEN / 2 + 1];
+   u16 first_word, last_word;
+   int i = 0;
+
+   if (info->length == 0)
+   return -EINVAL;
+
+   first_word = info->offset >> 1;
+   last_word = (info->offset + info->length - 1) >> 1;
+
+   /* Read EEPROM block, SFF-8079/SFF-8472, word at a time */
+   for (i = 0; i < last_word - first_word + 1; i++) {
+   status = e1000_read_phy_reg_i2c(

[dpdk-dev] [PATCH v5 5/5] net/i40e: add module EEPROM callbacks for i40e

2018-04-25 Thread Zijie Pan
Add new callbacks for eth_dev_ops of i40e to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: beilei.x...@intel.com
Cc: qi.z.zh...@intel.com

 drivers/net/i40e/i40e_ethdev.c |  147 
 1 file changed, 147 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 180ac74..1a24cd7 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -369,6 +369,11 @@ static int i40e_get_regs(struct rte_eth_dev *dev,
 static int i40e_get_eeprom(struct rte_eth_dev *dev,
   struct rte_dev_eeprom_info *eeprom);
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo);
+static int i40e_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info);
+
 static int i40e_set_default_mac_addr(struct rte_eth_dev *dev,
  struct ether_addr *mac_addr);
 
@@ -489,6 +494,8 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
.get_reg  = i40e_get_regs,
.get_eeprom_length= i40e_get_eeprom_length,
.get_eeprom   = i40e_get_eeprom,
+   .get_module_info  = i40e_get_module_info,
+   .get_module_eeprom= i40e_get_module_eeprom,
.mac_addr_set = i40e_set_default_mac_addr,
.mtu_set  = i40e_dev_mtu_set,
.tm_ops_get   = i40e_tm_ops_get,
@@ -11327,6 +11334,146 @@ static int i40e_get_eeprom(struct rte_eth_dev *dev,
return 0;
 }
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo)
+{
+   struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t sff8472_comp = 0;
+   uint32_t sff8472_swap = 0;
+   uint32_t sff8636_rev = 0;
+   i40e_status status;
+   uint32_t type = 0;
+
+   /* Check if firmware supports reading module EEPROM. */
+   if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE)) {
+   PMD_DRV_LOG(ERR,
+   "Module EEPROM memory read not supported. "
+   "Please update the NVM image.\n");
+   return -EINVAL;
+   }
+
+   status = i40e_update_link_info(hw);
+   if (status)
+   return -EIO;
+
+   if (hw->phy.link_info.phy_type == I40E_PHY_TYPE_EMPTY) {
+   PMD_DRV_LOG(ERR,
+   "Cannot read module EEPROM memory. "
+   "No module connected.\n");
+   return -EINVAL;
+   }
+
+   type = hw->phy.link_info.module_type[0];
+
+   switch (type) {
+   case I40E_MODULE_TYPE_SFP:
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_COMP,
+   &sff8472_comp, NULL);
+   if (status)
+   return -EIO;
+
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_SWAP,
+   &sff8472_swap, NULL);
+   if (status)
+   return -EIO;
+
+   /* Check if the module requires address swap to access
+* the other EEPROM memory page.
+*/
+   if (sff8472_swap & I40E_MODULE_SFF_ADDR_MODE) {
+   PMD_DRV_LOG(WARNING,
+   "Module address swap to access "
+   "page 0xA2 is not supported.\n");
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else if (sff8472_comp == 0x00) {
+   /* Module is not SFF-8472 compliant */
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else {
+   modinfo->type = RTE_ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+   }
+   break;
+   case I40E_MODULE_TYPE_QSFP_PLUS:
+   /* Read from memory page 0. */
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+

Re: [dpdk-dev] [PATCH v5 0/5] get the information and data of EEPROM

2018-04-25 Thread Zijie Pan
Hi Thomas,
> > v5 changes:
> >  - insert the new APIs in alphabetical order in rte_ethdev_version.map.
>
> I think there is a misunderstanding.
> I was asking to rename rte_dev_module_info as rte_eth_dev_module_info.
I will update the patch right now.

Thanks & Regards,
Zijie

[dpdk-dev] [PATCH v6 0/5] get the information and data of EEPROM

2018-04-25 Thread Zijie Pan
 0540  0540       .@...@..
180:          
190:          
1a0:  faff        
1b0:          
1c0:          
1d0:          
1e0:          
1f0:     0003 0100    

Both DPDK's my-module-eeprom.bin and Kernel's meeprom-kernel.bin
are the same.

v2 changes:
 - Fix typo in features.rst.
 - Fix checkpatch warnings regarding long lines.
 - Update function pcmd_module_eeprom_callback().

v3 changes:
 - fix compilation when dpdk is compiled with shared libs.

v4 changes:
 - add RTE_ prefix for the macros defined in rte_dev_info.h.
 - mark the new APIs as experimental.
 - some other minor fixes.

v5 changes:
 - insert the new APIs in alphabetical order in rte_ethdev_version.map.

v6 changes:
 - rename rte_dev_module_info as rte_eth_dev_module_info.

Zijie Pan (5):
  ethdev: add access to eeprom
  examples/ethtool: add a new command module-eeprom
  net/ixgbe: add module EEPROM callbacks for ixgbe
  net/e1000: add module EEPROM callbacks for e1000
  net/i40e: add module EEPROM callbacks for i40e

 doc/guides/nics/features.rst|   11 +++
 doc/guides/sample_app_ug/ethtool.rst|3 +
 drivers/net/e1000/base/e1000_phy.h  |8 ++
 drivers/net/e1000/igb_ethdev.c  |   86 ++
 drivers/net/i40e/i40e_ethdev.c  |  147 +++
 drivers/net/ixgbe/ixgbe_ethdev.c|   79 +
 examples/ethtool/ethtool-app/ethapp.c   |   64 ++
 examples/ethtool/lib/Makefile   |1 +
 examples/ethtool/lib/rte_ethtool.c  |   30 +++
 examples/ethtool/lib/rte_ethtool.h  |   34 +++
 lib/librte_ether/rte_dev_info.h |   18 
 lib/librte_ether/rte_ethdev.c   |   26 ++
 lib/librte_ether/rte_ethdev.h   |   43 +
 lib/librte_ether/rte_ethdev_core.h  |   12 +++
 lib/librte_ether/rte_ethdev_version.map |2 +
 15 files changed, 564 insertions(+)

-- 
1.7.10.4



[dpdk-dev] [PATCH v6 1/5] ethdev: add access to eeprom

2018-04-25 Thread Zijie Pan
add new APIs:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: john.mcnam...@intel.com
Cc: marko.kovace...@intel.com
Cc: tho...@monjalon.net

 doc/guides/nics/features.rst|   11 
 lib/librte_ether/rte_dev_info.h |   18 +
 lib/librte_ether/rte_ethdev.c   |   26 +++
 lib/librte_ether/rte_ethdev.h   |   43 +++
 lib/librte_ether/rte_ethdev_core.h  |   12 +
 lib/librte_ether/rte_ethdev_version.map |2 ++
 6 files changed, 112 insertions(+)

diff --git a/doc/guides/nics/features.rst b/doc/guides/nics/features.rst
index 1b4fb97..bb183e2 100644
--- a/doc/guides/nics/features.rst
+++ b/doc/guides/nics/features.rst
@@ -749,6 +749,17 @@ Supports getting/setting device eeprom data.
   ``rte_eth_dev_set_eeprom()``.
 
 
+.. _nic_features_module_eeprom_dump:
+
+Module EEPROM dump
+--
+
+Supports getting information and data of plugin module eeprom.
+
+* **[implements] eth_dev_ops**: ``get_module_info``, ``get_module_eeprom``.
+* **[related]API**: ``rte_eth_dev_get_module_info()``, 
``rte_eth_dev_get_module_eeprom()``.
+
+
 .. _nic_features_register_dump:
 
 Registers dump
diff --git a/lib/librte_ether/rte_dev_info.h b/lib/librte_ether/rte_dev_info.h
index 6b68584..fea5da8 100644
--- a/lib/librte_ether/rte_dev_info.h
+++ b/lib/librte_ether/rte_dev_info.h
@@ -28,4 +28,22 @@ struct rte_dev_eeprom_info {
uint32_t magic; /**< Device-specific key, such as device-id */
 };
 
+/**
+ * Placeholder for accessing plugin module eeprom
+ */
+struct rte_eth_dev_module_info {
+   uint32_t type; /**< Type of plugin module eeprom */
+   uint32_t eeprom_len; /**< Length of plugin module eeprom */
+};
+
+/* EEPROM Standards for plug in modules */
+#define RTE_ETH_MODULE_SFF_8079 0x1
+#define RTE_ETH_MODULE_SFF_8079_LEN 256
+#define RTE_ETH_MODULE_SFF_8472 0x2
+#define RTE_ETH_MODULE_SFF_8472_LEN 512
+#define RTE_ETH_MODULE_SFF_8636 0x3
+#define RTE_ETH_MODULE_SFF_8636_LEN 256
+#define RTE_ETH_MODULE_SFF_8436 0x4
+#define RTE_ETH_MODULE_SFF_8436_LEN 256
+
 #endif /* _RTE_DEV_INFO_H_ */
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 7821a88..100cbd8 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3947,6 +3947,32 @@ int rte_eth_set_queue_rate_limit(uint16_t port_id, 
uint16_t queue_idx,
return eth_err(port_id, (*dev->dev_ops->set_eeprom)(dev, info));
 }
 
+int __rte_experimental
+rte_eth_dev_get_module_info(uint16_t port_id,
+   struct rte_eth_dev_module_info *modinfo)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_info, -ENOTSUP);
+   return (*dev->dev_ops->get_module_info)(dev, modinfo);
+}
+
+int __rte_experimental
+rte_eth_dev_get_module_eeprom(uint16_t port_id,
+ struct rte_dev_eeprom_info *info)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_eeprom, -ENOTSUP);
+   return (*dev->dev_ops->get_module_eeprom)(dev, info);
+}
+
 int
 rte_eth_dev_get_dcb_info(uint16_t port_id,
 struct rte_eth_dcb_info *dcb_info)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 7e4e57b..4852246 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -3311,6 +3311,49 @@ int rte_eth_tx_queue_info_get(uint16_t port_id, uint16_t 
queue_id,
 int rte_eth_dev_set_eeprom(uint16_t port_id, struct rte_dev_eeprom_info *info);
 
 /**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Retrieve the type and size of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param modinfo
+ *   The type and size of plugin module EEPROM.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EIO) if device is removed.
+ *   - others depends on the specific operations implementation.
+ */
+int __rte_experimental
+rte_eth_dev_get_module_info(uint16_t port_id,
+   struct rte_eth_dev_module_info *modinfo);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Retrieve the data of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param info
+ *   The template includes the plugin module EEPROM attributes, and the
+ *   buffer for retu

[dpdk-dev] [PATCH v6 2/5] examples/ethtool: add a new command module-eeprom

2018-04-25 Thread Zijie Pan
Add a new command "module-eeprom" to get the data of plugin
module EEPROM.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: or...@mellanox.com
Cc: bruce.richard...@intel.com
Cc: pablo.de.lara.gua...@intel.com
Cc: radu.nico...@intel.com
Cc: akhil.go...@nxp.com
Cc: tomasz.kante...@intel.com
Cc: john.mcnam...@intel.com
Cc: marko.kovace...@intel.com

 doc/guides/sample_app_ug/ethtool.rst  |3 ++
 examples/ethtool/ethtool-app/ethapp.c |   64 +
 examples/ethtool/lib/Makefile |1 +
 examples/ethtool/lib/rte_ethtool.c|   30 
 examples/ethtool/lib/rte_ethtool.h|   34 ++
 5 files changed, 132 insertions(+)

diff --git a/doc/guides/sample_app_ug/ethtool.rst 
b/doc/guides/sample_app_ug/ethtool.rst
index 1b79aca..47e09f6 100644
--- a/doc/guides/sample_app_ug/ethtool.rst
+++ b/doc/guides/sample_app_ug/ethtool.rst
@@ -44,6 +44,7 @@ they do as as follows:
 
 * ``drvinfo``: Print driver info
 * ``eeprom``: Dump EEPROM to file
+* ``module-eeprom``: Dump plugin module EEPROM to file
 * ``link``: Print port link states
 * ``macaddr``: Gets/sets MAC address
 * ``mtu``: Set NIC MTU
@@ -97,6 +98,8 @@ the following functions:
 - ``rte_ethtool_get_eeprom_len()``
 - ``rte_ethtool_get_eeprom()``
 - ``rte_ethtool_set_eeprom()``
+- ``rte_ethtool_get_module_info()``
+- ``rte_ethtool_get_module_eeprom()``
 - ``rte_ethtool_get_pauseparam()``
 - ``rte_ethtool_set_pauseparam()``
 - ``rte_ethtool_net_open()``
diff --git a/examples/ethtool/ethtool-app/ethapp.c 
b/examples/ethtool/ethtool-app/ethapp.c
index 4d62f4c..a4e64b3 100644
--- a/examples/ethtool/ethtool-app/ethapp.c
+++ b/examples/ethtool/ethtool-app/ethapp.c
@@ -75,6 +75,9 @@ struct pcmd_intintint_params {
 /* Commands taking port id and string */
 cmdline_parse_token_string_t pcmd_eeprom_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "eeprom");
+cmdline_parse_token_string_t pcmd_module_eeprom_token_cmd =
+   TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd,
+"module-eeprom");
 cmdline_parse_token_string_t pcmd_mtu_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "mtu");
 cmdline_parse_token_string_t pcmd_regs_token_cmd =
@@ -298,6 +301,54 @@ struct pcmd_intintint_params {
 
 
 static void
+pcmd_module_eeprom_callback(void *ptr_params,
+   __rte_unused struct cmdline *ctx,
+   __rte_unused void *ptr_data)
+{
+   struct pcmd_intstr_params *params = ptr_params;
+   struct ethtool_eeprom info_eeprom;
+   uint32_t module_info[2];
+   int stat;
+   unsigned char bytes_eeprom[EEPROM_DUMP_CHUNKSIZE];
+   FILE *fp_eeprom;
+
+   if (!rte_eth_dev_is_valid_port(params->port)) {
+   printf("Error: Invalid port number %i\n", params->port);
+   return;
+   }
+
+   stat = rte_ethtool_get_module_info(params->port, module_info);
+   if (stat != 0) {
+   printf("Module EEPROM information read error %i\n", stat);
+   return;
+   }
+
+   info_eeprom.len = module_info[1];
+   info_eeprom.offset = 0;
+
+   stat = rte_ethtool_get_module_eeprom(params->port,
+&info_eeprom, bytes_eeprom);
+   if (stat != 0) {
+   printf("Module EEPROM read error %i\n", stat);
+   return;
+   }
+
+   fp_eeprom = fopen(params->opt, "wb");
+   if (fp_eeprom == NULL) {
+   printf("Error opening '%s' for writing\n", params->opt);
+   return;
+   }
+   printf("Total plugin module EEPROM length: %i bytes\n",
+  info_eeprom.len);
+   if (fwrite(bytes_eeprom, 1, info_eeprom.len,
+  fp_eeprom) != info_eeprom.len) {
+   printf("Error writing '%s'\n", params->opt);
+   }
+   fclose(fp_eeprom);
+}
+
+
+static void
 pcmd_pause_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
void *ptr_data)
@@ -664,6 +715,18 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
NULL
},
 };
+cmdline_parse_inst_t pcmd_module_eeprom = {
+   .f = pcmd_module_eeprom_callback,
+   .data = NULL,
+   .help_str = "module-eeprom  \n"
+   " Dump plugin module EEPROM to file",
+   .tokens = {
+   (void *)&pcmd_module_eeprom_token_cmd,
+   (void *)&pcmd_intstr_token_port,
+   (void *)&pcmd_intstr_token_opt,
+   NULL
+   },
+};
 cmdline_parse_inst_t pcmd_pause_noopt = {
.f = pcmd_pause_callback,
.data = (void *)0x01,
@@ -816,6 +879,7 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
 cmdl

[dpdk-dev] [PATCH v6 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe

2018-04-25 Thread Zijie Pan
Add new callbacks for eth_dev_ops of ixgbe to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: wenzhuo...@intel.com
Cc: konstantin.anan...@intel.com

 drivers/net/ixgbe/ixgbe_ethdev.c |   79 ++
 1 file changed, 79 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index a5e2fc0..228daaf 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -327,6 +327,11 @@ static int ixgbe_get_eeprom(struct rte_eth_dev *dev,
 static int ixgbe_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 
+static int ixgbe_get_module_info(struct rte_eth_dev *dev,
+struct rte_eth_dev_module_info *modinfo);
+static int ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+  struct rte_dev_eeprom_info *info);
+
 static int ixgbevf_get_reg_length(struct rte_eth_dev *dev);
 static int ixgbevf_get_regs(struct rte_eth_dev *dev,
struct rte_dev_reg_info *regs);
@@ -564,6 +569,8 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev 
*dev,
.get_eeprom_length= ixgbe_get_eeprom_length,
.get_eeprom   = ixgbe_get_eeprom,
.set_eeprom   = ixgbe_set_eeprom,
+   .get_module_info  = ixgbe_get_module_info,
+   .get_module_eeprom= ixgbe_get_module_eeprom,
.get_dcb_info = ixgbe_dev_get_dcb_info,
.timesync_adjust_time = ixgbe_timesync_adjust_time,
.timesync_read_time   = ixgbe_timesync_read_time,
@@ -7126,6 +7133,78 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev 
*dev, bool on)
return eeprom->ops.write_buffer(hw,  first, length, data);
 }
 
+static int
+ixgbe_get_module_info(struct rte_eth_dev *dev,
+ struct rte_eth_dev_module_info *modinfo)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status;
+   uint8_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   /* Check whether we support SFF-8472 or not */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_COMP,
+&sff8472_rev);
+   if (status != 0)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_SWAP,
+&addr_mode);
+   if (status != 0)
+   return -EIO;
+
+   if (addr_mode & IXGBE_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR,
+   "Address change required to access page 0xA2, "
+   "but not supported. Please report the module "
+   "type to the driver maintainers.");
+   page_swap = true;
+   }
+
+   if (sff8472_rev == IXGBE_SFF_SFF_8472_UNSUP || page_swap) {
+   /* We have a SFP, but it does not support SFF-8472 */
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have a SFP which supports a revision of SFF-8472. */
+   modinfo->type = RTE_ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+   struct rte_dev_eeprom_info *info)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status = IXGBE_ERR_PHY_ADDR_INVALID;
+   uint8_t databyte = 0xFF;
+   uint8_t *data = info->data;
+   uint32_t i = 0;
+
+   if (info->length == 0)
+   return -EINVAL;
+
+   for (i = info->offset; i < info->offset + info->length; i++) {
+   if (i < RTE_ETH_MODULE_SFF_8079_LEN)
+   status = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte);
+   else
+   status = hw->phy.ops.read_i2c_sff8472(hw, i, &databyte);
+
+   if (status != 0)
+   return -EIO;
+
+   data[i - info->offset] = databyte;
+   }
+
+   return 0;
+}
+
 uint16_t
 ixgbe_reta_size_get(enum ixgbe_mac_type mac_type) {
switch (mac_type) {
-- 
1.7.10.4



[dpdk-dev] [PATCH v6 5/5] net/i40e: add module EEPROM callbacks for i40e

2018-04-25 Thread Zijie Pan
Add new callbacks for eth_dev_ops of i40e to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: beilei.x...@intel.com
Cc: qi.z.zh...@intel.com

 drivers/net/i40e/i40e_ethdev.c |  147 
 1 file changed, 147 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 180ac74..948ee89 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -369,6 +369,11 @@ static int i40e_get_regs(struct rte_eth_dev *dev,
 static int i40e_get_eeprom(struct rte_eth_dev *dev,
   struct rte_dev_eeprom_info *eeprom);
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_eth_dev_module_info *modinfo);
+static int i40e_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info);
+
 static int i40e_set_default_mac_addr(struct rte_eth_dev *dev,
  struct ether_addr *mac_addr);
 
@@ -489,6 +494,8 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
.get_reg  = i40e_get_regs,
.get_eeprom_length= i40e_get_eeprom_length,
.get_eeprom   = i40e_get_eeprom,
+   .get_module_info  = i40e_get_module_info,
+   .get_module_eeprom= i40e_get_module_eeprom,
.mac_addr_set = i40e_set_default_mac_addr,
.mtu_set  = i40e_dev_mtu_set,
.tm_ops_get   = i40e_tm_ops_get,
@@ -11327,6 +11334,146 @@ static int i40e_get_eeprom(struct rte_eth_dev *dev,
return 0;
 }
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_eth_dev_module_info *modinfo)
+{
+   struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t sff8472_comp = 0;
+   uint32_t sff8472_swap = 0;
+   uint32_t sff8636_rev = 0;
+   i40e_status status;
+   uint32_t type = 0;
+
+   /* Check if firmware supports reading module EEPROM. */
+   if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE)) {
+   PMD_DRV_LOG(ERR,
+   "Module EEPROM memory read not supported. "
+   "Please update the NVM image.\n");
+   return -EINVAL;
+   }
+
+   status = i40e_update_link_info(hw);
+   if (status)
+   return -EIO;
+
+   if (hw->phy.link_info.phy_type == I40E_PHY_TYPE_EMPTY) {
+   PMD_DRV_LOG(ERR,
+   "Cannot read module EEPROM memory. "
+   "No module connected.\n");
+   return -EINVAL;
+   }
+
+   type = hw->phy.link_info.module_type[0];
+
+   switch (type) {
+   case I40E_MODULE_TYPE_SFP:
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_COMP,
+   &sff8472_comp, NULL);
+   if (status)
+   return -EIO;
+
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_SWAP,
+   &sff8472_swap, NULL);
+   if (status)
+   return -EIO;
+
+   /* Check if the module requires address swap to access
+* the other EEPROM memory page.
+*/
+   if (sff8472_swap & I40E_MODULE_SFF_ADDR_MODE) {
+   PMD_DRV_LOG(WARNING,
+   "Module address swap to access "
+   "page 0xA2 is not supported.\n");
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else if (sff8472_comp == 0x00) {
+   /* Module is not SFF-8472 compliant */
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else {
+   modinfo->type = RTE_ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+   }
+   break;
+   case I40E_MODULE_TYPE_QSFP_PLUS:
+   /* Read from memory page 0. */
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_

[dpdk-dev] [PATCH v6 4/5] net/e1000: add module EEPROM callbacks for e1000

2018-04-25 Thread Zijie Pan
Add new callbacks for eth_dev_ops of e1000 to get the information and
data of plugin module EEPROM.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: wenzhuo...@intel.com

 drivers/net/e1000/base/e1000_phy.h |8 
 drivers/net/e1000/igb_ethdev.c |   86 
 2 files changed, 94 insertions(+)

diff --git a/drivers/net/e1000/base/e1000_phy.h 
b/drivers/net/e1000/base/e1000_phy.h
index 3e45a9e..2cd0e14 100644
--- a/drivers/net/e1000/base/e1000_phy.h
+++ b/drivers/net/e1000/base/e1000_phy.h
@@ -330,4 +330,12 @@ struct sfp_e1000_flags {
 #define E1000_SFF_VENDOR_OUI_AVAGO 0x00176A00
 #define E1000_SFF_VENDOR_OUI_INTEL 0x001B2100
 
+/* EEPROM byte offsets */
+#define IGB_SFF_8472_SWAP  0x5C
+#define IGB_SFF_8472_COMP  0x5E
+
+/* Bitmasks */
+#define IGB_SFF_ADDRESSING_MODE0x4
+#define IGB_SFF_8472_UNSUP 0x00
+
 #endif
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 9b808a9..c35c935 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -223,6 +223,10 @@ static int eth_igb_get_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 static int eth_igb_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
+static int eth_igb_get_module_info(struct rte_eth_dev *dev,
+  struct rte_eth_dev_module_info *modinfo);
+static int eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+struct rte_dev_eeprom_info *info);
 static int eth_igb_set_mc_addr_list(struct rte_eth_dev *dev,
struct ether_addr *mc_addr_set,
uint32_t nb_mc_addr);
@@ -402,6 +406,8 @@ static void eth_igb_write_ivar(struct e1000_hw *hw, uint8_t 
msix_vector,
.get_eeprom_length= eth_igb_get_eeprom_length,
.get_eeprom   = eth_igb_get_eeprom,
.set_eeprom   = eth_igb_set_eeprom,
+   .get_module_info  = eth_igb_get_module_info,
+   .get_module_eeprom= eth_igb_get_module_eeprom,
.timesync_adjust_time = igb_timesync_adjust_time,
.timesync_read_time   = igb_timesync_read_time,
.timesync_write_time  = igb_timesync_write_time,
@@ -5329,6 +5335,86 @@ static void igbvf_set_vfta_all(struct rte_eth_dev *dev, 
bool on)
 }
 
 static int
+eth_igb_get_module_info(struct rte_eth_dev *dev,
+   struct rte_eth_dev_module_info *modinfo)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   if (hw->phy.media_type == e1000_media_type_copper ||
+   hw->phy.media_type == e1000_media_type_unknown)
+   return -EOPNOTSUPP;
+
+   /* Check whether we support SFF-8472 or not */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_COMP, &sff8472_rev);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_SWAP, &addr_mode);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   if ((addr_mode & 0xFF) & IGB_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR,
+   "Address change required to access page 0xA2, "
+   "but not supported. Please report the module "
+   "type to the driver maintainers.\n");
+   page_swap = true;
+   }
+
+   if ((sff8472_rev & 0xFF) == IGB_SFF_8472_UNSUP || page_swap) {
+   /* We have an SFP, but it does not support SFF-8472 */
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have an SFP which supports a revision of SFF-8472 */
+   modinfo->type = RTE_ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t dataword[RTE_ETH_MODULE_SFF_8472_LEN / 2 + 1];
+   u16 first_word, last_word;
+   int i = 0;
+
+   if (info->length == 0)
+   return -EINVAL;
+
+   first_word = info->offset >> 1;
+   last_word = (info->offset + info->length - 1) >> 1;
+
+   /* Read EEPROM block, SFF-8079/SFF-8472, word at a time */
+   for (i = 0; i < last_word - first_word + 1; i++) {
+   status = e

[dpdk-dev] [PATCH v7 0/5] get the information and data of EEPROM

2018-04-25 Thread Zijie Pan
 0540  0540       .@...@..
180:          
190:          
1a0:  faff        
1b0:          
1c0:          
1d0:          
1e0:          
1f0:     0003 0100    

Both DPDK's my-module-eeprom.bin and Kernel's meeprom-kernel.bin
are the same.

v2 changes:
 - Fix typo in features.rst.
 - Fix checkpatch warnings regarding long lines.
 - Update function pcmd_module_eeprom_callback().

v3 changes:
 - fix compilation when dpdk is compiled with shared libs.

v4 changes:
 - add RTE_ prefix for the macros defined in rte_dev_info.h.
 - mark the new APIs as experimental.
 - some other minor fixes.

v5 changes:
 - insert the new APIs in alphabetical order in rte_ethdev_version.map.

v6 changes:
 - rename rte_dev_module_info as rte_eth_dev_module_info.

v7 changes:
 - add module EEPROM dump feature in default.ini
 - add module EEPROM dump feature in .ini files for the three PMDs.

Zijie Pan (5):
  ethdev: add access to eeprom
  examples/ethtool: add a new command module-eeprom
  net/ixgbe: add module EEPROM callbacks for ixgbe
  net/e1000: add module EEPROM callbacks for e1000
  net/i40e: add module EEPROM callbacks for i40e

 doc/guides/nics/features.rst|   11 +++
 doc/guides/nics/features/default.ini|1 +
 doc/guides/nics/features/i40e.ini   |1 +
 doc/guides/nics/features/i40e_vec.ini   |1 +
 doc/guides/nics/features/igb.ini|1 +
 doc/guides/nics/features/ixgbe.ini  |1 +
 doc/guides/nics/features/ixgbe_vec.ini  |1 +
 doc/guides/sample_app_ug/ethtool.rst|3 +
 drivers/net/e1000/base/e1000_phy.h  |8 ++
 drivers/net/e1000/igb_ethdev.c  |   86 ++
 drivers/net/i40e/i40e_ethdev.c  |  147 +++
 drivers/net/ixgbe/ixgbe_ethdev.c|   79 +
 examples/ethtool/ethtool-app/ethapp.c   |   64 ++
 examples/ethtool/lib/Makefile   |1 +
 examples/ethtool/lib/rte_ethtool.c  |   30 +++
 examples/ethtool/lib/rte_ethtool.h  |   34 +++
 lib/librte_ether/rte_dev_info.h |   18 
 lib/librte_ether/rte_ethdev.c   |   26 ++
 lib/librte_ether/rte_ethdev.h   |   43 +
 lib/librte_ether/rte_ethdev_core.h  |   12 +++
 lib/librte_ether/rte_ethdev_version.map |2 +
 21 files changed, 570 insertions(+)

-- 
1.7.10.4



[dpdk-dev] [PATCH v7 2/5] examples/ethtool: add a new command module-eeprom

2018-04-25 Thread Zijie Pan
Add a new command "module-eeprom" to get the data of plugin
module EEPROM.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: or...@mellanox.com
Cc: bruce.richard...@intel.com
Cc: pablo.de.lara.gua...@intel.com
Cc: radu.nico...@intel.com
Cc: akhil.go...@nxp.com
Cc: tomasz.kante...@intel.com
Cc: john.mcnam...@intel.com
Cc: marko.kovace...@intel.com

 doc/guides/sample_app_ug/ethtool.rst  |3 ++
 examples/ethtool/ethtool-app/ethapp.c |   64 +
 examples/ethtool/lib/Makefile |1 +
 examples/ethtool/lib/rte_ethtool.c|   30 
 examples/ethtool/lib/rte_ethtool.h|   34 ++
 5 files changed, 132 insertions(+)

diff --git a/doc/guides/sample_app_ug/ethtool.rst 
b/doc/guides/sample_app_ug/ethtool.rst
index 1b79aca..47e09f6 100644
--- a/doc/guides/sample_app_ug/ethtool.rst
+++ b/doc/guides/sample_app_ug/ethtool.rst
@@ -44,6 +44,7 @@ they do as as follows:
 
 * ``drvinfo``: Print driver info
 * ``eeprom``: Dump EEPROM to file
+* ``module-eeprom``: Dump plugin module EEPROM to file
 * ``link``: Print port link states
 * ``macaddr``: Gets/sets MAC address
 * ``mtu``: Set NIC MTU
@@ -97,6 +98,8 @@ the following functions:
 - ``rte_ethtool_get_eeprom_len()``
 - ``rte_ethtool_get_eeprom()``
 - ``rte_ethtool_set_eeprom()``
+- ``rte_ethtool_get_module_info()``
+- ``rte_ethtool_get_module_eeprom()``
 - ``rte_ethtool_get_pauseparam()``
 - ``rte_ethtool_set_pauseparam()``
 - ``rte_ethtool_net_open()``
diff --git a/examples/ethtool/ethtool-app/ethapp.c 
b/examples/ethtool/ethtool-app/ethapp.c
index 4d62f4c..a4e64b3 100644
--- a/examples/ethtool/ethtool-app/ethapp.c
+++ b/examples/ethtool/ethtool-app/ethapp.c
@@ -75,6 +75,9 @@ struct pcmd_intintint_params {
 /* Commands taking port id and string */
 cmdline_parse_token_string_t pcmd_eeprom_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "eeprom");
+cmdline_parse_token_string_t pcmd_module_eeprom_token_cmd =
+   TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd,
+"module-eeprom");
 cmdline_parse_token_string_t pcmd_mtu_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "mtu");
 cmdline_parse_token_string_t pcmd_regs_token_cmd =
@@ -298,6 +301,54 @@ struct pcmd_intintint_params {
 
 
 static void
+pcmd_module_eeprom_callback(void *ptr_params,
+   __rte_unused struct cmdline *ctx,
+   __rte_unused void *ptr_data)
+{
+   struct pcmd_intstr_params *params = ptr_params;
+   struct ethtool_eeprom info_eeprom;
+   uint32_t module_info[2];
+   int stat;
+   unsigned char bytes_eeprom[EEPROM_DUMP_CHUNKSIZE];
+   FILE *fp_eeprom;
+
+   if (!rte_eth_dev_is_valid_port(params->port)) {
+   printf("Error: Invalid port number %i\n", params->port);
+   return;
+   }
+
+   stat = rte_ethtool_get_module_info(params->port, module_info);
+   if (stat != 0) {
+   printf("Module EEPROM information read error %i\n", stat);
+   return;
+   }
+
+   info_eeprom.len = module_info[1];
+   info_eeprom.offset = 0;
+
+   stat = rte_ethtool_get_module_eeprom(params->port,
+&info_eeprom, bytes_eeprom);
+   if (stat != 0) {
+   printf("Module EEPROM read error %i\n", stat);
+   return;
+   }
+
+   fp_eeprom = fopen(params->opt, "wb");
+   if (fp_eeprom == NULL) {
+   printf("Error opening '%s' for writing\n", params->opt);
+   return;
+   }
+   printf("Total plugin module EEPROM length: %i bytes\n",
+  info_eeprom.len);
+   if (fwrite(bytes_eeprom, 1, info_eeprom.len,
+  fp_eeprom) != info_eeprom.len) {
+   printf("Error writing '%s'\n", params->opt);
+   }
+   fclose(fp_eeprom);
+}
+
+
+static void
 pcmd_pause_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
void *ptr_data)
@@ -664,6 +715,18 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
NULL
},
 };
+cmdline_parse_inst_t pcmd_module_eeprom = {
+   .f = pcmd_module_eeprom_callback,
+   .data = NULL,
+   .help_str = "module-eeprom  \n"
+   " Dump plugin module EEPROM to file",
+   .tokens = {
+   (void *)&pcmd_module_eeprom_token_cmd,
+   (void *)&pcmd_intstr_token_port,
+   (void *)&pcmd_intstr_token_opt,
+   NULL
+   },
+};
 cmdline_parse_inst_t pcmd_pause_noopt = {
.f = pcmd_pause_callback,
.data = (void *)0x01,
@@ -816,6 +879,7 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
 cmdl

[dpdk-dev] [PATCH v7 1/5] ethdev: add access to eeprom

2018-04-25 Thread Zijie Pan
add new APIs:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
Acked-by: Thomas Monjalon 
---
Cc: remy.hor...@intel.com
Cc: john.mcnam...@intel.com
Cc: marko.kovace...@intel.com
Cc: tho...@monjalon.net

 doc/guides/nics/features.rst|   11 
 doc/guides/nics/features/default.ini|1 +
 lib/librte_ether/rte_dev_info.h |   18 +
 lib/librte_ether/rte_ethdev.c   |   26 +++
 lib/librte_ether/rte_ethdev.h   |   43 +++
 lib/librte_ether/rte_ethdev_core.h  |   12 +
 lib/librte_ether/rte_ethdev_version.map |2 ++
 7 files changed, 113 insertions(+)

diff --git a/doc/guides/nics/features.rst b/doc/guides/nics/features.rst
index 1b4fb97..bb183e2 100644
--- a/doc/guides/nics/features.rst
+++ b/doc/guides/nics/features.rst
@@ -749,6 +749,17 @@ Supports getting/setting device eeprom data.
   ``rte_eth_dev_set_eeprom()``.
 
 
+.. _nic_features_module_eeprom_dump:
+
+Module EEPROM dump
+--
+
+Supports getting information and data of plugin module eeprom.
+
+* **[implements] eth_dev_ops**: ``get_module_info``, ``get_module_eeprom``.
+* **[related]API**: ``rte_eth_dev_get_module_info()``, 
``rte_eth_dev_get_module_eeprom()``.
+
+
 .. _nic_features_register_dump:
 
 Registers dump
diff --git a/doc/guides/nics/features/default.ini 
b/doc/guides/nics/features/default.ini
index dae2ad7..7dfe56c 100644
--- a/doc/guides/nics/features/default.ini
+++ b/doc/guides/nics/features/default.ini
@@ -63,6 +63,7 @@ Extended stats   =
 Stats per queue  =
 FW version   =
 EEPROM dump  =
+Module EEPROM dump   =
 Registers dump   =
 LED  =
 Multiprocess aware   =
diff --git a/lib/librte_ether/rte_dev_info.h b/lib/librte_ether/rte_dev_info.h
index 6b68584..fea5da8 100644
--- a/lib/librte_ether/rte_dev_info.h
+++ b/lib/librte_ether/rte_dev_info.h
@@ -28,4 +28,22 @@ struct rte_dev_eeprom_info {
uint32_t magic; /**< Device-specific key, such as device-id */
 };
 
+/**
+ * Placeholder for accessing plugin module eeprom
+ */
+struct rte_eth_dev_module_info {
+   uint32_t type; /**< Type of plugin module eeprom */
+   uint32_t eeprom_len; /**< Length of plugin module eeprom */
+};
+
+/* EEPROM Standards for plug in modules */
+#define RTE_ETH_MODULE_SFF_8079 0x1
+#define RTE_ETH_MODULE_SFF_8079_LEN 256
+#define RTE_ETH_MODULE_SFF_8472 0x2
+#define RTE_ETH_MODULE_SFF_8472_LEN 512
+#define RTE_ETH_MODULE_SFF_8636 0x3
+#define RTE_ETH_MODULE_SFF_8636_LEN 256
+#define RTE_ETH_MODULE_SFF_8436 0x4
+#define RTE_ETH_MODULE_SFF_8436_LEN 256
+
 #endif /* _RTE_DEV_INFO_H_ */
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 7821a88..100cbd8 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3947,6 +3947,32 @@ int rte_eth_set_queue_rate_limit(uint16_t port_id, 
uint16_t queue_idx,
return eth_err(port_id, (*dev->dev_ops->set_eeprom)(dev, info));
 }
 
+int __rte_experimental
+rte_eth_dev_get_module_info(uint16_t port_id,
+   struct rte_eth_dev_module_info *modinfo)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_info, -ENOTSUP);
+   return (*dev->dev_ops->get_module_info)(dev, modinfo);
+}
+
+int __rte_experimental
+rte_eth_dev_get_module_eeprom(uint16_t port_id,
+ struct rte_dev_eeprom_info *info)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_eeprom, -ENOTSUP);
+   return (*dev->dev_ops->get_module_eeprom)(dev, info);
+}
+
 int
 rte_eth_dev_get_dcb_info(uint16_t port_id,
 struct rte_eth_dcb_info *dcb_info)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 7e4e57b..4852246 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -3311,6 +3311,49 @@ int rte_eth_tx_queue_info_get(uint16_t port_id, uint16_t 
queue_id,
 int rte_eth_dev_set_eeprom(uint16_t port_id, struct rte_dev_eeprom_info *info);
 
 /**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Retrieve the type and size of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param modinfo
+ *   The type and size of plugin module EEPROM.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EIO) if device is removed.
+ *   - others depends 

[dpdk-dev] [PATCH v7 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe

2018-04-25 Thread Zijie Pan
Add new callbacks for eth_dev_ops of ixgbe to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: wenzhuo...@intel.com
Cc: konstantin.anan...@intel.com

 doc/guides/nics/features/ixgbe.ini |1 +
 doc/guides/nics/features/ixgbe_vec.ini |1 +
 drivers/net/ixgbe/ixgbe_ethdev.c   |   79 
 3 files changed, 81 insertions(+)

diff --git a/doc/guides/nics/features/ixgbe.ini 
b/doc/guides/nics/features/ixgbe.ini
index 1d68ee8..4143111 100644
--- a/doc/guides/nics/features/ixgbe.ini
+++ b/doc/guides/nics/features/ixgbe.ini
@@ -51,6 +51,7 @@ Extended stats   = Y
 Stats per queue  = Y
 FW version   = Y
 EEPROM dump  = Y
+Module EEPROM dump   = Y
 Registers dump   = Y
 Multiprocess aware   = Y
 BSD nic_uio  = Y
diff --git a/doc/guides/nics/features/ixgbe_vec.ini 
b/doc/guides/nics/features/ixgbe_vec.ini
index 28bc054..ef3ee68 100644
--- a/doc/guides/nics/features/ixgbe_vec.ini
+++ b/doc/guides/nics/features/ixgbe_vec.ini
@@ -40,6 +40,7 @@ Basic stats  = Y
 Extended stats   = Y
 Stats per queue  = Y
 EEPROM dump  = Y
+Module EEPROM dump   = Y
 Registers dump   = Y
 Multiprocess aware   = Y
 BSD nic_uio  = Y
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index a5e2fc0..228daaf 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -327,6 +327,11 @@ static int ixgbe_get_eeprom(struct rte_eth_dev *dev,
 static int ixgbe_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 
+static int ixgbe_get_module_info(struct rte_eth_dev *dev,
+struct rte_eth_dev_module_info *modinfo);
+static int ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+  struct rte_dev_eeprom_info *info);
+
 static int ixgbevf_get_reg_length(struct rte_eth_dev *dev);
 static int ixgbevf_get_regs(struct rte_eth_dev *dev,
struct rte_dev_reg_info *regs);
@@ -564,6 +569,8 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev 
*dev,
.get_eeprom_length= ixgbe_get_eeprom_length,
.get_eeprom   = ixgbe_get_eeprom,
.set_eeprom   = ixgbe_set_eeprom,
+   .get_module_info  = ixgbe_get_module_info,
+   .get_module_eeprom= ixgbe_get_module_eeprom,
.get_dcb_info = ixgbe_dev_get_dcb_info,
.timesync_adjust_time = ixgbe_timesync_adjust_time,
.timesync_read_time   = ixgbe_timesync_read_time,
@@ -7126,6 +7133,78 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev 
*dev, bool on)
return eeprom->ops.write_buffer(hw,  first, length, data);
 }
 
+static int
+ixgbe_get_module_info(struct rte_eth_dev *dev,
+ struct rte_eth_dev_module_info *modinfo)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status;
+   uint8_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   /* Check whether we support SFF-8472 or not */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_COMP,
+&sff8472_rev);
+   if (status != 0)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_SWAP,
+&addr_mode);
+   if (status != 0)
+   return -EIO;
+
+   if (addr_mode & IXGBE_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR,
+   "Address change required to access page 0xA2, "
+   "but not supported. Please report the module "
+   "type to the driver maintainers.");
+   page_swap = true;
+   }
+
+   if (sff8472_rev == IXGBE_SFF_SFF_8472_UNSUP || page_swap) {
+   /* We have a SFP, but it does not support SFF-8472 */
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have a SFP which supports a revision of SFF-8472. */
+   modinfo->type = RTE_ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+   struct rte_dev_eeprom_info *info)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status = IXGBE_ERR_PHY_ADDR_INVALID;
+   uint8_t databyte = 0xFF;
+   uint8_t *data = info->data;
+   u

[dpdk-dev] [PATCH v7 4/5] net/e1000: add module EEPROM callbacks for e1000

2018-04-25 Thread Zijie Pan
Add new callbacks for eth_dev_ops of e1000 to get the information and
data of plugin module EEPROM.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: wenzhuo...@intel.com

 doc/guides/nics/features/igb.ini   |1 +
 drivers/net/e1000/base/e1000_phy.h |8 
 drivers/net/e1000/igb_ethdev.c |   86 
 3 files changed, 95 insertions(+)

diff --git a/doc/guides/nics/features/igb.ini b/doc/guides/nics/features/igb.ini
index 33d64d9..c53fd07 100644
--- a/doc/guides/nics/features/igb.ini
+++ b/doc/guides/nics/features/igb.ini
@@ -41,6 +41,7 @@ Basic stats  = Y
 Extended stats   = Y
 FW version   = Y
 EEPROM dump  = Y
+Module EEPROM dump   = Y
 Registers dump   = Y
 BSD nic_uio  = Y
 Linux UIO= Y
diff --git a/drivers/net/e1000/base/e1000_phy.h 
b/drivers/net/e1000/base/e1000_phy.h
index 3e45a9e..2cd0e14 100644
--- a/drivers/net/e1000/base/e1000_phy.h
+++ b/drivers/net/e1000/base/e1000_phy.h
@@ -330,4 +330,12 @@ struct sfp_e1000_flags {
 #define E1000_SFF_VENDOR_OUI_AVAGO 0x00176A00
 #define E1000_SFF_VENDOR_OUI_INTEL 0x001B2100
 
+/* EEPROM byte offsets */
+#define IGB_SFF_8472_SWAP  0x5C
+#define IGB_SFF_8472_COMP  0x5E
+
+/* Bitmasks */
+#define IGB_SFF_ADDRESSING_MODE0x4
+#define IGB_SFF_8472_UNSUP 0x00
+
 #endif
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 9b808a9..c35c935 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -223,6 +223,10 @@ static int eth_igb_get_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 static int eth_igb_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
+static int eth_igb_get_module_info(struct rte_eth_dev *dev,
+  struct rte_eth_dev_module_info *modinfo);
+static int eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+struct rte_dev_eeprom_info *info);
 static int eth_igb_set_mc_addr_list(struct rte_eth_dev *dev,
struct ether_addr *mc_addr_set,
uint32_t nb_mc_addr);
@@ -402,6 +406,8 @@ static void eth_igb_write_ivar(struct e1000_hw *hw, uint8_t 
msix_vector,
.get_eeprom_length= eth_igb_get_eeprom_length,
.get_eeprom   = eth_igb_get_eeprom,
.set_eeprom   = eth_igb_set_eeprom,
+   .get_module_info  = eth_igb_get_module_info,
+   .get_module_eeprom= eth_igb_get_module_eeprom,
.timesync_adjust_time = igb_timesync_adjust_time,
.timesync_read_time   = igb_timesync_read_time,
.timesync_write_time  = igb_timesync_write_time,
@@ -5329,6 +5335,86 @@ static void igbvf_set_vfta_all(struct rte_eth_dev *dev, 
bool on)
 }
 
 static int
+eth_igb_get_module_info(struct rte_eth_dev *dev,
+   struct rte_eth_dev_module_info *modinfo)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   if (hw->phy.media_type == e1000_media_type_copper ||
+   hw->phy.media_type == e1000_media_type_unknown)
+   return -EOPNOTSUPP;
+
+   /* Check whether we support SFF-8472 or not */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_COMP, &sff8472_rev);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_SWAP, &addr_mode);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   if ((addr_mode & 0xFF) & IGB_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR,
+   "Address change required to access page 0xA2, "
+   "but not supported. Please report the module "
+   "type to the driver maintainers.\n");
+   page_swap = true;
+   }
+
+   if ((sff8472_rev & 0xFF) == IGB_SFF_8472_UNSUP || page_swap) {
+   /* We have an SFP, but it does not support SFF-8472 */
+   modinfo->type = RTE_ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have an SFP which supports a revision of SFF-8472 */
+   modinfo->type = RTE_ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t 

[dpdk-dev] [PATCH v7 5/5] net/i40e: add module EEPROM callbacks for i40e

2018-04-25 Thread Zijie Pan
Add new callbacks for eth_dev_ops of i40e to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: beilei.x...@intel.com
Cc: qi.z.zh...@intel.com

 doc/guides/nics/features/i40e.ini |1 +
 doc/guides/nics/features/i40e_vec.ini |1 +
 drivers/net/i40e/i40e_ethdev.c|  147 +
 3 files changed, 149 insertions(+)

diff --git a/doc/guides/nics/features/i40e.ini 
b/doc/guides/nics/features/i40e.ini
index e862712..c9c4e4e 100644
--- a/doc/guides/nics/features/i40e.ini
+++ b/doc/guides/nics/features/i40e.ini
@@ -44,6 +44,7 @@ Tx descriptor status = Y
 Basic stats  = Y
 Extended stats   = Y
 FW version   = Y
+Module EEPROM dump   = Y
 Multiprocess aware   = Y
 BSD nic_uio  = Y
 Linux UIO= Y
diff --git a/doc/guides/nics/features/i40e_vec.ini 
b/doc/guides/nics/features/i40e_vec.ini
index 7d7b3a9..c65e8b0 100644
--- a/doc/guides/nics/features/i40e_vec.ini
+++ b/doc/guides/nics/features/i40e_vec.ini
@@ -34,6 +34,7 @@ Rx descriptor status = Y
 Tx descriptor status = Y
 Basic stats  = Y
 Extended stats   = Y
+Module EEPROM dump   = Y
 Multiprocess aware   = Y
 BSD nic_uio  = Y
 Linux UIO= Y
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 180ac74..948ee89 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -369,6 +369,11 @@ static int i40e_get_regs(struct rte_eth_dev *dev,
 static int i40e_get_eeprom(struct rte_eth_dev *dev,
   struct rte_dev_eeprom_info *eeprom);
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_eth_dev_module_info *modinfo);
+static int i40e_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info);
+
 static int i40e_set_default_mac_addr(struct rte_eth_dev *dev,
  struct ether_addr *mac_addr);
 
@@ -489,6 +494,8 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
.get_reg  = i40e_get_regs,
.get_eeprom_length= i40e_get_eeprom_length,
.get_eeprom   = i40e_get_eeprom,
+   .get_module_info  = i40e_get_module_info,
+   .get_module_eeprom= i40e_get_module_eeprom,
.mac_addr_set = i40e_set_default_mac_addr,
.mtu_set  = i40e_dev_mtu_set,
.tm_ops_get   = i40e_tm_ops_get,
@@ -11327,6 +11334,146 @@ static int i40e_get_eeprom(struct rte_eth_dev *dev,
return 0;
 }
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_eth_dev_module_info *modinfo)
+{
+   struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t sff8472_comp = 0;
+   uint32_t sff8472_swap = 0;
+   uint32_t sff8636_rev = 0;
+   i40e_status status;
+   uint32_t type = 0;
+
+   /* Check if firmware supports reading module EEPROM. */
+   if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE)) {
+   PMD_DRV_LOG(ERR,
+   "Module EEPROM memory read not supported. "
+   "Please update the NVM image.\n");
+   return -EINVAL;
+   }
+
+   status = i40e_update_link_info(hw);
+   if (status)
+   return -EIO;
+
+   if (hw->phy.link_info.phy_type == I40E_PHY_TYPE_EMPTY) {
+   PMD_DRV_LOG(ERR,
+   "Cannot read module EEPROM memory. "
+   "No module connected.\n");
+   return -EINVAL;
+   }
+
+   type = hw->phy.link_info.module_type[0];
+
+   switch (type) {
+   case I40E_MODULE_TYPE_SFP:
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_COMP,
+   &sff8472_comp, NULL);
+   if (status)
+   return -EIO;
+
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_SWAP,
+   &sff8472_swap, NULL);
+   if (status)
+   return -EIO;
+
+   /* Check if the module requires address swap to access
+* the other EEPROM memory page.
+*/
+   if (sff8472_swap & I40E_MODULE_SFF_ADDR_MODE) {
+   PMD_DRV_LOG(WARNING,
+   "Module address swap to

[dpdk-dev] [PATCH] net/i40e: add a specific API to control the LLDP agent

2018-05-18 Thread Zijie Pan
Add a new API rte_pmd_i40e_set_lldp_cmd to control LLDP agent for i40e.
It supports the following i40e debug lldp commands:
- start/stop of the LLDP agent.
- get local/remote of the LLDP MIB (Management Information Base).

Signed-off-by: Laurent Hardy 
Signed-off-by: Zijie Pan 
---
 drivers/net/i40e/i40e_ethdev.h|   19 +
 drivers/net/i40e/rte_pmd_i40e.c   |   64 +
 drivers/net/i40e/rte_pmd_i40e.h   |   22 ++
 drivers/net/i40e/rte_pmd_i40e_version.map |8 +++-
 4 files changed, 112 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 55c8875..459b3ff 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -267,6 +267,25 @@ enum i40e_flxpld_layer_idx {
 struct i40e_adapter;
 
 /**
+ * LLDP command type
+ */
+enum i40_lldp_cmd_type {
+   I40E_LLDP_CMD_START = 0,
+   I40E_LLDP_CMD_STOP,
+   I40E_LLDP_CMD_GET_LOCAL,
+   I40E_LLDP_CMD_GET_REMOTE,
+   I40E_LLDP_CMD_UNKNOWN,
+};
+
+/**
+ * LLDP command structure
+ */
+struct i40e_lldp_cmd {
+   const char *name;
+   enum i40_lldp_cmd_type cmd;
+};
+
+/**
  * MAC filter structure
  */
 struct i40e_mac_filter_info {
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index 7aa1a75..307c597 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -12,6 +12,14 @@
 #include "i40e_rxtx.h"
 #include "rte_pmd_i40e.h"
 
+static const struct i40e_lldp_cmd lldp_cmds_table[] = {
+   {"start", I40E_LLDP_CMD_START},
+   {"stop", I40E_LLDP_CMD_STOP},
+   {"get local", I40E_LLDP_CMD_GET_LOCAL},
+   {"get remote", I40E_LLDP_CMD_GET_REMOTE},
+   {"", I40E_LLDP_CMD_UNKNOWN},
+};
+
 int
 rte_pmd_i40e_ping_vfs(uint16_t port, uint16_t vf)
 {
@@ -3192,3 +3200,59 @@ int rte_pmd_i40e_flow_add_del_packet_template(
I40E_WRITE_FLUSH(hw);
return 0;
 }
+
+int __rte_experimental
+rte_pmd_i40e_set_lldp_cmd(uint16_t port, const char *cmd, void *lldpmib)
+{
+   struct rte_eth_dev *dev;
+   struct i40e_hw *hw;
+   uint8_t br_type;
+   int i, ret;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+   dev = &rte_eth_devices[port];
+
+   if (!is_i40e_supported(dev))
+   return -ENOTSUP;
+
+   hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   for (i = 0; i < I40E_LLDP_CMD_UNKNOWN; i++) {
+   if (!strcmp(cmd, lldp_cmds_table[i].name))
+   break;
+   }
+
+   if (lldp_cmds_table[i].cmd == I40E_LLDP_CMD_UNKNOWN) {
+   PMD_DRV_LOG(ERR, "Unknown LLDP command\n");
+   return -EINVAL;
+   }
+
+   switch (lldp_cmds_table[i].cmd) {
+   case I40E_LLDP_CMD_START:
+   ret = i40e_aq_start_lldp(hw, NULL);
+   break;
+   case I40E_LLDP_CMD_STOP:
+   ret = i40e_aq_stop_lldp(hw, true, NULL);
+   break;
+   case I40E_LLDP_CMD_GET_LOCAL:
+   ret = i40e_aq_get_lldp_mib(hw, 0,
+  I40E_AQ_LLDP_MIB_LOCAL,
+  lldpmib, I40E_LLDPDU_SIZE,
+  NULL, NULL, NULL);
+   break;
+   case I40E_LLDP_CMD_GET_REMOTE:
+   br_type = I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE;
+   ret = i40e_aq_get_lldp_mib(hw, br_type,
+  I40E_AQ_LLDP_MIB_REMOTE,
+  lldpmib, I40E_LLDPDU_SIZE,
+  NULL, NULL, NULL);
+   break;
+   default:
+   PMD_DRV_LOG(ERR, "Unknown LLDP command\n");
+   ret = -EINVAL;
+   break;
+   }
+
+   return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index be4a602..59b2eee 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -1061,4 +1061,26 @@ int rte_pmd_i40e_inset_set(uint16_t port, uint8_t pctype,
return 0;
 }
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Process the LLDP commands, including "lldp start", "lldp stop",
+ * "lldp get local" and "lldp get remote".
+ *
+ * @param port
+ *The port identifier of the Ethernet device.
+ * @param cmd
+ *The LLDP command.
+ * @param lldpmib
+ *The pointer to return the LLDP MIB.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if *cmd* invalid.
+ *   - (-ENOTSUP) not supported by firmware.
+ */
+int __rte_experimental
+rte_pmd_i40e_set_lldp_cmd(uint16_t port, const char *cmd, void *lldpmib);
+
 #endif /* _PMD_I40E_H_ */
diff --gi

Re: [dpdk-dev] [PATCH] net/i40e: add a specific API to control the LLDP agent

2018-05-20 Thread Zijie Pan
> > Add a new API rte_pmd_i40e_set_lldp_cmd to control LLDP agent for i40e.
> > It supports the following i40e debug lldp commands:
> > - start/stop of the LLDP agent.
> > - get local/remote of the LLDP MIB (Management Information Base).
> >
> > Signed-off-by: Laurent Hardy 
> > Signed-off-by: Zijie Pan 
>
> Does it mean that this feature is enabled by default in i40e devices?
> Should it be disabled by default?

The new API is just an interface to control the LLDP agent. No functions of 
i40e call it by default. It is only used to debug LLDP of i40e devices. For 
example we can add a new command for test-pmd to debug lldp of i40e by calling 
rte_pmd_i40e_set_lldp_cmd().

[dpdk-dev] [PATCH v2] net/i40e: add a specific API to control the LLDP agent

2018-05-23 Thread Zijie Pan
Add a new API rte_pmd_i40e_set_lldp_cmd to control LLDP agent for i40e.
It supports the following i40e debug lldp commands:
- start/stop of the LLDP agent.
- get local/remote of the LLDP MIB (Management Information Base).

Signed-off-by: Laurent Hardy 
Signed-off-by: Zijie Pan 
Acked-by: Qi Zhang 
---
 drivers/net/i40e/i40e_ethdev.h|   19 
 drivers/net/i40e/rte_pmd_i40e.c   |   69 +
 drivers/net/i40e/rte_pmd_i40e.h   |   22 +
 drivers/net/i40e/rte_pmd_i40e_version.map |8 +++-
 4 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 55c8875..459b3ff 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -267,6 +267,25 @@ enum i40e_flxpld_layer_idx {
 struct i40e_adapter;
 
 /**
+ * LLDP command type
+ */
+enum i40_lldp_cmd_type {
+   I40E_LLDP_CMD_START = 0,
+   I40E_LLDP_CMD_STOP,
+   I40E_LLDP_CMD_GET_LOCAL,
+   I40E_LLDP_CMD_GET_REMOTE,
+   I40E_LLDP_CMD_UNKNOWN,
+};
+
+/**
+ * LLDP command structure
+ */
+struct i40e_lldp_cmd {
+   const char *name;
+   enum i40_lldp_cmd_type cmd;
+};
+
+/**
  * MAC filter structure
  */
 struct i40e_mac_filter_info {
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index 7aa1a75..612eb6d 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -12,6 +12,14 @@
 #include "i40e_rxtx.h"
 #include "rte_pmd_i40e.h"
 
+static const struct i40e_lldp_cmd lldp_cmds_table[] = {
+   {"start", I40E_LLDP_CMD_START},
+   {"stop", I40E_LLDP_CMD_STOP},
+   {"get local", I40E_LLDP_CMD_GET_LOCAL},
+   {"get remote", I40E_LLDP_CMD_GET_REMOTE},
+   {"", I40E_LLDP_CMD_UNKNOWN},
+};
+
 int
 rte_pmd_i40e_ping_vfs(uint16_t port, uint16_t vf)
 {
@@ -3192,3 +3200,64 @@ int rte_pmd_i40e_flow_add_del_packet_template(
I40E_WRITE_FLUSH(hw);
return 0;
 }
+
+/**
+ * LLDP is enabled by default. Disabling LLDP when using NVM 4.53 or 5.x can
+ * result in the device firmware not configuring the Receive Packet Buffer
+ * according to the link mode and flow control settings.
+ */
+int __rte_experimental
+rte_pmd_i40e_set_lldp_cmd(uint16_t port, const char *cmd, void *lldpmib)
+{
+   struct rte_eth_dev *dev;
+   struct i40e_hw *hw;
+   uint8_t br_type;
+   int i, ret;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+   dev = &rte_eth_devices[port];
+
+   if (!is_i40e_supported(dev))
+   return -ENOTSUP;
+
+   hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   for (i = 0; i < I40E_LLDP_CMD_UNKNOWN; i++) {
+   if (!strcmp(cmd, lldp_cmds_table[i].name))
+   break;
+   }
+
+   if (lldp_cmds_table[i].cmd == I40E_LLDP_CMD_UNKNOWN) {
+   PMD_DRV_LOG(ERR, "Unknown LLDP command\n");
+   return -EINVAL;
+   }
+
+   switch (lldp_cmds_table[i].cmd) {
+   case I40E_LLDP_CMD_START:
+   ret = i40e_aq_start_lldp(hw, NULL);
+   break;
+   case I40E_LLDP_CMD_STOP:
+   ret = i40e_aq_stop_lldp(hw, true, NULL);
+   break;
+   case I40E_LLDP_CMD_GET_LOCAL:
+   ret = i40e_aq_get_lldp_mib(hw, 0,
+  I40E_AQ_LLDP_MIB_LOCAL,
+  lldpmib, I40E_LLDPDU_SIZE,
+  NULL, NULL, NULL);
+   break;
+   case I40E_LLDP_CMD_GET_REMOTE:
+   br_type = I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE;
+   ret = i40e_aq_get_lldp_mib(hw, br_type,
+  I40E_AQ_LLDP_MIB_REMOTE,
+  lldpmib, I40E_LLDPDU_SIZE,
+  NULL, NULL, NULL);
+   break;
+   default:
+   PMD_DRV_LOG(ERR, "Unknown LLDP command\n");
+   ret = -EINVAL;
+   break;
+   }
+
+   return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index be4a602..59b2eee 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -1061,4 +1061,26 @@ int rte_pmd_i40e_inset_set(uint16_t port, uint8_t pctype,
return 0;
 }
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Process the LLDP commands, including "lldp start", "lldp stop",
+ * "lldp get local" and "lldp get remote".
+ *
+ * @param port
+ *The port identifier of the Ethernet device.
+ * @param cmd
+ *The LLDP command.
+ * @param lldpmib
+ *The pointer to return the LLDP MIB.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *

Re: [dpdk-dev] [PATCH] net/i40e: add a specific API to control the LLDP agent

2018-05-23 Thread Zijie Pan
Thanks for the review.
I added a comment to explain why lldp is disabled in the code, and sent the v2 
patch.

Thanks,
Zijie
 
 
-- Original --
From:  "Zhang, Qi Z";
Date:  Tue, May 22, 2018 09:00 PM
To:  "Zijie Pan"; "dev@dpdk.org"; 
Cc:  "Xing, Beilei"; "Laurent 
Hardy"; 
Subject:  RE: [PATCH] net/i40e: add a specific API to control the LLDP agent

 
> -Original Message-
> From: Zijie Pan [mailto:zijie@6wind.com]
> Sent: Friday, May 18, 2018 6:14 PM
> To: dev@dpdk.org
> Cc: Xing, Beilei ; Zhang, Qi Z ;
> Laurent Hardy 
> Subject: [PATCH] net/i40e: add a specific API to control the LLDP agent
> 
> Add a new API rte_pmd_i40e_set_lldp_cmd to control LLDP agent for i40e.
> It supports the following i40e debug lldp commands:
> - start/stop of the LLDP agent.
> - get local/remote of the LLDP MIB (Management Information Base).
> 
> Signed-off-by: Laurent Hardy 
> Signed-off-by: Zijie Pan 

Acked-by: Qi Zhang 

[dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM

2018-03-13 Thread Zijie Pan
..
180:          
190:          
1a0:  faff        
1b0:          
1c0:          
1d0:          
1e0:          
1f0:     0003 0100    

Both DPDK's my-module-eeprom.bin and Kernel's meeprom-kernel.bin
are the same.

Zijie Pan (5):
  ethdev: add access to eeprom
  examples/ethtool: add a new command module-eeprom
  net/ixgbe: add module EEPROM callbacks for ixgbe
  net/e1000: add module EEPROM callbacks for e1000
  net/i40e: add module EEPROM callbacks for i40e

 doc/guides/nics/features.rst  |   11 +++
 doc/guides/sample_app_ug/ethtool.rst  |2 +
 drivers/net/e1000/base/e1000_phy.h|8 ++
 drivers/net/e1000/igb_ethdev.c|   83 +++
 drivers/net/i40e/i40e_ethdev.c|  141 +
 drivers/net/ixgbe/ixgbe_ethdev.c  |   76 ++
 examples/ethtool/ethtool-app/ethapp.c |   61 ++
 examples/ethtool/lib/rte_ethtool.c|   30 +++
 examples/ethtool/lib/rte_ethtool.h|   34 
 lib/librte_ether/rte_dev_info.h   |   18 +
 lib/librte_ether/rte_ethdev.c |   26 ++
 lib/librte_ether/rte_ethdev.h |   35 
 lib/librte_ether/rte_ethdev_core.h|   12 +++
 13 files changed, 537 insertions(+)

-- 
1.7.10.4



[dpdk-dev] [PATCH 2/5] examples/ethtool: add a new command module-eeprom

2018-03-13 Thread Zijie Pan
Add a new command "module-eeprom" to get the data of plugin
module EEPROM.

Signed-off-by: Zijie Pan 
---
 doc/guides/sample_app_ug/ethtool.rst  |2 ++
 examples/ethtool/ethtool-app/ethapp.c |   61 +
 examples/ethtool/lib/rte_ethtool.c|   30 
 examples/ethtool/lib/rte_ethtool.h|   34 ++
 4 files changed, 127 insertions(+)

diff --git a/doc/guides/sample_app_ug/ethtool.rst 
b/doc/guides/sample_app_ug/ethtool.rst
index 1b79aca..028b8e9 100644
--- a/doc/guides/sample_app_ug/ethtool.rst
+++ b/doc/guides/sample_app_ug/ethtool.rst
@@ -97,6 +97,8 @@ the following functions:
 - ``rte_ethtool_get_eeprom_len()``
 - ``rte_ethtool_get_eeprom()``
 - ``rte_ethtool_set_eeprom()``
+- ``rte_ethtool_get_module_info()``
+- ``rte_ethtool_get_module_eeprom()``
 - ``rte_ethtool_get_pauseparam()``
 - ``rte_ethtool_set_pauseparam()``
 - ``rte_ethtool_net_open()``
diff --git a/examples/ethtool/ethtool-app/ethapp.c 
b/examples/ethtool/ethtool-app/ethapp.c
index 0c3f1f6..93779c4 100644
--- a/examples/ethtool/ethtool-app/ethapp.c
+++ b/examples/ethtool/ethtool-app/ethapp.c
@@ -75,6 +75,8 @@ struct pcmd_intintint_params {
 /* Commands taking port id and string */
 cmdline_parse_token_string_t pcmd_eeprom_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "eeprom");
+cmdline_parse_token_string_t pcmd_module_eeprom_token_cmd =
+   TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, 
"module-eeprom");
 cmdline_parse_token_string_t pcmd_mtu_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "mtu");
 cmdline_parse_token_string_t pcmd_regs_token_cmd =
@@ -298,6 +300,52 @@ struct pcmd_intintint_params {
 
 
 static void
+pcmd_module_eeprom_callback(void *ptr_params,
+   __rte_unused struct cmdline *ctx,
+   __rte_unused void *ptr_data)
+{
+   struct pcmd_intstr_params *params = ptr_params;
+   struct ethtool_eeprom info_eeprom;
+   uint32_t module_info[2];
+   int stat;
+   unsigned char bytes_eeprom[EEPROM_DUMP_CHUNKSIZE];
+   FILE *fp_eeprom;
+
+   if (!rte_eth_dev_is_valid_port(params->port)) {
+   printf("Error: Invalid port number %i\n", params->port);
+   return;
+   }
+   stat = rte_ethtool_get_module_info(params->port, module_info);
+   if (stat != 0) {
+   printf("Plug-in module EEPROM read error %i\n", stat);
+   return;
+   }
+
+   info_eeprom.len = module_info[1];
+   info_eeprom.offset = 0;
+   stat = rte_ethtool_get_module_eeprom(params->port,
+&info_eeprom, bytes_eeprom);
+   if (stat != 0 || module_info[1] <= 0) {
+   printf("Plug-in module EEPROM read error %i\n", stat);
+   return;
+   }
+
+   fp_eeprom = fopen(params->opt, "wb");
+   if (fp_eeprom == NULL) {
+   printf("Error opening '%s' for writing\n", params->opt);
+   return;
+   }
+   printf("Total plugin module EEPROM length: %i bytes\n",
+  info_eeprom.len);
+   if (fwrite(bytes_eeprom, 1, info_eeprom.len,
+  fp_eeprom) != info_eeprom.len) {
+   printf("Error writing '%s'\n", params->opt);
+   }
+   fclose(fp_eeprom);
+}
+
+
+static void
 pcmd_pause_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
void *ptr_data)
@@ -664,6 +712,18 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
NULL
},
 };
+cmdline_parse_inst_t pcmd_module_eeprom = {
+   .f = pcmd_module_eeprom_callback,
+   .data = NULL,
+   .help_str = "module-eeprom  \n"
+   " Dump plugin module EEPROM to file",
+   .tokens = {
+   (void *)&pcmd_module_eeprom_token_cmd,
+   (void *)&pcmd_intstr_token_port,
+   (void *)&pcmd_intstr_token_opt,
+   NULL
+   },
+};
 cmdline_parse_inst_t pcmd_pause_noopt = {
.f = pcmd_pause_callback,
.data = (void *)0x01,
@@ -816,6 +876,7 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
 cmdline_parse_ctx_t list_prompt_commands[] = {
(cmdline_parse_inst_t *)&pcmd_drvinfo,
(cmdline_parse_inst_t *)&pcmd_eeprom,
+   (cmdline_parse_inst_t *)&pcmd_module_eeprom,
(cmdline_parse_inst_t *)&pcmd_link,
(cmdline_parse_inst_t *)&pcmd_macaddr_get,
(cmdline_parse_inst_t *)&pcmd_macaddr,
diff --git a/examples/ethtool/lib/rte_ethtool.c 
b/examples/ethtool/lib/rte_ethtool.c
index 90dfbb7..36c81d4 100644
--- a/examples/ethtool/lib/rte_ethtool.c
+++ b/examples/ethtool/lib/rte_ethtool.c
@@ -174,6 +174,36 @@
 }
 
 int
+rte_ethtool_get_modu

[dpdk-dev] [PATCH 1/5] ethdev: add access to eeprom

2018-03-13 Thread Zijie Pan
add new APIs:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

Signed-off-by: Zijie Pan 
---
 doc/guides/nics/features.rst   |   11 +++
 lib/librte_ether/rte_dev_info.h|   18 ++
 lib/librte_ether/rte_ethdev.c  |   26 ++
 lib/librte_ether/rte_ethdev.h  |   35 +++
 lib/librte_ether/rte_ethdev_core.h |   12 
 5 files changed, 102 insertions(+)

diff --git a/doc/guides/nics/features.rst b/doc/guides/nics/features.rst
index 1b4fb97..8223722 100644
--- a/doc/guides/nics/features.rst
+++ b/doc/guides/nics/features.rst
@@ -749,6 +749,17 @@ Supports getting/setting device eeprom data.
   ``rte_eth_dev_set_eeprom()``.
 
 
+.. _nic_features_module_eeprom_dump:
+
+Module EEPROM dump
+--
+
+Supports getting informatin and data of plugin module eeprom.
+
+* **[implements] eth_dev_ops**: ``get_module_info``, ``get_module_eeprom``.
+* **[related]API**: ``rte_eth_dev_get_module_info()``, 
``rte_eth_dev_get_module_eeprom()``.
+
+
 .. _nic_features_register_dump:
 
 Registers dump
diff --git a/lib/librte_ether/rte_dev_info.h b/lib/librte_ether/rte_dev_info.h
index 6b68584..c15a0fa 100644
--- a/lib/librte_ether/rte_dev_info.h
+++ b/lib/librte_ether/rte_dev_info.h
@@ -28,4 +28,22 @@ struct rte_dev_eeprom_info {
uint32_t magic; /**< Device-specific key, such as device-id */
 };
 
+/*
+ * Placeholder for accessing plugin module eeprom
+ */
+struct rte_dev_module_info {
+   uint32_t type; /**< Type of plugin module eeprom */
+   uint32_t eeprom_len; /**< Length of plugin module eeprom */
+};
+
+/* EEPROM Standards for plug in modules */
+#define ETH_MODULE_SFF_8079 0x1
+#define ETH_MODULE_SFF_8079_LEN 256
+#define ETH_MODULE_SFF_8472 0x2
+#define ETH_MODULE_SFF_8472_LEN 512
+#define ETH_MODULE_SFF_8636 0x3
+#define ETH_MODULE_SFF_8636_LEN 256
+#define ETH_MODULE_SFF_8436 0x4
+#define ETH_MODULE_SFF_8436_LEN 256
+
 #endif /* _RTE_DEV_INFO_H_ */
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 0590f0c..b83643d 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -4044,6 +4044,32 @@ int rte_eth_set_queue_rate_limit(uint16_t port_id, 
uint16_t queue_idx,
 }
 
 int
+rte_eth_dev_get_module_info(uint16_t port_id,
+   struct rte_dev_module_info *modinfo)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_info, -ENOTSUP);
+   return (*dev->dev_ops->get_module_info)(dev, modinfo);
+}
+
+   int
+rte_eth_dev_get_module_eeprom(uint16_t port_id,
+   struct rte_dev_eeprom_info *info)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_eeprom, -ENOTSUP);
+   return (*dev->dev_ops->get_module_eeprom)(dev, info);
+}
+
+int
 rte_eth_dev_get_dcb_info(uint16_t port_id,
 struct rte_eth_dcb_info *dcb_info)
 {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 0361533..e8b1d94 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -3262,6 +3262,41 @@ int rte_eth_tx_queue_info_get(uint16_t port_id, uint16_t 
queue_id,
 int rte_eth_dev_set_eeprom(uint16_t port_id, struct rte_dev_eeprom_info *info);
 
 /**
+ * Retrieve the type and size of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param modinfo
+ *   The type and size of plugin module EEPROM.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EIO) if device is removed.
+ *   - others depends on the specific operations implementation.
+ */
+int rte_eth_dev_get_module_info(uint16_t port_id,
+   struct rte_dev_module_info *modinfo);
+
+/**
+ * Retrieve the data of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param info
+ *   The template includes the plugin module EEPROM attributes, and the
+ *   buffer for return plugin module EEPROM data.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EIO) if device is removed.
+ *   - others depends on the specific operations implementation.
+ */
+int rte_eth_dev_get_module_eeprom(uint16_t port_id,
+ struct rte_dev_eeprom_info *info);
+
+/**
  * Set the list of multicast addresses to filter on an Ethernet device.
  *
  * @param port_id
diff --git a/lib/librte_ether/rte_

[dpdk-dev] [PATCH 4/5] net/e1000: add module EEPROM callbacks for e1000

2018-03-13 Thread Zijie Pan
Add new callbacks for eth_dev_ops of e1000 to get the information and
data of plugin module EEPROM.

Signed-off-by: Zijie Pan 
---
 drivers/net/e1000/base/e1000_phy.h |8 
 drivers/net/e1000/igb_ethdev.c |   83 
 2 files changed, 91 insertions(+)

diff --git a/drivers/net/e1000/base/e1000_phy.h 
b/drivers/net/e1000/base/e1000_phy.h
index 3e45a9e..2cd0e14 100644
--- a/drivers/net/e1000/base/e1000_phy.h
+++ b/drivers/net/e1000/base/e1000_phy.h
@@ -330,4 +330,12 @@ struct sfp_e1000_flags {
 #define E1000_SFF_VENDOR_OUI_AVAGO 0x00176A00
 #define E1000_SFF_VENDOR_OUI_INTEL 0x001B2100
 
+/* EEPROM byte offsets */
+#define IGB_SFF_8472_SWAP  0x5C
+#define IGB_SFF_8472_COMP  0x5E
+
+/* Bitmasks */
+#define IGB_SFF_ADDRESSING_MODE0x4
+#define IGB_SFF_8472_UNSUP 0x00
+
 #endif
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 3c5138d..048caaf 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -224,6 +224,10 @@ static int eth_igb_get_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 static int eth_igb_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
+static int eth_igb_get_module_info(struct rte_eth_dev *dev,
+  struct rte_dev_module_info *modinfo);
+static int eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+struct rte_dev_eeprom_info *info);
 static int eth_igb_set_mc_addr_list(struct rte_eth_dev *dev,
struct ether_addr *mc_addr_set,
uint32_t nb_mc_addr);
@@ -403,6 +407,8 @@ static void eth_igb_write_ivar(struct e1000_hw *hw, uint8_t 
msix_vector,
.get_eeprom_length= eth_igb_get_eeprom_length,
.get_eeprom   = eth_igb_get_eeprom,
.set_eeprom   = eth_igb_set_eeprom,
+   .get_module_info  = eth_igb_get_module_info,
+   .get_module_eeprom= eth_igb_get_module_eeprom,
.timesync_adjust_time = igb_timesync_adjust_time,
.timesync_read_time   = igb_timesync_read_time,
.timesync_write_time  = igb_timesync_write_time,
@@ -5384,6 +5390,83 @@ static void igbvf_set_vfta_all(struct rte_eth_dev *dev, 
bool on)
 }
 
 static int
+eth_igb_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   if (hw->phy.media_type == e1000_media_type_copper ||
+   hw->phy.media_type == e1000_media_type_unknown)
+   return -EOPNOTSUPP;
+
+   /* Check whether we support SFF-8472 or not */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_COMP, &sff8472_rev);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_SWAP, &addr_mode);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   if ((addr_mode & 0xFF) & IGB_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR, "Address change required to access page 0xA2, 
but not supported. Please report the module type to the driver maintainers.\n");
+   page_swap = true;
+   }
+
+   if ((sff8472_rev & 0xFF) == IGB_SFF_8472_UNSUP || page_swap) {
+   /* We have an SFP, but it does not support SFF-8472 */
+   modinfo->type = ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have an SFP which supports a revision of SFF-8472 */
+   modinfo->type = ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t dataword[ETH_MODULE_SFF_8472_LEN / 2 + 1];
+   u16 first_word, last_word;
+   int i = 0;
+
+   if (info->length == 0)
+   return -EINVAL;
+
+   first_word = info->offset >> 1;
+   last_word = (info->offset + info->length - 1) >> 1;
+
+   /* Read EEPROM block, SFF-8079/SFF-8472, word at a time */
+   for (i = 0; i < last_word - first_word + 1; i++) {
+   status = e1000_read_phy_reg_i2c(hw, (first_word + i) * 2,
+   &dataword[i]);
+   if (status) {
+   /* Error occurred while reading mo

[dpdk-dev] [PATCH 5/5] net/i40e: add module EEPROM callbacks for i40e

2018-03-13 Thread Zijie Pan
Add new callbacks for eth_dev_ops of i40e to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
---
 drivers/net/i40e/i40e_ethdev.c |  141 
 1 file changed, 141 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 508b417..6f09fc9 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -369,6 +369,11 @@ static int i40e_get_regs(struct rte_eth_dev *dev,
 static int i40e_get_eeprom(struct rte_eth_dev *dev,
   struct rte_dev_eeprom_info *eeprom);
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo);
+static int i40e_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info);
+
 static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
  struct ether_addr *mac_addr);
 
@@ -489,6 +494,8 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
.get_reg  = i40e_get_regs,
.get_eeprom_length= i40e_get_eeprom_length,
.get_eeprom   = i40e_get_eeprom,
+   .get_module_info  = i40e_get_module_info,
+   .get_module_eeprom= i40e_get_module_eeprom,
.mac_addr_set = i40e_set_default_mac_addr,
.mtu_set  = i40e_dev_mtu_set,
.tm_ops_get   = i40e_tm_ops_get,
@@ -11249,6 +11256,140 @@ static int i40e_get_eeprom(struct rte_eth_dev *dev,
return 0;
 }
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo)
+{
+   struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t sff8472_comp = 0;
+   uint32_t sff8472_swap = 0;
+   uint32_t sff8636_rev = 0;
+   i40e_status status;
+   uint32_t type = 0;
+
+   /* Check if firmware supports reading module EEPROM. */
+   if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE)) {
+   PMD_DRV_LOG(ERR, "Module EEPROM memory read not supported. 
Please update the NVM image.\n");
+   return -EINVAL;
+   }
+
+   status = i40e_update_link_info(hw);
+   if (status)
+   return -EIO;
+
+   if (hw->phy.link_info.phy_type == I40E_PHY_TYPE_EMPTY) {
+   PMD_DRV_LOG(ERR, "Cannot read module EEPROM memory. No module 
connected.\n");
+   return -EINVAL;
+   }
+
+   type = hw->phy.link_info.module_type[0];
+
+   switch (type) {
+   case I40E_MODULE_TYPE_SFP:
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_COMP,
+   &sff8472_comp, NULL);
+   if (status)
+   return -EIO;
+
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_SWAP,
+   &sff8472_swap, NULL);
+   if (status)
+   return -EIO;
+
+   /* Check if the module requires address swap to access
+* the other EEPROM memory page.
+*/
+   if (sff8472_swap & I40E_MODULE_SFF_ADDR_MODE) {
+   PMD_DRV_LOG(WARNING, "Module address swap to access 
page 0xA2 is not supported.\n");
+   modinfo->type = ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+   } else if (sff8472_comp == 0x00) {
+   /* Module is not SFF-8472 compliant */
+   modinfo->type = ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+   } else {
+   modinfo->type = ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+   }
+   break;
+   case I40E_MODULE_TYPE_QSFP_PLUS:
+   /* Read from memory page 0. */
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   0,
+   I40E_MODULE_REVISION_ADDR,
+   &sff8636_rev, NULL);
+   if (status)
+   return -EIO;
+   /* Determine revision compliance byte */
+   if (sff8636_rev > 0x02) {
+   /* Modul

[dpdk-dev] [PATCH 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe

2018-03-13 Thread Zijie Pan
Add new callbacks for eth_dev_ops of ixgbe to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
---
 drivers/net/ixgbe/ixgbe_ethdev.c |   76 ++
 1 file changed, 76 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 4483258..22a2270 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -328,6 +328,11 @@ static int ixgbe_get_eeprom(struct rte_eth_dev *dev,
 static int ixgbe_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 
+static int ixgbe_get_module_info(struct rte_eth_dev *dev,
+struct rte_dev_module_info *modinfo);
+static int ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+  struct rte_dev_eeprom_info *info);
+
 static int ixgbevf_get_reg_length(struct rte_eth_dev *dev);
 static int ixgbevf_get_regs(struct rte_eth_dev *dev,
struct rte_dev_reg_info *regs);
@@ -565,6 +570,8 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev 
*dev,
.get_eeprom_length= ixgbe_get_eeprom_length,
.get_eeprom   = ixgbe_get_eeprom,
.set_eeprom   = ixgbe_set_eeprom,
+   .get_module_info  = ixgbe_get_module_info,
+   .get_module_eeprom= ixgbe_get_module_eeprom,
.get_dcb_info = ixgbe_dev_get_dcb_info,
.timesync_adjust_time = ixgbe_timesync_adjust_time,
.timesync_read_time   = ixgbe_timesync_read_time,
@@ -7166,6 +7173,75 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev 
*dev, bool on)
return eeprom->ops.write_buffer(hw,  first, length, data);
 }
 
+static int
+ixgbe_get_module_info(struct rte_eth_dev *dev,
+ struct rte_dev_module_info *modinfo)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status;
+   uint8_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   /* Check whether we support SFF-8472 or not */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_COMP,
+&sff8472_rev);
+   if (status != 0)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_SWAP,
+&addr_mode);
+   if (status != 0)
+   return -EIO;
+
+   if (addr_mode & IXGBE_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR, "Address change required to access page 0xA2, 
but not supported. Please report the module type to the driver maintainers.");
+   page_swap = true;
+   }
+
+   if (sff8472_rev == IXGBE_SFF_SFF_8472_UNSUP || page_swap) {
+   /* We have a SFP, but it does not support SFF-8472 */
+   modinfo->type = ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have a SFP which supports a revision of SFF-8472. */
+   modinfo->type = ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+   struct rte_dev_eeprom_info *info)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status = IXGBE_ERR_PHY_ADDR_INVALID;
+   uint8_t databyte = 0xFF;
+   uint8_t *data = info->data;
+   uint32_t i = 0;
+
+   if (info->length == 0)
+   return -EINVAL;
+
+   for (i = info->offset; i < info->offset + info->length; i++) {
+   if (i < ETH_MODULE_SFF_8079_LEN)
+   status = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte);
+   else
+   status = hw->phy.ops.read_i2c_sff8472(hw, i, &databyte);
+
+   if (status != 0)
+   return -EIO;
+
+   data[i - info->offset] = databyte;
+   }
+
+   return 0;
+}
+
 uint16_t
 ixgbe_reta_size_get(enum ixgbe_mac_type mac_type) {
switch (mac_type) {
-- 
1.7.10.4



[dpdk-dev] [PATCH v2 0/5] get the information and data of EEPROM

2018-03-16 Thread Zijie Pan
 0540  0540       .@...@..
180:          
190:          
1a0:  faff        
1b0:          
1c0:          
1d0:          
1e0:          
1f0:     0003 0100    

Both DPDK's my-module-eeprom.bin and Kernel's meeprom-kernel.bin
are the same.

v2 changes:
 - Fix typo in features.rst.
 - Fix checkpatch warnings regarding long lines.
 - Update function pcmd_module_eeprom_callback().

Zijie Pan (5):
  ethdev: add access to eeprom
  examples/ethtool: add a new command module-eeprom
  net/ixgbe: add module EEPROM callbacks for ixgbe
  net/e1000: add module EEPROM callbacks for e1000
  net/i40e: add module EEPROM callbacks for i40e

 doc/guides/nics/features.rst  |   11 +++
 doc/guides/sample_app_ug/ethtool.rst  |2 +
 drivers/net/e1000/base/e1000_phy.h|8 ++
 drivers/net/e1000/igb_ethdev.c|   86 +++
 drivers/net/i40e/i40e_ethdev.c|  147 +
 drivers/net/ixgbe/ixgbe_ethdev.c  |   79 ++
 examples/ethtool/ethtool-app/ethapp.c |   64 ++
 examples/ethtool/lib/rte_ethtool.c|   30 +++
 examples/ethtool/lib/rte_ethtool.h|   34 
 lib/librte_ether/rte_dev_info.h   |   18 
 lib/librte_ether/rte_ethdev.c |   26 ++
 lib/librte_ether/rte_ethdev.h |   35 
 lib/librte_ether/rte_ethdev_core.h|   12 +++
 13 files changed, 552 insertions(+)

-- 
1.7.10.4



[dpdk-dev] [PATCH v2 1/5] ethdev: add access to eeprom

2018-03-16 Thread Zijie Pan
add new APIs:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

Signed-off-by: Zijie Pan 
---
 doc/guides/nics/features.rst   |   11 +++
 lib/librte_ether/rte_dev_info.h|   18 ++
 lib/librte_ether/rte_ethdev.c  |   26 ++
 lib/librte_ether/rte_ethdev.h  |   35 +++
 lib/librte_ether/rte_ethdev_core.h |   12 
 5 files changed, 102 insertions(+)

diff --git a/doc/guides/nics/features.rst b/doc/guides/nics/features.rst
index 1b4fb97..bb183e2 100644
--- a/doc/guides/nics/features.rst
+++ b/doc/guides/nics/features.rst
@@ -749,6 +749,17 @@ Supports getting/setting device eeprom data.
   ``rte_eth_dev_set_eeprom()``.
 
 
+.. _nic_features_module_eeprom_dump:
+
+Module EEPROM dump
+--
+
+Supports getting information and data of plugin module eeprom.
+
+* **[implements] eth_dev_ops**: ``get_module_info``, ``get_module_eeprom``.
+* **[related]API**: ``rte_eth_dev_get_module_info()``, 
``rte_eth_dev_get_module_eeprom()``.
+
+
 .. _nic_features_register_dump:
 
 Registers dump
diff --git a/lib/librte_ether/rte_dev_info.h b/lib/librte_ether/rte_dev_info.h
index 6b68584..c15a0fa 100644
--- a/lib/librte_ether/rte_dev_info.h
+++ b/lib/librte_ether/rte_dev_info.h
@@ -28,4 +28,22 @@ struct rte_dev_eeprom_info {
uint32_t magic; /**< Device-specific key, such as device-id */
 };
 
+/*
+ * Placeholder for accessing plugin module eeprom
+ */
+struct rte_dev_module_info {
+   uint32_t type; /**< Type of plugin module eeprom */
+   uint32_t eeprom_len; /**< Length of plugin module eeprom */
+};
+
+/* EEPROM Standards for plug in modules */
+#define ETH_MODULE_SFF_8079 0x1
+#define ETH_MODULE_SFF_8079_LEN 256
+#define ETH_MODULE_SFF_8472 0x2
+#define ETH_MODULE_SFF_8472_LEN 512
+#define ETH_MODULE_SFF_8636 0x3
+#define ETH_MODULE_SFF_8636_LEN 256
+#define ETH_MODULE_SFF_8436 0x4
+#define ETH_MODULE_SFF_8436_LEN 256
+
 #endif /* _RTE_DEV_INFO_H_ */
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 0590f0c..b83643d 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -4044,6 +4044,32 @@ int rte_eth_set_queue_rate_limit(uint16_t port_id, 
uint16_t queue_idx,
 }
 
 int
+rte_eth_dev_get_module_info(uint16_t port_id,
+   struct rte_dev_module_info *modinfo)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_info, -ENOTSUP);
+   return (*dev->dev_ops->get_module_info)(dev, modinfo);
+}
+
+   int
+rte_eth_dev_get_module_eeprom(uint16_t port_id,
+   struct rte_dev_eeprom_info *info)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_eeprom, -ENOTSUP);
+   return (*dev->dev_ops->get_module_eeprom)(dev, info);
+}
+
+int
 rte_eth_dev_get_dcb_info(uint16_t port_id,
 struct rte_eth_dcb_info *dcb_info)
 {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 0361533..e8b1d94 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -3262,6 +3262,41 @@ int rte_eth_tx_queue_info_get(uint16_t port_id, uint16_t 
queue_id,
 int rte_eth_dev_set_eeprom(uint16_t port_id, struct rte_dev_eeprom_info *info);
 
 /**
+ * Retrieve the type and size of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param modinfo
+ *   The type and size of plugin module EEPROM.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EIO) if device is removed.
+ *   - others depends on the specific operations implementation.
+ */
+int rte_eth_dev_get_module_info(uint16_t port_id,
+   struct rte_dev_module_info *modinfo);
+
+/**
+ * Retrieve the data of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param info
+ *   The template includes the plugin module EEPROM attributes, and the
+ *   buffer for return plugin module EEPROM data.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EIO) if device is removed.
+ *   - others depends on the specific operations implementation.
+ */
+int rte_eth_dev_get_module_eeprom(uint16_t port_id,
+ struct rte_dev_eeprom_info *info);
+
+/**
  * Set the list of multicast addresses to filter on an Ethernet device.
  *
  * @param port_id
diff --git a/lib/librte_ether/rte_

[dpdk-dev] [PATCH v2 2/5] examples/ethtool: add a new command module-eeprom

2018-03-16 Thread Zijie Pan
Add a new command "module-eeprom" to get the data of plugin
module EEPROM.

Signed-off-by: Zijie Pan 
---
 doc/guides/sample_app_ug/ethtool.rst  |2 ++
 examples/ethtool/ethtool-app/ethapp.c |   64 +
 examples/ethtool/lib/rte_ethtool.c|   30 
 examples/ethtool/lib/rte_ethtool.h|   34 ++
 4 files changed, 130 insertions(+)

diff --git a/doc/guides/sample_app_ug/ethtool.rst 
b/doc/guides/sample_app_ug/ethtool.rst
index 1b79aca..028b8e9 100644
--- a/doc/guides/sample_app_ug/ethtool.rst
+++ b/doc/guides/sample_app_ug/ethtool.rst
@@ -97,6 +97,8 @@ the following functions:
 - ``rte_ethtool_get_eeprom_len()``
 - ``rte_ethtool_get_eeprom()``
 - ``rte_ethtool_set_eeprom()``
+- ``rte_ethtool_get_module_info()``
+- ``rte_ethtool_get_module_eeprom()``
 - ``rte_ethtool_get_pauseparam()``
 - ``rte_ethtool_set_pauseparam()``
 - ``rte_ethtool_net_open()``
diff --git a/examples/ethtool/ethtool-app/ethapp.c 
b/examples/ethtool/ethtool-app/ethapp.c
index 0c3f1f6..c37b7c3 100644
--- a/examples/ethtool/ethtool-app/ethapp.c
+++ b/examples/ethtool/ethtool-app/ethapp.c
@@ -75,6 +75,9 @@ struct pcmd_intintint_params {
 /* Commands taking port id and string */
 cmdline_parse_token_string_t pcmd_eeprom_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "eeprom");
+cmdline_parse_token_string_t pcmd_module_eeprom_token_cmd =
+   TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd,
+"module-eeprom");
 cmdline_parse_token_string_t pcmd_mtu_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "mtu");
 cmdline_parse_token_string_t pcmd_regs_token_cmd =
@@ -298,6 +301,54 @@ struct pcmd_intintint_params {
 
 
 static void
+pcmd_module_eeprom_callback(void *ptr_params,
+   __rte_unused struct cmdline *ctx,
+   __rte_unused void *ptr_data)
+{
+   struct pcmd_intstr_params *params = ptr_params;
+   struct ethtool_eeprom info_eeprom;
+   uint32_t module_info[2];
+   int stat;
+   unsigned char bytes_eeprom[EEPROM_DUMP_CHUNKSIZE];
+   FILE *fp_eeprom;
+
+   if (!rte_eth_dev_is_valid_port(params->port)) {
+   printf("Error: Invalid port number %i\n", params->port);
+   return;
+   }
+
+   stat = rte_ethtool_get_module_info(params->port, module_info);
+   if (stat != 0) {
+   printf("Module EEPROM information read error %i\n", stat);
+   return;
+   }
+
+   info_eeprom.len = module_info[1];
+   info_eeprom.offset = 0;
+
+   stat = rte_ethtool_get_module_eeprom(params->port,
+&info_eeprom, bytes_eeprom);
+   if (stat != 0) {
+   printf("Module EEPROM read error %i\n", stat);
+   return;
+   }
+
+   fp_eeprom = fopen(params->opt, "wb");
+   if (fp_eeprom == NULL) {
+   printf("Error opening '%s' for writing\n", params->opt);
+   return;
+   }
+   printf("Total plugin module EEPROM length: %i bytes\n",
+  info_eeprom.len);
+   if (fwrite(bytes_eeprom, 1, info_eeprom.len,
+  fp_eeprom) != info_eeprom.len) {
+   printf("Error writing '%s'\n", params->opt);
+   }
+   fclose(fp_eeprom);
+}
+
+
+static void
 pcmd_pause_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
void *ptr_data)
@@ -664,6 +715,18 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
NULL
},
 };
+cmdline_parse_inst_t pcmd_module_eeprom = {
+   .f = pcmd_module_eeprom_callback,
+   .data = NULL,
+   .help_str = "module-eeprom  \n"
+   " Dump plugin module EEPROM to file",
+   .tokens = {
+   (void *)&pcmd_module_eeprom_token_cmd,
+   (void *)&pcmd_intstr_token_port,
+   (void *)&pcmd_intstr_token_opt,
+   NULL
+   },
+};
 cmdline_parse_inst_t pcmd_pause_noopt = {
.f = pcmd_pause_callback,
.data = (void *)0x01,
@@ -816,6 +879,7 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
 cmdline_parse_ctx_t list_prompt_commands[] = {
(cmdline_parse_inst_t *)&pcmd_drvinfo,
(cmdline_parse_inst_t *)&pcmd_eeprom,
+   (cmdline_parse_inst_t *)&pcmd_module_eeprom,
(cmdline_parse_inst_t *)&pcmd_link,
(cmdline_parse_inst_t *)&pcmd_macaddr_get,
(cmdline_parse_inst_t *)&pcmd_macaddr,
diff --git a/examples/ethtool/lib/rte_ethtool.c 
b/examples/ethtool/lib/rte_ethtool.c
index 90dfbb7..36c81d4 100644
--- a/examples/ethtool/lib/rte_ethtool.c
+++ b/examples/ethtool/lib/rte_ethtool.c
@@ -174,6 +174,36 @@
 }
 
 int
+rte_ethtool_get_module_

[dpdk-dev] [PATCH v2 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe

2018-03-16 Thread Zijie Pan
Add new callbacks for eth_dev_ops of ixgbe to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
---
 drivers/net/ixgbe/ixgbe_ethdev.c |   79 ++
 1 file changed, 79 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 4483258..28f09d3 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -328,6 +328,11 @@ static int ixgbe_get_eeprom(struct rte_eth_dev *dev,
 static int ixgbe_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 
+static int ixgbe_get_module_info(struct rte_eth_dev *dev,
+struct rte_dev_module_info *modinfo);
+static int ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+  struct rte_dev_eeprom_info *info);
+
 static int ixgbevf_get_reg_length(struct rte_eth_dev *dev);
 static int ixgbevf_get_regs(struct rte_eth_dev *dev,
struct rte_dev_reg_info *regs);
@@ -565,6 +570,8 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev 
*dev,
.get_eeprom_length= ixgbe_get_eeprom_length,
.get_eeprom   = ixgbe_get_eeprom,
.set_eeprom   = ixgbe_set_eeprom,
+   .get_module_info  = ixgbe_get_module_info,
+   .get_module_eeprom= ixgbe_get_module_eeprom,
.get_dcb_info = ixgbe_dev_get_dcb_info,
.timesync_adjust_time = ixgbe_timesync_adjust_time,
.timesync_read_time   = ixgbe_timesync_read_time,
@@ -7166,6 +7173,78 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev 
*dev, bool on)
return eeprom->ops.write_buffer(hw,  first, length, data);
 }
 
+static int
+ixgbe_get_module_info(struct rte_eth_dev *dev,
+ struct rte_dev_module_info *modinfo)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status;
+   uint8_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   /* Check whether we support SFF-8472 or not */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_COMP,
+&sff8472_rev);
+   if (status != 0)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_SWAP,
+&addr_mode);
+   if (status != 0)
+   return -EIO;
+
+   if (addr_mode & IXGBE_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR,
+   "Address change required to access page 0xA2, "
+   "but not supported. Please report the module "
+   "type to the driver maintainers.");
+   page_swap = true;
+   }
+
+   if (sff8472_rev == IXGBE_SFF_SFF_8472_UNSUP || page_swap) {
+   /* We have a SFP, but it does not support SFF-8472 */
+   modinfo->type = ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have a SFP which supports a revision of SFF-8472. */
+   modinfo->type = ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+   struct rte_dev_eeprom_info *info)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status = IXGBE_ERR_PHY_ADDR_INVALID;
+   uint8_t databyte = 0xFF;
+   uint8_t *data = info->data;
+   uint32_t i = 0;
+
+   if (info->length == 0)
+   return -EINVAL;
+
+   for (i = info->offset; i < info->offset + info->length; i++) {
+   if (i < ETH_MODULE_SFF_8079_LEN)
+   status = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte);
+   else
+   status = hw->phy.ops.read_i2c_sff8472(hw, i, &databyte);
+
+   if (status != 0)
+   return -EIO;
+
+   data[i - info->offset] = databyte;
+   }
+
+   return 0;
+}
+
 uint16_t
 ixgbe_reta_size_get(enum ixgbe_mac_type mac_type) {
switch (mac_type) {
-- 
1.7.10.4



[dpdk-dev] [PATCH v2 4/5] net/e1000: add module EEPROM callbacks for e1000

2018-03-16 Thread Zijie Pan
Add new callbacks for eth_dev_ops of e1000 to get the information and
data of plugin module EEPROM.

Signed-off-by: Zijie Pan 
---
 drivers/net/e1000/base/e1000_phy.h |8 
 drivers/net/e1000/igb_ethdev.c |   86 
 2 files changed, 94 insertions(+)

diff --git a/drivers/net/e1000/base/e1000_phy.h 
b/drivers/net/e1000/base/e1000_phy.h
index 3e45a9e..2cd0e14 100644
--- a/drivers/net/e1000/base/e1000_phy.h
+++ b/drivers/net/e1000/base/e1000_phy.h
@@ -330,4 +330,12 @@ struct sfp_e1000_flags {
 #define E1000_SFF_VENDOR_OUI_AVAGO 0x00176A00
 #define E1000_SFF_VENDOR_OUI_INTEL 0x001B2100
 
+/* EEPROM byte offsets */
+#define IGB_SFF_8472_SWAP  0x5C
+#define IGB_SFF_8472_COMP  0x5E
+
+/* Bitmasks */
+#define IGB_SFF_ADDRESSING_MODE0x4
+#define IGB_SFF_8472_UNSUP 0x00
+
 #endif
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 3c5138d..77ec4f9 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -224,6 +224,10 @@ static int eth_igb_get_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 static int eth_igb_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
+static int eth_igb_get_module_info(struct rte_eth_dev *dev,
+  struct rte_dev_module_info *modinfo);
+static int eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+struct rte_dev_eeprom_info *info);
 static int eth_igb_set_mc_addr_list(struct rte_eth_dev *dev,
struct ether_addr *mc_addr_set,
uint32_t nb_mc_addr);
@@ -403,6 +407,8 @@ static void eth_igb_write_ivar(struct e1000_hw *hw, uint8_t 
msix_vector,
.get_eeprom_length= eth_igb_get_eeprom_length,
.get_eeprom   = eth_igb_get_eeprom,
.set_eeprom   = eth_igb_set_eeprom,
+   .get_module_info  = eth_igb_get_module_info,
+   .get_module_eeprom= eth_igb_get_module_eeprom,
.timesync_adjust_time = igb_timesync_adjust_time,
.timesync_read_time   = igb_timesync_read_time,
.timesync_write_time  = igb_timesync_write_time,
@@ -5384,6 +5390,86 @@ static void igbvf_set_vfta_all(struct rte_eth_dev *dev, 
bool on)
 }
 
 static int
+eth_igb_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   if (hw->phy.media_type == e1000_media_type_copper ||
+   hw->phy.media_type == e1000_media_type_unknown)
+   return -EOPNOTSUPP;
+
+   /* Check whether we support SFF-8472 or not */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_COMP, &sff8472_rev);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_SWAP, &addr_mode);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   if ((addr_mode & 0xFF) & IGB_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR,
+   "Address change required to access page 0xA2, "
+   "but not supported. Please report the module "
+   "type to the driver maintainers.\n");
+   page_swap = true;
+   }
+
+   if ((sff8472_rev & 0xFF) == IGB_SFF_8472_UNSUP || page_swap) {
+   /* We have an SFP, but it does not support SFF-8472 */
+   modinfo->type = ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have an SFP which supports a revision of SFF-8472 */
+   modinfo->type = ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t dataword[ETH_MODULE_SFF_8472_LEN / 2 + 1];
+   u16 first_word, last_word;
+   int i = 0;
+
+   if (info->length == 0)
+   return -EINVAL;
+
+   first_word = info->offset >> 1;
+   last_word = (info->offset + info->length - 1) >> 1;
+
+   /* Read EEPROM block, SFF-8079/SFF-8472, word at a time */
+   for (i = 0; i < last_word - first_word + 1; i++) {
+   status = e1000_read_phy_reg_i2c(hw, (first_word + i) * 2,
+   

[dpdk-dev] [PATCH v2 5/5] net/i40e: add module EEPROM callbacks for i40e

2018-03-16 Thread Zijie Pan
Add new callbacks for eth_dev_ops of i40e to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
---
 drivers/net/i40e/i40e_ethdev.c |  147 
 1 file changed, 147 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 508b417..98e9c3b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -369,6 +369,11 @@ static int i40e_get_regs(struct rte_eth_dev *dev,
 static int i40e_get_eeprom(struct rte_eth_dev *dev,
   struct rte_dev_eeprom_info *eeprom);
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo);
+static int i40e_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info);
+
 static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
  struct ether_addr *mac_addr);
 
@@ -489,6 +494,8 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
.get_reg  = i40e_get_regs,
.get_eeprom_length= i40e_get_eeprom_length,
.get_eeprom   = i40e_get_eeprom,
+   .get_module_info  = i40e_get_module_info,
+   .get_module_eeprom= i40e_get_module_eeprom,
.mac_addr_set = i40e_set_default_mac_addr,
.mtu_set  = i40e_dev_mtu_set,
.tm_ops_get   = i40e_tm_ops_get,
@@ -11249,6 +11256,146 @@ static int i40e_get_eeprom(struct rte_eth_dev *dev,
return 0;
 }
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo)
+{
+   struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t sff8472_comp = 0;
+   uint32_t sff8472_swap = 0;
+   uint32_t sff8636_rev = 0;
+   i40e_status status;
+   uint32_t type = 0;
+
+   /* Check if firmware supports reading module EEPROM. */
+   if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE)) {
+   PMD_DRV_LOG(ERR,
+   "Module EEPROM memory read not supported. "
+   "Please update the NVM image.\n");
+   return -EINVAL;
+   }
+
+   status = i40e_update_link_info(hw);
+   if (status)
+   return -EIO;
+
+   if (hw->phy.link_info.phy_type == I40E_PHY_TYPE_EMPTY) {
+   PMD_DRV_LOG(ERR,
+   "Cannot read module EEPROM memory. "
+   "No module connected.\n");
+   return -EINVAL;
+   }
+
+   type = hw->phy.link_info.module_type[0];
+
+   switch (type) {
+   case I40E_MODULE_TYPE_SFP:
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_COMP,
+   &sff8472_comp, NULL);
+   if (status)
+   return -EIO;
+
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_SWAP,
+   &sff8472_swap, NULL);
+   if (status)
+   return -EIO;
+
+   /* Check if the module requires address swap to access
+* the other EEPROM memory page.
+*/
+   if (sff8472_swap & I40E_MODULE_SFF_ADDR_MODE) {
+   PMD_DRV_LOG(WARNING,
+   "Module address swap to access "
+   "page 0xA2 is not supported.\n");
+   modinfo->type = ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+   } else if (sff8472_comp == 0x00) {
+   /* Module is not SFF-8472 compliant */
+   modinfo->type = ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+   } else {
+   modinfo->type = ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+   }
+   break;
+   case I40E_MODULE_TYPE_QSFP_PLUS:
+   /* Read from memory page 0. */
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   0,
+   I40E_MODULE_REVISION_ADDR,
+   &

[dpdk-dev] [PATCH v3 0/5] get the information and data of EEPROM

2018-03-21 Thread Zijie Pan
 0540  0540       .@...@..
180:          
190:          
1a0:  faff        
1b0:          
1c0:          
1d0:          
1e0:          
1f0:     0003 0100    

Both DPDK's my-module-eeprom.bin and Kernel's meeprom-kernel.bin
are the same.

v2 changes:
 - Fix typo in features.rst.
 - Fix checkpatch warnings regarding long lines.
 - Update function pcmd_module_eeprom_callback().

v3 changes:
 - fix compilation when dpdk is compiled with shared libs.

Zijie Pan (5):
  ethdev: add access to eeprom
  examples/ethtool: add a new command module-eeprom
  net/ixgbe: add module EEPROM callbacks for ixgbe
  net/e1000: add module EEPROM callbacks for e1000
  net/i40e: add module EEPROM callbacks for i40e

 doc/guides/nics/features.rst|   11 +++
 doc/guides/sample_app_ug/ethtool.rst|2 +
 drivers/net/e1000/base/e1000_phy.h  |8 ++
 drivers/net/e1000/igb_ethdev.c  |   86 ++
 drivers/net/i40e/i40e_ethdev.c  |  147 +++
 drivers/net/ixgbe/ixgbe_ethdev.c|   79 +
 examples/ethtool/ethtool-app/ethapp.c   |   64 ++
 examples/ethtool/lib/rte_ethtool.c  |   30 +++
 examples/ethtool/lib/rte_ethtool.h  |   34 +++
 lib/librte_ether/rte_dev_info.h |   18 
 lib/librte_ether/rte_ethdev.c   |   26 ++
 lib/librte_ether/rte_ethdev.h   |   35 
 lib/librte_ether/rte_ethdev_core.h  |   12 +++
 lib/librte_ether/rte_ethdev_version.map |2 +
 14 files changed, 554 insertions(+)

-- 
1.7.10.4



[dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom

2018-03-21 Thread Zijie Pan
add new APIs:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: john.mcnam...@intel.com
Cc: marko.kovace...@intel.com
Cc: tho...@monjalon.net

 doc/guides/nics/features.rst|   11 ++
 lib/librte_ether/rte_dev_info.h |   18 
 lib/librte_ether/rte_ethdev.c   |   26 +++
 lib/librte_ether/rte_ethdev.h   |   35 +++
 lib/librte_ether/rte_ethdev_core.h  |   12 +++
 lib/librte_ether/rte_ethdev_version.map |2 ++
 6 files changed, 104 insertions(+)

diff --git a/doc/guides/nics/features.rst b/doc/guides/nics/features.rst
index 1b4fb97..bb183e2 100644
--- a/doc/guides/nics/features.rst
+++ b/doc/guides/nics/features.rst
@@ -749,6 +749,17 @@ Supports getting/setting device eeprom data.
   ``rte_eth_dev_set_eeprom()``.
 
 
+.. _nic_features_module_eeprom_dump:
+
+Module EEPROM dump
+--
+
+Supports getting information and data of plugin module eeprom.
+
+* **[implements] eth_dev_ops**: ``get_module_info``, ``get_module_eeprom``.
+* **[related]API**: ``rte_eth_dev_get_module_info()``, 
``rte_eth_dev_get_module_eeprom()``.
+
+
 .. _nic_features_register_dump:
 
 Registers dump
diff --git a/lib/librte_ether/rte_dev_info.h b/lib/librte_ether/rte_dev_info.h
index 6b68584..c15a0fa 100644
--- a/lib/librte_ether/rte_dev_info.h
+++ b/lib/librte_ether/rte_dev_info.h
@@ -28,4 +28,22 @@ struct rte_dev_eeprom_info {
uint32_t magic; /**< Device-specific key, such as device-id */
 };
 
+/*
+ * Placeholder for accessing plugin module eeprom
+ */
+struct rte_dev_module_info {
+   uint32_t type; /**< Type of plugin module eeprom */
+   uint32_t eeprom_len; /**< Length of plugin module eeprom */
+};
+
+/* EEPROM Standards for plug in modules */
+#define ETH_MODULE_SFF_8079 0x1
+#define ETH_MODULE_SFF_8079_LEN 256
+#define ETH_MODULE_SFF_8472 0x2
+#define ETH_MODULE_SFF_8472_LEN 512
+#define ETH_MODULE_SFF_8636 0x3
+#define ETH_MODULE_SFF_8636_LEN 256
+#define ETH_MODULE_SFF_8436 0x4
+#define ETH_MODULE_SFF_8436_LEN 256
+
 #endif /* _RTE_DEV_INFO_H_ */
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 0590f0c..b83643d 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -4044,6 +4044,32 @@ int rte_eth_set_queue_rate_limit(uint16_t port_id, 
uint16_t queue_idx,
 }
 
 int
+rte_eth_dev_get_module_info(uint16_t port_id,
+   struct rte_dev_module_info *modinfo)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_info, -ENOTSUP);
+   return (*dev->dev_ops->get_module_info)(dev, modinfo);
+}
+
+   int
+rte_eth_dev_get_module_eeprom(uint16_t port_id,
+   struct rte_dev_eeprom_info *info)
+{
+   struct rte_eth_dev *dev;
+
+   RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+   dev = &rte_eth_devices[port_id];
+   RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_eeprom, -ENOTSUP);
+   return (*dev->dev_ops->get_module_eeprom)(dev, info);
+}
+
+int
 rte_eth_dev_get_dcb_info(uint16_t port_id,
 struct rte_eth_dcb_info *dcb_info)
 {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 0361533..e8b1d94 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -3262,6 +3262,41 @@ int rte_eth_tx_queue_info_get(uint16_t port_id, uint16_t 
queue_id,
 int rte_eth_dev_set_eeprom(uint16_t port_id, struct rte_dev_eeprom_info *info);
 
 /**
+ * Retrieve the type and size of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param modinfo
+ *   The type and size of plugin module EEPROM.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EIO) if device is removed.
+ *   - others depends on the specific operations implementation.
+ */
+int rte_eth_dev_get_module_info(uint16_t port_id,
+   struct rte_dev_module_info *modinfo);
+
+/**
+ * Retrieve the data of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param info
+ *   The template includes the plugin module EEPROM attributes, and the
+ *   buffer for return plugin module EEPROM data.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EIO) if device is removed.
+ *   - others depends on the specific operations implementation.
+ */
+int rte_eth_dev_get_module_eeprom(uint16_t port_id,
+

[dpdk-dev] [PATCH v3 2/5] examples/ethtool: add a new command module-eeprom

2018-03-21 Thread Zijie Pan
Add a new command "module-eeprom" to get the data of plugin
module EEPROM.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: or...@mellanox.com
Cc: bruce.richard...@intel.com
Cc: pablo.de.lara.gua...@intel.com
Cc: radu.nico...@intel.com
Cc: akhil.go...@nxp.com
Cc: tomasz.kante...@intel.com
Cc: john.mcnam...@intel.com
Cc: marko.kovace...@intel.com

 doc/guides/sample_app_ug/ethtool.rst  |2 ++
 examples/ethtool/ethtool-app/ethapp.c |   64 +
 examples/ethtool/lib/rte_ethtool.c|   30 
 examples/ethtool/lib/rte_ethtool.h|   34 ++
 4 files changed, 130 insertions(+)

diff --git a/doc/guides/sample_app_ug/ethtool.rst 
b/doc/guides/sample_app_ug/ethtool.rst
index 1b79aca..028b8e9 100644
--- a/doc/guides/sample_app_ug/ethtool.rst
+++ b/doc/guides/sample_app_ug/ethtool.rst
@@ -97,6 +97,8 @@ the following functions:
 - ``rte_ethtool_get_eeprom_len()``
 - ``rte_ethtool_get_eeprom()``
 - ``rte_ethtool_set_eeprom()``
+- ``rte_ethtool_get_module_info()``
+- ``rte_ethtool_get_module_eeprom()``
 - ``rte_ethtool_get_pauseparam()``
 - ``rte_ethtool_set_pauseparam()``
 - ``rte_ethtool_net_open()``
diff --git a/examples/ethtool/ethtool-app/ethapp.c 
b/examples/ethtool/ethtool-app/ethapp.c
index 0c3f1f6..c37b7c3 100644
--- a/examples/ethtool/ethtool-app/ethapp.c
+++ b/examples/ethtool/ethtool-app/ethapp.c
@@ -75,6 +75,9 @@ struct pcmd_intintint_params {
 /* Commands taking port id and string */
 cmdline_parse_token_string_t pcmd_eeprom_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "eeprom");
+cmdline_parse_token_string_t pcmd_module_eeprom_token_cmd =
+   TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd,
+"module-eeprom");
 cmdline_parse_token_string_t pcmd_mtu_token_cmd =
TOKEN_STRING_INITIALIZER(struct pcmd_intstr_params, cmd, "mtu");
 cmdline_parse_token_string_t pcmd_regs_token_cmd =
@@ -298,6 +301,54 @@ struct pcmd_intintint_params {
 
 
 static void
+pcmd_module_eeprom_callback(void *ptr_params,
+   __rte_unused struct cmdline *ctx,
+   __rte_unused void *ptr_data)
+{
+   struct pcmd_intstr_params *params = ptr_params;
+   struct ethtool_eeprom info_eeprom;
+   uint32_t module_info[2];
+   int stat;
+   unsigned char bytes_eeprom[EEPROM_DUMP_CHUNKSIZE];
+   FILE *fp_eeprom;
+
+   if (!rte_eth_dev_is_valid_port(params->port)) {
+   printf("Error: Invalid port number %i\n", params->port);
+   return;
+   }
+
+   stat = rte_ethtool_get_module_info(params->port, module_info);
+   if (stat != 0) {
+   printf("Module EEPROM information read error %i\n", stat);
+   return;
+   }
+
+   info_eeprom.len = module_info[1];
+   info_eeprom.offset = 0;
+
+   stat = rte_ethtool_get_module_eeprom(params->port,
+&info_eeprom, bytes_eeprom);
+   if (stat != 0) {
+   printf("Module EEPROM read error %i\n", stat);
+   return;
+   }
+
+   fp_eeprom = fopen(params->opt, "wb");
+   if (fp_eeprom == NULL) {
+   printf("Error opening '%s' for writing\n", params->opt);
+   return;
+   }
+   printf("Total plugin module EEPROM length: %i bytes\n",
+  info_eeprom.len);
+   if (fwrite(bytes_eeprom, 1, info_eeprom.len,
+  fp_eeprom) != info_eeprom.len) {
+   printf("Error writing '%s'\n", params->opt);
+   }
+   fclose(fp_eeprom);
+}
+
+
+static void
 pcmd_pause_callback(void *ptr_params,
__rte_unused struct cmdline *ctx,
void *ptr_data)
@@ -664,6 +715,18 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
NULL
},
 };
+cmdline_parse_inst_t pcmd_module_eeprom = {
+   .f = pcmd_module_eeprom_callback,
+   .data = NULL,
+   .help_str = "module-eeprom  \n"
+   " Dump plugin module EEPROM to file",
+   .tokens = {
+   (void *)&pcmd_module_eeprom_token_cmd,
+   (void *)&pcmd_intstr_token_port,
+   (void *)&pcmd_intstr_token_opt,
+   NULL
+   },
+};
 cmdline_parse_inst_t pcmd_pause_noopt = {
.f = pcmd_pause_callback,
.data = (void *)0x01,
@@ -816,6 +879,7 @@ static void pcmd_vlan_callback(__rte_unused void 
*ptr_params,
 cmdline_parse_ctx_t list_prompt_commands[] = {
(cmdline_parse_inst_t *)&pcmd_drvinfo,
(cmdline_parse_inst_t *)&pcmd_eeprom,
+   (cmdline_parse_inst_t *)&pcmd_module_eeprom,
(cmdline_parse_inst_t *)&pcmd_link,
(cmdline_parse_inst_t *)&pcmd_macaddr_get,
(cmdline_parse_inst_t *)&

[dpdk-dev] [PATCH v3 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe

2018-03-21 Thread Zijie Pan
Add new callbacks for eth_dev_ops of ixgbe to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
Acked-by: Remy Horton 
---
Cc: remy.hor...@intel.com
Cc: wenzhuo...@intel.com
Cc: konstantin.anan...@intel.com

 drivers/net/ixgbe/ixgbe_ethdev.c |   79 ++
 1 file changed, 79 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 4483258..28f09d3 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -328,6 +328,11 @@ static int ixgbe_get_eeprom(struct rte_eth_dev *dev,
 static int ixgbe_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 
+static int ixgbe_get_module_info(struct rte_eth_dev *dev,
+struct rte_dev_module_info *modinfo);
+static int ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+  struct rte_dev_eeprom_info *info);
+
 static int ixgbevf_get_reg_length(struct rte_eth_dev *dev);
 static int ixgbevf_get_regs(struct rte_eth_dev *dev,
struct rte_dev_reg_info *regs);
@@ -565,6 +570,8 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev 
*dev,
.get_eeprom_length= ixgbe_get_eeprom_length,
.get_eeprom   = ixgbe_get_eeprom,
.set_eeprom   = ixgbe_set_eeprom,
+   .get_module_info  = ixgbe_get_module_info,
+   .get_module_eeprom= ixgbe_get_module_eeprom,
.get_dcb_info = ixgbe_dev_get_dcb_info,
.timesync_adjust_time = ixgbe_timesync_adjust_time,
.timesync_read_time   = ixgbe_timesync_read_time,
@@ -7166,6 +7173,78 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev 
*dev, bool on)
return eeprom->ops.write_buffer(hw,  first, length, data);
 }
 
+static int
+ixgbe_get_module_info(struct rte_eth_dev *dev,
+ struct rte_dev_module_info *modinfo)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status;
+   uint8_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   /* Check whether we support SFF-8472 or not */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_COMP,
+&sff8472_rev);
+   if (status != 0)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = hw->phy.ops.read_i2c_eeprom(hw,
+IXGBE_SFF_SFF_8472_SWAP,
+&addr_mode);
+   if (status != 0)
+   return -EIO;
+
+   if (addr_mode & IXGBE_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR,
+   "Address change required to access page 0xA2, "
+   "but not supported. Please report the module "
+   "type to the driver maintainers.");
+   page_swap = true;
+   }
+
+   if (sff8472_rev == IXGBE_SFF_SFF_8472_UNSUP || page_swap) {
+   /* We have a SFP, but it does not support SFF-8472 */
+   modinfo->type = ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have a SFP which supports a revision of SFF-8472. */
+   modinfo->type = ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+   struct rte_dev_eeprom_info *info)
+{
+   struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t status = IXGBE_ERR_PHY_ADDR_INVALID;
+   uint8_t databyte = 0xFF;
+   uint8_t *data = info->data;
+   uint32_t i = 0;
+
+   if (info->length == 0)
+   return -EINVAL;
+
+   for (i = info->offset; i < info->offset + info->length; i++) {
+   if (i < ETH_MODULE_SFF_8079_LEN)
+   status = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte);
+   else
+   status = hw->phy.ops.read_i2c_sff8472(hw, i, &databyte);
+
+   if (status != 0)
+   return -EIO;
+
+   data[i - info->offset] = databyte;
+   }
+
+   return 0;
+}
+
 uint16_t
 ixgbe_reta_size_get(enum ixgbe_mac_type mac_type) {
switch (mac_type) {
-- 
1.7.10.4



[dpdk-dev] [PATCH v3 4/5] net/e1000: add module EEPROM callbacks for e1000

2018-03-21 Thread Zijie Pan
Add new callbacks for eth_dev_ops of e1000 to get the information and
data of plugin module EEPROM.

Signed-off-by: Zijie Pan 
---
Cc: wenzhuo...@intel.com

 drivers/net/e1000/base/e1000_phy.h |8 
 drivers/net/e1000/igb_ethdev.c |   86 
 2 files changed, 94 insertions(+)

diff --git a/drivers/net/e1000/base/e1000_phy.h 
b/drivers/net/e1000/base/e1000_phy.h
index 3e45a9e..2cd0e14 100644
--- a/drivers/net/e1000/base/e1000_phy.h
+++ b/drivers/net/e1000/base/e1000_phy.h
@@ -330,4 +330,12 @@ struct sfp_e1000_flags {
 #define E1000_SFF_VENDOR_OUI_AVAGO 0x00176A00
 #define E1000_SFF_VENDOR_OUI_INTEL 0x001B2100
 
+/* EEPROM byte offsets */
+#define IGB_SFF_8472_SWAP  0x5C
+#define IGB_SFF_8472_COMP  0x5E
+
+/* Bitmasks */
+#define IGB_SFF_ADDRESSING_MODE0x4
+#define IGB_SFF_8472_UNSUP 0x00
+
 #endif
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 3c5138d..77ec4f9 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -224,6 +224,10 @@ static int eth_igb_get_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
 static int eth_igb_set_eeprom(struct rte_eth_dev *dev,
struct rte_dev_eeprom_info *eeprom);
+static int eth_igb_get_module_info(struct rte_eth_dev *dev,
+  struct rte_dev_module_info *modinfo);
+static int eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+struct rte_dev_eeprom_info *info);
 static int eth_igb_set_mc_addr_list(struct rte_eth_dev *dev,
struct ether_addr *mc_addr_set,
uint32_t nb_mc_addr);
@@ -403,6 +407,8 @@ static void eth_igb_write_ivar(struct e1000_hw *hw, uint8_t 
msix_vector,
.get_eeprom_length= eth_igb_get_eeprom_length,
.get_eeprom   = eth_igb_get_eeprom,
.set_eeprom   = eth_igb_set_eeprom,
+   .get_module_info  = eth_igb_get_module_info,
+   .get_module_eeprom= eth_igb_get_module_eeprom,
.timesync_adjust_time = igb_timesync_adjust_time,
.timesync_read_time   = igb_timesync_read_time,
.timesync_write_time  = igb_timesync_write_time,
@@ -5384,6 +5390,86 @@ static void igbvf_set_vfta_all(struct rte_eth_dev *dev, 
bool on)
 }
 
 static int
+eth_igb_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t sff8472_rev, addr_mode;
+   bool page_swap = false;
+
+   if (hw->phy.media_type == e1000_media_type_copper ||
+   hw->phy.media_type == e1000_media_type_unknown)
+   return -EOPNOTSUPP;
+
+   /* Check whether we support SFF-8472 or not */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_COMP, &sff8472_rev);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_SWAP, &addr_mode);
+   if (status)
+   return -EIO;
+
+   /* addressing mode is not supported */
+   if ((addr_mode & 0xFF) & IGB_SFF_ADDRESSING_MODE) {
+   PMD_DRV_LOG(ERR,
+   "Address change required to access page 0xA2, "
+   "but not supported. Please report the module "
+   "type to the driver maintainers.\n");
+   page_swap = true;
+   }
+
+   if ((sff8472_rev & 0xFF) == IGB_SFF_8472_UNSUP || page_swap) {
+   /* We have an SFP, but it does not support SFF-8472 */
+   modinfo->type = ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+   } else {
+   /* We have an SFP which supports a revision of SFF-8472 */
+   modinfo->type = ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+   }
+
+   return 0;
+}
+
+static int
+eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info)
+{
+   struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   uint32_t status = 0;
+   uint16_t dataword[ETH_MODULE_SFF_8472_LEN / 2 + 1];
+   u16 first_word, last_word;
+   int i = 0;
+
+   if (info->length == 0)
+   return -EINVAL;
+
+   first_word = info->offset >> 1;
+   last_word = (info->offset + info->length - 1) >> 1;
+
+   /* Read EEPROM block, SFF-8079/SFF-8472, word at a time */
+   for (i = 0; i < last_word - first_word + 1; i++) {
+   status = e1000_read_phy_reg_i2c(hw, (first_word + i) * 2,
+ 

[dpdk-dev] [PATCH v3 5/5] net/i40e: add module EEPROM callbacks for i40e

2018-03-21 Thread Zijie Pan
Add new callbacks for eth_dev_ops of i40e to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan 
---
Cc: beilei.x...@intel.com
Cc: qi.z.zh...@intel.com

 drivers/net/i40e/i40e_ethdev.c |  147 
 1 file changed, 147 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 508b417..98e9c3b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -369,6 +369,11 @@ static int i40e_get_regs(struct rte_eth_dev *dev,
 static int i40e_get_eeprom(struct rte_eth_dev *dev,
   struct rte_dev_eeprom_info *eeprom);
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo);
+static int i40e_get_module_eeprom(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *info);
+
 static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
  struct ether_addr *mac_addr);
 
@@ -489,6 +494,8 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
.get_reg  = i40e_get_regs,
.get_eeprom_length= i40e_get_eeprom_length,
.get_eeprom   = i40e_get_eeprom,
+   .get_module_info  = i40e_get_module_info,
+   .get_module_eeprom= i40e_get_module_eeprom,
.mac_addr_set = i40e_set_default_mac_addr,
.mtu_set  = i40e_dev_mtu_set,
.tm_ops_get   = i40e_tm_ops_get,
@@ -11249,6 +11256,146 @@ static int i40e_get_eeprom(struct rte_eth_dev *dev,
return 0;
 }
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+   struct rte_dev_module_info *modinfo)
+{
+   struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   uint32_t sff8472_comp = 0;
+   uint32_t sff8472_swap = 0;
+   uint32_t sff8636_rev = 0;
+   i40e_status status;
+   uint32_t type = 0;
+
+   /* Check if firmware supports reading module EEPROM. */
+   if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE)) {
+   PMD_DRV_LOG(ERR,
+   "Module EEPROM memory read not supported. "
+   "Please update the NVM image.\n");
+   return -EINVAL;
+   }
+
+   status = i40e_update_link_info(hw);
+   if (status)
+   return -EIO;
+
+   if (hw->phy.link_info.phy_type == I40E_PHY_TYPE_EMPTY) {
+   PMD_DRV_LOG(ERR,
+   "Cannot read module EEPROM memory. "
+   "No module connected.\n");
+   return -EINVAL;
+   }
+
+   type = hw->phy.link_info.module_type[0];
+
+   switch (type) {
+   case I40E_MODULE_TYPE_SFP:
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_COMP,
+   &sff8472_comp, NULL);
+   if (status)
+   return -EIO;
+
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   I40E_I2C_EEPROM_DEV_ADDR,
+   I40E_MODULE_SFF_8472_SWAP,
+   &sff8472_swap, NULL);
+   if (status)
+   return -EIO;
+
+   /* Check if the module requires address swap to access
+* the other EEPROM memory page.
+*/
+   if (sff8472_swap & I40E_MODULE_SFF_ADDR_MODE) {
+   PMD_DRV_LOG(WARNING,
+   "Module address swap to access "
+   "page 0xA2 is not supported.\n");
+   modinfo->type = ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+   } else if (sff8472_comp == 0x00) {
+   /* Module is not SFF-8472 compliant */
+   modinfo->type = ETH_MODULE_SFF_8079;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+   } else {
+   modinfo->type = ETH_MODULE_SFF_8472;
+   modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+   }
+   break;
+   case I40E_MODULE_TYPE_QSFP_PLUS:
+   /* Read from memory page 0. */
+   status = i40e_aq_get_phy_register(hw,
+   I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+   0,
+