All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/5] get the information and data of EEPROM
       [not found] <1524563176-7795-1-git-send-email-zijie.pan@6wind.com>
@ 2018-04-25  9:13 ` Zijie Pan
  2018-04-25  9:13   ` [PATCH v5 1/5] ethdev: add access to eeprom Zijie Pan
                     ` (6 more replies)
  0 siblings, 7 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25  9:13 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas

Add APIs to read information from the DPDK applictions.
It can be used to dump the EEPROM of plugin modules (SFP+, QSFP, etc.).

Two APIs are introduced to access eeprom:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

Applications based on DPDK can dump eeprom by calling those two APIs.

Then, each PMD has to implement these callbacks for e1000, ixgbe, i40e, etc.

Patch for example/ethtool is used to test this function. It can get the raw 
data of eeprom. See below how both DPDK applications (ethtool) and Linux
kernel are dumping the same eeprom of a same NIC.

- Start example/ethtool:
    ./examples/ethtool/ethtool-app/x86_64-native-linuxapp-gcc/ethtool -c 0xf -n 4 --socket-mem 1024,0 -- -i
EthApp> drvinfo
Port 0 driver: net_ixgbe (ver: DPDK 18.05.0-rc0)
firmware-version: 0x18b30001
bus-info: 0000:04:00.0

EthApp> module-eeprom
 [UINT16]: module-eeprom <port_id> <filename>
     Dump plug-in module EEPROM to file

EthApp> module-eeprom 0 my-module-eeprom.bin
Total plug-in module EEPROM length: 512 bytes

EthApp> quit

- HexDump of this eeprom file:
# xxd my-module-eeprom.bin
0000000: 0304 0710 0000 0100 0000 0006 6702 0000  ............g...
0000010: 0803 001e 4f45 4d20 2020 2020 2020 2020  ....OEM
0000020: 2020 2020 0000 1b21 5346 502d 3130 472d      ...!SFP-10G-
0000030: 5352 2d49 5420 2020 4120 2020 0352 0024  SR-IT   A   .R.$
0000040: 003a 0000 5751 3136 3034 3132 4131 3135  .:..WQ160412A115
0000050: 2020 2020 3135 3136 3130 2020 68fa 033b      151610  h..;
0000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000f0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000100: 5000 fb00 4b00 0000 8ca0 7530 88b8 7918  P...K.....u0..y.
0000110: 1d4c 01f4 1b58 03e8 3de9 03e8 2710 04eb  .L...X..=...'...
0000120: 2710 0064 1f07 007e 0000 0000 0000 0000  '..d...~........
0000130: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000140: 0000 0000 3f80 0000 0000 0000 0100 0000  ....?...........
0000150: 0100 0000 0100 0000 0100 0000 0000 002d  ...............-
0000160: 2c59 810a 13c7 1752 0001 0000 0000 0200  ,Y.....R........
0000170: 0040 0000 0040 0000 0000 0000 0000 0000  .@...@..........
0000180: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000190: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001a0: ffff faff ffff ffff ffff ffff ffff ffff  ................
00001b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001f0: ffff ffff ffff ffff 0003 0100 0000 0000  ................

- Rerun same dump using Linux's kernel ethtool.

# ./install/sbin/dpdk-devbind --bind=ixgbe 04:00.0
# ethtool -m p2p1 raw on > meeprom-kernel.bin

# xxd meeprom-kernel.bin
0000000: 0304 0710 0000 0100 0000 0006 6702 0000  ............g...
0000010: 0803 001e 4f45 4d20 2020 2020 2020 2020  ....OEM
0000020: 2020 2020 0000 1b21 5346 502d 3130 472d      ...!SFP-10G-
0000030: 5352 2d49 5420 2020 4120 2020 0352 0024  SR-IT   A   .R.$
0000040: 003a 0000 5751 3136 3034 3132 4131 3135  .:..WQ160412A115
0000050: 2020 2020 3135 3136 3130 2020 68fa 033b      151610  h..;
0000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000f0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000100: 5000 fb00 4b00 0000 8ca0 7530 88b8 7918  P...K.....u0..y.
0000110: 1d4c 01f4 1b58 03e8 3de9 03e8 2710 04eb  .L...X..=...'...
0000120: 2710 0064 1f07 007e 0000 0000 0000 0000  '..d...~........
0000130: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000140: 0000 0000 3f80 0000 0000 0000 0100 0000  ....?...........
0000150: 0100 0000 0100 0000 0100 0000 0000 002d  ...............-
0000160: 2899 8146 0058 0001 0001 0000 0000 8200  (..F.X..........
0000170: 0540 0000 0540 0000 0000 0000 0000 0000  .@...@..........
0000180: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000190: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001a0: ffff faff ffff ffff ffff ffff ffff ffff  ................
00001b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001f0: ffff ffff ffff ffff 0003 0100 0000 0000  ................

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

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v5 1/5] ethdev: add access to eeprom
  2018-04-25  9:13 ` [PATCH v5 0/5] get the information and data of EEPROM Zijie Pan
@ 2018-04-25  9:13   ` Zijie Pan
  2018-04-25  9:13   ` [PATCH v5 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25  9:13 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas, john.mcnamara, marko.kovacevic

add new APIs:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: remy.horton@intel.com
Cc: john.mcnamara@intel.com
Cc: marko.kovacevic@intel.com
Cc: thomas@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 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_experimental
+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_ethdev_core.h b/lib/librte_ether/rte_ethdev_core.h
index 55eb2b0..ec623c2 100644
--- a/lib/librte_ether/rte_ethdev_core.h
+++ b/lib/librte_ether/rte_ethdev_core.h
@@ -337,6 +337,14 @@ typedef int (*eth_set_eeprom_t)(struct rte_eth_dev *dev,
 				struct rte_dev_eeprom_info *info);
 /**< @internal Program eeprom data  */
 
+typedef int (*eth_get_module_info_t)(struct rte_eth_dev *dev,
+				     struct rte_dev_module_info *modinfo);
+/**< @internal Retrieve type and size of plugin module eeprom */
+
+typedef int (*eth_get_module_eeprom_t)(struct rte_eth_dev *dev,
+				       struct rte_dev_eeprom_info *info);
+/**< @internal Retrieve plugin module eeprom data */
+
 typedef int (*eth_l2_tunnel_eth_type_conf_t)
 	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel_conf *l2_tunnel);
 /**< @internal config l2 tunnel ether type */
@@ -467,6 +475,10 @@ struct eth_dev_ops {
 	eth_get_eeprom_t           get_eeprom;        /**< Get eeprom data. */
 	eth_set_eeprom_t           set_eeprom;        /**< Set eeprom. */
 
+	eth_get_module_info_t      get_module_info;
+	/** Get plugin module eeprom attribute. */
+	eth_get_module_eeprom_t    get_module_eeprom;
+	/** Get plugin module eeprom data. */
 
 	eth_filter_ctrl_t          filter_ctrl; /**< common filter control. */
 
diff --git a/lib/librte_ether/rte_ethdev_version.map b/lib/librte_ether/rte_ethdev_version.map
index 8fe0788..b8e7566 100644
--- a/lib/librte_ether/rte_ethdev_version.map
+++ b/lib/librte_ether/rte_ethdev_version.map
@@ -208,6 +208,8 @@ EXPERIMENTAL {
 
 	rte_eth_dev_count_avail;
 	rte_eth_dev_count_total;
+	rte_eth_dev_get_module_info;
+	rte_eth_dev_get_module_eeprom;
 	rte_eth_dev_is_removed;
 	rte_eth_dev_owner_delete;
 	rte_eth_dev_owner_get;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v5 2/5] examples/ethtool: add a new command module-eeprom
  2018-04-25  9:13 ` [PATCH v5 0/5] get the information and data of EEPROM Zijie Pan
  2018-04-25  9:13   ` [PATCH v5 1/5] ethdev: add access to eeprom Zijie Pan
@ 2018-04-25  9:13   ` Zijie Pan
  2018-04-25  9:13   ` [PATCH v5 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25  9:13 UTC (permalink / raw)
  To: dev
  Cc: remy.horton, ferruh.yigit, thomas, orika, bruce.richardson,
	pablo.de.lara.guarch, radu.nicolau, akhil.goyal, tomasz.kantecki,
	john.mcnamara, marko.kovacevic

Add a new command "module-eeprom" to get the data of plugin
module EEPROM.

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: remy.horton@intel.com
Cc: orika@mellanox.com
Cc: bruce.richardson@intel.com
Cc: pablo.de.lara.guarch@intel.com
Cc: radu.nicolau@intel.com
Cc: akhil.goyal@nxp.com
Cc: tomasz.kantecki@intel.com
Cc: john.mcnamara@intel.com
Cc: marko.kovacevic@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 <port_id> <filename>\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/Makefile b/examples/ethtool/lib/Makefile
index fbafa6d..2576910 100644
--- a/examples/ethtool/lib/Makefile
+++ b/examples/ethtool/lib/Makefile
@@ -25,6 +25,7 @@ SRCS-y := rte_ethtool.c
 
 CFLAGS += -O3
 CFLAGS += $(WERROR_FLAGS)
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 
 ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
 ifeq ($(CONFIG_RTE_LIBRTE_IXGBE_PMD),y)
diff --git a/examples/ethtool/lib/rte_ethtool.c b/examples/ethtool/lib/rte_ethtool.c
index d519a50..cb3dfa5 100644
--- a/examples/ethtool/lib/rte_ethtool.c
+++ b/examples/ethtool/lib/rte_ethtool.c
@@ -178,6 +178,36 @@
 }
 
 int
+rte_ethtool_get_module_info(uint16_t port_id, uint32_t *modinfo)
+{
+	struct rte_dev_module_info *info;
+
+	info = (struct rte_dev_module_info *)modinfo;
+	return rte_eth_dev_get_module_info(port_id, info);
+}
+
+int
+rte_ethtool_get_module_eeprom(uint16_t port_id, struct ethtool_eeprom *eeprom,
+	void *words)
+{
+	struct rte_dev_eeprom_info eeprom_info;
+	int status;
+
+	if (eeprom == NULL || words == NULL)
+		return -EINVAL;
+
+	eeprom_info.offset = eeprom->offset;
+	eeprom_info.length = eeprom->len;
+	eeprom_info.data = words;
+
+	status = rte_eth_dev_get_module_eeprom(port_id, &eeprom_info);
+	if (status)
+		return status;
+
+	return 0;
+}
+
+int
 rte_ethtool_get_pauseparam(uint16_t port_id,
 	struct ethtool_pauseparam *pause_param)
 {
diff --git a/examples/ethtool/lib/rte_ethtool.h b/examples/ethtool/lib/rte_ethtool.h
index c962396..43adc97 100644
--- a/examples/ethtool/lib/rte_ethtool.h
+++ b/examples/ethtool/lib/rte_ethtool.h
@@ -154,6 +154,40 @@ int rte_ethtool_set_eeprom(uint16_t port_id, struct ethtool_eeprom *eeprom,
 			      void *words);
 
 /**
+ * Retrieve the type and size of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param modinfo
+ *	 The pointer that provides the type and size of plugin module EEPROM.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - others depends on the specific operations implementation.
+ */
+int rte_ethtool_get_module_info(uint16_t port_id, uint32_t *modinfo);
+
+/**
+ * Retrieve the data of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param eeprom
+ *	 The pointer of ethtool_eeprom that provides plugin module eeprom
+ *   offset and length
+ * @param words
+ *	 A buffer that holds data read from plugin module eeprom
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - others depends on the specific operations implementation.
+ */
+int rte_ethtool_get_module_eeprom(uint16_t port_id,
+				  struct ethtool_eeprom *eeprom, void *words);
+
+/**
  * Retrieve the Ethernet device pause frame configuration according to
  * parameter attributes desribed by ethtool data structure,
  * ethtool_pauseparam.
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v5 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe
  2018-04-25  9:13 ` [PATCH v5 0/5] get the information and data of EEPROM Zijie Pan
  2018-04-25  9:13   ` [PATCH v5 1/5] ethdev: add access to eeprom Zijie Pan
  2018-04-25  9:13   ` [PATCH v5 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
@ 2018-04-25  9:13   ` Zijie Pan
  2018-04-25  9:13   ` [PATCH v5 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25  9:13 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas, wenzhuo.lu, konstantin.ananyev

Add new callbacks for eth_dev_ops of ixgbe to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: remy.horton@intel.com
Cc: wenzhuo.lu@intel.com
Cc: konstantin.ananyev@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

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v5 4/5] net/e1000: add module EEPROM callbacks for e1000
  2018-04-25  9:13 ` [PATCH v5 0/5] get the information and data of EEPROM Zijie Pan
                     ` (2 preceding siblings ...)
  2018-04-25  9:13   ` [PATCH v5 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
@ 2018-04-25  9:13   ` Zijie Pan
  2018-04-25  9:13   ` [PATCH v5 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25  9:13 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas, wenzhuo.lu

Add new callbacks for eth_dev_ops of e1000 to get the information and
data of plugin module EEPROM.

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: wenzhuo.lu@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_MODE	0x4
+#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(hw, (first_word + i) * 2,
+						&dataword[i]);
+		if (status) {
+			/* Error occurred while reading module */
+			return -EIO;
+		}
+
+		dataword[i] = rte_be_to_cpu_16(dataword[i]);
+	}
+
+	memcpy(info->data, (u8 *)dataword + (info->offset & 1), info->length);
+
+	return 0;
+}
+
+static int
 eth_igb_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 {
 	struct e1000_hw *hw =
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v5 5/5] net/i40e: add module EEPROM callbacks for i40e
  2018-04-25  9:13 ` [PATCH v5 0/5] get the information and data of EEPROM Zijie Pan
                     ` (3 preceding siblings ...)
  2018-04-25  9:13   ` [PATCH v5 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
@ 2018-04-25  9:13   ` Zijie Pan
  2018-04-25  9:22   ` [PATCH v5 0/5] get the information and data of EEPROM Thomas Monjalon
  2018-04-25 10:01   ` [PATCH v6 " Zijie Pan
  6 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25  9:13 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas, beilei.xing, qi.z.zhang

Add new callbacks for eth_dev_ops of i40e to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: beilei.xing@intel.com
Cc: qi.z.zhang@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,
+				0,
+				I40E_MODULE_REVISION_ADDR,
+				&sff8636_rev, NULL);
+		if (status)
+			return -EIO;
+		/* Determine revision compliance byte */
+		if (sff8636_rev > 0x02) {
+			/* Module is SFF-8636 compliant */
+			modinfo->type = RTE_ETH_MODULE_SFF_8636;
+			modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+		} else {
+			modinfo->type = RTE_ETH_MODULE_SFF_8436;
+			modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+		}
+		break;
+	case I40E_MODULE_TYPE_QSFP28:
+		modinfo->type = RTE_ETH_MODULE_SFF_8636;
+		modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Module type unrecognized\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int i40e_get_module_eeprom(struct rte_eth_dev *dev,
+				  struct rte_dev_eeprom_info *info)
+{
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	bool is_sfp = false;
+	i40e_status status;
+	uint8_t *data = info->data;
+	uint32_t value = 0;
+	uint32_t i;
+
+	if (!info || !info->length || !data)
+		return -EINVAL;
+
+	if (hw->phy.link_info.module_type[0] == I40E_MODULE_TYPE_SFP)
+		is_sfp = true;
+
+	for (i = 0; i < info->length; i++) {
+		u32 offset = i + info->offset;
+		u32 addr = is_sfp ? I40E_I2C_EEPROM_DEV_ADDR : 0;
+
+		/* Check if we need to access the other memory page */
+		if (is_sfp) {
+			if (offset >= RTE_ETH_MODULE_SFF_8079_LEN) {
+				offset -= RTE_ETH_MODULE_SFF_8079_LEN;
+				addr = I40E_I2C_EEPROM_DEV_ADDR2;
+			}
+		} else {
+			while (offset >= RTE_ETH_MODULE_SFF_8436_LEN) {
+				/* Compute memory page number and offset. */
+				offset -= RTE_ETH_MODULE_SFF_8436_LEN / 2;
+				addr++;
+			}
+		}
+		status = i40e_aq_get_phy_register(hw,
+				I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+				addr, offset, &value, NULL);
+		if (status)
+			return -EIO;
+		data[i] = (uint8_t)value;
+	}
+	return 0;
+}
+
 static int i40e_set_default_mac_addr(struct rte_eth_dev *dev,
 				     struct ether_addr *mac_addr)
 {
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH v5 0/5] get the information and data of EEPROM
  2018-04-25  9:13 ` [PATCH v5 0/5] get the information and data of EEPROM Zijie Pan
                     ` (4 preceding siblings ...)
  2018-04-25  9:13   ` [PATCH v5 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
@ 2018-04-25  9:22   ` Thomas Monjalon
  2018-04-25  9:32     ` Zijie Pan
  2018-04-25 10:01   ` [PATCH v6 " Zijie Pan
  6 siblings, 1 reply; 25+ messages in thread
From: Thomas Monjalon @ 2018-04-25  9:22 UTC (permalink / raw)
  To: Zijie Pan; +Cc: dev, remy.horton, ferruh.yigit

25/04/2018 11:13, Zijie Pan:
> 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.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v5 0/5] get the information and data of EEPROM
  2018-04-25  9:22   ` [PATCH v5 0/5] get the information and data of EEPROM Thomas Monjalon
@ 2018-04-25  9:32     ` Zijie Pan
  0 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25  9:32 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev, remy.horton, ferruh.yigit

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

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v6 0/5] get the information and data of EEPROM
  2018-04-25  9:13 ` [PATCH v5 0/5] get the information and data of EEPROM Zijie Pan
                     ` (5 preceding siblings ...)
  2018-04-25  9:22   ` [PATCH v5 0/5] get the information and data of EEPROM Thomas Monjalon
@ 2018-04-25 10:01   ` Zijie Pan
  2018-04-25 10:01     ` [PATCH v6 1/5] ethdev: add access to eeprom Zijie Pan
                       ` (5 more replies)
  6 siblings, 6 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25 10:01 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas

Add APIs to read information from the DPDK applictions.
It can be used to dump the EEPROM of plugin modules (SFP+, QSFP, etc.).

Two APIs are introduced to access eeprom:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

Applications based on DPDK can dump eeprom by calling those two APIs.

Then, each PMD has to implement these callbacks for e1000, ixgbe, i40e, etc.

Patch for example/ethtool is used to test this function. It can get the raw 
data of eeprom. See below how both DPDK applications (ethtool) and Linux
kernel are dumping the same eeprom of a same NIC.

- Start example/ethtool:
    ./examples/ethtool/ethtool-app/x86_64-native-linuxapp-gcc/ethtool -c 0xf -n 4 --socket-mem 1024,0 -- -i
EthApp> drvinfo
Port 0 driver: net_ixgbe (ver: DPDK 18.05.0-rc0)
firmware-version: 0x18b30001
bus-info: 0000:04:00.0

EthApp> module-eeprom
 [UINT16]: module-eeprom <port_id> <filename>
     Dump plug-in module EEPROM to file

EthApp> module-eeprom 0 my-module-eeprom.bin
Total plug-in module EEPROM length: 512 bytes

EthApp> quit

- HexDump of this eeprom file:
# xxd my-module-eeprom.bin
0000000: 0304 0710 0000 0100 0000 0006 6702 0000  ............g...
0000010: 0803 001e 4f45 4d20 2020 2020 2020 2020  ....OEM
0000020: 2020 2020 0000 1b21 5346 502d 3130 472d      ...!SFP-10G-
0000030: 5352 2d49 5420 2020 4120 2020 0352 0024  SR-IT   A   .R.$
0000040: 003a 0000 5751 3136 3034 3132 4131 3135  .:..WQ160412A115
0000050: 2020 2020 3135 3136 3130 2020 68fa 033b      151610  h..;
0000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000f0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000100: 5000 fb00 4b00 0000 8ca0 7530 88b8 7918  P...K.....u0..y.
0000110: 1d4c 01f4 1b58 03e8 3de9 03e8 2710 04eb  .L...X..=...'...
0000120: 2710 0064 1f07 007e 0000 0000 0000 0000  '..d...~........
0000130: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000140: 0000 0000 3f80 0000 0000 0000 0100 0000  ....?...........
0000150: 0100 0000 0100 0000 0100 0000 0000 002d  ...............-
0000160: 2c59 810a 13c7 1752 0001 0000 0000 0200  ,Y.....R........
0000170: 0040 0000 0040 0000 0000 0000 0000 0000  .@...@..........
0000180: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000190: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001a0: ffff faff ffff ffff ffff ffff ffff ffff  ................
00001b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001f0: ffff ffff ffff ffff 0003 0100 0000 0000  ................

- Rerun same dump using Linux's kernel ethtool.

# ./install/sbin/dpdk-devbind --bind=ixgbe 04:00.0
# ethtool -m p2p1 raw on > meeprom-kernel.bin

# xxd meeprom-kernel.bin
0000000: 0304 0710 0000 0100 0000 0006 6702 0000  ............g...
0000010: 0803 001e 4f45 4d20 2020 2020 2020 2020  ....OEM
0000020: 2020 2020 0000 1b21 5346 502d 3130 472d      ...!SFP-10G-
0000030: 5352 2d49 5420 2020 4120 2020 0352 0024  SR-IT   A   .R.$
0000040: 003a 0000 5751 3136 3034 3132 4131 3135  .:..WQ160412A115
0000050: 2020 2020 3135 3136 3130 2020 68fa 033b      151610  h..;
0000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000f0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000100: 5000 fb00 4b00 0000 8ca0 7530 88b8 7918  P...K.....u0..y.
0000110: 1d4c 01f4 1b58 03e8 3de9 03e8 2710 04eb  .L...X..=...'...
0000120: 2710 0064 1f07 007e 0000 0000 0000 0000  '..d...~........
0000130: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000140: 0000 0000 3f80 0000 0000 0000 0100 0000  ....?...........
0000150: 0100 0000 0100 0000 0100 0000 0000 002d  ...............-
0000160: 2899 8146 0058 0001 0001 0000 0000 8200  (..F.X..........
0000170: 0540 0000 0540 0000 0000 0000 0000 0000  .@...@..........
0000180: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000190: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001a0: ffff faff ffff ffff ffff ffff ffff ffff  ................
00001b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001f0: ffff ffff ffff ffff 0003 0100 0000 0000  ................

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

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v6 1/5] ethdev: add access to eeprom
  2018-04-25 10:01   ` [PATCH v6 " Zijie Pan
@ 2018-04-25 10:01     ` Zijie Pan
  2018-04-25 10:28       ` Thomas Monjalon
  2018-04-25 10:40       ` Ferruh Yigit
  2018-04-25 10:01     ` [PATCH v6 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
                       ` (4 subsequent siblings)
  5 siblings, 2 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25 10:01 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas, john.mcnamara, marko.kovacevic

add new APIs:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: remy.horton@intel.com
Cc: john.mcnamara@intel.com
Cc: marko.kovacevic@intel.com
Cc: thomas@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 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_experimental
+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_ethdev_core.h b/lib/librte_ether/rte_ethdev_core.h
index 55eb2b0..33d12b3 100644
--- a/lib/librte_ether/rte_ethdev_core.h
+++ b/lib/librte_ether/rte_ethdev_core.h
@@ -337,6 +337,14 @@ typedef int (*eth_set_eeprom_t)(struct rte_eth_dev *dev,
 				struct rte_dev_eeprom_info *info);
 /**< @internal Program eeprom data  */
 
+typedef int (*eth_get_module_info_t)(struct rte_eth_dev *dev,
+				     struct rte_eth_dev_module_info *modinfo);
+/**< @internal Retrieve type and size of plugin module eeprom */
+
+typedef int (*eth_get_module_eeprom_t)(struct rte_eth_dev *dev,
+				       struct rte_dev_eeprom_info *info);
+/**< @internal Retrieve plugin module eeprom data */
+
 typedef int (*eth_l2_tunnel_eth_type_conf_t)
 	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel_conf *l2_tunnel);
 /**< @internal config l2 tunnel ether type */
@@ -467,6 +475,10 @@ struct eth_dev_ops {
 	eth_get_eeprom_t           get_eeprom;        /**< Get eeprom data. */
 	eth_set_eeprom_t           set_eeprom;        /**< Set eeprom. */
 
+	eth_get_module_info_t      get_module_info;
+	/** Get plugin module eeprom attribute. */
+	eth_get_module_eeprom_t    get_module_eeprom;
+	/** Get plugin module eeprom data. */
 
 	eth_filter_ctrl_t          filter_ctrl; /**< common filter control. */
 
diff --git a/lib/librte_ether/rte_ethdev_version.map b/lib/librte_ether/rte_ethdev_version.map
index 8fe0788..b8e7566 100644
--- a/lib/librte_ether/rte_ethdev_version.map
+++ b/lib/librte_ether/rte_ethdev_version.map
@@ -208,6 +208,8 @@ EXPERIMENTAL {
 
 	rte_eth_dev_count_avail;
 	rte_eth_dev_count_total;
+	rte_eth_dev_get_module_info;
+	rte_eth_dev_get_module_eeprom;
 	rte_eth_dev_is_removed;
 	rte_eth_dev_owner_delete;
 	rte_eth_dev_owner_get;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v6 2/5] examples/ethtool: add a new command module-eeprom
  2018-04-25 10:01   ` [PATCH v6 " Zijie Pan
  2018-04-25 10:01     ` [PATCH v6 1/5] ethdev: add access to eeprom Zijie Pan
@ 2018-04-25 10:01     ` Zijie Pan
  2018-04-25 10:01     ` [PATCH v6 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
                       ` (3 subsequent siblings)
  5 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25 10:01 UTC (permalink / raw)
  To: dev
  Cc: remy.horton, ferruh.yigit, thomas, orika, bruce.richardson,
	pablo.de.lara.guarch, radu.nicolau, akhil.goyal, tomasz.kantecki,
	john.mcnamara, marko.kovacevic

Add a new command "module-eeprom" to get the data of plugin
module EEPROM.

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: remy.horton@intel.com
Cc: orika@mellanox.com
Cc: bruce.richardson@intel.com
Cc: pablo.de.lara.guarch@intel.com
Cc: radu.nicolau@intel.com
Cc: akhil.goyal@nxp.com
Cc: tomasz.kantecki@intel.com
Cc: john.mcnamara@intel.com
Cc: marko.kovacevic@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 <port_id> <filename>\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/Makefile b/examples/ethtool/lib/Makefile
index fbafa6d..2576910 100644
--- a/examples/ethtool/lib/Makefile
+++ b/examples/ethtool/lib/Makefile
@@ -25,6 +25,7 @@ SRCS-y := rte_ethtool.c
 
 CFLAGS += -O3
 CFLAGS += $(WERROR_FLAGS)
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 
 ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
 ifeq ($(CONFIG_RTE_LIBRTE_IXGBE_PMD),y)
diff --git a/examples/ethtool/lib/rte_ethtool.c b/examples/ethtool/lib/rte_ethtool.c
index d519a50..e6a2e88 100644
--- a/examples/ethtool/lib/rte_ethtool.c
+++ b/examples/ethtool/lib/rte_ethtool.c
@@ -178,6 +178,36 @@
 }
 
 int
+rte_ethtool_get_module_info(uint16_t port_id, uint32_t *modinfo)
+{
+	struct rte_eth_dev_module_info *info;
+
+	info = (struct rte_eth_dev_module_info *)modinfo;
+	return rte_eth_dev_get_module_info(port_id, info);
+}
+
+int
+rte_ethtool_get_module_eeprom(uint16_t port_id, struct ethtool_eeprom *eeprom,
+	void *words)
+{
+	struct rte_dev_eeprom_info eeprom_info;
+	int status;
+
+	if (eeprom == NULL || words == NULL)
+		return -EINVAL;
+
+	eeprom_info.offset = eeprom->offset;
+	eeprom_info.length = eeprom->len;
+	eeprom_info.data = words;
+
+	status = rte_eth_dev_get_module_eeprom(port_id, &eeprom_info);
+	if (status)
+		return status;
+
+	return 0;
+}
+
+int
 rte_ethtool_get_pauseparam(uint16_t port_id,
 	struct ethtool_pauseparam *pause_param)
 {
diff --git a/examples/ethtool/lib/rte_ethtool.h b/examples/ethtool/lib/rte_ethtool.h
index c962396..43adc97 100644
--- a/examples/ethtool/lib/rte_ethtool.h
+++ b/examples/ethtool/lib/rte_ethtool.h
@@ -154,6 +154,40 @@ int rte_ethtool_set_eeprom(uint16_t port_id, struct ethtool_eeprom *eeprom,
 			      void *words);
 
 /**
+ * Retrieve the type and size of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param modinfo
+ *	 The pointer that provides the type and size of plugin module EEPROM.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - others depends on the specific operations implementation.
+ */
+int rte_ethtool_get_module_info(uint16_t port_id, uint32_t *modinfo);
+
+/**
+ * Retrieve the data of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param eeprom
+ *	 The pointer of ethtool_eeprom that provides plugin module eeprom
+ *   offset and length
+ * @param words
+ *	 A buffer that holds data read from plugin module eeprom
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - others depends on the specific operations implementation.
+ */
+int rte_ethtool_get_module_eeprom(uint16_t port_id,
+				  struct ethtool_eeprom *eeprom, void *words);
+
+/**
  * Retrieve the Ethernet device pause frame configuration according to
  * parameter attributes desribed by ethtool data structure,
  * ethtool_pauseparam.
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v6 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe
  2018-04-25 10:01   ` [PATCH v6 " Zijie Pan
  2018-04-25 10:01     ` [PATCH v6 1/5] ethdev: add access to eeprom Zijie Pan
  2018-04-25 10:01     ` [PATCH v6 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
@ 2018-04-25 10:01     ` Zijie Pan
  2018-04-25 10:44       ` Ferruh Yigit
  2018-04-25 10:01     ` [PATCH v6 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
                       ` (2 subsequent siblings)
  5 siblings, 1 reply; 25+ messages in thread
From: Zijie Pan @ 2018-04-25 10:01 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas, wenzhuo.lu, konstantin.ananyev

Add new callbacks for eth_dev_ops of ixgbe to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: remy.horton@intel.com
Cc: wenzhuo.lu@intel.com
Cc: konstantin.ananyev@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

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v6 4/5] net/e1000: add module EEPROM callbacks for e1000
  2018-04-25 10:01   ` [PATCH v6 " Zijie Pan
                       ` (2 preceding siblings ...)
  2018-04-25 10:01     ` [PATCH v6 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
@ 2018-04-25 10:01     ` Zijie Pan
  2018-04-25 10:01     ` [PATCH v6 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
  2018-04-25 14:02     ` [PATCH v7 0/5] get the information and data of EEPROM Zijie Pan
  5 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25 10:01 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas, wenzhuo.lu

Add new callbacks for eth_dev_ops of e1000 to get the information and
data of plugin module EEPROM.

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: wenzhuo.lu@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_MODE	0x4
+#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 = e1000_read_phy_reg_i2c(hw, (first_word + i) * 2,
+						&dataword[i]);
+		if (status) {
+			/* Error occurred while reading module */
+			return -EIO;
+		}
+
+		dataword[i] = rte_be_to_cpu_16(dataword[i]);
+	}
+
+	memcpy(info->data, (u8 *)dataword + (info->offset & 1), info->length);
+
+	return 0;
+}
+
+static int
 eth_igb_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 {
 	struct e1000_hw *hw =
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v6 5/5] net/i40e: add module EEPROM callbacks for i40e
  2018-04-25 10:01   ` [PATCH v6 " Zijie Pan
                       ` (3 preceding siblings ...)
  2018-04-25 10:01     ` [PATCH v6 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
@ 2018-04-25 10:01     ` Zijie Pan
  2018-04-25 14:02     ` [PATCH v7 0/5] get the information and data of EEPROM Zijie Pan
  5 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25 10:01 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas, beilei.xing, qi.z.zhang

Add new callbacks for eth_dev_ops of i40e to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: beilei.xing@intel.com
Cc: qi.z.zhang@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_EXTERNAL_MODULE,
+				0,
+				I40E_MODULE_REVISION_ADDR,
+				&sff8636_rev, NULL);
+		if (status)
+			return -EIO;
+		/* Determine revision compliance byte */
+		if (sff8636_rev > 0x02) {
+			/* Module is SFF-8636 compliant */
+			modinfo->type = RTE_ETH_MODULE_SFF_8636;
+			modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+		} else {
+			modinfo->type = RTE_ETH_MODULE_SFF_8436;
+			modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+		}
+		break;
+	case I40E_MODULE_TYPE_QSFP28:
+		modinfo->type = RTE_ETH_MODULE_SFF_8636;
+		modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Module type unrecognized\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int i40e_get_module_eeprom(struct rte_eth_dev *dev,
+				  struct rte_dev_eeprom_info *info)
+{
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	bool is_sfp = false;
+	i40e_status status;
+	uint8_t *data = info->data;
+	uint32_t value = 0;
+	uint32_t i;
+
+	if (!info || !info->length || !data)
+		return -EINVAL;
+
+	if (hw->phy.link_info.module_type[0] == I40E_MODULE_TYPE_SFP)
+		is_sfp = true;
+
+	for (i = 0; i < info->length; i++) {
+		u32 offset = i + info->offset;
+		u32 addr = is_sfp ? I40E_I2C_EEPROM_DEV_ADDR : 0;
+
+		/* Check if we need to access the other memory page */
+		if (is_sfp) {
+			if (offset >= RTE_ETH_MODULE_SFF_8079_LEN) {
+				offset -= RTE_ETH_MODULE_SFF_8079_LEN;
+				addr = I40E_I2C_EEPROM_DEV_ADDR2;
+			}
+		} else {
+			while (offset >= RTE_ETH_MODULE_SFF_8436_LEN) {
+				/* Compute memory page number and offset. */
+				offset -= RTE_ETH_MODULE_SFF_8436_LEN / 2;
+				addr++;
+			}
+		}
+		status = i40e_aq_get_phy_register(hw,
+				I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+				addr, offset, &value, NULL);
+		if (status)
+			return -EIO;
+		data[i] = (uint8_t)value;
+	}
+	return 0;
+}
+
 static int i40e_set_default_mac_addr(struct rte_eth_dev *dev,
 				     struct ether_addr *mac_addr)
 {
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 1/5] ethdev: add access to eeprom
  2018-04-25 10:01     ` [PATCH v6 1/5] ethdev: add access to eeprom Zijie Pan
@ 2018-04-25 10:28       ` Thomas Monjalon
  2018-04-25 10:40       ` Ferruh Yigit
  1 sibling, 0 replies; 25+ messages in thread
From: Thomas Monjalon @ 2018-04-25 10:28 UTC (permalink / raw)
  To: Zijie Pan; +Cc: dev, remy.horton, ferruh.yigit, john.mcnamara, marko.kovacevic

25/04/2018 12:01, Zijie Pan:
> add new APIs:
> - rte_eth_dev_get_module_info
> - rte_eth_dev_get_module_eeprom
> 
> Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
> Acked-by: Remy Horton <remy.horton@intel.com>

Acked-by: Thomas Monjalon <thomas@monjalon.net>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 1/5] ethdev: add access to eeprom
  2018-04-25 10:01     ` [PATCH v6 1/5] ethdev: add access to eeprom Zijie Pan
  2018-04-25 10:28       ` Thomas Monjalon
@ 2018-04-25 10:40       ` Ferruh Yigit
  1 sibling, 0 replies; 25+ messages in thread
From: Ferruh Yigit @ 2018-04-25 10:40 UTC (permalink / raw)
  To: Zijie Pan, dev; +Cc: remy.horton, thomas, john.mcnamara, marko.kovacevic

On 4/25/2018 11:01 AM, Zijie Pan wrote:
> add new APIs:
> - rte_eth_dev_get_module_info
> - rte_eth_dev_get_module_eeprom
> 
> Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
> Acked-by: Remy Horton <remy.horton@intel.com>
> ---
> Cc: remy.horton@intel.com
> Cc: john.mcnamara@intel.com
> Cc: marko.kovacevic@intel.com
> Cc: thomas@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()``.
> +
> +

New feature added also needs to be added default.ini file, please replace this
feature somewhere close the related features in default.ini

And please keep Thomas' Ack for next version

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe
  2018-04-25 10:01     ` [PATCH v6 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
@ 2018-04-25 10:44       ` Ferruh Yigit
  0 siblings, 0 replies; 25+ messages in thread
From: Ferruh Yigit @ 2018-04-25 10:44 UTC (permalink / raw)
  To: Zijie Pan, dev; +Cc: remy.horton, thomas, wenzhuo.lu, konstantin.ananyev

On 4/25/2018 11:01 AM, Zijie Pan wrote:
> Add new callbacks for eth_dev_ops of ixgbe to get the information
> and data of plugin module eeprom.
> 
> Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
> Acked-by: Remy Horton <remy.horton@intel.com>
> ---
> Cc: remy.horton@intel.com
> Cc: wenzhuo.lu@intel.com
> Cc: konstantin.ananyev@intel.com
> 
>  drivers/net/ixgbe/ixgbe_ethdev.c |   79 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 79 insertions(+)

For all three PMDs, please update their .ini file [1] (in their corresponding
patches) to announce this new feature they support. The order should be same
with default.ini file

[1]
doc/guides/nics/features/ixgbe.ini
doc/guides/nics/features/ixgbe_vec.ini
doc/guides/nics/features/ixgbe_vf.ini
doc/guides/nics/features/ixgbe_vf_vec.ini
doc/guides/nics/features/i40e.ini
doc/guides/nics/features/i40e_vec.ini
doc/guides/nics/features/i40e_vf.ini
doc/guides/nics/features/i40e_vf_vec.ini
doc/guides/nics/features/igb.ini
doc/guides/nics/features/igb_vf.ini
doc/guides/nics/features/e1000.ini

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v7 0/5] get the information and data of EEPROM
  2018-04-25 10:01   ` [PATCH v6 " Zijie Pan
                       ` (4 preceding siblings ...)
  2018-04-25 10:01     ` [PATCH v6 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
@ 2018-04-25 14:02     ` Zijie Pan
  2018-04-25 14:02       ` [PATCH v7 1/5] ethdev: add access to eeprom Zijie Pan
                         ` (5 more replies)
  5 siblings, 6 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25 14:02 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas

Add APIs to read information from the DPDK applictions.
It can be used to dump the EEPROM of plugin modules (SFP+, QSFP, etc.).

Two APIs are introduced to access eeprom:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

Applications based on DPDK can dump eeprom by calling those two APIs.

Then, each PMD has to implement these callbacks for e1000, ixgbe, i40e, etc.

Patch for example/ethtool is used to test this function. It can get the raw 
data of eeprom. See below how both DPDK applications (ethtool) and Linux
kernel are dumping the same eeprom of a same NIC.

- Start example/ethtool:
    ./examples/ethtool/ethtool-app/x86_64-native-linuxapp-gcc/ethtool -c 0xf -n 4 --socket-mem 1024,0 -- -i
EthApp> drvinfo
Port 0 driver: net_ixgbe (ver: DPDK 18.05.0-rc0)
firmware-version: 0x18b30001
bus-info: 0000:04:00.0

EthApp> module-eeprom
 [UINT16]: module-eeprom <port_id> <filename>
     Dump plug-in module EEPROM to file

EthApp> module-eeprom 0 my-module-eeprom.bin
Total plug-in module EEPROM length: 512 bytes

EthApp> quit

- HexDump of this eeprom file:
# xxd my-module-eeprom.bin
0000000: 0304 0710 0000 0100 0000 0006 6702 0000  ............g...
0000010: 0803 001e 4f45 4d20 2020 2020 2020 2020  ....OEM
0000020: 2020 2020 0000 1b21 5346 502d 3130 472d      ...!SFP-10G-
0000030: 5352 2d49 5420 2020 4120 2020 0352 0024  SR-IT   A   .R.$
0000040: 003a 0000 5751 3136 3034 3132 4131 3135  .:..WQ160412A115
0000050: 2020 2020 3135 3136 3130 2020 68fa 033b      151610  h..;
0000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000f0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000100: 5000 fb00 4b00 0000 8ca0 7530 88b8 7918  P...K.....u0..y.
0000110: 1d4c 01f4 1b58 03e8 3de9 03e8 2710 04eb  .L...X..=...'...
0000120: 2710 0064 1f07 007e 0000 0000 0000 0000  '..d...~........
0000130: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000140: 0000 0000 3f80 0000 0000 0000 0100 0000  ....?...........
0000150: 0100 0000 0100 0000 0100 0000 0000 002d  ...............-
0000160: 2c59 810a 13c7 1752 0001 0000 0000 0200  ,Y.....R........
0000170: 0040 0000 0040 0000 0000 0000 0000 0000  .@...@..........
0000180: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000190: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001a0: ffff faff ffff ffff ffff ffff ffff ffff  ................
00001b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001f0: ffff ffff ffff ffff 0003 0100 0000 0000  ................

- Rerun same dump using Linux's kernel ethtool.

# ./install/sbin/dpdk-devbind --bind=ixgbe 04:00.0
# ethtool -m p2p1 raw on > meeprom-kernel.bin

# xxd meeprom-kernel.bin
0000000: 0304 0710 0000 0100 0000 0006 6702 0000  ............g...
0000010: 0803 001e 4f45 4d20 2020 2020 2020 2020  ....OEM
0000020: 2020 2020 0000 1b21 5346 502d 3130 472d      ...!SFP-10G-
0000030: 5352 2d49 5420 2020 4120 2020 0352 0024  SR-IT   A   .R.$
0000040: 003a 0000 5751 3136 3034 3132 4131 3135  .:..WQ160412A115
0000050: 2020 2020 3135 3136 3130 2020 68fa 033b      151610  h..;
0000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000f0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000100: 5000 fb00 4b00 0000 8ca0 7530 88b8 7918  P...K.....u0..y.
0000110: 1d4c 01f4 1b58 03e8 3de9 03e8 2710 04eb  .L...X..=...'...
0000120: 2710 0064 1f07 007e 0000 0000 0000 0000  '..d...~........
0000130: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000140: 0000 0000 3f80 0000 0000 0000 0100 0000  ....?...........
0000150: 0100 0000 0100 0000 0100 0000 0000 002d  ...............-
0000160: 2899 8146 0058 0001 0001 0000 0000 8200  (..F.X..........
0000170: 0540 0000 0540 0000 0000 0000 0000 0000  .@...@..........
0000180: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000190: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001a0: ffff faff ffff ffff ffff ffff ffff ffff  ................
00001b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00001f0: ffff ffff ffff ffff 0003 0100 0000 0000  ................

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

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v7 1/5] ethdev: add access to eeprom
  2018-04-25 14:02     ` [PATCH v7 0/5] get the information and data of EEPROM Zijie Pan
@ 2018-04-25 14:02       ` Zijie Pan
  2018-04-25 14:02       ` [PATCH v7 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
                         ` (4 subsequent siblings)
  5 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25 14:02 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas, john.mcnamara, marko.kovacevic

add new APIs:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
Acked-by: Thomas Monjalon <thomas@monjalon.net>
---
Cc: remy.horton@intel.com
Cc: john.mcnamara@intel.com
Cc: marko.kovacevic@intel.com
Cc: thomas@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 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 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_experimental
+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_ethdev_core.h b/lib/librte_ether/rte_ethdev_core.h
index 55eb2b0..33d12b3 100644
--- a/lib/librte_ether/rte_ethdev_core.h
+++ b/lib/librte_ether/rte_ethdev_core.h
@@ -337,6 +337,14 @@ typedef int (*eth_set_eeprom_t)(struct rte_eth_dev *dev,
 				struct rte_dev_eeprom_info *info);
 /**< @internal Program eeprom data  */
 
+typedef int (*eth_get_module_info_t)(struct rte_eth_dev *dev,
+				     struct rte_eth_dev_module_info *modinfo);
+/**< @internal Retrieve type and size of plugin module eeprom */
+
+typedef int (*eth_get_module_eeprom_t)(struct rte_eth_dev *dev,
+				       struct rte_dev_eeprom_info *info);
+/**< @internal Retrieve plugin module eeprom data */
+
 typedef int (*eth_l2_tunnel_eth_type_conf_t)
 	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel_conf *l2_tunnel);
 /**< @internal config l2 tunnel ether type */
@@ -467,6 +475,10 @@ struct eth_dev_ops {
 	eth_get_eeprom_t           get_eeprom;        /**< Get eeprom data. */
 	eth_set_eeprom_t           set_eeprom;        /**< Set eeprom. */
 
+	eth_get_module_info_t      get_module_info;
+	/** Get plugin module eeprom attribute. */
+	eth_get_module_eeprom_t    get_module_eeprom;
+	/** Get plugin module eeprom data. */
 
 	eth_filter_ctrl_t          filter_ctrl; /**< common filter control. */
 
diff --git a/lib/librte_ether/rte_ethdev_version.map b/lib/librte_ether/rte_ethdev_version.map
index 8fe0788..b8e7566 100644
--- a/lib/librte_ether/rte_ethdev_version.map
+++ b/lib/librte_ether/rte_ethdev_version.map
@@ -208,6 +208,8 @@ EXPERIMENTAL {
 
 	rte_eth_dev_count_avail;
 	rte_eth_dev_count_total;
+	rte_eth_dev_get_module_info;
+	rte_eth_dev_get_module_eeprom;
 	rte_eth_dev_is_removed;
 	rte_eth_dev_owner_delete;
 	rte_eth_dev_owner_get;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v7 2/5] examples/ethtool: add a new command module-eeprom
  2018-04-25 14:02     ` [PATCH v7 0/5] get the information and data of EEPROM Zijie Pan
  2018-04-25 14:02       ` [PATCH v7 1/5] ethdev: add access to eeprom Zijie Pan
@ 2018-04-25 14:02       ` Zijie Pan
  2018-04-25 14:02       ` [PATCH v7 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
                         ` (3 subsequent siblings)
  5 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25 14:02 UTC (permalink / raw)
  To: dev
  Cc: remy.horton, ferruh.yigit, thomas, orika, bruce.richardson,
	pablo.de.lara.guarch, radu.nicolau, akhil.goyal, tomasz.kantecki,
	john.mcnamara, marko.kovacevic

Add a new command "module-eeprom" to get the data of plugin
module EEPROM.

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: remy.horton@intel.com
Cc: orika@mellanox.com
Cc: bruce.richardson@intel.com
Cc: pablo.de.lara.guarch@intel.com
Cc: radu.nicolau@intel.com
Cc: akhil.goyal@nxp.com
Cc: tomasz.kantecki@intel.com
Cc: john.mcnamara@intel.com
Cc: marko.kovacevic@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 <port_id> <filename>\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/Makefile b/examples/ethtool/lib/Makefile
index fbafa6d..2576910 100644
--- a/examples/ethtool/lib/Makefile
+++ b/examples/ethtool/lib/Makefile
@@ -25,6 +25,7 @@ SRCS-y := rte_ethtool.c
 
 CFLAGS += -O3
 CFLAGS += $(WERROR_FLAGS)
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 
 ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
 ifeq ($(CONFIG_RTE_LIBRTE_IXGBE_PMD),y)
diff --git a/examples/ethtool/lib/rte_ethtool.c b/examples/ethtool/lib/rte_ethtool.c
index d519a50..e6a2e88 100644
--- a/examples/ethtool/lib/rte_ethtool.c
+++ b/examples/ethtool/lib/rte_ethtool.c
@@ -178,6 +178,36 @@
 }
 
 int
+rte_ethtool_get_module_info(uint16_t port_id, uint32_t *modinfo)
+{
+	struct rte_eth_dev_module_info *info;
+
+	info = (struct rte_eth_dev_module_info *)modinfo;
+	return rte_eth_dev_get_module_info(port_id, info);
+}
+
+int
+rte_ethtool_get_module_eeprom(uint16_t port_id, struct ethtool_eeprom *eeprom,
+	void *words)
+{
+	struct rte_dev_eeprom_info eeprom_info;
+	int status;
+
+	if (eeprom == NULL || words == NULL)
+		return -EINVAL;
+
+	eeprom_info.offset = eeprom->offset;
+	eeprom_info.length = eeprom->len;
+	eeprom_info.data = words;
+
+	status = rte_eth_dev_get_module_eeprom(port_id, &eeprom_info);
+	if (status)
+		return status;
+
+	return 0;
+}
+
+int
 rte_ethtool_get_pauseparam(uint16_t port_id,
 	struct ethtool_pauseparam *pause_param)
 {
diff --git a/examples/ethtool/lib/rte_ethtool.h b/examples/ethtool/lib/rte_ethtool.h
index c962396..43adc97 100644
--- a/examples/ethtool/lib/rte_ethtool.h
+++ b/examples/ethtool/lib/rte_ethtool.h
@@ -154,6 +154,40 @@ int rte_ethtool_set_eeprom(uint16_t port_id, struct ethtool_eeprom *eeprom,
 			      void *words);
 
 /**
+ * Retrieve the type and size of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param modinfo
+ *	 The pointer that provides the type and size of plugin module EEPROM.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - others depends on the specific operations implementation.
+ */
+int rte_ethtool_get_module_info(uint16_t port_id, uint32_t *modinfo);
+
+/**
+ * Retrieve the data of plugin module EEPROM
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param eeprom
+ *	 The pointer of ethtool_eeprom that provides plugin module eeprom
+ *   offset and length
+ * @param words
+ *	 A buffer that holds data read from plugin module eeprom
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - others depends on the specific operations implementation.
+ */
+int rte_ethtool_get_module_eeprom(uint16_t port_id,
+				  struct ethtool_eeprom *eeprom, void *words);
+
+/**
  * Retrieve the Ethernet device pause frame configuration according to
  * parameter attributes desribed by ethtool data structure,
  * ethtool_pauseparam.
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v7 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe
  2018-04-25 14:02     ` [PATCH v7 0/5] get the information and data of EEPROM Zijie Pan
  2018-04-25 14:02       ` [PATCH v7 1/5] ethdev: add access to eeprom Zijie Pan
  2018-04-25 14:02       ` [PATCH v7 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
@ 2018-04-25 14:02       ` Zijie Pan
  2018-04-25 14:02       ` [PATCH v7 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
                         ` (2 subsequent siblings)
  5 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25 14:02 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas, wenzhuo.lu, konstantin.ananyev

Add new callbacks for eth_dev_ops of ixgbe to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: remy.horton@intel.com
Cc: wenzhuo.lu@intel.com
Cc: konstantin.ananyev@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;
+	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

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v7 4/5] net/e1000: add module EEPROM callbacks for e1000
  2018-04-25 14:02     ` [PATCH v7 0/5] get the information and data of EEPROM Zijie Pan
                         ` (2 preceding siblings ...)
  2018-04-25 14:02       ` [PATCH v7 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
@ 2018-04-25 14:02       ` Zijie Pan
  2018-04-25 14:02       ` [PATCH v7 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
  2018-04-25 14:24       ` [PATCH v7 0/5] get the information and data of EEPROM Ferruh Yigit
  5 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25 14:02 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas, wenzhuo.lu

Add new callbacks for eth_dev_ops of e1000 to get the information and
data of plugin module EEPROM.

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: wenzhuo.lu@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_MODE	0x4
+#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 = e1000_read_phy_reg_i2c(hw, (first_word + i) * 2,
+						&dataword[i]);
+		if (status) {
+			/* Error occurred while reading module */
+			return -EIO;
+		}
+
+		dataword[i] = rte_be_to_cpu_16(dataword[i]);
+	}
+
+	memcpy(info->data, (u8 *)dataword + (info->offset & 1), info->length);
+
+	return 0;
+}
+
+static int
 eth_igb_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 {
 	struct e1000_hw *hw =
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v7 5/5] net/i40e: add module EEPROM callbacks for i40e
  2018-04-25 14:02     ` [PATCH v7 0/5] get the information and data of EEPROM Zijie Pan
                         ` (3 preceding siblings ...)
  2018-04-25 14:02       ` [PATCH v7 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
@ 2018-04-25 14:02       ` Zijie Pan
  2018-04-25 14:24       ` [PATCH v7 0/5] get the information and data of EEPROM Ferruh Yigit
  5 siblings, 0 replies; 25+ messages in thread
From: Zijie Pan @ 2018-04-25 14:02 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, ferruh.yigit, thomas, beilei.xing, qi.z.zhang

Add new callbacks for eth_dev_ops of i40e to get the information
and data of plugin module eeprom.

Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
Cc: beilei.xing@intel.com
Cc: qi.z.zhang@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 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,
+				0,
+				I40E_MODULE_REVISION_ADDR,
+				&sff8636_rev, NULL);
+		if (status)
+			return -EIO;
+		/* Determine revision compliance byte */
+		if (sff8636_rev > 0x02) {
+			/* Module is SFF-8636 compliant */
+			modinfo->type = RTE_ETH_MODULE_SFF_8636;
+			modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+		} else {
+			modinfo->type = RTE_ETH_MODULE_SFF_8436;
+			modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+		}
+		break;
+	case I40E_MODULE_TYPE_QSFP28:
+		modinfo->type = RTE_ETH_MODULE_SFF_8636;
+		modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Module type unrecognized\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int i40e_get_module_eeprom(struct rte_eth_dev *dev,
+				  struct rte_dev_eeprom_info *info)
+{
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	bool is_sfp = false;
+	i40e_status status;
+	uint8_t *data = info->data;
+	uint32_t value = 0;
+	uint32_t i;
+
+	if (!info || !info->length || !data)
+		return -EINVAL;
+
+	if (hw->phy.link_info.module_type[0] == I40E_MODULE_TYPE_SFP)
+		is_sfp = true;
+
+	for (i = 0; i < info->length; i++) {
+		u32 offset = i + info->offset;
+		u32 addr = is_sfp ? I40E_I2C_EEPROM_DEV_ADDR : 0;
+
+		/* Check if we need to access the other memory page */
+		if (is_sfp) {
+			if (offset >= RTE_ETH_MODULE_SFF_8079_LEN) {
+				offset -= RTE_ETH_MODULE_SFF_8079_LEN;
+				addr = I40E_I2C_EEPROM_DEV_ADDR2;
+			}
+		} else {
+			while (offset >= RTE_ETH_MODULE_SFF_8436_LEN) {
+				/* Compute memory page number and offset. */
+				offset -= RTE_ETH_MODULE_SFF_8436_LEN / 2;
+				addr++;
+			}
+		}
+		status = i40e_aq_get_phy_register(hw,
+				I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+				addr, offset, &value, NULL);
+		if (status)
+			return -EIO;
+		data[i] = (uint8_t)value;
+	}
+	return 0;
+}
+
 static int i40e_set_default_mac_addr(struct rte_eth_dev *dev,
 				     struct ether_addr *mac_addr)
 {
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH v7 0/5] get the information and data of EEPROM
  2018-04-25 14:02     ` [PATCH v7 0/5] get the information and data of EEPROM Zijie Pan
                         ` (4 preceding siblings ...)
  2018-04-25 14:02       ` [PATCH v7 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
@ 2018-04-25 14:24       ` Ferruh Yigit
  2018-04-25 14:39         ` Ferruh Yigit
  5 siblings, 1 reply; 25+ messages in thread
From: Ferruh Yigit @ 2018-04-25 14:24 UTC (permalink / raw)
  To: Zijie Pan, dev; +Cc: remy.horton, thomas

On 4/25/2018 3:02 PM, Zijie Pan wrote:
> Add APIs to read information from the DPDK applictions.
> It can be used to dump the EEPROM of plugin modules (SFP+, QSFP, etc.).
> 
> Two APIs are introduced to access eeprom:
> - rte_eth_dev_get_module_info
> - rte_eth_dev_get_module_eeprom
> 
> Applications based on DPDK can dump eeprom by calling those two APIs.
> 
> Then, each PMD has to implement these callbacks for e1000, ixgbe, i40e, etc.
> 
> Patch for example/ethtool is used to test this function. It can get the raw 
> data of eeprom. See below how both DPDK applications (ethtool) and Linux
> kernel are dumping the same eeprom of a same NIC.
> 
> - Start example/ethtool:
>     ./examples/ethtool/ethtool-app/x86_64-native-linuxapp-gcc/ethtool -c 0xf -n 4 --socket-mem 1024,0 -- -i
> EthApp> drvinfo
> Port 0 driver: net_ixgbe (ver: DPDK 18.05.0-rc0)
> firmware-version: 0x18b30001
> bus-info: 0000:04:00.0
> 
> EthApp> module-eeprom
>  [UINT16]: module-eeprom <port_id> <filename>
>      Dump plug-in module EEPROM to file
> 
> EthApp> module-eeprom 0 my-module-eeprom.bin
> Total plug-in module EEPROM length: 512 bytes
> 
> EthApp> quit
> 
> - HexDump of this eeprom file:
> # xxd my-module-eeprom.bin
> 0000000: 0304 0710 0000 0100 0000 0006 6702 0000  ............g...
> 0000010: 0803 001e 4f45 4d20 2020 2020 2020 2020  ....OEM
> 0000020: 2020 2020 0000 1b21 5346 502d 3130 472d      ...!SFP-10G-
> 0000030: 5352 2d49 5420 2020 4120 2020 0352 0024  SR-IT   A   .R.$
> 0000040: 003a 0000 5751 3136 3034 3132 4131 3135  .:..WQ160412A115
> 0000050: 2020 2020 3135 3136 3130 2020 68fa 033b      151610  h..;
> 0000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
> 0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
> 0000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 0000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00000c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00000d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00000e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00000f0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 0000100: 5000 fb00 4b00 0000 8ca0 7530 88b8 7918  P...K.....u0..y.
> 0000110: 1d4c 01f4 1b58 03e8 3de9 03e8 2710 04eb  .L...X..=...'...
> 0000120: 2710 0064 1f07 007e 0000 0000 0000 0000  '..d...~........
> 0000130: 0000 0000 0000 0000 0000 0000 0000 0000  ................
> 0000140: 0000 0000 3f80 0000 0000 0000 0100 0000  ....?...........
> 0000150: 0100 0000 0100 0000 0100 0000 0000 002d  ...............-
> 0000160: 2c59 810a 13c7 1752 0001 0000 0000 0200  ,Y.....R........
> 0000170: 0040 0000 0040 0000 0000 0000 0000 0000  .@...@..........
> 0000180: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 0000190: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00001a0: ffff faff ffff ffff ffff ffff ffff ffff  ................
> 00001b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00001c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00001d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00001e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00001f0: ffff ffff ffff ffff 0003 0100 0000 0000  ................
> 
> - Rerun same dump using Linux's kernel ethtool.
> 
> # ./install/sbin/dpdk-devbind --bind=ixgbe 04:00.0
> # ethtool -m p2p1 raw on > meeprom-kernel.bin
> 
> # xxd meeprom-kernel.bin
> 0000000: 0304 0710 0000 0100 0000 0006 6702 0000  ............g...
> 0000010: 0803 001e 4f45 4d20 2020 2020 2020 2020  ....OEM
> 0000020: 2020 2020 0000 1b21 5346 502d 3130 472d      ...!SFP-10G-
> 0000030: 5352 2d49 5420 2020 4120 2020 0352 0024  SR-IT   A   .R.$
> 0000040: 003a 0000 5751 3136 3034 3132 4131 3135  .:..WQ160412A115
> 0000050: 2020 2020 3135 3136 3130 2020 68fa 033b      151610  h..;
> 0000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
> 0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
> 0000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 0000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00000c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00000d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00000e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00000f0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 0000100: 5000 fb00 4b00 0000 8ca0 7530 88b8 7918  P...K.....u0..y.
> 0000110: 1d4c 01f4 1b58 03e8 3de9 03e8 2710 04eb  .L...X..=...'...
> 0000120: 2710 0064 1f07 007e 0000 0000 0000 0000  '..d...~........
> 0000130: 0000 0000 0000 0000 0000 0000 0000 0000  ................
> 0000140: 0000 0000 3f80 0000 0000 0000 0100 0000  ....?...........
> 0000150: 0100 0000 0100 0000 0100 0000 0000 002d  ...............-
> 0000160: 2899 8146 0058 0001 0001 0000 0000 8200  (..F.X..........
> 0000170: 0540 0000 0540 0000 0000 0000 0000 0000  .@...@..........
> 0000180: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 0000190: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00001a0: ffff faff ffff ffff ffff ffff ffff ffff  ................
> 00001b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00001c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00001d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00001e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
> 00001f0: ffff ffff ffff ffff 0003 0100 0000 0000  ................
> 
> 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

For series,
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v7 0/5] get the information and data of EEPROM
  2018-04-25 14:24       ` [PATCH v7 0/5] get the information and data of EEPROM Ferruh Yigit
@ 2018-04-25 14:39         ` Ferruh Yigit
  0 siblings, 0 replies; 25+ messages in thread
From: Ferruh Yigit @ 2018-04-25 14:39 UTC (permalink / raw)
  To: Zijie Pan, dev; +Cc: remy.horton, thomas

On 4/25/2018 3:24 PM, Ferruh Yigit wrote:
> On 4/25/2018 3:02 PM, Zijie Pan wrote:
>> Add APIs to read information from the DPDK applictions.
>> It can be used to dump the EEPROM of plugin modules (SFP+, QSFP, etc.).
>>
>> Two APIs are introduced to access eeprom:
>> - rte_eth_dev_get_module_info
>> - rte_eth_dev_get_module_eeprom
>>
>> Applications based on DPDK can dump eeprom by calling those two APIs.
>>
>> Then, each PMD has to implement these callbacks for e1000, ixgbe, i40e, etc.
>>
>> Patch for example/ethtool is used to test this function. It can get the raw 
>> data of eeprom. See below how both DPDK applications (ethtool) and Linux
>> kernel are dumping the same eeprom of a same NIC.
>>
>> - Start example/ethtool:
>>     ./examples/ethtool/ethtool-app/x86_64-native-linuxapp-gcc/ethtool -c 0xf -n 4 --socket-mem 1024,0 -- -i
>> EthApp> drvinfo
>> Port 0 driver: net_ixgbe (ver: DPDK 18.05.0-rc0)
>> firmware-version: 0x18b30001
>> bus-info: 0000:04:00.0
>>
>> EthApp> module-eeprom
>>  [UINT16]: module-eeprom <port_id> <filename>
>>      Dump plug-in module EEPROM to file
>>
>> EthApp> module-eeprom 0 my-module-eeprom.bin
>> Total plug-in module EEPROM length: 512 bytes
>>
>> EthApp> quit
>>
>> - HexDump of this eeprom file:
>> # xxd my-module-eeprom.bin
>> 0000000: 0304 0710 0000 0100 0000 0006 6702 0000  ............g...
>> 0000010: 0803 001e 4f45 4d20 2020 2020 2020 2020  ....OEM
>> 0000020: 2020 2020 0000 1b21 5346 502d 3130 472d      ...!SFP-10G-
>> 0000030: 5352 2d49 5420 2020 4120 2020 0352 0024  SR-IT   A   .R.$
>> 0000040: 003a 0000 5751 3136 3034 3132 4131 3135  .:..WQ160412A115
>> 0000050: 2020 2020 3135 3136 3130 2020 68fa 033b      151610  h..;
>> 0000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
>> 0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
>> 0000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 0000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00000c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00000d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00000e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00000f0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 0000100: 5000 fb00 4b00 0000 8ca0 7530 88b8 7918  P...K.....u0..y.
>> 0000110: 1d4c 01f4 1b58 03e8 3de9 03e8 2710 04eb  .L...X..=...'...
>> 0000120: 2710 0064 1f07 007e 0000 0000 0000 0000  '..d...~........
>> 0000130: 0000 0000 0000 0000 0000 0000 0000 0000  ................
>> 0000140: 0000 0000 3f80 0000 0000 0000 0100 0000  ....?...........
>> 0000150: 0100 0000 0100 0000 0100 0000 0000 002d  ...............-
>> 0000160: 2c59 810a 13c7 1752 0001 0000 0000 0200  ,Y.....R........
>> 0000170: 0040 0000 0040 0000 0000 0000 0000 0000  .@...@..........
>> 0000180: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 0000190: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00001a0: ffff faff ffff ffff ffff ffff ffff ffff  ................
>> 00001b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00001c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00001d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00001e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00001f0: ffff ffff ffff ffff 0003 0100 0000 0000  ................
>>
>> - Rerun same dump using Linux's kernel ethtool.
>>
>> # ./install/sbin/dpdk-devbind --bind=ixgbe 04:00.0
>> # ethtool -m p2p1 raw on > meeprom-kernel.bin
>>
>> # xxd meeprom-kernel.bin
>> 0000000: 0304 0710 0000 0100 0000 0006 6702 0000  ............g...
>> 0000010: 0803 001e 4f45 4d20 2020 2020 2020 2020  ....OEM
>> 0000020: 2020 2020 0000 1b21 5346 502d 3130 472d      ...!SFP-10G-
>> 0000030: 5352 2d49 5420 2020 4120 2020 0352 0024  SR-IT   A   .R.$
>> 0000040: 003a 0000 5751 3136 3034 3132 4131 3135  .:..WQ160412A115
>> 0000050: 2020 2020 3135 3136 3130 2020 68fa 033b      151610  h..;
>> 0000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
>> 0000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
>> 0000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 0000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00000c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00000d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00000e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00000f0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 0000100: 5000 fb00 4b00 0000 8ca0 7530 88b8 7918  P...K.....u0..y.
>> 0000110: 1d4c 01f4 1b58 03e8 3de9 03e8 2710 04eb  .L...X..=...'...
>> 0000120: 2710 0064 1f07 007e 0000 0000 0000 0000  '..d...~........
>> 0000130: 0000 0000 0000 0000 0000 0000 0000 0000  ................
>> 0000140: 0000 0000 3f80 0000 0000 0000 0100 0000  ....?...........
>> 0000150: 0100 0000 0100 0000 0100 0000 0000 002d  ...............-
>> 0000160: 2899 8146 0058 0001 0001 0000 0000 8200  (..F.X..........
>> 0000170: 0540 0000 0540 0000 0000 0000 0000 0000  .@...@..........
>> 0000180: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 0000190: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00001a0: ffff faff ffff ffff ffff ffff ffff ffff  ................
>> 00001b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00001c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00001d0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00001e0: ffff ffff ffff ffff ffff ffff ffff ffff  ................
>> 00001f0: ffff ffff ffff ffff 0003 0100 0000 0000  ................
>>
>> 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
> 
> For series,
> Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>

Series applied to dpdk-next-net/master, thanks.

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2018-04-25 14:39 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1524563176-7795-1-git-send-email-zijie.pan@6wind.com>
2018-04-25  9:13 ` [PATCH v5 0/5] get the information and data of EEPROM Zijie Pan
2018-04-25  9:13   ` [PATCH v5 1/5] ethdev: add access to eeprom Zijie Pan
2018-04-25  9:13   ` [PATCH v5 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
2018-04-25  9:13   ` [PATCH v5 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
2018-04-25  9:13   ` [PATCH v5 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
2018-04-25  9:13   ` [PATCH v5 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
2018-04-25  9:22   ` [PATCH v5 0/5] get the information and data of EEPROM Thomas Monjalon
2018-04-25  9:32     ` Zijie Pan
2018-04-25 10:01   ` [PATCH v6 " Zijie Pan
2018-04-25 10:01     ` [PATCH v6 1/5] ethdev: add access to eeprom Zijie Pan
2018-04-25 10:28       ` Thomas Monjalon
2018-04-25 10:40       ` Ferruh Yigit
2018-04-25 10:01     ` [PATCH v6 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
2018-04-25 10:01     ` [PATCH v6 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
2018-04-25 10:44       ` Ferruh Yigit
2018-04-25 10:01     ` [PATCH v6 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
2018-04-25 10:01     ` [PATCH v6 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
2018-04-25 14:02     ` [PATCH v7 0/5] get the information and data of EEPROM Zijie Pan
2018-04-25 14:02       ` [PATCH v7 1/5] ethdev: add access to eeprom Zijie Pan
2018-04-25 14:02       ` [PATCH v7 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
2018-04-25 14:02       ` [PATCH v7 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
2018-04-25 14:02       ` [PATCH v7 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
2018-04-25 14:02       ` [PATCH v7 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
2018-04-25 14:24       ` [PATCH v7 0/5] get the information and data of EEPROM Ferruh Yigit
2018-04-25 14:39         ` Ferruh Yigit

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.