en_port.c revision 219893
119304Speter/*
219304Speter * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
319304Speter *
419304Speter * This software is available to you under a choice of one of two
519304Speter * licenses.  You may choose to be licensed under the terms of the GNU
619304Speter * General Public License (GPL) Version 2, available from the file
719304Speter * COPYING in the main directory of this source tree, or the
819304Speter * OpenIB.org BSD license below:
919304Speter *
1019304Speter *     Redistribution and use in source and binary forms, with or
1119304Speter *     without modification, are permitted provided that the following
1219304Speter *     conditions are met:
13254225Speter *
1419304Speter *      - Redistributions of source code must retain the above
1519304Speter *        copyright notice, this list of conditions and the following
1619304Speter *        disclaimer.
1719304Speter *
1819304Speter *      - Redistributions in binary form must reproduce the above
1919304Speter *        copyright notice, this list of conditions and the following
2019304Speter *        disclaimer in the documentation and/or other materials
2119304Speter *        provided with the distribution.
2219304Speter *
2319304Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2419304Speter * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2519304Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26254225Speter * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27254225Speter * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28254225Speter * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2919304Speter * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3019304Speter * SOFTWARE.
3119304Speter *
3219304Speter */
3319304Speter
3419304Speter
3519304Speter#include "mlx4_en.h"
3619304Speter
3719304Speter#include <linux/if_vlan.h>
3819304Speter
3919304Speter#include <linux/mlx4/device.h>
4019304Speter#include <linux/mlx4/cmd.h>
4119304Speter
4219304Speter
4319304Speterint mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port,
4419304Speter			u64 mac, u64 clear, u8 mode)
4519304Speter{
4619304Speter	return mlx4_cmd(dev, (mac | (clear << 63)), port, mode,
4719304Speter			MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B);
4819304Speter}
4919304Speter
5019304Speterint mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, u32 *vlans)
5119304Speter{
52254225Speter	struct mlx4_cmd_mailbox *mailbox;
5319304Speter	struct mlx4_set_vlan_fltr_mbox *filter;
5419304Speter	int i, j;
5519304Speter	int err = 0;
5619304Speter
5719304Speter	mailbox = mlx4_alloc_cmd_mailbox(dev);
5819304Speter	if (IS_ERR(mailbox))
59254225Speter		return PTR_ERR(mailbox);
6019304Speter
6119304Speter	filter = mailbox->buf;
6219304Speter	memset(filter, 0, sizeof *filter);
6319304Speter	if (vlans)
6419304Speter		for (i = 0, j = VLAN_FLTR_SIZE - 1; i < VLAN_FLTR_SIZE;
6519304Speter		    i++, j--)
6619304Speter			filter->entry[j] = cpu_to_be32(vlans[i]);
6719304Speter	err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_VLAN_FLTR,
6819304Speter		       MLX4_CMD_TIME_CLASS_B);
6919304Speter	mlx4_free_cmd_mailbox(dev, mailbox);
7019304Speter	return err;
7119304Speter}
7219304Speter
7319304Speter
7419304Speterint mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
7519304Speter			  u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx)
7619304Speter{
7719304Speter	struct mlx4_cmd_mailbox *mailbox;
7819304Speter	struct mlx4_set_port_general_context *context;
7919304Speter	int err;
8019304Speter	u32 in_mod;
8119304Speter
8219304Speter	mailbox = mlx4_alloc_cmd_mailbox(dev);
8319304Speter	if (IS_ERR(mailbox))
8419304Speter		return PTR_ERR(mailbox);
8519304Speter	context = mailbox->buf;
8619304Speter	memset(context, 0, sizeof *context);
8719304Speter
8819304Speter	context->flags = SET_PORT_GEN_ALL_VALID;
8919304Speter	context->mtu = cpu_to_be16(mtu);
9019304Speter	context->pptx = (pptx * (!pfctx)) << 7;
9119304Speter	context->pfctx = pfctx;
9219304Speter	context->pprx = (pprx * (!pfcrx)) << 7;
9319304Speter	context->pfcrx = pfcrx;
9419304Speter
9519304Speter	in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
9619304Speter	err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
9719304Speter		       MLX4_CMD_TIME_CLASS_B);
9819304Speter
9919304Speter	mlx4_free_cmd_mailbox(dev, mailbox);
10019304Speter	return err;
10119304Speter}
10219304Speter
10319304Speterint mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
10419304Speter			   u8 promisc)
10519304Speter{
10619304Speter	struct mlx4_cmd_mailbox *mailbox;
10719304Speter	struct mlx4_set_port_rqp_calc_context *context;
10819304Speter	int err;
10919304Speter	u32 in_mod;
11019304Speter
11119304Speter	mailbox = mlx4_alloc_cmd_mailbox(dev);
11219304Speter	if (IS_ERR(mailbox))
11319304Speter		return PTR_ERR(mailbox);
11419304Speter	context = mailbox->buf;
11519304Speter	memset(context, 0, sizeof *context);
11619304Speter
11719304Speter	context->base_qpn = cpu_to_be32(base_qpn);
11819304Speter	context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_EN_SHIFT | base_qpn);
11919304Speter	context->mcast = cpu_to_be32((dev->caps.mc_promisc_mode <<
12019304Speter				      SET_PORT_PROMISC_MODE_SHIFT) | base_qpn);
12119304Speter	context->intra_no_vlan = 0;
12219304Speter	context->no_vlan = MLX4_NO_VLAN_IDX;
12319304Speter	context->intra_vlan_miss = 0;
12419304Speter	context->vlan_miss = MLX4_VLAN_MISS_IDX;
12519304Speter
12619304Speter	in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port;
12719304Speter	err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
12819304Speter		       MLX4_CMD_TIME_CLASS_B);
12919304Speter
13019304Speter	mlx4_free_cmd_mailbox(dev, mailbox);
13119304Speter	return err;
13219304Speter}
13319304Speter
13419304Speterint mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port)
13519304Speter{
13619304Speter	struct mlx4_en_query_port_context *qport_context;
13719304Speter	struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]);
138254225Speter	struct mlx4_en_port_state *state = &priv->port_state;
139254225Speter	struct mlx4_cmd_mailbox *mailbox;
14019304Speter	int err;
14119304Speter
14219304Speter	mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
14319304Speter	if (IS_ERR(mailbox))
14419304Speter		return PTR_ERR(mailbox);
14519304Speter	memset(mailbox->buf, 0, sizeof(*qport_context));
14619304Speter	err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0,
14719304Speter			   MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B);
14819304Speter	if (err)
14919304Speter		goto out;
150254225Speter	qport_context = mailbox->buf;
151254225Speter
15219304Speter	/* This command is always accessed from Ethtool context
153254225Speter	 * already synchronized, no need in locking */
15419304Speter	state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK);
15519304Speter	if ((qport_context->link_speed & MLX4_EN_SPEED_MASK) ==
15619304Speter	    MLX4_EN_1G_SPEED)
15719304Speter		state->link_speed = 1000;
15819304Speter	else
15919304Speter		state->link_speed = 10000;
16019304Speter	state->transciver = qport_context->transceiver;
16119304Speter	if (be32_to_cpu(qport_context->transceiver_code_hi) & 0x400)
16219304Speter		state->transciver = 0x80;
16319304Speter
16419304Speterout:
165254225Speter	mlx4_free_cmd_mailbox(mdev->dev, mailbox);
16619304Speter	return err;
16719304Speter}
16819304Speter
16919304Speterstatic int read_iboe_counters(struct mlx4_dev *dev, int index, u64 counters[])
17019304Speter{
17119304Speter	struct mlx4_cmd_mailbox *mailbox;
17219304Speter	int err;
17319304Speter	int mode;
17419304Speter	struct mlx4_counters_ext *ext;
17519304Speter	struct mlx4_counters *reg;
17619304Speter
17719304Speter	mailbox = mlx4_alloc_cmd_mailbox(dev);
17819304Speter	if (IS_ERR(mailbox))
17919304Speter		return -ENOMEM;
18019304Speter
18119304Speter	err = mlx4_cmd_box(dev, 0, mailbox->dma, index, 0,
18219304Speter			   MLX4_CMD_QUERY_IF_STAT, MLX4_CMD_TIME_CLASS_C);
18319304Speter	if (err)
18419304Speter		goto out;
18519304Speter
18619304Speter	mode = be32_to_cpu(((struct mlx4_counters *)mailbox->buf)->counter_mode) & 0xf;
18719304Speter	switch (mode) {
188254225Speter	case 0:
18919304Speter		reg = mailbox->buf;
19019304Speter		counters[0] = be64_to_cpu(reg->rx_frames);
19119304Speter		counters[1] = be64_to_cpu(reg->tx_frames);
19219304Speter		counters[2] = be64_to_cpu(reg->rx_bytes);
19319304Speter		counters[3] = be64_to_cpu(reg->tx_bytes);
19419304Speter		break;
19519304Speter	case 1:
19619304Speter		ext = mailbox->buf;
19719304Speter		counters[0] = be64_to_cpu(ext->rx_uni_frames);
19819304Speter		counters[1] = be64_to_cpu(ext->tx_uni_frames);
19919304Speter		counters[2] = be64_to_cpu(ext->rx_uni_bytes);
20019304Speter		counters[3] = be64_to_cpu(ext->tx_uni_bytes);
20119304Speter		break;
20219304Speter	default:
20319304Speter		err = -EINVAL;
20419304Speter	}
20519304Speter
20619304Speterout:
20719304Speter	mlx4_free_cmd_mailbox(dev, mailbox);
20819304Speter	return err;
20919304Speter}
21019304Speter
21119304Speterint mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
21219304Speter{
21319304Speter	struct mlx4_en_stat_out_mbox *mlx4_en_stats;
21419304Speter	struct net_device *dev;
21519304Speter	struct mlx4_en_priv *priv;
21619304Speter	struct mlx4_cmd_mailbox *mailbox;
21719304Speter	u64 in_mod = reset << 8 | port;
21819304Speter	unsigned long oerror;
21919304Speter	unsigned long ierror;
22019304Speter	int err;
22119304Speter	int i;
22219304Speter	int counter;
22319304Speter	u64 counters[4];
22419304Speter
22519304Speter	dev = mdev->pndev[port];
22619304Speter	priv = netdev_priv(dev);
22719304Speter	memset(counters, 0, sizeof counters);
22819304Speter	counter = mlx4_get_iboe_counter(priv->mdev->dev, port);
22919304Speter	if (counter >= 0)
23019304Speter		err = read_iboe_counters(priv->mdev->dev, counter, counters);
23119304Speter
23219304Speter	mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
23319304Speter	if (IS_ERR(mailbox))
23419304Speter		return PTR_ERR(mailbox);
23519304Speter	memset(mailbox->buf, 0, sizeof(*mlx4_en_stats));
236254225Speter	err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, in_mod, 0,
23719304Speter			   MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B);
23819304Speter	if (err)
23919304Speter		goto out;
24019304Speter
24119304Speter	mlx4_en_stats = mailbox->buf;
24219304Speter
24319304Speter	spin_lock(&priv->stats_lock);
24419304Speter
24519304Speter	oerror = ierror = 0;
24619304Speter	dev->if_ipackets = counters[0];
24719304Speter	dev->if_ibytes = counters[2];
24819304Speter	for (i = 0; i < priv->rx_ring_num; i++) {
24919304Speter		dev->if_ipackets += priv->rx_ring[i].packets;
25019304Speter		dev->if_ibytes += priv->rx_ring[i].bytes;
25119304Speter		ierror += priv->rx_ring[i].errors;
25219304Speter	}
25319304Speter	dev->if_opackets = counters[1];
25419304Speter	dev->if_obytes = counters[3];
25519304Speter	for (i = 0; i <= priv->tx_ring_num; i++) {
25619304Speter		dev->if_opackets += priv->tx_ring[i].packets;
257254225Speter		dev->if_obytes += priv->tx_ring[i].bytes;
25819304Speter		oerror += priv->tx_ring[i].errors;
25919304Speter	}
26019304Speter
26119304Speter	dev->if_ierrors = be32_to_cpu(mlx4_en_stats->RDROP) + ierror;
26219304Speter	dev->if_oerrors = be32_to_cpu(mlx4_en_stats->TDROP) + oerror;
26319304Speter	dev->if_imcasts = be64_to_cpu(mlx4_en_stats->MCAST_prio_0) +
26419304Speter			  be64_to_cpu(mlx4_en_stats->MCAST_prio_1) +
26519304Speter			  be64_to_cpu(mlx4_en_stats->MCAST_prio_2) +
266254225Speter			  be64_to_cpu(mlx4_en_stats->MCAST_prio_3) +
26719304Speter			  be64_to_cpu(mlx4_en_stats->MCAST_prio_4) +
26819304Speter			  be64_to_cpu(mlx4_en_stats->MCAST_prio_5) +
26919304Speter			  be64_to_cpu(mlx4_en_stats->MCAST_prio_6) +
27019304Speter			  be64_to_cpu(mlx4_en_stats->MCAST_prio_7) +
27119304Speter			  be64_to_cpu(mlx4_en_stats->MCAST_novlan);
27219304Speter	dev->if_omcasts = be64_to_cpu(mlx4_en_stats->TMCAST_prio_0) +
27319304Speter			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_1) +
274254225Speter			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_2) +
27519304Speter			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_3) +
27619304Speter			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_4) +
27719304Speter			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_5) +
27819304Speter			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_6) +
27919304Speter			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_7) +
28019304Speter			  be64_to_cpu(mlx4_en_stats->TMCAST_novlan);
28119304Speter	dev->if_collisions = 0;
28219304Speter
283254225Speter	priv->pkstats.broadcast =
28419304Speter				be64_to_cpu(mlx4_en_stats->RBCAST_prio_0) +
28519304Speter				be64_to_cpu(mlx4_en_stats->RBCAST_prio_1) +
28619304Speter				be64_to_cpu(mlx4_en_stats->RBCAST_prio_2) +
28719304Speter				be64_to_cpu(mlx4_en_stats->RBCAST_prio_3) +
28819304Speter				be64_to_cpu(mlx4_en_stats->RBCAST_prio_4) +
28919304Speter				be64_to_cpu(mlx4_en_stats->RBCAST_prio_5) +
29019304Speter				be64_to_cpu(mlx4_en_stats->RBCAST_prio_6) +
29119304Speter				be64_to_cpu(mlx4_en_stats->RBCAST_prio_7) +
29219304Speter				be64_to_cpu(mlx4_en_stats->RBCAST_novlan);
29319304Speter	priv->pkstats.rx_prio[0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_0);
29419304Speter	priv->pkstats.rx_prio[1] = be64_to_cpu(mlx4_en_stats->RTOT_prio_1);
29519304Speter	priv->pkstats.rx_prio[2] = be64_to_cpu(mlx4_en_stats->RTOT_prio_2);
29619304Speter	priv->pkstats.rx_prio[3] = be64_to_cpu(mlx4_en_stats->RTOT_prio_3);
29719304Speter	priv->pkstats.rx_prio[4] = be64_to_cpu(mlx4_en_stats->RTOT_prio_4);
298254225Speter	priv->pkstats.rx_prio[5] = be64_to_cpu(mlx4_en_stats->RTOT_prio_5);
29919304Speter	priv->pkstats.rx_prio[6] = be64_to_cpu(mlx4_en_stats->RTOT_prio_6);
30019304Speter	priv->pkstats.rx_prio[7] = be64_to_cpu(mlx4_en_stats->RTOT_prio_7);
30119304Speter	priv->pkstats.tx_prio[0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_0);
30219304Speter	priv->pkstats.tx_prio[1] = be64_to_cpu(mlx4_en_stats->TTOT_prio_1);
30319304Speter	priv->pkstats.tx_prio[2] = be64_to_cpu(mlx4_en_stats->TTOT_prio_2);
30419304Speter	priv->pkstats.tx_prio[3] = be64_to_cpu(mlx4_en_stats->TTOT_prio_3);
30519304Speter	priv->pkstats.tx_prio[4] = be64_to_cpu(mlx4_en_stats->TTOT_prio_4);
30619304Speter	priv->pkstats.tx_prio[5] = be64_to_cpu(mlx4_en_stats->TTOT_prio_5);
30719304Speter	priv->pkstats.tx_prio[6] = be64_to_cpu(mlx4_en_stats->TTOT_prio_6);
30819304Speter	priv->pkstats.tx_prio[7] = be64_to_cpu(mlx4_en_stats->TTOT_prio_7);
30919304Speter	spin_unlock(&priv->stats_lock);
31019304Speter
31119304Speterout:
31219304Speter	mlx4_free_cmd_mailbox(mdev->dev, mailbox);
31319304Speter	return err;
31419304Speter}
31519304Speter
31619304Speter