1219820Sjeff/*
2219820Sjeff * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
3219820Sjeff *
4219820Sjeff * This software is available to you under a choice of one of two
5219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
6219820Sjeff * General Public License (GPL) Version 2, available from the file
7219820Sjeff * COPYING in the main directory of this source tree, or the
8219820Sjeff * OpenIB.org BSD license below:
9219820Sjeff *
10219820Sjeff *     Redistribution and use in source and binary forms, with or
11219820Sjeff *     without modification, are permitted provided that the following
12219820Sjeff *     conditions are met:
13219820Sjeff *
14219820Sjeff *      - Redistributions of source code must retain the above
15219820Sjeff *        copyright notice, this list of conditions and the following
16219820Sjeff *        disclaimer.
17219820Sjeff *
18219820Sjeff *      - Redistributions in binary form must reproduce the above
19219820Sjeff *        copyright notice, this list of conditions and the following
20219820Sjeff *        disclaimer in the documentation and/or other materials
21219820Sjeff *        provided with the distribution.
22219820Sjeff *
23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30219820Sjeff * SOFTWARE.
31219820Sjeff *
32219820Sjeff */
33219820Sjeff
34219820Sjeff
35219820Sjeff#include "mlx4_en.h"
36219820Sjeff
37219820Sjeff#include <linux/if_vlan.h>
38219820Sjeff
39219820Sjeff#include <linux/mlx4/device.h>
40219820Sjeff#include <linux/mlx4/cmd.h>
41219820Sjeff
42255932Salfred#if 0 //  moved to port.c
43219820Sjeffint mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port,
44219820Sjeff			u64 mac, u64 clear, u8 mode)
45219820Sjeff{
46219820Sjeff	return mlx4_cmd(dev, (mac | (clear << 63)), port, mode,
47255932Salfred			MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
48219820Sjeff}
49255932Salfred#endif
50219820Sjeff
51219820Sjeffint mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, u32 *vlans)
52219820Sjeff{
53219820Sjeff	struct mlx4_cmd_mailbox *mailbox;
54219820Sjeff	struct mlx4_set_vlan_fltr_mbox *filter;
55219893Sjeff	int i, j;
56219820Sjeff	int err = 0;
57219820Sjeff
58219820Sjeff	mailbox = mlx4_alloc_cmd_mailbox(dev);
59219820Sjeff	if (IS_ERR(mailbox))
60219820Sjeff		return PTR_ERR(mailbox);
61219820Sjeff
62219820Sjeff	filter = mailbox->buf;
63219820Sjeff	memset(filter, 0, sizeof *filter);
64219820Sjeff	if (vlans)
65219893Sjeff		for (i = 0, j = VLAN_FLTR_SIZE - 1; i < VLAN_FLTR_SIZE;
66219893Sjeff		    i++, j--)
67219893Sjeff			filter->entry[j] = cpu_to_be32(vlans[i]);
68219820Sjeff	err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_VLAN_FLTR,
69255932Salfred		       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
70219820Sjeff	mlx4_free_cmd_mailbox(dev, mailbox);
71219820Sjeff	return err;
72219820Sjeff}
73219820Sjeff
74219820Sjeff
75255932Salfred#if 0 //moved to port.c - shahark
76219820Sjeffint mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
77219820Sjeff			  u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx)
78219820Sjeff{
79219820Sjeff	struct mlx4_cmd_mailbox *mailbox;
80219820Sjeff	struct mlx4_set_port_general_context *context;
81219820Sjeff	int err;
82219820Sjeff	u32 in_mod;
83219820Sjeff
84219820Sjeff	mailbox = mlx4_alloc_cmd_mailbox(dev);
85219820Sjeff	if (IS_ERR(mailbox))
86219820Sjeff		return PTR_ERR(mailbox);
87219820Sjeff	context = mailbox->buf;
88219820Sjeff	memset(context, 0, sizeof *context);
89219820Sjeff
90219820Sjeff	context->flags = SET_PORT_GEN_ALL_VALID;
91219820Sjeff	context->mtu = cpu_to_be16(mtu);
92219820Sjeff	context->pptx = (pptx * (!pfctx)) << 7;
93219820Sjeff	context->pfctx = pfctx;
94219820Sjeff	context->pprx = (pprx * (!pfcrx)) << 7;
95219820Sjeff	context->pfcrx = pfcrx;
96219820Sjeff
97219820Sjeff	in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
98219820Sjeff	err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
99255932Salfred		       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
100219820Sjeff
101219820Sjeff	mlx4_free_cmd_mailbox(dev, mailbox);
102219820Sjeff	return err;
103219820Sjeff}
104219820Sjeffint mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
105219820Sjeff			   u8 promisc)
106219820Sjeff{
107255932Salfred
108255932Salfred        printf("%s %s:%d\n", __func__, __FILE__, __LINE__);
109255932Salfred
110255932Salfred
111255932Salfred
112219820Sjeff	struct mlx4_cmd_mailbox *mailbox;
113219820Sjeff	struct mlx4_set_port_rqp_calc_context *context;
114219820Sjeff	int err;
115219820Sjeff	u32 in_mod;
116219820Sjeff
117219820Sjeff	mailbox = mlx4_alloc_cmd_mailbox(dev);
118219820Sjeff	if (IS_ERR(mailbox))
119219820Sjeff		return PTR_ERR(mailbox);
120219820Sjeff	context = mailbox->buf;
121219820Sjeff	memset(context, 0, sizeof *context);
122219820Sjeff
123219820Sjeff	context->base_qpn = cpu_to_be32(base_qpn);
124219820Sjeff	context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_EN_SHIFT | base_qpn);
125255932Salfred/*
126219820Sjeff	context->mcast = cpu_to_be32((dev->caps.mc_promisc_mode <<
127219820Sjeff				      SET_PORT_PROMISC_MODE_SHIFT) | base_qpn);
128255932Salfred*/
129219820Sjeff	context->intra_no_vlan = 0;
130219820Sjeff	context->no_vlan = MLX4_NO_VLAN_IDX;
131219820Sjeff	context->intra_vlan_miss = 0;
132219820Sjeff	context->vlan_miss = MLX4_VLAN_MISS_IDX;
133219820Sjeff
134219820Sjeff	in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port;
135219820Sjeff	err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
136255932Salfred		       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
137219820Sjeff
138219820Sjeff	mlx4_free_cmd_mailbox(dev, mailbox);
139219820Sjeff	return err;
140219820Sjeff}
141255932Salfred#endif
142219820Sjeff
143219820Sjeffint mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port)
144219820Sjeff{
145219820Sjeff	struct mlx4_en_query_port_context *qport_context;
146219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]);
147219820Sjeff	struct mlx4_en_port_state *state = &priv->port_state;
148219820Sjeff	struct mlx4_cmd_mailbox *mailbox;
149219820Sjeff	int err;
150219820Sjeff
151219820Sjeff	mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
152219820Sjeff	if (IS_ERR(mailbox))
153219820Sjeff		return PTR_ERR(mailbox);
154219820Sjeff	memset(mailbox->buf, 0, sizeof(*qport_context));
155219820Sjeff	err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0,
156255932Salfred			   MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
157219820Sjeff	if (err)
158219820Sjeff		goto out;
159219820Sjeff	qport_context = mailbox->buf;
160219820Sjeff
161219820Sjeff	/* This command is always accessed from Ethtool context
162219820Sjeff	 * already synchronized, no need in locking */
163219820Sjeff	state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK);
164234099Sjhb	switch (qport_context->link_speed & MLX4_EN_SPEED_MASK) {
165234099Sjhb	case MLX4_EN_1G_SPEED:
166219820Sjeff		state->link_speed = 1000;
167234099Sjhb		break;
168234099Sjhb	case MLX4_EN_10G_SPEED_XAUI:
169234099Sjhb	case MLX4_EN_10G_SPEED_XFI:
170219820Sjeff		state->link_speed = 10000;
171234099Sjhb		break;
172234099Sjhb	case MLX4_EN_40G_SPEED:
173234099Sjhb		state->link_speed = 40000;
174234099Sjhb		break;
175234099Sjhb	default:
176234099Sjhb		state->link_speed = -1;
177234099Sjhb		break;
178234099Sjhb	}
179219820Sjeff	state->transciver = qport_context->transceiver;
180219820Sjeff	if (be32_to_cpu(qport_context->transceiver_code_hi) & 0x400)
181219820Sjeff		state->transciver = 0x80;
182219820Sjeff
183219820Sjeffout:
184219820Sjeff	mlx4_free_cmd_mailbox(mdev->dev, mailbox);
185219820Sjeff	return err;
186219820Sjeff}
187219820Sjeff
188255932Salfred#if 0
189219820Sjeffstatic int read_iboe_counters(struct mlx4_dev *dev, int index, u64 counters[])
190219820Sjeff{
191219820Sjeff	struct mlx4_cmd_mailbox *mailbox;
192219820Sjeff	int err;
193219820Sjeff	int mode;
194219820Sjeff	struct mlx4_counters_ext *ext;
195219820Sjeff	struct mlx4_counters *reg;
196219820Sjeff
197219820Sjeff	mailbox = mlx4_alloc_cmd_mailbox(dev);
198219820Sjeff	if (IS_ERR(mailbox))
199219820Sjeff		return -ENOMEM;
200219820Sjeff
201219820Sjeff	err = mlx4_cmd_box(dev, 0, mailbox->dma, index, 0,
202255932Salfred			   MLX4_CMD_QUERY_IF_STAT, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_WRAPPED);
203219820Sjeff	if (err)
204219820Sjeff		goto out;
205219820Sjeff
206219820Sjeff	mode = be32_to_cpu(((struct mlx4_counters *)mailbox->buf)->counter_mode) & 0xf;
207219820Sjeff	switch (mode) {
208219820Sjeff	case 0:
209219820Sjeff		reg = mailbox->buf;
210219820Sjeff		counters[0] = be64_to_cpu(reg->rx_frames);
211219820Sjeff		counters[1] = be64_to_cpu(reg->tx_frames);
212219820Sjeff		counters[2] = be64_to_cpu(reg->rx_bytes);
213219820Sjeff		counters[3] = be64_to_cpu(reg->tx_bytes);
214219820Sjeff		break;
215219820Sjeff	case 1:
216219820Sjeff		ext = mailbox->buf;
217219820Sjeff		counters[0] = be64_to_cpu(ext->rx_uni_frames);
218219820Sjeff		counters[1] = be64_to_cpu(ext->tx_uni_frames);
219219820Sjeff		counters[2] = be64_to_cpu(ext->rx_uni_bytes);
220219820Sjeff		counters[3] = be64_to_cpu(ext->tx_uni_bytes);
221219820Sjeff		break;
222219820Sjeff	default:
223219820Sjeff		err = -EINVAL;
224219820Sjeff	}
225219820Sjeff
226219820Sjeffout:
227219820Sjeff	mlx4_free_cmd_mailbox(dev, mailbox);
228219820Sjeff	return err;
229219820Sjeff}
230255932Salfred#endif
231219820Sjeff
232219820Sjeffint mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
233219820Sjeff{
234219820Sjeff	struct mlx4_en_stat_out_mbox *mlx4_en_stats;
235219820Sjeff	struct net_device *dev;
236219820Sjeff	struct mlx4_en_priv *priv;
237219820Sjeff	struct mlx4_cmd_mailbox *mailbox;
238219820Sjeff	u64 in_mod = reset << 8 | port;
239219820Sjeff	unsigned long oerror;
240219820Sjeff	unsigned long ierror;
241219820Sjeff	int err;
242219820Sjeff	int i;
243255932Salfred	//int counter;
244219820Sjeff	u64 counters[4];
245219820Sjeff
246219820Sjeff	dev = mdev->pndev[port];
247219820Sjeff	priv = netdev_priv(dev);
248219820Sjeff	memset(counters, 0, sizeof counters);
249255932Salfred        /*
250219820Sjeff	counter = mlx4_get_iboe_counter(priv->mdev->dev, port);
251219820Sjeff	if (counter >= 0)
252219820Sjeff		err = read_iboe_counters(priv->mdev->dev, counter, counters);
253255932Salfred        */
254219820Sjeff
255219820Sjeff	mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
256219820Sjeff	if (IS_ERR(mailbox))
257219820Sjeff		return PTR_ERR(mailbox);
258219820Sjeff	memset(mailbox->buf, 0, sizeof(*mlx4_en_stats));
259219820Sjeff	err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, in_mod, 0,
260255932Salfred			   MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
261219820Sjeff	if (err)
262219820Sjeff		goto out;
263219820Sjeff
264219820Sjeff	mlx4_en_stats = mailbox->buf;
265219820Sjeff
266219820Sjeff	spin_lock(&priv->stats_lock);
267219820Sjeff
268219820Sjeff	oerror = ierror = 0;
269219820Sjeff	dev->if_ipackets = counters[0];
270219820Sjeff	dev->if_ibytes = counters[2];
271219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++) {
272219820Sjeff		dev->if_ipackets += priv->rx_ring[i].packets;
273219820Sjeff		dev->if_ibytes += priv->rx_ring[i].bytes;
274219820Sjeff		ierror += priv->rx_ring[i].errors;
275219820Sjeff	}
276219820Sjeff	dev->if_opackets = counters[1];
277219820Sjeff	dev->if_obytes = counters[3];
278219820Sjeff	for (i = 0; i <= priv->tx_ring_num; i++) {
279219820Sjeff		dev->if_opackets += priv->tx_ring[i].packets;
280219820Sjeff		dev->if_obytes += priv->tx_ring[i].bytes;
281219820Sjeff		oerror += priv->tx_ring[i].errors;
282219820Sjeff	}
283219820Sjeff
284219820Sjeff	dev->if_ierrors = be32_to_cpu(mlx4_en_stats->RDROP) + ierror;
285219820Sjeff	dev->if_oerrors = be32_to_cpu(mlx4_en_stats->TDROP) + oerror;
286219820Sjeff	dev->if_imcasts = be64_to_cpu(mlx4_en_stats->MCAST_prio_0) +
287219820Sjeff			  be64_to_cpu(mlx4_en_stats->MCAST_prio_1) +
288219820Sjeff			  be64_to_cpu(mlx4_en_stats->MCAST_prio_2) +
289219820Sjeff			  be64_to_cpu(mlx4_en_stats->MCAST_prio_3) +
290219820Sjeff			  be64_to_cpu(mlx4_en_stats->MCAST_prio_4) +
291219820Sjeff			  be64_to_cpu(mlx4_en_stats->MCAST_prio_5) +
292219820Sjeff			  be64_to_cpu(mlx4_en_stats->MCAST_prio_6) +
293219820Sjeff			  be64_to_cpu(mlx4_en_stats->MCAST_prio_7) +
294219820Sjeff			  be64_to_cpu(mlx4_en_stats->MCAST_novlan);
295219820Sjeff	dev->if_omcasts = be64_to_cpu(mlx4_en_stats->TMCAST_prio_0) +
296219820Sjeff			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_1) +
297219820Sjeff			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_2) +
298219820Sjeff			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_3) +
299219820Sjeff			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_4) +
300219820Sjeff			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_5) +
301219820Sjeff			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_6) +
302219820Sjeff			  be64_to_cpu(mlx4_en_stats->TMCAST_prio_7) +
303219820Sjeff			  be64_to_cpu(mlx4_en_stats->TMCAST_novlan);
304219820Sjeff	dev->if_collisions = 0;
305219820Sjeff
306219820Sjeff	priv->pkstats.broadcast =
307219820Sjeff				be64_to_cpu(mlx4_en_stats->RBCAST_prio_0) +
308219820Sjeff				be64_to_cpu(mlx4_en_stats->RBCAST_prio_1) +
309219820Sjeff				be64_to_cpu(mlx4_en_stats->RBCAST_prio_2) +
310219820Sjeff				be64_to_cpu(mlx4_en_stats->RBCAST_prio_3) +
311219820Sjeff				be64_to_cpu(mlx4_en_stats->RBCAST_prio_4) +
312219820Sjeff				be64_to_cpu(mlx4_en_stats->RBCAST_prio_5) +
313219820Sjeff				be64_to_cpu(mlx4_en_stats->RBCAST_prio_6) +
314219820Sjeff				be64_to_cpu(mlx4_en_stats->RBCAST_prio_7) +
315219820Sjeff				be64_to_cpu(mlx4_en_stats->RBCAST_novlan);
316219820Sjeff	priv->pkstats.rx_prio[0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_0);
317219820Sjeff	priv->pkstats.rx_prio[1] = be64_to_cpu(mlx4_en_stats->RTOT_prio_1);
318219820Sjeff	priv->pkstats.rx_prio[2] = be64_to_cpu(mlx4_en_stats->RTOT_prio_2);
319219820Sjeff	priv->pkstats.rx_prio[3] = be64_to_cpu(mlx4_en_stats->RTOT_prio_3);
320219820Sjeff	priv->pkstats.rx_prio[4] = be64_to_cpu(mlx4_en_stats->RTOT_prio_4);
321219820Sjeff	priv->pkstats.rx_prio[5] = be64_to_cpu(mlx4_en_stats->RTOT_prio_5);
322219820Sjeff	priv->pkstats.rx_prio[6] = be64_to_cpu(mlx4_en_stats->RTOT_prio_6);
323219820Sjeff	priv->pkstats.rx_prio[7] = be64_to_cpu(mlx4_en_stats->RTOT_prio_7);
324219820Sjeff	priv->pkstats.tx_prio[0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_0);
325219820Sjeff	priv->pkstats.tx_prio[1] = be64_to_cpu(mlx4_en_stats->TTOT_prio_1);
326219820Sjeff	priv->pkstats.tx_prio[2] = be64_to_cpu(mlx4_en_stats->TTOT_prio_2);
327219820Sjeff	priv->pkstats.tx_prio[3] = be64_to_cpu(mlx4_en_stats->TTOT_prio_3);
328219820Sjeff	priv->pkstats.tx_prio[4] = be64_to_cpu(mlx4_en_stats->TTOT_prio_4);
329219820Sjeff	priv->pkstats.tx_prio[5] = be64_to_cpu(mlx4_en_stats->TTOT_prio_5);
330219820Sjeff	priv->pkstats.tx_prio[6] = be64_to_cpu(mlx4_en_stats->TTOT_prio_6);
331219820Sjeff	priv->pkstats.tx_prio[7] = be64_to_cpu(mlx4_en_stats->TTOT_prio_7);
332219820Sjeff	spin_unlock(&priv->stats_lock);
333219820Sjeff
334219820Sjeffout:
335219820Sjeff	mlx4_free_cmd_mailbox(mdev->dev, mailbox);
336219820Sjeff	return err;
337219820Sjeff}
338219820Sjeff
339