Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 62a89055 authored by Eran Ben Elisha's avatar Eran Ben Elisha Committed by David S. Miller
Browse files

net/mlx4_en: Support ndo_get_vf_stats



Implement the ndo to gather VF statistics through the PF.

All counters related to this VF are stored in a per slave
list, run over the slave's list and collect all statistics.

Signed-off-by: default avatarEran Ben Elisha <eranbe@mellanox.com>
Signed-off-by: default avatarHadar Hen Zion <hadarh@mellanox.com>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3b766cd8
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -3223,6 +3223,36 @@ int mlx4_get_counter_stats(struct mlx4_dev *dev, int counter_index,
}
EXPORT_SYMBOL_GPL(mlx4_get_counter_stats);

int mlx4_get_vf_stats(struct mlx4_dev *dev, int port, int vf_idx,
		      struct ifla_vf_stats *vf_stats)
{
	struct mlx4_counter tmp_vf_stats;
	int slave;
	int err = 0;

	if (!vf_stats)
		return -EINVAL;

	if (!mlx4_is_master(dev))
		return -EPROTONOSUPPORT;

	slave = mlx4_get_slave_indx(dev, vf_idx);
	if (slave < 0)
		return -EINVAL;

	port = mlx4_slaves_closest_port(dev, slave, port);
	err = mlx4_calc_vf_counters(dev, slave, port, &tmp_vf_stats);
	if (!err && tmp_vf_stats.counter_mode == 0) {
		vf_stats->rx_packets = be64_to_cpu(tmp_vf_stats.rx_frames);
		vf_stats->tx_packets = be64_to_cpu(tmp_vf_stats.tx_frames);
		vf_stats->rx_bytes = be64_to_cpu(tmp_vf_stats.rx_bytes);
		vf_stats->tx_bytes = be64_to_cpu(tmp_vf_stats.tx_bytes);
	}

	return err;
}
EXPORT_SYMBOL_GPL(mlx4_get_vf_stats);

int mlx4_vf_smi_enabled(struct mlx4_dev *dev, int slave, int port)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
+10 −0
Original line number Diff line number Diff line
@@ -2292,6 +2292,15 @@ static int mlx4_en_set_vf_link_state(struct net_device *dev, int vf, int link_st
	return mlx4_set_vf_link_state(mdev->dev, en_priv->port, vf, link_state);
}

static int mlx4_en_get_vf_stats(struct net_device *dev, int vf,
				struct ifla_vf_stats *vf_stats)
{
	struct mlx4_en_priv *en_priv = netdev_priv(dev);
	struct mlx4_en_dev *mdev = en_priv->mdev;

	return mlx4_get_vf_stats(mdev->dev, en_priv->port, vf, vf_stats);
}

#define PORT_ID_BYTE_LEN 8
static int mlx4_en_get_phys_port_id(struct net_device *dev,
				    struct netdev_phys_item_id *ppid)
@@ -2489,6 +2498,7 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
	.ndo_set_vf_rate	= mlx4_en_set_vf_rate,
	.ndo_set_vf_spoofchk	= mlx4_en_set_vf_spoofchk,
	.ndo_set_vf_link_state	= mlx4_en_set_vf_link_state,
	.ndo_get_vf_stats       = mlx4_en_get_vf_stats,
	.ndo_get_vf_config	= mlx4_en_get_vf_config,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= mlx4_en_netpoll,
+2 −0
Original line number Diff line number Diff line
@@ -1010,6 +1010,8 @@ int __mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
		     int start_index, int npages, u64 *page_list);
int __mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx);
void __mlx4_counter_free(struct mlx4_dev *dev, u32 idx);
int mlx4_calc_vf_counters(struct mlx4_dev *dev, int slave, int port,
			  struct mlx4_counter *data);
int __mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn);
void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn);

+48 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@

#include "mlx4.h"
#include "fw.h"
#include "mlx4_stats.h"

#define MLX4_MAC_VALID		(1ull << 63)
#define MLX4_PF_COUNTERS_PER_PORT	2
@@ -1147,6 +1148,53 @@ static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave,
	return ret;
}

int mlx4_calc_vf_counters(struct mlx4_dev *dev, int slave, int port,
			  struct mlx4_counter *data)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
	struct res_common *tmp;
	struct res_counter *counter;
	int *counters_arr;
	int i = 0, err = 0;

	memset(data, 0, sizeof(*data));

	counters_arr = kmalloc_array(dev->caps.max_counters,
				     sizeof(*counters_arr), GFP_KERNEL);
	if (!counters_arr)
		return -ENOMEM;

	spin_lock_irq(mlx4_tlock(dev));
	list_for_each_entry(tmp,
			    &tracker->slave_list[slave].res_list[RES_COUNTER],
			    list) {
		counter = container_of(tmp, struct res_counter, com);
		if (counter->port == port) {
			counters_arr[i] = (int)tmp->res_id;
			i++;
		}
	}
	spin_unlock_irq(mlx4_tlock(dev));
	counters_arr[i] = -1;

	i = 0;

	while (counters_arr[i] != -1) {
		err = mlx4_get_counter_stats(dev, counters_arr[i], data,
					     0);
		if (err) {
			memset(data, 0, sizeof(*data));
			goto table_changed;
		}
		i++;
	}

table_changed:
	kfree(counters_arr);
	return 0;
}

static int add_res_range(struct mlx4_dev *dev, int slave, u64 base, int count,
			 enum mlx4_resource type, int extra)
{
+3 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <linux/dma-mapping.h>
#include <linux/if_link.h>
#include <linux/mlx4/device.h>
#include <linux/netdevice.h>

enum {
	/* initialization and general commands */
@@ -303,6 +304,8 @@ void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbo

int mlx4_get_counter_stats(struct mlx4_dev *dev, int counter_index,
			   struct mlx4_counter *counter_stats, int reset);
int mlx4_get_vf_stats(struct mlx4_dev *dev, int port, int vf_idx,
		      struct ifla_vf_stats *vf_stats);
u32 mlx4_comm_get_version(void);
int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac);
int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos);