DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM
@ 2018-03-12  4:17 Zijie Pan
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 1/5] ethdev: add access to eeprom Zijie Pan
                   ` (6 more replies)
  0 siblings, 7 replies; 39+ messages in thread
From: Zijie Pan @ 2018-03-12  4:17 UTC (permalink / raw)
  To: dev

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

# 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.

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

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

-- 
1.7.10.4

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

* [dpdk-dev] [PATCH 1/5] ethdev: add access to eeprom
  2018-03-12  4:17 [dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM Zijie Pan
@ 2018-03-12  4:17 ` Zijie Pan
  2018-03-13 14:51   ` Remy Horton
  2018-03-16  9:38   ` [dpdk-dev] [PATCH v2 " Zijie Pan
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 39+ messages in thread
From: Zijie Pan @ 2018-03-12  4:17 UTC (permalink / raw)
  To: dev

add new APIs:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

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

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

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

* [dpdk-dev] [PATCH 2/5] examples/ethtool: add a new command module-eeprom
  2018-03-12  4:17 [dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM Zijie Pan
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 1/5] ethdev: add access to eeprom Zijie Pan
@ 2018-03-12  4:17 ` Zijie Pan
  2018-03-13 14:46   ` Remy Horton
  2018-03-16  9:41   ` [dpdk-dev] [PATCH v2 " Zijie Pan
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 39+ messages in thread
From: Zijie Pan @ 2018-03-12  4:17 UTC (permalink / raw)
  To: dev

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

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

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

* [dpdk-dev] [PATCH 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe
  2018-03-12  4:17 [dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM Zijie Pan
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 1/5] ethdev: add access to eeprom Zijie Pan
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
@ 2018-03-12  4:17 ` Zijie Pan
  2018-03-13 14:46   ` Remy Horton
  2018-03-16  9:42   ` [dpdk-dev] [PATCH v2 " Zijie Pan
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 39+ messages in thread
From: Zijie Pan @ 2018-03-12  4:17 UTC (permalink / raw)
  To: dev

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>
---
 drivers/net/ixgbe/ixgbe_ethdev.c |   76 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

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

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

* [dpdk-dev] [PATCH 4/5] net/e1000: add module EEPROM callbacks for e1000
  2018-03-12  4:17 [dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM Zijie Pan
                   ` (2 preceding siblings ...)
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
@ 2018-03-12  4:17 ` Zijie Pan
  2018-03-16  9:42   ` [dpdk-dev] [PATCH v2 " Zijie Pan
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 39+ messages in thread
From: Zijie Pan @ 2018-03-12  4:17 UTC (permalink / raw)
  To: dev

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>
---
 drivers/net/e1000/base/e1000_phy.h |    8 ++++
 drivers/net/e1000/igb_ethdev.c     |   83 ++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)

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

* [dpdk-dev] [PATCH 5/5] net/i40e: add module EEPROM callbacks for i40e
  2018-03-12  4:17 [dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM Zijie Pan
                   ` (3 preceding siblings ...)
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
@ 2018-03-12  4:17 ` Zijie Pan
  2018-03-16  9:42   ` [dpdk-dev] [PATCH v2 " Zijie Pan
  2018-03-13 15:19 ` [dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM Remy Horton
  2018-03-16  9:36 ` [dpdk-dev] [PATCH v2 0/5] " Zijie Pan
  6 siblings, 1 reply; 39+ messages in thread
From: Zijie Pan @ 2018-03-12  4:17 UTC (permalink / raw)
  To: dev

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>
---
 drivers/net/i40e/i40e_ethdev.c |  141 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 141 insertions(+)

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

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

* Re: [dpdk-dev] [PATCH 2/5] examples/ethtool: add a new command module-eeprom
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
@ 2018-03-13 14:46   ` Remy Horton
  2018-03-16  9:41   ` [dpdk-dev] [PATCH v2 " Zijie Pan
  1 sibling, 0 replies; 39+ messages in thread
From: Remy Horton @ 2018-03-13 14:46 UTC (permalink / raw)
  To: dev; +Cc: Zijie Pan

Comments inline. On the whole looks good to me.

On 12/03/2018 04:17, Zijie Pan wrote:
[..]
> Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
> ---
>  doc/guides/sample_app_ug/ethtool.rst  |    2 ++
>  examples/ethtool/ethtool-app/ethapp.c |   61 +++++++++++++++++++++++++++++++++
>  examples/ethtool/lib/rte_ethtool.c    |   30 ++++++++++++++++
>  examples/ethtool/lib/rte_ethtool.h    |   34 ++++++++++++++++++
>  4 files changed, 127 insertions(+)

Reviewed-by: Remy Horton <remy.horton@intel.com>


>  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");

Checkpatch: 80 character limit.


> +	info_eeprom.len = module_info[1];
> +	info_eeprom.offset = 0;
> +	stat = rte_ethtool_get_module_eeprom(params->port,
> +					     &info_eeprom, bytes_eeprom);
> +	if (stat != 0 || module_info[1] <= 0) {

This supposed to be module_info[1] rather than info_eeprom.len ?

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

* Re: [dpdk-dev] [PATCH 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
@ 2018-03-13 14:46   ` Remy Horton
  2018-03-16  9:42   ` [dpdk-dev] [PATCH v2 " Zijie Pan
  1 sibling, 0 replies; 39+ messages in thread
From: Remy Horton @ 2018-03-13 14:46 UTC (permalink / raw)
  To: dev; +Cc: Zijie Pan


On 12/03/2018 04:17, Zijie Pan wrote:
[..]
> Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
> ---
>  drivers/net/ixgbe/ixgbe_ethdev.c |   76 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 76 insertions(+)

Reviewed-by: Remy Horton <remy.horton@intel.com>


> +	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.");

Checkpatch: 80 characters

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

* Re: [dpdk-dev] [PATCH 1/5] ethdev: add access to eeprom
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 1/5] ethdev: add access to eeprom Zijie Pan
@ 2018-03-13 14:51   ` Remy Horton
  2018-03-16  9:38   ` [dpdk-dev] [PATCH v2 " Zijie Pan
  1 sibling, 0 replies; 39+ messages in thread
From: Remy Horton @ 2018-03-13 14:51 UTC (permalink / raw)
  To: Zijie Pan, dev


On 12/03/2018 04:17, Zijie Pan wrote:
[..]
> Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
> ---
>  doc/guides/nics/features.rst       |   11 +++++++++++
>  lib/librte_ether/rte_dev_info.h    |   18 ++++++++++++++++++
>  lib/librte_ether/rte_ethdev.c      |   26 ++++++++++++++++++++++++++
>  lib/librte_ether/rte_ethdev.h      |   35 +++++++++++++++++++++++++++++++++++
>  lib/librte_ether/rte_ethdev_core.h |   12 ++++++++++++
>  5 files changed, 102 insertions(+)

Acked-by: Remy Horton <remy.horton@intel.com>

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

* Re: [dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM
  2018-03-12  4:17 [dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM Zijie Pan
                   ` (4 preceding siblings ...)
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
@ 2018-03-13 15:19 ` Remy Horton
  2018-03-16  9:36 ` [dpdk-dev] [PATCH v2 0/5] " Zijie Pan
  6 siblings, 0 replies; 39+ messages in thread
From: Remy Horton @ 2018-03-13 15:19 UTC (permalink / raw)
  To: dev; +Cc: Zijie Pan


On 12/03/2018 04:17, 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.).

Quite a few checkpatch warnings regarding long lines, but did a quick 
test with ixgbe and on the whole it looks good to me. CC the 
ixgbe/e1000/i40e maintainers on any v2 patchset, as they might catch 
something I've missed.

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

* [dpdk-dev] [PATCH v2 0/5] get the information and data of EEPROM
  2018-03-12  4:17 [dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM Zijie Pan
                   ` (5 preceding siblings ...)
  2018-03-13 15:19 ` [dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM Remy Horton
@ 2018-03-16  9:36 ` Zijie Pan
  2018-03-21 11:06   ` [dpdk-dev] [PATCH v3 " Zijie Pan
  6 siblings, 1 reply; 39+ messages in thread
From: Zijie Pan @ 2018-03-16  9:36 UTC (permalink / raw)
  To: dev; +Cc: remy.horton

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().

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

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

-- 
1.7.10.4

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

* [dpdk-dev] [PATCH v2 1/5] ethdev: add access to eeprom
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 1/5] ethdev: add access to eeprom Zijie Pan
  2018-03-13 14:51   ` Remy Horton
@ 2018-03-16  9:38   ` Zijie Pan
  2018-03-16  9:59     ` Remy Horton
  1 sibling, 1 reply; 39+ messages in thread
From: Zijie Pan @ 2018-03-16  9:38 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, john.mcnamara, marko.kovacevic, thomas

add new APIs:
- rte_eth_dev_get_module_info
- rte_eth_dev_get_module_eeprom

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

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

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

* [dpdk-dev] [PATCH v2 2/5] examples/ethtool: add a new command module-eeprom
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
  2018-03-13 14:46   ` Remy Horton
@ 2018-03-16  9:41   ` Zijie Pan
  2018-03-16  9:59     ` Remy Horton
  1 sibling, 1 reply; 39+ messages in thread
From: Zijie Pan @ 2018-03-16  9:41 UTC (permalink / raw)
  To: dev
  Cc: remy.horton, 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>
---
 doc/guides/sample_app_ug/ethtool.rst  |    2 ++
 examples/ethtool/ethtool-app/ethapp.c |   64 +++++++++++++++++++++++++++++++++
 examples/ethtool/lib/rte_ethtool.c    |   30 ++++++++++++++++
 examples/ethtool/lib/rte_ethtool.h    |   34 ++++++++++++++++++
 4 files changed, 130 insertions(+)

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

* [dpdk-dev] [PATCH v2 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
  2018-03-13 14:46   ` Remy Horton
@ 2018-03-16  9:42   ` Zijie Pan
  2018-03-16 10:08     ` Remy Horton
  1 sibling, 1 reply; 39+ messages in thread
From: Zijie Pan @ 2018-03-16  9:42 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, 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>
---
 drivers/net/ixgbe/ixgbe_ethdev.c |   79 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

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

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

* [dpdk-dev] [PATCH v2 4/5] net/e1000: add module EEPROM callbacks for e1000
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
@ 2018-03-16  9:42   ` Zijie Pan
  0 siblings, 0 replies; 39+ messages in thread
From: Zijie Pan @ 2018-03-16  9:42 UTC (permalink / raw)
  To: dev

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

* [dpdk-dev] [PATCH v2 5/5] net/i40e: add module EEPROM callbacks for i40e
  2018-03-12  4:17 ` [dpdk-dev] [PATCH 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
@ 2018-03-16  9:42   ` Zijie Pan
  0 siblings, 0 replies; 39+ messages in thread
From: Zijie Pan @ 2018-03-16  9:42 UTC (permalink / raw)
  To: dev; +Cc: 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>
---
 drivers/net/i40e/i40e_ethdev.c |  147 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 147 insertions(+)

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

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

* Re: [dpdk-dev] [PATCH v2 1/5] ethdev: add access to eeprom
  2018-03-16  9:38   ` [dpdk-dev] [PATCH v2 " Zijie Pan
@ 2018-03-16  9:59     ` Remy Horton
  0 siblings, 0 replies; 39+ messages in thread
From: Remy Horton @ 2018-03-16  9:59 UTC (permalink / raw)
  To: Zijie Pan, dev; +Cc: john.mcnamara, marko.kovacevic, thomas


On 16/03/2018 09:38, Zijie Pan wrote:
[..]
> Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
> ---
>  doc/guides/nics/features.rst       |   11 +++++++++++
>  lib/librte_ether/rte_dev_info.h    |   18 ++++++++++++++++++
>  lib/librte_ether/rte_ethdev.c      |   26 ++++++++++++++++++++++++++
>  lib/librte_ether/rte_ethdev.h      |   35 +++++++++++++++++++++++++++++++++++
>  lib/librte_ether/rte_ethdev_core.h |   12 ++++++++++++
>  5 files changed, 102 insertions(+)

Acked-by: Remy Horton <remy.horton@intel.com>

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

* Re: [dpdk-dev] [PATCH v2 2/5] examples/ethtool: add a new command module-eeprom
  2018-03-16  9:41   ` [dpdk-dev] [PATCH v2 " Zijie Pan
@ 2018-03-16  9:59     ` Remy Horton
  0 siblings, 0 replies; 39+ messages in thread
From: Remy Horton @ 2018-03-16  9:59 UTC (permalink / raw)
  To: Zijie Pan, dev
  Cc: orika, bruce.richardson, pablo.de.lara.guarch, radu.nicolau,
	akhil.goyal, tomasz.kantecki, john.mcnamara, marko.kovacevic


On 16/03/2018 09:41, Zijie Pan wrote:
[..]
> Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
> ---
>  doc/guides/sample_app_ug/ethtool.rst  |    2 ++
>  examples/ethtool/ethtool-app/ethapp.c |   64 +++++++++++++++++++++++++++++++++
>  examples/ethtool/lib/rte_ethtool.c    |   30 ++++++++++++++++
>  examples/ethtool/lib/rte_ethtool.h    |   34 ++++++++++++++++++
>  4 files changed, 130 insertions(+)

Acked-by: Remy Horton <remy.horton@intel.com>

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

* Re: [dpdk-dev] [PATCH v2 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe
  2018-03-16  9:42   ` [dpdk-dev] [PATCH v2 " Zijie Pan
@ 2018-03-16 10:08     ` Remy Horton
  0 siblings, 0 replies; 39+ messages in thread
From: Remy Horton @ 2018-03-16 10:08 UTC (permalink / raw)
  To: Zijie Pan, dev; +Cc: wenzhuo.lu, konstantin.ananyev

Did quick test and seems OK to me.

On 16/03/2018 09:42, 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>
> ---
>  drivers/net/ixgbe/ixgbe_ethdev.c |   79 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 79 insertions(+)

Acked-by: Remy Horton <remy.horton@intel.com>

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

* [dpdk-dev] [PATCH v3 0/5] get the information and data of EEPROM
  2018-03-16  9:36 ` [dpdk-dev] [PATCH v2 0/5] " Zijie Pan
@ 2018-03-21 11:06   ` Zijie Pan
  2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom Zijie Pan
                       ` (6 more replies)
  0 siblings, 7 replies; 39+ messages in thread
From: Zijie Pan @ 2018-03-21 11:06 UTC (permalink / raw)
  To: dev; +Cc: remy.horton

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.

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

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

-- 
1.7.10.4

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

* [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom
  2018-03-21 11:06   ` [dpdk-dev] [PATCH v3 " Zijie Pan
@ 2018-03-21 11:06     ` Zijie Pan
  2018-04-19 13:34       ` Ferruh Yigit
  2018-04-22 21:13       ` Thomas Monjalon
  2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
                       ` (5 subsequent siblings)
  6 siblings, 2 replies; 39+ messages in thread
From: Zijie Pan @ 2018-03-21 11:06 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, john.mcnamara, marko.kovacevic, thomas

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           |   35 +++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev_core.h      |   12 +++++++++++
 lib/librte_ether/rte_ethdev_version.map |    2 ++
 6 files changed, 104 insertions(+)

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

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

* [dpdk-dev] [PATCH v3 2/5] examples/ethtool: add a new command module-eeprom
  2018-03-21 11:06   ` [dpdk-dev] [PATCH v3 " Zijie Pan
  2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom Zijie Pan
@ 2018-03-21 11:06     ` Zijie Pan
  2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
                       ` (4 subsequent siblings)
  6 siblings, 0 replies; 39+ messages in thread
From: Zijie Pan @ 2018-03-21 11:06 UTC (permalink / raw)
  To: dev
  Cc: remy.horton, 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  |    2 ++
 examples/ethtool/ethtool-app/ethapp.c |   64 +++++++++++++++++++++++++++++++++
 examples/ethtool/lib/rte_ethtool.c    |   30 ++++++++++++++++
 examples/ethtool/lib/rte_ethtool.h    |   34 ++++++++++++++++++
 4 files changed, 130 insertions(+)

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

* [dpdk-dev] [PATCH v3 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe
  2018-03-21 11:06   ` [dpdk-dev] [PATCH v3 " Zijie Pan
  2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom Zijie Pan
  2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
@ 2018-03-21 11:06     ` Zijie Pan
  2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
                       ` (3 subsequent siblings)
  6 siblings, 0 replies; 39+ messages in thread
From: Zijie Pan @ 2018-03-21 11:06 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, 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 4483258..28f09d3 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -328,6 +328,11 @@ static int ixgbe_get_eeprom(struct rte_eth_dev *dev,
 static int ixgbe_set_eeprom(struct rte_eth_dev *dev,
 				struct rte_dev_eeprom_info *eeprom);
 
+static int ixgbe_get_module_info(struct rte_eth_dev *dev,
+				 struct rte_dev_module_info *modinfo);
+static int ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+				   struct rte_dev_eeprom_info *info);
+
 static int ixgbevf_get_reg_length(struct rte_eth_dev *dev);
 static int ixgbevf_get_regs(struct rte_eth_dev *dev,
 				struct rte_dev_reg_info *regs);
@@ -565,6 +570,8 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
 	.get_eeprom_length    = ixgbe_get_eeprom_length,
 	.get_eeprom           = ixgbe_get_eeprom,
 	.set_eeprom           = ixgbe_set_eeprom,
+	.get_module_info      = ixgbe_get_module_info,
+	.get_module_eeprom    = ixgbe_get_module_eeprom,
 	.get_dcb_info         = ixgbe_dev_get_dcb_info,
 	.timesync_adjust_time = ixgbe_timesync_adjust_time,
 	.timesync_read_time   = ixgbe_timesync_read_time,
@@ -7166,6 +7173,78 @@ static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
 	return eeprom->ops.write_buffer(hw,  first, length, data);
 }
 
+static int
+ixgbe_get_module_info(struct rte_eth_dev *dev,
+		      struct rte_dev_module_info *modinfo)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t status;
+	uint8_t sff8472_rev, addr_mode;
+	bool page_swap = false;
+
+	/* Check whether we support SFF-8472 or not */
+	status = hw->phy.ops.read_i2c_eeprom(hw,
+					     IXGBE_SFF_SFF_8472_COMP,
+					     &sff8472_rev);
+	if (status != 0)
+		return -EIO;
+
+	/* addressing mode is not supported */
+	status = hw->phy.ops.read_i2c_eeprom(hw,
+					     IXGBE_SFF_SFF_8472_SWAP,
+					     &addr_mode);
+	if (status != 0)
+		return -EIO;
+
+	if (addr_mode & IXGBE_SFF_ADDRESSING_MODE) {
+		PMD_DRV_LOG(ERR,
+			    "Address change required to access page 0xA2, "
+			    "but not supported. Please report the module "
+			    "type to the driver maintainers.");
+		page_swap = true;
+	}
+
+	if (sff8472_rev == IXGBE_SFF_SFF_8472_UNSUP || page_swap) {
+		/* We have a SFP, but it does not support SFF-8472 */
+		modinfo->type = ETH_MODULE_SFF_8079;
+		modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+	} else {
+		/* We have a SFP which supports a revision of SFF-8472. */
+		modinfo->type = ETH_MODULE_SFF_8472;
+		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+	}
+
+	return 0;
+}
+
+static int
+ixgbe_get_module_eeprom(struct rte_eth_dev *dev,
+			struct rte_dev_eeprom_info *info)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t status = IXGBE_ERR_PHY_ADDR_INVALID;
+	uint8_t databyte = 0xFF;
+	uint8_t *data = info->data;
+	uint32_t i = 0;
+
+	if (info->length == 0)
+		return -EINVAL;
+
+	for (i = info->offset; i < info->offset + info->length; i++) {
+		if (i < ETH_MODULE_SFF_8079_LEN)
+			status = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte);
+		else
+			status = hw->phy.ops.read_i2c_sff8472(hw, i, &databyte);
+
+		if (status != 0)
+			return -EIO;
+
+		data[i - info->offset] = databyte;
+	}
+
+	return 0;
+}
+
 uint16_t
 ixgbe_reta_size_get(enum ixgbe_mac_type mac_type) {
 	switch (mac_type) {
-- 
1.7.10.4

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

* [dpdk-dev] [PATCH v3 4/5] net/e1000: add module EEPROM callbacks for e1000
  2018-03-21 11:06   ` [dpdk-dev] [PATCH v3 " Zijie Pan
                       ` (2 preceding siblings ...)
  2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
@ 2018-03-21 11:06     ` Zijie Pan
  2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
                       ` (2 subsequent siblings)
  6 siblings, 0 replies; 39+ messages in thread
From: Zijie Pan @ 2018-03-21 11:06 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, 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>
---
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 3c5138d..77ec4f9 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -224,6 +224,10 @@ static int eth_igb_get_eeprom(struct rte_eth_dev *dev,
 		struct rte_dev_eeprom_info *eeprom);
 static int eth_igb_set_eeprom(struct rte_eth_dev *dev,
 		struct rte_dev_eeprom_info *eeprom);
+static int eth_igb_get_module_info(struct rte_eth_dev *dev,
+				   struct rte_dev_module_info *modinfo);
+static int eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+				     struct rte_dev_eeprom_info *info);
 static int eth_igb_set_mc_addr_list(struct rte_eth_dev *dev,
 				    struct ether_addr *mc_addr_set,
 				    uint32_t nb_mc_addr);
@@ -403,6 +407,8 @@ static void eth_igb_write_ivar(struct e1000_hw *hw, uint8_t msix_vector,
 	.get_eeprom_length    = eth_igb_get_eeprom_length,
 	.get_eeprom           = eth_igb_get_eeprom,
 	.set_eeprom           = eth_igb_set_eeprom,
+	.get_module_info      = eth_igb_get_module_info,
+	.get_module_eeprom    = eth_igb_get_module_eeprom,
 	.timesync_adjust_time = igb_timesync_adjust_time,
 	.timesync_read_time   = igb_timesync_read_time,
 	.timesync_write_time  = igb_timesync_write_time,
@@ -5384,6 +5390,86 @@ static void igbvf_set_vfta_all(struct rte_eth_dev *dev, bool on)
 }
 
 static int
+eth_igb_get_module_info(struct rte_eth_dev *dev,
+			struct rte_dev_module_info *modinfo)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	uint32_t status = 0;
+	uint16_t sff8472_rev, addr_mode;
+	bool page_swap = false;
+
+	if (hw->phy.media_type == e1000_media_type_copper ||
+	    hw->phy.media_type == e1000_media_type_unknown)
+		return -EOPNOTSUPP;
+
+	/* Check whether we support SFF-8472 or not */
+	status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_COMP, &sff8472_rev);
+	if (status)
+		return -EIO;
+
+	/* addressing mode is not supported */
+	status = e1000_read_phy_reg_i2c(hw, IGB_SFF_8472_SWAP, &addr_mode);
+	if (status)
+		return -EIO;
+
+	/* addressing mode is not supported */
+	if ((addr_mode & 0xFF) & IGB_SFF_ADDRESSING_MODE) {
+		PMD_DRV_LOG(ERR,
+			    "Address change required to access page 0xA2, "
+			    "but not supported. Please report the module "
+			    "type to the driver maintainers.\n");
+		page_swap = true;
+	}
+
+	if ((sff8472_rev & 0xFF) == IGB_SFF_8472_UNSUP || page_swap) {
+		/* We have an SFP, but it does not support SFF-8472 */
+		modinfo->type = ETH_MODULE_SFF_8079;
+		modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+	} else {
+		/* We have an SFP which supports a revision of SFF-8472 */
+		modinfo->type = ETH_MODULE_SFF_8472;
+		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+	}
+
+	return 0;
+}
+
+static int
+eth_igb_get_module_eeprom(struct rte_eth_dev *dev,
+			  struct rte_dev_eeprom_info *info)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	uint32_t status = 0;
+	uint16_t dataword[ETH_MODULE_SFF_8472_LEN / 2 + 1];
+	u16 first_word, last_word;
+	int i = 0;
+
+	if (info->length == 0)
+		return -EINVAL;
+
+	first_word = info->offset >> 1;
+	last_word = (info->offset + info->length - 1) >> 1;
+
+	/* Read EEPROM block, SFF-8079/SFF-8472, word at a time */
+	for (i = 0; i < last_word - first_word + 1; i++) {
+		status = e1000_read_phy_reg_i2c(hw, (first_word + i) * 2,
+						&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	[flat|nested] 39+ messages in thread

* [dpdk-dev] [PATCH v3 5/5] net/i40e: add module EEPROM callbacks for i40e
  2018-03-21 11:06   ` [dpdk-dev] [PATCH v3 " Zijie Pan
                       ` (3 preceding siblings ...)
  2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
@ 2018-03-21 11:06     ` Zijie Pan
  2018-04-19 13:36     ` [dpdk-dev] [PATCH v3 0/5] get the information and data of EEPROM Ferruh Yigit
  2018-04-24 10:17     ` [dpdk-dev] [PATCH v4 " Zijie Pan
  6 siblings, 0 replies; 39+ messages in thread
From: Zijie Pan @ 2018-03-21 11:06 UTC (permalink / raw)
  To: dev; +Cc: remy.horton, 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>
---
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 508b417..98e9c3b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -369,6 +369,11 @@ static int i40e_get_regs(struct rte_eth_dev *dev,
 static int i40e_get_eeprom(struct rte_eth_dev *dev,
 			   struct rte_dev_eeprom_info *eeprom);
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+				struct rte_dev_module_info *modinfo);
+static int i40e_get_module_eeprom(struct rte_eth_dev *dev,
+				  struct rte_dev_eeprom_info *info);
+
 static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
 				      struct ether_addr *mac_addr);
 
@@ -489,6 +494,8 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
 	.get_reg                      = i40e_get_regs,
 	.get_eeprom_length            = i40e_get_eeprom_length,
 	.get_eeprom                   = i40e_get_eeprom,
+	.get_module_info              = i40e_get_module_info,
+	.get_module_eeprom            = i40e_get_module_eeprom,
 	.mac_addr_set                 = i40e_set_default_mac_addr,
 	.mtu_set                      = i40e_dev_mtu_set,
 	.tm_ops_get                   = i40e_tm_ops_get,
@@ -11249,6 +11256,146 @@ static int i40e_get_eeprom(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int i40e_get_module_info(struct rte_eth_dev *dev,
+				struct rte_dev_module_info *modinfo)
+{
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t sff8472_comp = 0;
+	uint32_t sff8472_swap = 0;
+	uint32_t sff8636_rev = 0;
+	i40e_status status;
+	uint32_t type = 0;
+
+	/* Check if firmware supports reading module EEPROM. */
+	if (!(hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE)) {
+		PMD_DRV_LOG(ERR,
+			    "Module EEPROM memory read not supported. "
+			    "Please update the NVM image.\n");
+		return -EINVAL;
+	}
+
+	status = i40e_update_link_info(hw);
+	if (status)
+		return -EIO;
+
+	if (hw->phy.link_info.phy_type == I40E_PHY_TYPE_EMPTY) {
+		PMD_DRV_LOG(ERR,
+			    "Cannot read module EEPROM memory. "
+			    "No module connected.\n");
+		return -EINVAL;
+	}
+
+	type = hw->phy.link_info.module_type[0];
+
+	switch (type) {
+	case I40E_MODULE_TYPE_SFP:
+		status = i40e_aq_get_phy_register(hw,
+				I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+				I40E_I2C_EEPROM_DEV_ADDR,
+				I40E_MODULE_SFF_8472_COMP,
+				&sff8472_comp, NULL);
+		if (status)
+			return -EIO;
+
+		status = i40e_aq_get_phy_register(hw,
+				I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+				I40E_I2C_EEPROM_DEV_ADDR,
+				I40E_MODULE_SFF_8472_SWAP,
+				&sff8472_swap, NULL);
+		if (status)
+			return -EIO;
+
+		/* Check if the module requires address swap to access
+		 * the other EEPROM memory page.
+		 */
+		if (sff8472_swap & I40E_MODULE_SFF_ADDR_MODE) {
+			PMD_DRV_LOG(WARNING,
+				    "Module address swap to access "
+				    "page 0xA2 is not supported.\n");
+			modinfo->type = ETH_MODULE_SFF_8079;
+			modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+		} else if (sff8472_comp == 0x00) {
+			/* Module is not SFF-8472 compliant */
+			modinfo->type = ETH_MODULE_SFF_8079;
+			modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+		} else {
+			modinfo->type = ETH_MODULE_SFF_8472;
+			modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+		}
+		break;
+	case I40E_MODULE_TYPE_QSFP_PLUS:
+		/* Read from memory page 0. */
+		status = i40e_aq_get_phy_register(hw,
+				I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
+				0,
+				I40E_MODULE_REVISION_ADDR,
+				&sff8636_rev, NULL);
+		if (status)
+			return -EIO;
+		/* Determine revision compliance byte */
+		if (sff8636_rev > 0x02) {
+			/* Module is SFF-8636 compliant */
+			modinfo->type = ETH_MODULE_SFF_8636;
+			modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+		} else {
+			modinfo->type = ETH_MODULE_SFF_8436;
+			modinfo->eeprom_len = I40E_MODULE_QSFP_MAX_LEN;
+		}
+		break;
+	case I40E_MODULE_TYPE_QSFP28:
+		modinfo->type = 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 >= ETH_MODULE_SFF_8079_LEN) {
+				offset -= ETH_MODULE_SFF_8079_LEN;
+				addr = I40E_I2C_EEPROM_DEV_ADDR2;
+			}
+		} else {
+			while (offset >= ETH_MODULE_SFF_8436_LEN) {
+				/* Compute memory page number and offset. */
+				offset -= 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 void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
 				      struct ether_addr *mac_addr)
 {
-- 
1.7.10.4

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

* Re: [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom
  2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom Zijie Pan
@ 2018-04-19 13:34       ` Ferruh Yigit
  2018-04-22 21:13       ` Thomas Monjalon
  1 sibling, 0 replies; 39+ messages in thread
From: Ferruh Yigit @ 2018-04-19 13:34 UTC (permalink / raw)
  To: Zijie Pan, dev; +Cc: remy.horton, john.mcnamara, marko.kovacevic, thomas

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

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

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

* Re: [dpdk-dev] [PATCH v3 0/5] get the information and data of EEPROM
  2018-03-21 11:06   ` [dpdk-dev] [PATCH v3 " Zijie Pan
                       ` (4 preceding siblings ...)
  2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
@ 2018-04-19 13:36     ` Ferruh Yigit
  2018-04-19 14:17       ` Remy Horton
  2018-04-24 10:17     ` [dpdk-dev] [PATCH v4 " Zijie Pan
  6 siblings, 1 reply; 39+ messages in thread
From: Ferruh Yigit @ 2018-04-19 13:36 UTC (permalink / raw)
  To: Zijie Pan, dev, Beilei Xing, Qi Zhang, Helin Zhang
  Cc: remy.horton, Thomas Monjalon, Wenzhuo Lu, Konstantin Ananyev

On 3/21/2018 11:06 AM, 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.
> 
> 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

This patch is waiting for a while without comment, please share if there is any
concern about patch.

Thanks,
ferruh

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

* Re: [dpdk-dev] [PATCH v3 0/5] get the information and data of EEPROM
  2018-04-19 13:36     ` [dpdk-dev] [PATCH v3 0/5] get the information and data of EEPROM Ferruh Yigit
@ 2018-04-19 14:17       ` Remy Horton
  0 siblings, 0 replies; 39+ messages in thread
From: Remy Horton @ 2018-04-19 14:17 UTC (permalink / raw)
  To: Ferruh Yigit, Zijie Pan, dev, Beilei Xing, Qi Zhang, Helin Zhang
  Cc: Thomas Monjalon, Wenzhuo Lu, Konstantin Ananyev


On 19/04/2018 14:36, Ferruh Yigit wrote:
[..]
>> 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
>
> This patch is waiting for a while without comment, please share if there is any
> concern about patch.

Wasn't able to test the e1000/i40e callbacks but that aside the patchset 
looks good to me. Extend my previous ack to the whole series.

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

* Re: [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom
  2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom Zijie Pan
  2018-04-19 13:34       ` Ferruh Yigit
@ 2018-04-22 21:13       ` Thomas Monjalon
  1 sibling, 0 replies; 39+ messages in thread
From: Thomas Monjalon @ 2018-04-22 21:13 UTC (permalink / raw)
  To: Zijie Pan; +Cc: dev, remy.horton, john.mcnamara, marko.kovacevic

Hi Zijie,

21/03/2018 12:06, Zijie Pan:
> +/*
> + * Placeholder for accessing plugin module eeprom
> + */

I think you missed a "*" to make it a doxygen comment.

> +struct rte_dev_module_info {
> +	uint32_t type; /**< Type of plugin module eeprom */
> +	uint32_t eeprom_len; /**< Length of plugin module eeprom */
> +};
> +
> +/* EEPROM Standards for plug in modules */
> +#define ETH_MODULE_SFF_8079             0x1
> +#define ETH_MODULE_SFF_8079_LEN         256
> +#define ETH_MODULE_SFF_8472             0x2
> +#define ETH_MODULE_SFF_8472_LEN         512
> +#define ETH_MODULE_SFF_8636             0x3
> +#define ETH_MODULE_SFF_8636_LEN         256
> +#define ETH_MODULE_SFF_8436             0x4
> +#define ETH_MODULE_SFF_8436_LEN         256

Can you add a RTE_ prefix please?

> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -4044,6 +4044,32 @@ int rte_eth_set_queue_rate_limit(uint16_t port_id, uint16_t queue_idx,
>  }
>  
>  int
> +rte_eth_dev_get_module_info(uint16_t port_id,
> +			    struct rte_dev_module_info *modinfo)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_info, -ENOTSUP);
> +	return (*dev->dev_ops->get_module_info)(dev, modinfo);
> +}
> +
> +	int
> +rte_eth_dev_get_module_eeprom(uint16_t port_id,
> +		struct rte_dev_eeprom_info *info)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_module_eeprom, -ENOTSUP);
> +	return (*dev->dev_ops->get_module_eeprom)(dev, info);
> +}
> +
> +int
>  rte_eth_dev_get_dcb_info(uint16_t port_id,

Please move these new functions after other eeprom functions.

> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
>  /**
> + * Retrieve the type and size of plugin module EEPROM
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param modinfo
> + *   The type and size of plugin module EEPROM.
> + * @return
> + *   - (0) if successful.
> + *   - (-ENOTSUP) if hardware doesn't support.
> + *   - (-ENODEV) if *port_id* invalid.
> + *   - (-EIO) if device is removed.
> + *   - others depends on the specific operations implementation.
> + */
> +int rte_eth_dev_get_module_info(uint16_t port_id,
> +				struct rte_dev_module_info *modinfo);
> +
> +/**
> + * Retrieve the data of plugin module EEPROM
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param info
> + *   The template includes the plugin module EEPROM attributes, and the
> + *   buffer for return plugin module EEPROM data.
> + * @return
> + *   - (0) if successful.
> + *   - (-ENOTSUP) if hardware doesn't support.
> + *   - (-ENODEV) if *port_id* invalid.
> + *   - (-EIO) if device is removed.
> + *   - others depends on the specific operations implementation.
> + */
> +int rte_eth_dev_get_module_eeprom(uint16_t port_id,
> +				  struct rte_dev_eeprom_info *info);

Please add the usual EXPERIMENTAL warnings for the new functions.

> --- a/lib/librte_ether/rte_ethdev_version.map
> +++ b/lib/librte_ether/rte_ethdev_version.map
> @@ -201,6 +201,8 @@ DPDK_18.02 {
>  	global:
>  
>  	rte_eth_dev_filter_ctrl;
> +	rte_eth_dev_get_module_info;
> +	rte_eth_dev_get_module_eeprom;

As noticed by Ferruh, they should be experimental.

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

* [dpdk-dev] [PATCH v4 0/5] get the information and data of EEPROM
  2018-03-21 11:06   ` [dpdk-dev] [PATCH v3 " Zijie Pan
                       ` (5 preceding siblings ...)
  2018-04-19 13:36     ` [dpdk-dev] [PATCH v3 0/5] get the information and data of EEPROM Ferruh Yigit
@ 2018-04-24 10:17     ` Zijie Pan
  2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 1/5] ethdev: add access to eeprom Zijie Pan
                         ` (4 more replies)
  6 siblings, 5 replies; 39+ messages in thread
From: Zijie Pan @ 2018-04-24 10:17 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.

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] 39+ messages in thread

* [dpdk-dev] [PATCH v4 1/5] ethdev: add access to eeprom
  2018-04-24 10:17     ` [dpdk-dev] [PATCH v4 " Zijie Pan
@ 2018-04-24 10:17       ` Zijie Pan
  2018-04-24 10:25         ` Thomas Monjalon
  2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
                         ` (3 subsequent siblings)
  4 siblings, 1 reply; 39+ messages in thread
From: Zijie Pan @ 2018-04-24 10:17 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..43a23f4 100644
--- a/lib/librte_ether/rte_ethdev_version.map
+++ b/lib/librte_ether/rte_ethdev_version.map
@@ -229,5 +229,7 @@ EXPERIMENTAL {
 	rte_mtr_policer_actions_update;
 	rte_mtr_stats_read;
 	rte_mtr_stats_update;
+	rte_eth_dev_get_module_info;
+	rte_eth_dev_get_module_eeprom;
 
 } DPDK_18.02;
-- 
1.7.10.4

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

* [dpdk-dev] [PATCH v4 2/5] examples/ethtool: add a new command module-eeprom
  2018-04-24 10:17     ` [dpdk-dev] [PATCH v4 " Zijie Pan
  2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 1/5] ethdev: add access to eeprom Zijie Pan
@ 2018-04-24 10:17       ` Zijie Pan
  2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
                         ` (2 subsequent siblings)
  4 siblings, 0 replies; 39+ messages in thread
From: Zijie Pan @ 2018-04-24 10:17 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	[flat|nested] 39+ messages in thread

* [dpdk-dev] [PATCH v4 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe
  2018-04-24 10:17     ` [dpdk-dev] [PATCH v4 " Zijie Pan
  2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 1/5] ethdev: add access to eeprom Zijie Pan
  2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
@ 2018-04-24 10:17       ` Zijie Pan
  2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
  2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
  4 siblings, 0 replies; 39+ messages in thread
From: Zijie Pan @ 2018-04-24 10:17 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	[flat|nested] 39+ messages in thread

* [dpdk-dev] [PATCH v4 4/5] net/e1000: add module EEPROM callbacks for e1000
  2018-04-24 10:17     ` [dpdk-dev] [PATCH v4 " Zijie Pan
                         ` (2 preceding siblings ...)
  2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
@ 2018-04-24 10:17       ` Zijie Pan
  2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
  4 siblings, 0 replies; 39+ messages in thread
From: Zijie Pan @ 2018-04-24 10:17 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	[flat|nested] 39+ messages in thread

* [dpdk-dev] [PATCH v4 5/5] net/i40e: add module EEPROM callbacks for i40e
  2018-04-24 10:17     ` [dpdk-dev] [PATCH v4 " Zijie Pan
                         ` (3 preceding siblings ...)
  2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
@ 2018-04-24 10:17       ` Zijie Pan
  4 siblings, 0 replies; 39+ messages in thread
From: Zijie Pan @ 2018-04-24 10:17 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	[flat|nested] 39+ messages in thread

* Re: [dpdk-dev] [PATCH v4 1/5] ethdev: add access to eeprom
  2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 1/5] ethdev: add access to eeprom Zijie Pan
@ 2018-04-24 10:25         ` Thomas Monjalon
  2018-04-25  8:21           ` Zijie Pan
  0 siblings, 1 reply; 39+ messages in thread
From: Thomas Monjalon @ 2018-04-24 10:25 UTC (permalink / raw)
  To: Zijie Pan; +Cc: dev, remy.horton, ferruh.yigit, john.mcnamara, marko.kovacevic

24/04/2018 12:17, Zijie Pan:
> +/**
> + * Placeholder for accessing plugin module eeprom
> + */
> +struct rte_dev_module_info {
> +	uint32_t type; /**< Type of plugin module eeprom */
> +	uint32_t eeprom_len; /**< Length of plugin module eeprom */
> +};

I am not sure "plugin module" is descriptive enough.
And I think the structure name should be rte_eth_dev_module_info
to make clear that we are talking about NIC modules.
Any better idea?

> +
> +/* 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

> --- 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,

Please move this code after other EEPROM related functions.


> --- a/lib/librte_ether/rte_ethdev_version.map
> +++ b/lib/librte_ether/rte_ethdev_version.map
> @@ -229,5 +229,7 @@ EXPERIMENTAL {
>  	rte_mtr_policer_actions_update;
>  	rte_mtr_stats_read;
>  	rte_mtr_stats_update;
> +	rte_eth_dev_get_module_info;
> +	rte_eth_dev_get_module_eeprom;

This must be inserted in alphabetical order.

Thanks

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

* Re: [dpdk-dev] [PATCH v4 1/5] ethdev: add access to eeprom
  2018-04-24 10:25         ` Thomas Monjalon
@ 2018-04-25  8:21           ` Zijie Pan
  2018-04-25  8:31             ` Thomas Monjalon
  0 siblings, 1 reply; 39+ messages in thread
From: Zijie Pan @ 2018-04-25  8:21 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, remy.horton, ferruh.yigit, john.mcnamara, marko.kovacevic

Hi Thomas,

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

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

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

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

Thanks & Regards,
Zijie

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

* Re: [dpdk-dev] [PATCH v4 1/5] ethdev: add access to eeprom
  2018-04-25  8:21           ` Zijie Pan
@ 2018-04-25  8:31             ` Thomas Monjalon
  0 siblings, 0 replies; 39+ messages in thread
From: Thomas Monjalon @ 2018-04-25  8:31 UTC (permalink / raw)
  To: Zijie Pan; +Cc: dev, remy.horton, ferruh.yigit, john.mcnamara, marko.kovacevic

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

No better idea.

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

No you can just focus on your change.
If more clean-up is required in your opinion, you can do it later.


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

OK

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

Please send v5 ASAP, thanks.

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

* Re: [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom
@ 2018-04-20  9:06 Zijie Pan
  0 siblings, 0 replies; 39+ messages in thread
From: Zijie Pan @ 2018-04-20  9:06 UTC (permalink / raw)
  To: Ferruh Yigit, dev; +Cc: remy.horton, john.mcnamara, marko.kovacevic, thomas

Hi Ferruh,

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

Thanks & Regards,
Zijie
 
 
------------------ Original ------------------
From:  "Ferruh Yigit"<ferruh.yigit@intel.com>;
Date:  Thu, Apr 19, 2018 09:34 PM
To:  "Zijie Pan"<zijie.pan@6wind.com>; "dev"<dev@dpdk.org>; 
Cc:  "remy.horton"<remy.horton@intel.com>; "john.mcnamara"<john.mcnamara@intel.com>; "marko.kovacevic"<marko.kovacevic@intel.com>; "thomas"<thomas@monjalon.net>; 
Subject:  Re: [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom

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

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

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

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

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-12  4:17 [dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM Zijie Pan
2018-03-12  4:17 ` [dpdk-dev] [PATCH 1/5] ethdev: add access to eeprom Zijie Pan
2018-03-13 14:51   ` Remy Horton
2018-03-16  9:38   ` [dpdk-dev] [PATCH v2 " Zijie Pan
2018-03-16  9:59     ` Remy Horton
2018-03-12  4:17 ` [dpdk-dev] [PATCH 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
2018-03-13 14:46   ` Remy Horton
2018-03-16  9:41   ` [dpdk-dev] [PATCH v2 " Zijie Pan
2018-03-16  9:59     ` Remy Horton
2018-03-12  4:17 ` [dpdk-dev] [PATCH 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
2018-03-13 14:46   ` Remy Horton
2018-03-16  9:42   ` [dpdk-dev] [PATCH v2 " Zijie Pan
2018-03-16 10:08     ` Remy Horton
2018-03-12  4:17 ` [dpdk-dev] [PATCH 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
2018-03-16  9:42   ` [dpdk-dev] [PATCH v2 " Zijie Pan
2018-03-12  4:17 ` [dpdk-dev] [PATCH 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
2018-03-16  9:42   ` [dpdk-dev] [PATCH v2 " Zijie Pan
2018-03-13 15:19 ` [dpdk-dev] [PATCH 0/5] Patches to get the information and data of EEPROM Remy Horton
2018-03-16  9:36 ` [dpdk-dev] [PATCH v2 0/5] " Zijie Pan
2018-03-21 11:06   ` [dpdk-dev] [PATCH v3 " Zijie Pan
2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom Zijie Pan
2018-04-19 13:34       ` Ferruh Yigit
2018-04-22 21:13       ` Thomas Monjalon
2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
2018-03-21 11:06     ` [dpdk-dev] [PATCH v3 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
2018-04-19 13:36     ` [dpdk-dev] [PATCH v3 0/5] get the information and data of EEPROM Ferruh Yigit
2018-04-19 14:17       ` Remy Horton
2018-04-24 10:17     ` [dpdk-dev] [PATCH v4 " Zijie Pan
2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 1/5] ethdev: add access to eeprom Zijie Pan
2018-04-24 10:25         ` Thomas Monjalon
2018-04-25  8:21           ` Zijie Pan
2018-04-25  8:31             ` Thomas Monjalon
2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 2/5] examples/ethtool: add a new command module-eeprom Zijie Pan
2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 3/5] net/ixgbe: add module EEPROM callbacks for ixgbe Zijie Pan
2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 4/5] net/e1000: add module EEPROM callbacks for e1000 Zijie Pan
2018-04-24 10:17       ` [dpdk-dev] [PATCH v4 5/5] net/i40e: add module EEPROM callbacks for i40e Zijie Pan
2018-04-20  9:06 [dpdk-dev] [PATCH v3 1/5] ethdev: add access to eeprom Zijie Pan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).