net/mlx: support firmware version query

Message ID 20190206215909.30147-1-thomas@monjalon.net (mailing list archive)
State Superseded, archived
Delegated to: Shahaf Shuler
Headers
Series net/mlx: support firmware version query |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/intel-Performance-Testing success Performance Testing PASS
ci/mellanox-Performance-Testing success Performance Testing PASS

Commit Message

Thomas Monjalon Feb. 6, 2019, 9:59 p.m. UTC
  The API function rte_eth_dev_fw_version_get() is querying drivers
via the operation callback fw_version_get().
The implementation of this operation is added for mlx4 and mlx5.
Both functions are copying the same ibverbs field fw_ver
which is retrieved when calling ibv_query_device[_ex]()
during the port probing.

It is tested with command "drvinfo" of examples/ethtool/.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 drivers/net/mlx4/mlx4.c        |  1 +
 drivers/net/mlx4/mlx4.h        |  1 +
 drivers/net/mlx4/mlx4_ethdev.c | 26 ++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5.c        |  6 +++++-
 drivers/net/mlx5/mlx5.h        |  1 +
 drivers/net/mlx5/mlx5_ethdev.c | 26 ++++++++++++++++++++++++++
 6 files changed, 60 insertions(+), 1 deletion(-)
  

Comments

Stephen Hemminger Feb. 6, 2019, 10:16 p.m. UTC | #1
On Wed,  6 Feb 2019 22:59:09 +0100
Thomas Monjalon <thomas@monjalon.net> wrote:

> The API function rte_eth_dev_fw_version_get() is querying drivers
> via the operation callback fw_version_get().
> The implementation of this operation is added for mlx4 and mlx5.
> Both functions are copying the same ibverbs field fw_ver
> which is retrieved when calling ibv_query_device[_ex]()
> during the port probing.
> 
> It is tested with command "drvinfo" of examples/ethtool/.
> 
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

Looks good, but hard to test because:
  * testpmd doesn't report it
  * with netvsc (and failsafe) the device is owned and not visible

Fixing testpmd is not hard, but what is best way to handle
the nested device situation.
  
Thomas Monjalon Feb. 6, 2019, 10:23 p.m. UTC | #2
06/02/2019 23:16, Stephen Hemminger:
> On Wed,  6 Feb 2019 22:59:09 +0100
> Thomas Monjalon <thomas@monjalon.net> wrote:
> 
> > The API function rte_eth_dev_fw_version_get() is querying drivers
> > via the operation callback fw_version_get().
> > The implementation of this operation is added for mlx4 and mlx5.
> > Both functions are copying the same ibverbs field fw_ver
> > which is retrieved when calling ibv_query_device[_ex]()
> > during the port probing.
> > 
> > It is tested with command "drvinfo" of examples/ethtool/.
> > 
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> 
> Looks good, but hard to test because:
>   * testpmd doesn't report it

Yes, good idea, we should do this query somewhere in testpmd.
Can be a separate command or part of some other infos.

>   * with netvsc (and failsafe) the device is owned and not visible
> 
> Fixing testpmd is not hard, but what is best way to handle
> the nested device situation.

I am not sure we want to expose such info via failsafe or bonding.
If we are interested to know the underlying hardware, we should
access directly to the nested device.
  
Stephen Hemminger Feb. 6, 2019, 10:27 p.m. UTC | #3
On Wed, 06 Feb 2019 23:23:07 +0100
Thomas Monjalon <thomas@monjalon.net> wrote:

> 06/02/2019 23:16, Stephen Hemminger:
> > On Wed,  6 Feb 2019 22:59:09 +0100
> > Thomas Monjalon <thomas@monjalon.net> wrote:
> >   
> > > The API function rte_eth_dev_fw_version_get() is querying drivers
> > > via the operation callback fw_version_get().
> > > The implementation of this operation is added for mlx4 and mlx5.
> > > Both functions are copying the same ibverbs field fw_ver
> > > which is retrieved when calling ibv_query_device[_ex]()
> > > during the port probing.
> > > 
> > > It is tested with command "drvinfo" of examples/ethtool/.
> > > 
> > > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>  
> > 
> > Looks good, but hard to test because:
> >   * testpmd doesn't report it  
> 
> Yes, good idea, we should do this query somewhere in testpmd.
> Can be a separate command or part of some other infos.
> 
> >   * with netvsc (and failsafe) the device is owned and not visible
> > 
> > Fixing testpmd is not hard, but what is best way to handle
> > the nested device situation.  
> 
> I am not sure we want to expose such info via failsafe or bonding.
> If we are interested to know the underlying hardware, we should
> access directly to the nested device.

The nested devices are not visible in testpmd (or other
applications that iterate over ports).
  

Patch

diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 070cf7111..6f29e5a62 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -237,6 +237,7 @@  static const struct eth_dev_ops mlx4_dev_ops = {
 	.mac_addr_set = mlx4_mac_addr_set,
 	.stats_get = mlx4_stats_get,
 	.stats_reset = mlx4_stats_reset,
+	.fw_version_get = mlx4_fw_version_get,
 	.dev_infos_get = mlx4_dev_infos_get,
 	.dev_supported_ptypes_get = mlx4_dev_supported_ptypes_get,
 	.vlan_filter_set = mlx4_vlan_filter_set,
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index e6fb934fa..6f4111582 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -131,6 +131,7 @@  int mlx4_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr);
 int mlx4_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on);
 int mlx4_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats);
 void mlx4_stats_reset(struct rte_eth_dev *dev);
+int mlx4_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size);
 void mlx4_dev_infos_get(struct rte_eth_dev *dev,
 			struct rte_eth_dev_info *info);
 int mlx4_link_update(struct rte_eth_dev *dev, int wait_to_complete);
diff --git a/drivers/net/mlx4/mlx4_ethdev.c b/drivers/net/mlx4/mlx4_ethdev.c
index 195a1b6df..d0efa7d06 100644
--- a/drivers/net/mlx4/mlx4_ethdev.c
+++ b/drivers/net/mlx4/mlx4_ethdev.c
@@ -592,6 +592,32 @@  mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 	info->flow_type_rss_offloads = mlx4_conv_rss_types(priv, 0, 1);
 }
 
+/**
+ * Get firmware version of a device.
+ *
+ * @param dev
+ *   Ethernet device port.
+ * @param fw_ver
+ *   String output allocated by caller.
+ * @param fw_size
+ *   Size of the output string, including terminating null byte.
+ *
+ * @return
+ *   0 on success, or the size of the non truncated string if too big.
+ */
+int mlx4_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size)
+{
+	struct priv *priv = dev->data->dev_private;
+	struct ibv_device_attr *attr = &priv->device_attr;
+	size_t size = strnlen(attr->fw_ver, sizeof(attr->fw_ver)) + 1;
+
+	if (fw_size < size)
+		return size;
+	if (fw_ver != NULL)
+		strlcpy(fw_ver, attr->fw_ver, fw_size);
+	return 0;
+}
+
 /**
  * DPDK callback to get device statistics.
  *
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index a913a5955..df71707cc 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -374,6 +374,7 @@  const struct eth_dev_ops mlx5_dev_ops = {
 	.xstats_get = mlx5_xstats_get,
 	.xstats_reset = mlx5_xstats_reset,
 	.xstats_get_names = mlx5_xstats_get_names,
+	.fw_version_get = mlx5_fw_version_get,
 	.dev_infos_get = mlx5_dev_infos_get,
 	.dev_supported_ptypes_get = mlx5_dev_supported_ptypes_get,
 	.vlan_filter_set = mlx5_vlan_filter_set,
@@ -403,18 +404,20 @@  const struct eth_dev_ops mlx5_dev_ops = {
 	.is_removed = mlx5_is_removed,
 };
 
+/* Available operations from secondary process. */
 static const struct eth_dev_ops mlx5_dev_sec_ops = {
 	.stats_get = mlx5_stats_get,
 	.stats_reset = mlx5_stats_reset,
 	.xstats_get = mlx5_xstats_get,
 	.xstats_reset = mlx5_xstats_reset,
 	.xstats_get_names = mlx5_xstats_get_names,
+	.fw_version_get = mlx5_fw_version_get,
 	.dev_infos_get = mlx5_dev_infos_get,
 	.rx_descriptor_status = mlx5_rx_descriptor_status,
 	.tx_descriptor_status = mlx5_tx_descriptor_status,
 };
 
-/* Available operators in flow isolated mode. */
+/* Available operations in flow isolated mode. */
 const struct eth_dev_ops mlx5_dev_ops_isolate = {
 	.dev_configure = mlx5_dev_configure,
 	.dev_start = mlx5_dev_start,
@@ -432,6 +435,7 @@  const struct eth_dev_ops mlx5_dev_ops_isolate = {
 	.xstats_get = mlx5_xstats_get,
 	.xstats_reset = mlx5_xstats_reset,
 	.xstats_get_names = mlx5_xstats_get_names,
+	.fw_version_get = mlx5_fw_version_get,
 	.dev_infos_get = mlx5_dev_infos_get,
 	.dev_supported_ptypes_get = mlx5_dev_supported_ptypes_get,
 	.vlan_filter_set = mlx5_vlan_filter_set,
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 45f039821..3193ed9ca 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -274,6 +274,7 @@  int mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep,
 		   unsigned int flags);
 int mlx5_dev_configure(struct rte_eth_dev *dev);
 void mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info);
+int mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size);
 const uint32_t *mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev);
 int mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete);
 int mlx5_force_link_status_change(struct rte_eth_dev *dev, int status);
diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c
index d178ed6a1..8158b4a9f 100644
--- a/drivers/net/mlx5/mlx5_ethdev.c
+++ b/drivers/net/mlx5/mlx5_ethdev.c
@@ -557,6 +557,32 @@  mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 	}
 }
 
+/**
+ * Get firmware version of a device.
+ *
+ * @param dev
+ *   Ethernet device port.
+ * @param fw_ver
+ *   String output allocated by caller.
+ * @param fw_size
+ *   Size of the output string, including terminating null byte.
+ *
+ * @return
+ *   0 on success, or the size of the non truncated string if too big.
+ */
+int mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size)
+{
+	struct priv *priv = dev->data->dev_private;
+	struct ibv_device_attr *attr = &priv->device_attr.orig_attr;
+	size_t size = strnlen(attr->fw_ver, sizeof(attr->fw_ver)) + 1;
+
+	if (fw_size < size)
+		return size;
+	if (fw_ver != NULL)
+		strlcpy(fw_ver, attr->fw_ver, fw_size);
+	return 0;
+}
+
 /**
  * Get supported packet types.
  *