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

Commit 511d5d5b authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mlx5-next'



Saeed Mahameed says:

====================
Mellanox 100G mlx5 update 2016-11-15

This series contains four humble mlx5 features.

From Gal,
 - Add the support for PCIe statistics and expose them in ethtool

From Huy,
 - Add the support for port module events reporting and statistics
 - Add the support for driver version setting into FW (for display purposes only)

From Mohamad,
 - Extended the command interface cache flexibility

This series was generated against commit
6a02f5eb ("Merge branch 'mlxsw-i2c")

V2:
 - Changed plain "unsigned" to "unsigned int"
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7a8bca04 9c726239
Loading
Loading
Loading
Loading
+69 −76
Original line number Diff line number Diff line
@@ -53,14 +53,6 @@ enum {
	CMD_MODE_EVENTS
};

enum {
	NUM_LONG_LISTS	  = 2,
	NUM_MED_LISTS	  = 64,
	LONG_LIST_SIZE	  = (2ULL * 1024 * 1024 * 1024 / PAGE_SIZE) * 8 + 16 +
				MLX5_CMD_DATA_BLOCK_SIZE,
	MED_LIST_SIZE	  = 16 + MLX5_CMD_DATA_BLOCK_SIZE,
};

enum {
	MLX5_CMD_DELIVERY_STAT_OK			= 0x0,
	MLX5_CMD_DELIVERY_STAT_SIGNAT_ERR		= 0x1,
@@ -1372,10 +1364,10 @@ static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg)
{
	unsigned long flags;

	if (msg->cache) {
		spin_lock_irqsave(&msg->cache->lock, flags);
		list_add_tail(&msg->list, &msg->cache->head);
		spin_unlock_irqrestore(&msg->cache->lock, flags);
	if (msg->parent) {
		spin_lock_irqsave(&msg->parent->lock, flags);
		list_add_tail(&msg->list, &msg->parent->head);
		spin_unlock_irqrestore(&msg->parent->lock, flags);
	} else {
		mlx5_free_cmd_msg(dev, msg);
	}
@@ -1472,30 +1464,37 @@ static struct mlx5_cmd_msg *alloc_msg(struct mlx5_core_dev *dev, int in_size,
				      gfp_t gfp)
{
	struct mlx5_cmd_msg *msg = ERR_PTR(-ENOMEM);
	struct cmd_msg_cache *ch = NULL;
	struct mlx5_cmd *cmd = &dev->cmd;
	struct cache_ent *ent = NULL;
	int i;

	if (in_size > MED_LIST_SIZE && in_size <= LONG_LIST_SIZE)
		ent = &cmd->cache.large;
	else if (in_size > 16 && in_size <= MED_LIST_SIZE)
		ent = &cmd->cache.med;
	if (in_size <= 16)
		goto cache_miss;

	if (ent) {
		spin_lock_irq(&ent->lock);
		if (!list_empty(&ent->head)) {
			msg = list_entry(ent->head.next, typeof(*msg), list);
	for (i = 0; i < MLX5_NUM_COMMAND_CACHES; i++) {
		ch = &cmd->cache[i];
		if (in_size > ch->max_inbox_size)
			continue;
		spin_lock_irq(&ch->lock);
		if (list_empty(&ch->head)) {
			spin_unlock_irq(&ch->lock);
			continue;
		}
		msg = list_entry(ch->head.next, typeof(*msg), list);
		/* For cached lists, we must explicitly state what is
		 * the real size
		 */
		msg->len = in_size;
		list_del(&msg->list);
		}
		spin_unlock_irq(&ent->lock);
		spin_unlock_irq(&ch->lock);
		break;
	}

	if (IS_ERR(msg))
		msg = mlx5_alloc_cmd_msg(dev, gfp, in_size, 0);
	if (!IS_ERR(msg))
		return msg;

cache_miss:
	msg = mlx5_alloc_cmd_msg(dev, gfp, in_size, 0);
	return msg;
}

@@ -1593,58 +1592,56 @@ EXPORT_SYMBOL(mlx5_cmd_exec_cb);

static void destroy_msg_cache(struct mlx5_core_dev *dev)
{
	struct mlx5_cmd *cmd = &dev->cmd;
	struct cmd_msg_cache *ch;
	struct mlx5_cmd_msg *msg;
	struct mlx5_cmd_msg *n;
	int i;

	list_for_each_entry_safe(msg, n, &cmd->cache.large.head, list) {
	for (i = 0; i < MLX5_NUM_COMMAND_CACHES; i++) {
		ch = &dev->cmd.cache[i];
		list_for_each_entry_safe(msg, n, &ch->head, list) {
			list_del(&msg->list);
			mlx5_free_cmd_msg(dev, msg);
		}

	list_for_each_entry_safe(msg, n, &cmd->cache.med.head, list) {
		list_del(&msg->list);
		mlx5_free_cmd_msg(dev, msg);
	}
}

static int create_msg_cache(struct mlx5_core_dev *dev)
static unsigned cmd_cache_num_ent[MLX5_NUM_COMMAND_CACHES] = {
	512, 32, 16, 8, 2
};

static unsigned cmd_cache_ent_size[MLX5_NUM_COMMAND_CACHES] = {
	16 + MLX5_CMD_DATA_BLOCK_SIZE,
	16 + MLX5_CMD_DATA_BLOCK_SIZE * 2,
	16 + MLX5_CMD_DATA_BLOCK_SIZE * 16,
	16 + MLX5_CMD_DATA_BLOCK_SIZE * 256,
	16 + MLX5_CMD_DATA_BLOCK_SIZE * 512,
};

static void create_msg_cache(struct mlx5_core_dev *dev)
{
	struct mlx5_cmd *cmd = &dev->cmd;
	struct cmd_msg_cache *ch;
	struct mlx5_cmd_msg *msg;
	int err;
	int i;

	spin_lock_init(&cmd->cache.large.lock);
	INIT_LIST_HEAD(&cmd->cache.large.head);
	spin_lock_init(&cmd->cache.med.lock);
	INIT_LIST_HEAD(&cmd->cache.med.head);

	for (i = 0; i < NUM_LONG_LISTS; i++) {
		msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, LONG_LIST_SIZE, 0);
		if (IS_ERR(msg)) {
			err = PTR_ERR(msg);
			goto ex_err;
		}
		msg->cache = &cmd->cache.large;
		list_add_tail(&msg->list, &cmd->cache.large.head);
	int k;

	/* Initialize and fill the caches with initial entries */
	for (k = 0; k < MLX5_NUM_COMMAND_CACHES; k++) {
		ch = &cmd->cache[k];
		spin_lock_init(&ch->lock);
		INIT_LIST_HEAD(&ch->head);
		ch->num_ent = cmd_cache_num_ent[k];
		ch->max_inbox_size = cmd_cache_ent_size[k];
		for (i = 0; i < ch->num_ent; i++) {
			msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL | __GFP_NOWARN,
						 ch->max_inbox_size, 0);
			if (IS_ERR(msg))
				break;
			msg->parent = ch;
			list_add_tail(&msg->list, &ch->head);
		}

	for (i = 0; i < NUM_MED_LISTS; i++) {
		msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, MED_LIST_SIZE, 0);
		if (IS_ERR(msg)) {
			err = PTR_ERR(msg);
			goto ex_err;
	}
		msg->cache = &cmd->cache.med;
		list_add_tail(&msg->list, &cmd->cache.med.head);
	}

	return 0;

ex_err:
	destroy_msg_cache(dev);
	return err;
}

static int alloc_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd)
@@ -1767,11 +1764,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)

	cmd->mode = CMD_MODE_POLLING;

	err = create_msg_cache(dev);
	if (err) {
		dev_err(&dev->pdev->dev, "failed to create command cache\n");
		goto err_free_page;
	}
	create_msg_cache(dev);

	set_wqname(dev);
	cmd->wq = create_singlethread_workqueue(cmd->wq_name);
+39 −1
Original line number Diff line number Diff line
@@ -171,9 +171,13 @@ static int mlx5e_get_sset_count(struct net_device *dev, int sset)
		return NUM_SW_COUNTERS +
		       MLX5E_NUM_Q_CNTRS(priv) +
		       NUM_VPORT_COUNTERS + NUM_PPORT_COUNTERS +
		       NUM_PCIE_COUNTERS +
		       MLX5E_NUM_RQ_STATS(priv) +
		       MLX5E_NUM_SQ_STATS(priv) +
		       MLX5E_NUM_PFC_COUNTERS(priv);
		       MLX5E_NUM_PFC_COUNTERS(priv) +
		       ARRAY_SIZE(mlx5e_pme_status_desc) +
		       ARRAY_SIZE(mlx5e_pme_error_desc);

	case ETH_SS_PRIV_FLAGS:
		return ARRAY_SIZE(mlx5e_priv_flags);
	/* fallthrough */
@@ -213,6 +217,14 @@ static void mlx5e_fill_stats_strings(struct mlx5e_priv *priv, uint8_t *data)
		strcpy(data + (idx++) * ETH_GSTRING_LEN,
		       pport_2819_stats_desc[i].format);

	for (i = 0; i < NUM_PCIE_PERF_COUNTERS; i++)
		strcpy(data + (idx++) * ETH_GSTRING_LEN,
		       pcie_perf_stats_desc[i].format);

	for (i = 0; i < NUM_PCIE_TAS_COUNTERS; i++)
		strcpy(data + (idx++) * ETH_GSTRING_LEN,
		       pcie_tas_stats_desc[i].format);

	for (prio = 0; prio < NUM_PPORT_PRIO; prio++) {
		for (i = 0; i < NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS; i++)
			sprintf(data + (idx++) * ETH_GSTRING_LEN,
@@ -237,6 +249,13 @@ static void mlx5e_fill_stats_strings(struct mlx5e_priv *priv, uint8_t *data)
		}
	}

	/* port module event counters */
	for (i = 0; i < ARRAY_SIZE(mlx5e_pme_status_desc); i++)
		strcpy(data + (idx++) * ETH_GSTRING_LEN, mlx5e_pme_status_desc[i].format);

	for (i = 0; i < ARRAY_SIZE(mlx5e_pme_error_desc); i++)
		strcpy(data + (idx++) * ETH_GSTRING_LEN, mlx5e_pme_error_desc[i].format);

	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
		return;

@@ -279,6 +298,7 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev,
				    struct ethtool_stats *stats, u64 *data)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_priv *mlx5_priv;
	int i, j, tc, prio, idx = 0;
	unsigned long pfc_combined;

@@ -314,6 +334,14 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev,
		data[idx++] = MLX5E_READ_CTR64_BE(&priv->stats.pport.RFC_2819_counters,
						  pport_2819_stats_desc, i);

	for (i = 0; i < NUM_PCIE_PERF_COUNTERS; i++)
		data[idx++] = MLX5E_READ_CTR32_BE(&priv->stats.pcie.pcie_perf_counters,
						  pcie_perf_stats_desc, i);

	for (i = 0; i < NUM_PCIE_TAS_COUNTERS; i++)
		data[idx++] = MLX5E_READ_CTR32_BE(&priv->stats.pcie.pcie_tas_counters,
						  pcie_tas_stats_desc, i);

	for (prio = 0; prio < NUM_PPORT_PRIO; prio++) {
		for (i = 0; i < NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS; i++)
			data[idx++] = MLX5E_READ_CTR64_BE(&priv->stats.pport.per_prio_counters[prio],
@@ -335,6 +363,16 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev,
		}
	}

	/* port module event counters */
	mlx5_priv =  &priv->mdev->priv;
	for (i = 0; i < ARRAY_SIZE(mlx5e_pme_status_desc); i++)
		data[idx++] = MLX5E_READ_CTR64_CPU(mlx5_priv->pme_stats.status_counters,
						   mlx5e_pme_status_desc, i);

	for (i = 0; i < ARRAY_SIZE(mlx5e_pme_error_desc); i++)
		data[idx++] = MLX5E_READ_CTR64_CPU(mlx5_priv->pme_stats.error_counters,
						   mlx5e_pme_error_desc, i);

	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
		return;

+24 −0
Original line number Diff line number Diff line
@@ -290,12 +290,36 @@ static void mlx5e_update_q_counter(struct mlx5e_priv *priv)
				      &qcnt->rx_out_of_buffer);
}

static void mlx5e_update_pcie_counters(struct mlx5e_priv *priv)
{
	struct mlx5e_pcie_stats *pcie_stats = &priv->stats.pcie;
	struct mlx5_core_dev *mdev = priv->mdev;
	int sz = MLX5_ST_SZ_BYTES(mpcnt_reg);
	void *out;
	u32 *in;

	in = mlx5_vzalloc(sz);
	if (!in)
		return;

	out = pcie_stats->pcie_perf_counters;
	MLX5_SET(mpcnt_reg, in, grp, MLX5_PCIE_PERFORMANCE_COUNTERS_GROUP);
	mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_MPCNT, 0, 0);

	out = pcie_stats->pcie_tas_counters;
	MLX5_SET(mpcnt_reg, in, grp, MLX5_PCIE_TIMERS_AND_STATES_COUNTERS_GROUP);
	mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_MPCNT, 0, 0);

	kvfree(in);
}

void mlx5e_update_stats(struct mlx5e_priv *priv)
{
	mlx5e_update_q_counter(priv);
	mlx5e_update_vport_counters(priv);
	mlx5e_update_pport_counters(priv);
	mlx5e_update_sw_counters(priv);
	mlx5e_update_pcie_counters(priv);
}

void mlx5e_update_stats_work(struct work_struct *work)
+48 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@
#define MLX5E_READ_CTR32_CPU(ptr, dsc, i) \
	(*(u32 *)((char *)ptr + dsc[i].offset))
#define MLX5E_READ_CTR32_BE(ptr, dsc, i) \
	be64_to_cpu(*(__be32 *)((char *)ptr + dsc[i].offset))
	be32_to_cpu(*(__be32 *)((char *)ptr + dsc[i].offset))

#define MLX5E_DECLARE_STAT(type, fld) #fld, offsetof(type, fld)
#define MLX5E_DECLARE_RX_STAT(type, fld) "rx%d_"#fld, offsetof(type, fld)
@@ -276,6 +276,32 @@ static const struct counter_desc pport_per_prio_pfc_stats_desc[] = {
	{ "rx_%s_pause_transition", PPORT_PER_PRIO_OFF(rx_pause_transition) },
};

#define PCIE_PERF_OFF(c) \
	MLX5_BYTE_OFF(mpcnt_reg, counter_set.pcie_perf_cntrs_grp_data_layout.c)
#define PCIE_PERF_GET(pcie_stats, c) \
	MLX5_GET(mpcnt_reg, pcie_stats->pcie_perf_counters, \
		 counter_set.pcie_perf_cntrs_grp_data_layout.c)
#define PCIE_TAS_OFF(c) \
	MLX5_BYTE_OFF(mpcnt_reg, counter_set.pcie_tas_cntrs_grp_data_layout.c)
#define PCIE_TAS_GET(pcie_stats, c) \
	MLX5_GET(mpcnt_reg, pcie_stats->pcie_tas_counters, \
		 counter_set.pcie_tas_cntrs_grp_data_layout.c)

struct mlx5e_pcie_stats {
	__be64 pcie_perf_counters[MLX5_ST_SZ_QW(mpcnt_reg)];
	__be64 pcie_tas_counters[MLX5_ST_SZ_QW(mpcnt_reg)];
};

static const struct counter_desc pcie_perf_stats_desc[] = {
	{ "rx_pci_signal_integrity", PCIE_PERF_OFF(rx_errors) },
	{ "tx_pci_signal_integrity", PCIE_PERF_OFF(tx_errors) },
};

static const struct counter_desc pcie_tas_stats_desc[] = {
	{ "tx_pci_transport_nonfatal_msg", PCIE_TAS_OFF(non_fatal_err_msg_sent) },
	{ "tx_pci_transport_fatal_msg", PCIE_TAS_OFF(fatal_err_msg_sent) },
};

struct mlx5e_rq_stats {
	u64 packets;
	u64 bytes;
@@ -360,6 +386,8 @@ static const struct counter_desc sq_stats_desc[] = {
#define NUM_PPORT_802_3_COUNTERS	ARRAY_SIZE(pport_802_3_stats_desc)
#define NUM_PPORT_2863_COUNTERS		ARRAY_SIZE(pport_2863_stats_desc)
#define NUM_PPORT_2819_COUNTERS		ARRAY_SIZE(pport_2819_stats_desc)
#define NUM_PCIE_PERF_COUNTERS		ARRAY_SIZE(pcie_perf_stats_desc)
#define NUM_PCIE_TAS_COUNTERS		ARRAY_SIZE(pcie_tas_stats_desc)
#define NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS \
	ARRAY_SIZE(pport_per_prio_traffic_stats_desc)
#define NUM_PPORT_PER_PRIO_PFC_COUNTERS \
@@ -369,6 +397,7 @@ static const struct counter_desc sq_stats_desc[] = {
					 NUM_PPORT_2819_COUNTERS  + \
					 NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS * \
					 NUM_PPORT_PRIO)
#define NUM_PCIE_COUNTERS		(NUM_PCIE_PERF_COUNTERS + NUM_PCIE_TAS_COUNTERS)
#define NUM_RQ_STATS			ARRAY_SIZE(rq_stats_desc)
#define NUM_SQ_STATS			ARRAY_SIZE(sq_stats_desc)

@@ -377,6 +406,24 @@ struct mlx5e_stats {
	struct mlx5e_qcounter_stats qcnt;
	struct mlx5e_vport_stats vport;
	struct mlx5e_pport_stats pport;
	struct mlx5e_pcie_stats pcie;
};

static const struct counter_desc mlx5e_pme_status_desc[] = {
	{ "module_plug", 0 },
	{ "module_unplug", 8 },
};

static const struct counter_desc mlx5e_pme_error_desc[] = {
	{ "module_pwr_budget_exd", 0 },  /* power budget exceed */
	{ "module_long_range", 8 },      /* long range for non MLNX cable */
	{ "module_bus_stuck", 16 },      /* bus stuck (I2C or data shorted) */
	{ "module_no_eeprom", 24 },      /* no eeprom/retry time out */
	{ "module_enforce_part", 32 },   /* enforce part number list */
	{ "module_unknown_id", 40 },     /* unknown identifier */
	{ "module_high_temp", 48 },      /* high temperature */
	{ "module_bad_shorted", 56 },    /* bad or shorted cable/module */
	{ "module_unknown_status", 64 },
};

#endif /* __MLX5_EN_STATS_H__ */
+12 −0
Original line number Diff line number Diff line
@@ -139,6 +139,8 @@ static const char *eqe_type_str(u8 type)
		return "MLX5_EVENT_TYPE_PORT_CHANGE";
	case MLX5_EVENT_TYPE_GPIO_EVENT:
		return "MLX5_EVENT_TYPE_GPIO_EVENT";
	case MLX5_EVENT_TYPE_PORT_MODULE_EVENT:
		return "MLX5_EVENT_TYPE_PORT_MODULE_EVENT";
	case MLX5_EVENT_TYPE_REMOTE_CONFIG:
		return "MLX5_EVENT_TYPE_REMOTE_CONFIG";
	case MLX5_EVENT_TYPE_DB_BF_CONGESTION:
@@ -285,6 +287,11 @@ static int mlx5_eq_int(struct mlx5_core_dev *dev, struct mlx5_eq *eq)
			mlx5_eswitch_vport_event(dev->priv.eswitch, eqe);
			break;
#endif

		case MLX5_EVENT_TYPE_PORT_MODULE_EVENT:
			mlx5_port_module_event(dev, eqe);
			break;

		default:
			mlx5_core_warn(dev, "Unhandled event 0x%x on EQ 0x%x\n",
				       eqe->type, eq->eqn);
@@ -480,6 +487,11 @@ int mlx5_start_eqs(struct mlx5_core_dev *dev)
	    mlx5_core_is_pf(dev))
		async_event_mask |= (1ull << MLX5_EVENT_TYPE_NIC_VPORT_CHANGE);

	if (MLX5_CAP_GEN(dev, port_module_event))
		async_event_mask |= (1ull << MLX5_EVENT_TYPE_PORT_MODULE_EVENT);
	else
		mlx5_core_dbg(dev, "port_module_event is not set\n");

	err = mlx5_create_map_eq(dev, &table->cmd_eq, MLX5_EQ_VEC_CMD,
				 MLX5_NUM_CMD_EQE, 1ull << MLX5_EVENT_TYPE_CMD,
				 "mlx5_cmd_eq", &dev->priv.uuari.uars[0]);
Loading