1219820Sjeff/*
2272407Shselasky * Copyright (c) 2007, 2014 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
34272407Shselasky#include <linux/etherdevice.h>
35272407Shselasky#include <linux/delay.h>
36272407Shselasky#include <linux/slab.h>
37272407Shselasky#ifdef CONFIG_NET_RX_BUSY_POLL
38272407Shselasky#include <net/busy_poll.h>
39272407Shselasky#endif
40219820Sjeff
41272407Shselasky#include <linux/list.h>
42272407Shselasky#include <linux/if_ether.h>
43272407Shselasky
44219820Sjeff#include <linux/mlx4/driver.h>
45219820Sjeff#include <linux/mlx4/device.h>
46219820Sjeff#include <linux/mlx4/cmd.h>
47219820Sjeff#include <linux/mlx4/cq.h>
48219820Sjeff
49219820Sjeff#include <sys/sockio.h>
50272407Shselasky#include <sys/sysctl.h>
51219820Sjeff
52272407Shselasky#include "mlx4_en.h"
53272407Shselasky#include "en_port.h"
54272407Shselasky
55219820Sjeffstatic void mlx4_en_sysctl_stat(struct mlx4_en_priv *priv);
56272407Shselaskystatic void mlx4_en_sysctl_conf(struct mlx4_en_priv *priv);
57219820Sjeff
58272407Shselasky#ifdef CONFIG_NET_RX_BUSY_POLL
59272407Shselasky/* must be called with local_bh_disable()d */
60272407Shselaskystatic int mlx4_en_low_latency_recv(struct napi_struct *napi)
61272407Shselasky{
62272407Shselasky	struct mlx4_en_cq *cq = container_of(napi, struct mlx4_en_cq, napi);
63272407Shselasky	struct net_device *dev = cq->dev;
64272407Shselasky	struct mlx4_en_priv *priv = netdev_priv(dev);
65272407Shselasky	struct mlx4_en_rx_ring *rx_ring = priv->rx_ring[cq->ring];
66272407Shselasky	int done;
67272407Shselasky
68272407Shselasky	if (!priv->port_up)
69272407Shselasky		return LL_FLUSH_FAILED;
70272407Shselasky
71272407Shselasky	if (!mlx4_en_cq_lock_poll(cq))
72272407Shselasky		return LL_FLUSH_BUSY;
73272407Shselasky
74272407Shselasky	done = mlx4_en_process_rx_cq(dev, cq, 4);
75272407Shselasky#ifdef LL_EXTENDED_STATS
76272407Shselasky	if (done)
77272407Shselasky		rx_ring->cleaned += done;
78272407Shselasky	else
79272407Shselasky		rx_ring->misses++;
80272407Shselasky#endif
81272407Shselasky
82272407Shselasky	mlx4_en_cq_unlock_poll(cq);
83272407Shselasky
84272407Shselasky	return done;
85272407Shselasky}
86272407Shselasky#endif	/* CONFIG_NET_RX_BUSY_POLL */
87272407Shselasky
88272407Shselasky#ifdef CONFIG_RFS_ACCEL
89272407Shselasky
90272407Shselaskystruct mlx4_en_filter {
91272407Shselasky	struct list_head next;
92272407Shselasky	struct work_struct work;
93272407Shselasky
94272407Shselasky	u8     ip_proto;
95272407Shselasky	__be32 src_ip;
96272407Shselasky	__be32 dst_ip;
97272407Shselasky	__be16 src_port;
98272407Shselasky	__be16 dst_port;
99272407Shselasky
100272407Shselasky	int rxq_index;
101272407Shselasky	struct mlx4_en_priv *priv;
102272407Shselasky	u32 flow_id;			/* RFS infrastructure id */
103272407Shselasky	int id;				/* mlx4_en driver id */
104272407Shselasky	u64 reg_id;			/* Flow steering API id */
105272407Shselasky	u8 activated;			/* Used to prevent expiry before filter
106272407Shselasky					 * is attached
107272407Shselasky					 */
108272407Shselasky	struct hlist_node filter_chain;
109272407Shselasky};
110272407Shselasky
111272407Shselaskystatic void mlx4_en_filter_rfs_expire(struct mlx4_en_priv *priv);
112272407Shselasky
113272407Shselaskystatic enum mlx4_net_trans_rule_id mlx4_ip_proto_to_trans_rule_id(u8 ip_proto)
114272407Shselasky{
115272407Shselasky	switch (ip_proto) {
116272407Shselasky	case IPPROTO_UDP:
117272407Shselasky		return MLX4_NET_TRANS_RULE_ID_UDP;
118272407Shselasky	case IPPROTO_TCP:
119272407Shselasky		return MLX4_NET_TRANS_RULE_ID_TCP;
120272407Shselasky	default:
121272407Shselasky		return -EPROTONOSUPPORT;
122272407Shselasky	}
123272407Shselasky};
124272407Shselasky
125272407Shselaskystatic void mlx4_en_filter_work(struct work_struct *work)
126272407Shselasky{
127272407Shselasky	struct mlx4_en_filter *filter = container_of(work,
128272407Shselasky						     struct mlx4_en_filter,
129272407Shselasky						     work);
130272407Shselasky	struct mlx4_en_priv *priv = filter->priv;
131272407Shselasky	struct mlx4_spec_list spec_tcp_udp = {
132272407Shselasky		.id = mlx4_ip_proto_to_trans_rule_id(filter->ip_proto),
133272407Shselasky		{
134272407Shselasky			.tcp_udp = {
135272407Shselasky				.dst_port = filter->dst_port,
136272407Shselasky				.dst_port_msk = (__force __be16)-1,
137272407Shselasky				.src_port = filter->src_port,
138272407Shselasky				.src_port_msk = (__force __be16)-1,
139272407Shselasky			},
140272407Shselasky		},
141272407Shselasky	};
142272407Shselasky	struct mlx4_spec_list spec_ip = {
143272407Shselasky		.id = MLX4_NET_TRANS_RULE_ID_IPV4,
144272407Shselasky		{
145272407Shselasky			.ipv4 = {
146272407Shselasky				.dst_ip = filter->dst_ip,
147272407Shselasky				.dst_ip_msk = (__force __be32)-1,
148272407Shselasky				.src_ip = filter->src_ip,
149272407Shselasky				.src_ip_msk = (__force __be32)-1,
150272407Shselasky			},
151272407Shselasky		},
152272407Shselasky	};
153272407Shselasky	struct mlx4_spec_list spec_eth = {
154272407Shselasky		.id = MLX4_NET_TRANS_RULE_ID_ETH,
155272407Shselasky	};
156272407Shselasky	struct mlx4_net_trans_rule rule = {
157272407Shselasky		.list = LIST_HEAD_INIT(rule.list),
158272407Shselasky		.queue_mode = MLX4_NET_TRANS_Q_LIFO,
159272407Shselasky		.exclusive = 1,
160272407Shselasky		.allow_loopback = 1,
161272407Shselasky		.promisc_mode = MLX4_FS_REGULAR,
162272407Shselasky		.port = priv->port,
163272407Shselasky		.priority = MLX4_DOMAIN_RFS,
164272407Shselasky	};
165272407Shselasky	int rc;
166272407Shselasky	__be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
167272407Shselasky
168272407Shselasky	if (spec_tcp_udp.id < 0) {
169272407Shselasky		en_warn(priv, "RFS: ignoring unsupported ip protocol (%d)\n",
170272407Shselasky			filter->ip_proto);
171272407Shselasky		goto ignore;
172272407Shselasky	}
173272407Shselasky	list_add_tail(&spec_eth.list, &rule.list);
174272407Shselasky	list_add_tail(&spec_ip.list, &rule.list);
175272407Shselasky	list_add_tail(&spec_tcp_udp.list, &rule.list);
176272407Shselasky
177272407Shselasky	rule.qpn = priv->rss_map.qps[filter->rxq_index].qpn;
178272407Shselasky	memcpy(spec_eth.eth.dst_mac, priv->dev->dev_addr, ETH_ALEN);
179272407Shselasky	memcpy(spec_eth.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
180272407Shselasky
181272407Shselasky	filter->activated = 0;
182272407Shselasky
183272407Shselasky	if (filter->reg_id) {
184272407Shselasky		rc = mlx4_flow_detach(priv->mdev->dev, filter->reg_id);
185272407Shselasky		if (rc && rc != -ENOENT)
186272407Shselasky			en_err(priv, "Error detaching flow. rc = %d\n", rc);
187272407Shselasky	}
188272407Shselasky
189272407Shselasky	rc = mlx4_flow_attach(priv->mdev->dev, &rule, &filter->reg_id);
190272407Shselasky	if (rc)
191272407Shselasky		en_err(priv, "Error attaching flow. err = %d\n", rc);
192272407Shselasky
193272407Shselaskyignore:
194272407Shselasky	mlx4_en_filter_rfs_expire(priv);
195272407Shselasky
196272407Shselasky	filter->activated = 1;
197272407Shselasky}
198272407Shselasky
199272407Shselaskystatic inline struct hlist_head *
200272407Shselaskyfilter_hash_bucket(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip,
201272407Shselasky		   __be16 src_port, __be16 dst_port)
202272407Shselasky{
203272407Shselasky	unsigned long l;
204272407Shselasky	int bucket_idx;
205272407Shselasky
206272407Shselasky	l = (__force unsigned long)src_port |
207272407Shselasky	    ((__force unsigned long)dst_port << 2);
208272407Shselasky	l ^= (__force unsigned long)(src_ip ^ dst_ip);
209272407Shselasky
210272407Shselasky	bucket_idx = hash_long(l, MLX4_EN_FILTER_HASH_SHIFT);
211272407Shselasky
212272407Shselasky	return &priv->filter_hash[bucket_idx];
213272407Shselasky}
214272407Shselasky
215272407Shselaskystatic struct mlx4_en_filter *
216272407Shselaskymlx4_en_filter_alloc(struct mlx4_en_priv *priv, int rxq_index, __be32 src_ip,
217272407Shselasky		     __be32 dst_ip, u8 ip_proto, __be16 src_port,
218272407Shselasky		     __be16 dst_port, u32 flow_id)
219272407Shselasky{
220272407Shselasky	struct mlx4_en_filter *filter = NULL;
221272407Shselasky
222272407Shselasky	filter = kzalloc(sizeof(struct mlx4_en_filter), GFP_ATOMIC);
223272407Shselasky	if (!filter)
224272407Shselasky		return NULL;
225272407Shselasky
226272407Shselasky	filter->priv = priv;
227272407Shselasky	filter->rxq_index = rxq_index;
228272407Shselasky	INIT_WORK(&filter->work, mlx4_en_filter_work);
229272407Shselasky
230272407Shselasky	filter->src_ip = src_ip;
231272407Shselasky	filter->dst_ip = dst_ip;
232272407Shselasky	filter->ip_proto = ip_proto;
233272407Shselasky	filter->src_port = src_port;
234272407Shselasky	filter->dst_port = dst_port;
235272407Shselasky
236272407Shselasky	filter->flow_id = flow_id;
237272407Shselasky
238272407Shselasky	filter->id = priv->last_filter_id++ % RPS_NO_FILTER;
239272407Shselasky
240272407Shselasky	list_add_tail(&filter->next, &priv->filters);
241272407Shselasky	hlist_add_head(&filter->filter_chain,
242272407Shselasky		       filter_hash_bucket(priv, src_ip, dst_ip, src_port,
243272407Shselasky					  dst_port));
244272407Shselasky
245272407Shselasky	return filter;
246272407Shselasky}
247272407Shselasky
248272407Shselaskystatic void mlx4_en_filter_free(struct mlx4_en_filter *filter)
249272407Shselasky{
250272407Shselasky	struct mlx4_en_priv *priv = filter->priv;
251272407Shselasky	int rc;
252272407Shselasky
253272407Shselasky	list_del(&filter->next);
254272407Shselasky
255272407Shselasky	rc = mlx4_flow_detach(priv->mdev->dev, filter->reg_id);
256272407Shselasky	if (rc && rc != -ENOENT)
257272407Shselasky		en_err(priv, "Error detaching flow. rc = %d\n", rc);
258272407Shselasky
259272407Shselasky	kfree(filter);
260272407Shselasky}
261272407Shselasky
262272407Shselaskystatic inline struct mlx4_en_filter *
263272407Shselaskymlx4_en_filter_find(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip,
264272407Shselasky		    u8 ip_proto, __be16 src_port, __be16 dst_port)
265272407Shselasky{
266272407Shselasky	struct hlist_node *elem;
267272407Shselasky	struct mlx4_en_filter *filter;
268272407Shselasky	struct mlx4_en_filter *ret = NULL;
269272407Shselasky
270272407Shselasky	hlist_for_each_entry(filter, elem,
271272407Shselasky			     filter_hash_bucket(priv, src_ip, dst_ip,
272272407Shselasky						src_port, dst_port),
273272407Shselasky			     filter_chain) {
274272407Shselasky		if (filter->src_ip == src_ip &&
275272407Shselasky		    filter->dst_ip == dst_ip &&
276272407Shselasky		    filter->ip_proto == ip_proto &&
277272407Shselasky		    filter->src_port == src_port &&
278272407Shselasky		    filter->dst_port == dst_port) {
279272407Shselasky			ret = filter;
280272407Shselasky			break;
281272407Shselasky		}
282272407Shselasky	}
283272407Shselasky
284272407Shselasky	return ret;
285272407Shselasky}
286272407Shselasky
287272407Shselaskystatic int
288272407Shselaskymlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
289272407Shselasky		   u16 rxq_index, u32 flow_id)
290272407Shselasky{
291272407Shselasky	struct mlx4_en_priv *priv = netdev_priv(net_dev);
292272407Shselasky	struct mlx4_en_filter *filter;
293272407Shselasky	const struct iphdr *ip;
294272407Shselasky	const __be16 *ports;
295272407Shselasky	u8 ip_proto;
296272407Shselasky	__be32 src_ip;
297272407Shselasky	__be32 dst_ip;
298272407Shselasky	__be16 src_port;
299272407Shselasky	__be16 dst_port;
300272407Shselasky	int nhoff = skb_network_offset(skb);
301272407Shselasky	int ret = 0;
302272407Shselasky
303272407Shselasky	if (skb->protocol != htons(ETH_P_IP))
304272407Shselasky		return -EPROTONOSUPPORT;
305272407Shselasky
306272407Shselasky	ip = (const struct iphdr *)(skb->data + nhoff);
307272407Shselasky	if (ip_is_fragment(ip))
308272407Shselasky		return -EPROTONOSUPPORT;
309272407Shselasky
310272407Shselasky	if ((ip->protocol != IPPROTO_TCP) && (ip->protocol != IPPROTO_UDP))
311272407Shselasky		return -EPROTONOSUPPORT;
312272407Shselasky	ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
313272407Shselasky
314272407Shselasky	ip_proto = ip->protocol;
315272407Shselasky	src_ip = ip->saddr;
316272407Shselasky	dst_ip = ip->daddr;
317272407Shselasky	src_port = ports[0];
318272407Shselasky	dst_port = ports[1];
319272407Shselasky
320272407Shselasky	spin_lock_bh(&priv->filters_lock);
321272407Shselasky	filter = mlx4_en_filter_find(priv, src_ip, dst_ip, ip_proto,
322272407Shselasky				     src_port, dst_port);
323272407Shselasky	if (filter) {
324272407Shselasky		if (filter->rxq_index == rxq_index)
325272407Shselasky			goto out;
326272407Shselasky
327272407Shselasky		filter->rxq_index = rxq_index;
328272407Shselasky	} else {
329272407Shselasky		filter = mlx4_en_filter_alloc(priv, rxq_index,
330272407Shselasky					      src_ip, dst_ip, ip_proto,
331272407Shselasky					      src_port, dst_port, flow_id);
332272407Shselasky		if (!filter) {
333272407Shselasky			ret = -ENOMEM;
334272407Shselasky			goto err;
335272407Shselasky		}
336272407Shselasky	}
337272407Shselasky
338272407Shselasky	queue_work(priv->mdev->workqueue, &filter->work);
339272407Shselasky
340272407Shselaskyout:
341272407Shselasky	ret = filter->id;
342272407Shselaskyerr:
343272407Shselasky	spin_unlock_bh(&priv->filters_lock);
344272407Shselasky
345272407Shselasky	return ret;
346272407Shselasky}
347272407Shselasky
348272407Shselaskyvoid mlx4_en_cleanup_filters(struct mlx4_en_priv *priv,
349272407Shselasky			     struct mlx4_en_rx_ring *rx_ring)
350272407Shselasky{
351272407Shselasky	struct mlx4_en_filter *filter, *tmp;
352272407Shselasky	LIST_HEAD(del_list);
353272407Shselasky
354272407Shselasky	spin_lock_bh(&priv->filters_lock);
355272407Shselasky	list_for_each_entry_safe(filter, tmp, &priv->filters, next) {
356272407Shselasky		list_move(&filter->next, &del_list);
357272407Shselasky		hlist_del(&filter->filter_chain);
358272407Shselasky	}
359272407Shselasky	spin_unlock_bh(&priv->filters_lock);
360272407Shselasky
361272407Shselasky	list_for_each_entry_safe(filter, tmp, &del_list, next) {
362272407Shselasky		cancel_work_sync(&filter->work);
363272407Shselasky		mlx4_en_filter_free(filter);
364272407Shselasky	}
365272407Shselasky}
366272407Shselasky
367272407Shselaskystatic void mlx4_en_filter_rfs_expire(struct mlx4_en_priv *priv)
368272407Shselasky{
369272407Shselasky	struct mlx4_en_filter *filter = NULL, *tmp, *last_filter = NULL;
370272407Shselasky	LIST_HEAD(del_list);
371272407Shselasky	int i = 0;
372272407Shselasky
373272407Shselasky	spin_lock_bh(&priv->filters_lock);
374272407Shselasky	list_for_each_entry_safe(filter, tmp, &priv->filters, next) {
375272407Shselasky		if (i > MLX4_EN_FILTER_EXPIRY_QUOTA)
376272407Shselasky			break;
377272407Shselasky
378272407Shselasky		if (filter->activated &&
379272407Shselasky		    !work_pending(&filter->work) &&
380272407Shselasky		    rps_may_expire_flow(priv->dev,
381272407Shselasky					filter->rxq_index, filter->flow_id,
382272407Shselasky					filter->id)) {
383272407Shselasky			list_move(&filter->next, &del_list);
384272407Shselasky			hlist_del(&filter->filter_chain);
385272407Shselasky		} else
386272407Shselasky			last_filter = filter;
387272407Shselasky
388272407Shselasky		i++;
389272407Shselasky	}
390272407Shselasky
391272407Shselasky	if (last_filter && (&last_filter->next != priv->filters.next))
392272407Shselasky		list_move(&priv->filters, &last_filter->next);
393272407Shselasky
394272407Shselasky	spin_unlock_bh(&priv->filters_lock);
395272407Shselasky
396272407Shselasky	list_for_each_entry_safe(filter, tmp, &del_list, next)
397272407Shselasky		mlx4_en_filter_free(filter);
398272407Shselasky}
399272407Shselasky#endif
400272407Shselasky
401219820Sjeffstatic void mlx4_en_vlan_rx_add_vid(void *arg, struct net_device *dev, u16 vid)
402219820Sjeff{
403219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
404272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
405272407Shselasky	int err;
406219820Sjeff	int idx;
407219820Sjeff
408258280Salfred	if (arg != priv)
409258280Salfred		return;
410258280Salfred
411219820Sjeff	en_dbg(HW, priv, "adding VLAN:%d\n", vid);
412272407Shselasky
413272407Shselasky	set_bit(vid, priv->active_vlans);
414272407Shselasky
415272407Shselasky	/* Add VID to port VLAN filter */
416272407Shselasky	mutex_lock(&mdev->state_lock);
417272407Shselasky	if (mdev->device_up && priv->port_up) {
418272407Shselasky		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
419272407Shselasky		if (err)
420272407Shselasky			en_err(priv, "Failed configuring VLAN filter\n");
421272407Shselasky	}
422272407Shselasky	if (mlx4_register_vlan(mdev->dev, priv->port, vid, &idx))
423272407Shselasky		en_dbg(HW, priv, "failed adding vlan %d\n", vid);
424272407Shselasky	mutex_unlock(&mdev->state_lock);
425272407Shselasky
426219820Sjeff}
427219820Sjeff
428219820Sjeffstatic void mlx4_en_vlan_rx_kill_vid(void *arg, struct net_device *dev, u16 vid)
429219820Sjeff{
430219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
431272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
432272407Shselasky	int err;
433219820Sjeff
434258280Salfred	if (arg != priv)
435258280Salfred		return;
436258280Salfred
437219820Sjeff	en_dbg(HW, priv, "Killing VID:%d\n", vid);
438272407Shselasky
439272407Shselasky	clear_bit(vid, priv->active_vlans);
440272407Shselasky
441272407Shselasky	/* Remove VID from port VLAN filter */
442272407Shselasky	mutex_lock(&mdev->state_lock);
443272407Shselasky	mlx4_unregister_vlan(mdev->dev, priv->port, vid);
444272407Shselasky
445272407Shselasky	if (mdev->device_up && priv->port_up) {
446272407Shselasky		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
447272407Shselasky		if (err)
448272407Shselasky			en_err(priv, "Failed configuring VLAN filter\n");
449272407Shselasky	}
450272407Shselasky	mutex_unlock(&mdev->state_lock);
451272407Shselasky
452219820Sjeff}
453219820Sjeff
454272407Shselaskystatic int mlx4_en_uc_steer_add(struct mlx4_en_priv *priv,
455272407Shselasky				unsigned char *mac, int *qpn, u64 *reg_id)
456219820Sjeff{
457272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
458272407Shselasky	struct mlx4_dev *dev = mdev->dev;
459272407Shselasky	int err;
460219820Sjeff
461272407Shselasky	switch (dev->caps.steering_mode) {
462272407Shselasky	case MLX4_STEERING_MODE_B0: {
463272407Shselasky		struct mlx4_qp qp;
464272407Shselasky		u8 gid[16] = {0};
465272407Shselasky
466272407Shselasky		qp.qpn = *qpn;
467272407Shselasky		memcpy(&gid[10], mac, ETH_ALEN);
468272407Shselasky		gid[5] = priv->port;
469272407Shselasky
470272407Shselasky		err = mlx4_unicast_attach(dev, &qp, gid, 0, MLX4_PROT_ETH);
471272407Shselasky		break;
472219820Sjeff	}
473272407Shselasky	case MLX4_STEERING_MODE_DEVICE_MANAGED: {
474272407Shselasky		struct mlx4_spec_list spec_eth = { {NULL} };
475272407Shselasky		__be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
476272407Shselasky
477272407Shselasky		struct mlx4_net_trans_rule rule = {
478272407Shselasky			.queue_mode = MLX4_NET_TRANS_Q_FIFO,
479272407Shselasky			.exclusive = 0,
480272407Shselasky			.allow_loopback = 1,
481272407Shselasky			.promisc_mode = MLX4_FS_REGULAR,
482272407Shselasky			.priority = MLX4_DOMAIN_NIC,
483272407Shselasky		};
484272407Shselasky
485272407Shselasky		rule.port = priv->port;
486272407Shselasky		rule.qpn = *qpn;
487272407Shselasky		INIT_LIST_HEAD(&rule.list);
488272407Shselasky
489272407Shselasky		spec_eth.id = MLX4_NET_TRANS_RULE_ID_ETH;
490272407Shselasky		memcpy(spec_eth.eth.dst_mac, mac, ETH_ALEN);
491272407Shselasky		memcpy(spec_eth.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
492272407Shselasky		list_add_tail(&spec_eth.list, &rule.list);
493272407Shselasky
494272407Shselasky		err = mlx4_flow_attach(dev, &rule, reg_id);
495272407Shselasky		break;
496272407Shselasky	}
497272407Shselasky	default:
498272407Shselasky		return -EINVAL;
499272407Shselasky	}
500272407Shselasky	if (err)
501272407Shselasky		en_warn(priv, "Failed Attaching Unicast\n");
502272407Shselasky
503272407Shselasky	return err;
504219820Sjeff}
505219820Sjeff
506272407Shselaskystatic void mlx4_en_uc_steer_release(struct mlx4_en_priv *priv,
507272407Shselasky				     unsigned char *mac, int qpn, u64 reg_id)
508219820Sjeff{
509272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
510272407Shselasky	struct mlx4_dev *dev = mdev->dev;
511219820Sjeff
512272407Shselasky	switch (dev->caps.steering_mode) {
513272407Shselasky	case MLX4_STEERING_MODE_B0: {
514272407Shselasky		struct mlx4_qp qp;
515272407Shselasky		u8 gid[16] = {0};
516272407Shselasky
517272407Shselasky		qp.qpn = qpn;
518272407Shselasky		memcpy(&gid[10], mac, ETH_ALEN);
519272407Shselasky		gid[5] = priv->port;
520272407Shselasky
521272407Shselasky		mlx4_unicast_detach(dev, &qp, gid, MLX4_PROT_ETH);
522272407Shselasky		break;
523219820Sjeff	}
524272407Shselasky	case MLX4_STEERING_MODE_DEVICE_MANAGED: {
525272407Shselasky		mlx4_flow_detach(dev, reg_id);
526272407Shselasky		break;
527272407Shselasky	}
528272407Shselasky	default:
529272407Shselasky		en_err(priv, "Invalid steering mode.\n");
530272407Shselasky	}
531272407Shselasky}
532272407Shselasky
533272407Shselaskystatic int mlx4_en_get_qp(struct mlx4_en_priv *priv)
534272407Shselasky{
535272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
536272407Shselasky	struct mlx4_dev *dev = mdev->dev;
537272407Shselasky	struct mlx4_mac_entry *entry;
538272407Shselasky	int index = 0;
539272407Shselasky	int err = 0;
540272407Shselasky	u64 reg_id;
541272407Shselasky	int *qpn = &priv->base_qpn;
542272407Shselasky	u64 mac = mlx4_mac_to_u64(IF_LLADDR(priv->dev));
543272407Shselasky
544272407Shselasky	en_dbg(DRV, priv, "Registering MAC: %pM for adding\n",
545272407Shselasky	       IF_LLADDR(priv->dev));
546272407Shselasky	index = mlx4_register_mac(dev, priv->port, mac);
547272407Shselasky	if (index < 0) {
548272407Shselasky		err = index;
549272407Shselasky		en_err(priv, "Failed adding MAC: %pM\n",
550272407Shselasky		       IF_LLADDR(priv->dev));
551272407Shselasky		return err;
552272407Shselasky	}
553272407Shselasky
554272407Shselasky	if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
555272407Shselasky		int base_qpn = mlx4_get_base_qpn(dev, priv->port);
556272407Shselasky		*qpn = base_qpn + index;
557272407Shselasky		return 0;
558272407Shselasky	}
559272407Shselasky
560272407Shselasky	err = mlx4_qp_reserve_range(dev, 1, 1, qpn, 0);
561272407Shselasky	en_dbg(DRV, priv, "Reserved qp %d\n", *qpn);
562272407Shselasky	if (err) {
563272407Shselasky		en_err(priv, "Failed to reserve qp for mac registration\n");
564272407Shselasky		goto qp_err;
565272407Shselasky	}
566272407Shselasky
567272407Shselasky	err = mlx4_en_uc_steer_add(priv, IF_LLADDR(priv->dev), qpn, &reg_id);
568272407Shselasky	if (err)
569272407Shselasky		goto steer_err;
570272407Shselasky
571272407Shselasky	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
572272407Shselasky	if (!entry) {
573272407Shselasky		err = -ENOMEM;
574272407Shselasky		goto alloc_err;
575272407Shselasky	}
576272407Shselasky	memcpy(entry->mac, IF_LLADDR(priv->dev), sizeof(entry->mac));
577272407Shselasky	entry->reg_id = reg_id;
578272407Shselasky
579272407Shselasky	hlist_add_head(&entry->hlist,
580272407Shselasky			   &priv->mac_hash[entry->mac[MLX4_EN_MAC_HASH_IDX]]);
581272407Shselasky
582272407Shselasky	return 0;
583272407Shselasky
584272407Shselaskyalloc_err:
585272407Shselasky	mlx4_en_uc_steer_release(priv, IF_LLADDR(priv->dev), *qpn, reg_id);
586272407Shselasky
587272407Shselaskysteer_err:
588272407Shselasky	mlx4_qp_release_range(dev, *qpn, 1);
589272407Shselasky
590272407Shselaskyqp_err:
591272407Shselasky	mlx4_unregister_mac(dev, priv->port, mac);
592272407Shselasky	return err;
593272407Shselasky}
594272407Shselasky
595272407Shselaskystatic void mlx4_en_put_qp(struct mlx4_en_priv *priv)
596272407Shselasky{
597272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
598272407Shselasky	struct mlx4_dev *dev = mdev->dev;
599272407Shselasky	int qpn = priv->base_qpn;
600272407Shselasky	u64 mac;
601272407Shselasky
602272407Shselasky	if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
603272407Shselasky		mac = mlx4_mac_to_u64(IF_LLADDR(priv->dev));
604272407Shselasky		en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
605272407Shselasky		       IF_LLADDR(priv->dev));
606272407Shselasky		mlx4_unregister_mac(dev, priv->port, mac);
607272407Shselasky	} else {
608272407Shselasky		struct mlx4_mac_entry *entry;
609272407Shselasky		struct hlist_node *n, *tmp;
610272407Shselasky		struct hlist_head *bucket;
611272407Shselasky		unsigned int i;
612272407Shselasky
613272407Shselasky		for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) {
614272407Shselasky			bucket = &priv->mac_hash[i];
615272407Shselasky			hlist_for_each_entry_safe(entry, n, tmp, bucket, hlist) {
616272407Shselasky				mac = mlx4_mac_to_u64(entry->mac);
617272407Shselasky				en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
618272407Shselasky				       entry->mac);
619272407Shselasky				mlx4_en_uc_steer_release(priv, entry->mac,
620272407Shselasky							 qpn, entry->reg_id);
621272407Shselasky
622272407Shselasky				mlx4_unregister_mac(dev, priv->port, mac);
623272407Shselasky				hlist_del(&entry->hlist);
624272407Shselasky				kfree(entry);
625272407Shselasky			}
626219820Sjeff		}
627272407Shselasky
628272407Shselasky		en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n",
629272407Shselasky		       priv->port, qpn);
630272407Shselasky		mlx4_qp_release_range(dev, qpn, 1);
631272407Shselasky		priv->flags &= ~MLX4_EN_FLAG_FORCE_PROMISC;
632219820Sjeff	}
633219820Sjeff}
634219820Sjeff
635272407Shselaskystatic void mlx4_en_clear_list(struct net_device *dev)
636259608Salfred{
637259608Salfred	struct mlx4_en_priv *priv = netdev_priv(dev);
638272407Shselasky	struct mlx4_en_mc_list *tmp, *mc_to_del;
639272407Shselasky
640272407Shselasky	list_for_each_entry_safe(mc_to_del, tmp, &priv->mc_list, list) {
641272407Shselasky		list_del(&mc_to_del->list);
642272407Shselasky		kfree(mc_to_del);
643272407Shselasky	}
644259608Salfred}
645219820Sjeff
646272407Shselaskystatic void mlx4_en_cache_mclist(struct net_device *dev)
647259608Salfred{
648272407Shselasky        struct ifmultiaddr *ifma;
649272407Shselasky	struct mlx4_en_mc_list *tmp;
650259608Salfred	struct mlx4_en_priv *priv = netdev_priv(dev);
651259608Salfred
652283175Shselasky        if_maddr_rlock(dev);
653272407Shselasky        TAILQ_FOREACH(ifma, &dev->if_multiaddrs, ifma_link) {
654272407Shselasky                if (ifma->ifma_addr->sa_family != AF_LINK)
655272407Shselasky                        continue;
656272407Shselasky                if (((struct sockaddr_dl *)ifma->ifma_addr)->sdl_alen !=
657272407Shselasky                                ETHER_ADDR_LEN)
658272407Shselasky                        continue;
659272407Shselasky                /* Make sure the list didn't grow. */
660272407Shselasky		tmp = kzalloc(sizeof(struct mlx4_en_mc_list), GFP_ATOMIC);
661292107Shselasky		if (tmp == NULL) {
662292107Shselasky			en_err(priv, "Failed to allocate multicast list\n");
663283175Shselasky			break;
664292107Shselasky		}
665272407Shselasky		memcpy(tmp->addr,
666272407Shselasky			LLADDR((struct sockaddr_dl *)ifma->ifma_addr), ETH_ALEN);
667272407Shselasky		list_add_tail(&tmp->list, &priv->mc_list);
668272407Shselasky        }
669283175Shselasky        if_maddr_runlock(dev);
670259608Salfred}
671259608Salfred
672272407Shselaskystatic void update_mclist_flags(struct mlx4_en_priv *priv,
673272407Shselasky				struct list_head *dst,
674272407Shselasky				struct list_head *src)
675219820Sjeff{
676272407Shselasky	struct mlx4_en_mc_list *dst_tmp, *src_tmp, *new_mc;
677272407Shselasky	bool found;
678272407Shselasky
679272407Shselasky	/* Find all the entries that should be removed from dst,
680272407Shselasky	 * These are the entries that are not found in src
681272407Shselasky	 */
682272407Shselasky	list_for_each_entry(dst_tmp, dst, list) {
683272407Shselasky		found = false;
684272407Shselasky		list_for_each_entry(src_tmp, src, list) {
685272407Shselasky			if (!memcmp(dst_tmp->addr, src_tmp->addr, ETH_ALEN)) {
686272407Shselasky				found = true;
687272407Shselasky				break;
688272407Shselasky			}
689272407Shselasky		}
690272407Shselasky		if (!found)
691272407Shselasky			dst_tmp->action = MCLIST_REM;
692272407Shselasky	}
693272407Shselasky
694272407Shselasky	/* Add entries that exist in src but not in dst
695272407Shselasky	 * mark them as need to add
696272407Shselasky	 */
697272407Shselasky	list_for_each_entry(src_tmp, src, list) {
698272407Shselasky		found = false;
699272407Shselasky		list_for_each_entry(dst_tmp, dst, list) {
700272407Shselasky			if (!memcmp(dst_tmp->addr, src_tmp->addr, ETH_ALEN)) {
701272407Shselasky				dst_tmp->action = MCLIST_NONE;
702272407Shselasky				found = true;
703272407Shselasky				break;
704272407Shselasky			}
705272407Shselasky		}
706272407Shselasky		if (!found) {
707272407Shselasky			new_mc = kmalloc(sizeof(struct mlx4_en_mc_list),
708272407Shselasky					 GFP_KERNEL);
709272407Shselasky			if (!new_mc) {
710272407Shselasky				en_err(priv, "Failed to allocate current multicast list\n");
711272407Shselasky				return;
712272407Shselasky			}
713272407Shselasky			memcpy(new_mc, src_tmp,
714272407Shselasky			       sizeof(struct mlx4_en_mc_list));
715272407Shselasky			new_mc->action = MCLIST_ADD;
716272407Shselasky			list_add_tail(&new_mc->list, dst);
717272407Shselasky		}
718272407Shselasky	}
719272407Shselasky}
720272407Shselasky
721272407Shselaskystatic void mlx4_en_set_rx_mode(struct net_device *dev)
722272407Shselasky{
723219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
724219820Sjeff
725219820Sjeff	if (!priv->port_up)
726219820Sjeff		return;
727219820Sjeff
728272407Shselasky	queue_work(priv->mdev->workqueue, &priv->rx_mode_task);
729219820Sjeff}
730219820Sjeff
731272407Shselaskystatic void mlx4_en_set_promisc_mode(struct mlx4_en_priv *priv,
732272407Shselasky				     struct mlx4_en_dev *mdev)
733219820Sjeff{
734272407Shselasky	int err = 0;
735272407Shselasky	if (!(priv->flags & MLX4_EN_FLAG_PROMISC)) {
736272407Shselasky		priv->flags |= MLX4_EN_FLAG_PROMISC;
737219820Sjeff
738272407Shselasky		/* Enable promiscouos mode */
739272407Shselasky		switch (mdev->dev->caps.steering_mode) {
740272407Shselasky		case MLX4_STEERING_MODE_DEVICE_MANAGED:
741272407Shselasky			err = mlx4_flow_steer_promisc_add(mdev->dev,
742272407Shselasky							  priv->port,
743272407Shselasky							  priv->base_qpn,
744272407Shselasky							  MLX4_FS_ALL_DEFAULT);
745219820Sjeff			if (err)
746272407Shselasky				en_err(priv, "Failed enabling promiscuous mode\n");
747272407Shselasky			priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
748272407Shselasky			break;
749219820Sjeff
750272407Shselasky		case MLX4_STEERING_MODE_B0:
751272407Shselasky			err = mlx4_unicast_promisc_add(mdev->dev,
752272407Shselasky						       priv->base_qpn,
753272407Shselasky						       priv->port);
754219820Sjeff			if (err)
755272407Shselasky				en_err(priv, "Failed enabling unicast promiscuous mode\n");
756219820Sjeff
757272407Shselasky			/* Add the default qp number as multicast
758272407Shselasky			 * promisc
759272407Shselasky			 */
760272407Shselasky			if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
761272407Shselasky				err = mlx4_multicast_promisc_add(mdev->dev,
762272407Shselasky								 priv->base_qpn,
763272407Shselasky								 priv->port);
764272407Shselasky				if (err)
765272407Shselasky					en_err(priv, "Failed enabling multicast promiscuous mode\n");
766272407Shselasky				priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
767272407Shselasky			}
768272407Shselasky			break;
769272407Shselasky
770272407Shselasky		case MLX4_STEERING_MODE_A0:
771272407Shselasky			err = mlx4_SET_PORT_qpn_calc(mdev->dev,
772272407Shselasky						     priv->port,
773272407Shselasky						     priv->base_qpn,
774272407Shselasky						     1);
775219820Sjeff			if (err)
776272407Shselasky				en_err(priv, "Failed enabling promiscuous mode\n");
777272407Shselasky			break;
778219820Sjeff		}
779272407Shselasky
780272407Shselasky		/* Disable port multicast filter (unconditionally) */
781272407Shselasky		err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
782272407Shselasky					  0, MLX4_MCAST_DISABLE);
783272407Shselasky		if (err)
784272407Shselasky			en_err(priv, "Failed disabling multicast filter\n");
785219820Sjeff	}
786272407Shselasky}
787219820Sjeff
788272407Shselaskystatic void mlx4_en_clear_promisc_mode(struct mlx4_en_priv *priv,
789272407Shselasky				       struct mlx4_en_dev *mdev)
790272407Shselasky{
791272407Shselasky	int err = 0;
792219820Sjeff
793272407Shselasky	priv->flags &= ~MLX4_EN_FLAG_PROMISC;
794219820Sjeff
795272407Shselasky	/* Disable promiscouos mode */
796272407Shselasky	switch (mdev->dev->caps.steering_mode) {
797272407Shselasky	case MLX4_STEERING_MODE_DEVICE_MANAGED:
798272407Shselasky		err = mlx4_flow_steer_promisc_remove(mdev->dev,
799272407Shselasky						     priv->port,
800272407Shselasky						     MLX4_FS_ALL_DEFAULT);
801219820Sjeff		if (err)
802272407Shselasky			en_err(priv, "Failed disabling promiscuous mode\n");
803272407Shselasky		priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
804272407Shselasky		break;
805219820Sjeff
806272407Shselasky	case MLX4_STEERING_MODE_B0:
807272407Shselasky		err = mlx4_unicast_promisc_remove(mdev->dev,
808272407Shselasky						  priv->base_qpn,
809272407Shselasky						  priv->port);
810219820Sjeff		if (err)
811272407Shselasky			en_err(priv, "Failed disabling unicast promiscuous mode\n");
812272407Shselasky		/* Disable Multicast promisc */
813272407Shselasky		if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
814272407Shselasky			err = mlx4_multicast_promisc_remove(mdev->dev,
815272407Shselasky							    priv->base_qpn,
816272407Shselasky							    priv->port);
817272407Shselasky			if (err)
818272407Shselasky				en_err(priv, "Failed disabling multicast promiscuous mode\n");
819272407Shselasky			priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
820272407Shselasky		}
821272407Shselasky		break;
822272407Shselasky
823272407Shselasky	case MLX4_STEERING_MODE_A0:
824272407Shselasky		err = mlx4_SET_PORT_qpn_calc(mdev->dev,
825272407Shselasky					     priv->port,
826272407Shselasky					     priv->base_qpn, 0);
827272407Shselasky		if (err)
828272407Shselasky			en_err(priv, "Failed disabling promiscuous mode\n");
829272407Shselasky		break;
830219820Sjeff	}
831272407Shselasky}
832219820Sjeff
833272407Shselaskystatic void mlx4_en_do_multicast(struct mlx4_en_priv *priv,
834272407Shselasky				 struct net_device *dev,
835272407Shselasky				 struct mlx4_en_dev *mdev)
836272407Shselasky{
837272407Shselasky	struct mlx4_en_mc_list *mclist, *tmp;
838272407Shselasky	u8 mc_list[16] = {0};
839272407Shselasky	int err = 0;
840272407Shselasky	u64 mcast_addr = 0;
841272407Shselasky
842272407Shselasky
843219820Sjeff	/* Enable/disable the multicast filter according to IFF_ALLMULTI */
844219820Sjeff	if (dev->if_flags & IFF_ALLMULTI) {
845219820Sjeff		err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
846219820Sjeff					  0, MLX4_MCAST_DISABLE);
847219820Sjeff		if (err)
848219820Sjeff			en_err(priv, "Failed disabling multicast filter\n");
849272407Shselasky
850272407Shselasky		/* Add the default qp number as multicast promisc */
851272407Shselasky		if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
852272407Shselasky			switch (mdev->dev->caps.steering_mode) {
853272407Shselasky			case MLX4_STEERING_MODE_DEVICE_MANAGED:
854272407Shselasky				err = mlx4_flow_steer_promisc_add(mdev->dev,
855272407Shselasky								  priv->port,
856272407Shselasky								  priv->base_qpn,
857272407Shselasky								  MLX4_FS_MC_DEFAULT);
858272407Shselasky				break;
859272407Shselasky
860272407Shselasky			case MLX4_STEERING_MODE_B0:
861272407Shselasky				err = mlx4_multicast_promisc_add(mdev->dev,
862272407Shselasky								 priv->base_qpn,
863272407Shselasky								 priv->port);
864272407Shselasky				break;
865272407Shselasky
866272407Shselasky			case MLX4_STEERING_MODE_A0:
867272407Shselasky				break;
868272407Shselasky			}
869272407Shselasky			if (err)
870272407Shselasky				en_err(priv, "Failed entering multicast promisc mode\n");
871272407Shselasky			priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
872272407Shselasky		}
873219820Sjeff	} else {
874272407Shselasky		/* Disable Multicast promisc */
875272407Shselasky		if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
876272407Shselasky			switch (mdev->dev->caps.steering_mode) {
877272407Shselasky			case MLX4_STEERING_MODE_DEVICE_MANAGED:
878272407Shselasky				err = mlx4_flow_steer_promisc_remove(mdev->dev,
879272407Shselasky								     priv->port,
880272407Shselasky								     MLX4_FS_MC_DEFAULT);
881272407Shselasky				break;
882219820Sjeff
883272407Shselasky			case MLX4_STEERING_MODE_B0:
884272407Shselasky				err = mlx4_multicast_promisc_remove(mdev->dev,
885272407Shselasky								    priv->base_qpn,
886272407Shselasky								    priv->port);
887272407Shselasky				break;
888272407Shselasky
889272407Shselasky			case MLX4_STEERING_MODE_A0:
890272407Shselasky				break;
891272407Shselasky			}
892272407Shselasky			if (err)
893272407Shselasky				en_err(priv, "Failed disabling multicast promiscuous mode\n");
894272407Shselasky			priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
895272407Shselasky		}
896272407Shselasky
897219820Sjeff		err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
898219820Sjeff					  0, MLX4_MCAST_DISABLE);
899219820Sjeff		if (err)
900219820Sjeff			en_err(priv, "Failed disabling multicast filter\n");
901219820Sjeff
902219820Sjeff		/* Flush mcast filter and init it with broadcast address */
903219820Sjeff		mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST,
904219820Sjeff				    1, MLX4_MCAST_CONFIG);
905219820Sjeff
906219820Sjeff		/* Update multicast list - we cache all addresses so they won't
907219820Sjeff		 * change while HW is updated holding the command semaphor */
908272407Shselasky		mlx4_en_cache_mclist(dev);
909272407Shselasky		list_for_each_entry(mclist, &priv->mc_list, list) {
910272407Shselasky			mcast_addr = mlx4_mac_to_u64(mclist->addr);
911219820Sjeff			mlx4_SET_MCAST_FLTR(mdev->dev, priv->port,
912272407Shselasky					mcast_addr, 0, MLX4_MCAST_CONFIG);
913272407Shselasky		}
914219820Sjeff		err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
915219820Sjeff					  0, MLX4_MCAST_ENABLE);
916219820Sjeff		if (err)
917219820Sjeff			en_err(priv, "Failed enabling multicast filter\n");
918219820Sjeff
919272407Shselasky		update_mclist_flags(priv, &priv->curr_list, &priv->mc_list);
920272407Shselasky		list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) {
921272407Shselasky			if (mclist->action == MCLIST_REM) {
922272407Shselasky				/* detach this address and delete from list */
923272407Shselasky				memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
924272407Shselasky				mc_list[5] = priv->port;
925272407Shselasky				err = mlx4_multicast_detach(mdev->dev,
926272407Shselasky							    &priv->rss_map.indir_qp,
927272407Shselasky							    mc_list,
928272407Shselasky							    MLX4_PROT_ETH,
929272407Shselasky							    mclist->reg_id);
930272407Shselasky				if (err)
931272407Shselasky					en_err(priv, "Fail to detach multicast address\n");
932272407Shselasky
933272407Shselasky				/* remove from list */
934272407Shselasky				list_del(&mclist->list);
935272407Shselasky				kfree(mclist);
936272407Shselasky			} else if (mclist->action == MCLIST_ADD) {
937272407Shselasky				/* attach the address */
938272407Shselasky				memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
939272407Shselasky				/* needed for B0 steering support */
940272407Shselasky				mc_list[5] = priv->port;
941272407Shselasky				err = mlx4_multicast_attach(mdev->dev,
942272407Shselasky							    &priv->rss_map.indir_qp,
943272407Shselasky							    mc_list,
944272407Shselasky							    priv->port, 0,
945272407Shselasky							    MLX4_PROT_ETH,
946272407Shselasky							    &mclist->reg_id);
947272407Shselasky				if (err)
948272407Shselasky					en_err(priv, "Fail to attach multicast address\n");
949272407Shselasky
950272407Shselasky			}
951272407Shselasky		}
952219820Sjeff	}
953272407Shselasky}
954272407Shselasky
955272407Shselaskystatic void mlx4_en_do_set_rx_mode(struct work_struct *work)
956272407Shselasky{
957272407Shselasky	struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
958272407Shselasky						 rx_mode_task);
959272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
960272407Shselasky	struct net_device *dev = priv->dev;
961272407Shselasky
962272407Shselasky
963272407Shselasky	mutex_lock(&mdev->state_lock);
964272407Shselasky	if (!mdev->device_up) {
965272407Shselasky		en_dbg(HW, priv, "Card is not up, ignoring rx mode change.\n");
966272407Shselasky		goto out;
967272407Shselasky	}
968272407Shselasky	if (!priv->port_up) {
969272407Shselasky		en_dbg(HW, priv, "Port is down, ignoring rx mode change.\n");
970272407Shselasky		goto out;
971272407Shselasky	}
972272407Shselasky	if (!mlx4_en_QUERY_PORT(mdev, priv->port)) {
973272407Shselasky		if (priv->port_state.link_state) {
974272407Shselasky			priv->last_link_state = MLX4_DEV_EVENT_PORT_UP;
975292107Shselasky			/* update netif baudrate */
976292107Shselasky			priv->dev->if_baudrate =
977292107Shselasky			    IF_Mbps(priv->port_state.link_speed);
978272407Shselasky			/* Important note: the following call for if_link_state_change
979272407Shselasky			 * is needed for interface up scenario (start port, link state
980272407Shselasky			 * change) */
981272407Shselasky			if_link_state_change(priv->dev, LINK_STATE_UP);
982272407Shselasky			en_dbg(HW, priv, "Link Up\n");
983272407Shselasky		}
984272407Shselasky	}
985272407Shselasky
986272407Shselasky	/* Promsicuous mode: disable all filters */
987272407Shselasky	if ((dev->if_flags & IFF_PROMISC) ||
988272407Shselasky	    (priv->flags & MLX4_EN_FLAG_FORCE_PROMISC)) {
989272407Shselasky		mlx4_en_set_promisc_mode(priv, mdev);
990272407Shselasky		goto out;
991272407Shselasky	}
992272407Shselasky
993272407Shselasky	/* Not in promiscuous mode */
994272407Shselasky	if (priv->flags & MLX4_EN_FLAG_PROMISC)
995272407Shselasky		mlx4_en_clear_promisc_mode(priv, mdev);
996272407Shselasky
997272407Shselasky	mlx4_en_do_multicast(priv, dev, mdev);
998219820Sjeffout:
999219820Sjeff	mutex_unlock(&mdev->state_lock);
1000219820Sjeff}
1001219820Sjeff
1002219820Sjeff#ifdef CONFIG_NET_POLL_CONTROLLER
1003219820Sjeffstatic void mlx4_en_netpoll(struct net_device *dev)
1004219820Sjeff{
1005219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
1006219820Sjeff	struct mlx4_en_cq *cq;
1007219820Sjeff	unsigned long flags;
1008219820Sjeff	int i;
1009219820Sjeff
1010219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++) {
1011272407Shselasky		cq = priv->rx_cq[i];
1012219820Sjeff		spin_lock_irqsave(&cq->lock, flags);
1013219820Sjeff		napi_synchronize(&cq->napi);
1014219859Sjeff		mlx4_en_process_rx_cq(dev, cq, 0);
1015219820Sjeff		spin_unlock_irqrestore(&cq->lock, flags);
1016219820Sjeff	}
1017219820Sjeff}
1018219820Sjeff#endif
1019219820Sjeff
1020219820Sjeffstatic void mlx4_en_watchdog_timeout(void *arg)
1021219820Sjeff{
1022272407Shselasky        struct mlx4_en_priv *priv = arg;
1023272407Shselasky        struct mlx4_en_dev *mdev = priv->mdev;
1024219820Sjeff
1025272407Shselasky        en_dbg(DRV, priv, "Scheduling watchdog\n");
1026272407Shselasky        queue_work(mdev->workqueue, &priv->watchdog_task);
1027272407Shselasky        if (priv->port_up)
1028272407Shselasky                callout_reset(&priv->watchdog_timer, MLX4_EN_WATCHDOG_TIMEOUT,
1029272407Shselasky                                mlx4_en_watchdog_timeout, priv);
1030219820Sjeff}
1031219820Sjeff
1032219820Sjeff
1033272407Shselasky
1034219820Sjeffstatic void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
1035219820Sjeff{
1036219820Sjeff	struct mlx4_en_cq *cq;
1037219820Sjeff	int i;
1038219820Sjeff
1039219820Sjeff	/* If we haven't received a specific coalescing setting
1040272407Shselasky	 * (module param), we set the moderation parameters as follows:
1041219820Sjeff	 * - moder_cnt is set to the number of mtu sized packets to
1042219820Sjeff	 *   satisfy our coelsing target.
1043219820Sjeff	 * - moder_time is set to a fixed value.
1044219820Sjeff	 */
1045219820Sjeff	priv->rx_frames = MLX4_EN_RX_COAL_TARGET / priv->dev->if_mtu + 1;
1046219820Sjeff	priv->rx_usecs = MLX4_EN_RX_COAL_TIME;
1047272407Shselasky	priv->tx_frames = MLX4_EN_TX_COAL_PKTS;
1048272407Shselasky	priv->tx_usecs = MLX4_EN_TX_COAL_TIME;
1049272407Shselasky	en_dbg(INTR, priv, "Default coalesing params for mtu: %u - "
1050272407Shselasky	       "rx_frames:%d rx_usecs:%d\n",
1051272407Shselasky	       (unsigned)priv->dev->if_mtu, priv->rx_frames, priv->rx_usecs);
1052219820Sjeff
1053219820Sjeff	/* Setup cq moderation params */
1054219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++) {
1055272407Shselasky		cq = priv->rx_cq[i];
1056219820Sjeff		cq->moder_cnt = priv->rx_frames;
1057219820Sjeff		cq->moder_time = priv->rx_usecs;
1058257867Salfred		priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
1059257867Salfred		priv->last_moder_packets[i] = 0;
1060257867Salfred		priv->last_moder_bytes[i] = 0;
1061219820Sjeff	}
1062219820Sjeff
1063219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++) {
1064272407Shselasky		cq = priv->tx_cq[i];
1065272407Shselasky		cq->moder_cnt = priv->tx_frames;
1066272407Shselasky		cq->moder_time = priv->tx_usecs;
1067219820Sjeff	}
1068219820Sjeff
1069219820Sjeff	/* Reset auto-moderation params */
1070219820Sjeff	priv->pkt_rate_low = MLX4_EN_RX_RATE_LOW;
1071219820Sjeff	priv->rx_usecs_low = MLX4_EN_RX_COAL_TIME_LOW;
1072219820Sjeff	priv->pkt_rate_high = MLX4_EN_RX_RATE_HIGH;
1073219820Sjeff	priv->rx_usecs_high = MLX4_EN_RX_COAL_TIME_HIGH;
1074219820Sjeff	priv->sample_interval = MLX4_EN_SAMPLE_INTERVAL;
1075219820Sjeff	priv->adaptive_rx_coal = 1;
1076219820Sjeff	priv->last_moder_jiffies = 0;
1077219820Sjeff	priv->last_moder_tx_packets = 0;
1078219820Sjeff}
1079219820Sjeff
1080219820Sjeffstatic void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
1081219820Sjeff{
1082219820Sjeff	unsigned long period = (unsigned long) (jiffies - priv->last_moder_jiffies);
1083219820Sjeff	struct mlx4_en_cq *cq;
1084219820Sjeff	unsigned long packets;
1085219820Sjeff	unsigned long rate;
1086219820Sjeff	unsigned long avg_pkt_size;
1087219820Sjeff	unsigned long rx_packets;
1088219820Sjeff	unsigned long rx_bytes;
1089219820Sjeff	unsigned long rx_pkt_diff;
1090219820Sjeff	int moder_time;
1091257867Salfred	int ring, err;
1092219820Sjeff
1093219820Sjeff	if (!priv->adaptive_rx_coal || period < priv->sample_interval * HZ)
1094219820Sjeff		return;
1095272407Shselasky
1096257867Salfred	for (ring = 0; ring < priv->rx_ring_num; ring++) {
1097272407Shselasky                spin_lock(&priv->stats_lock);
1098272407Shselasky		rx_packets = priv->rx_ring[ring]->packets;
1099272407Shselasky		rx_bytes = priv->rx_ring[ring]->bytes;
1100257867Salfred		spin_unlock(&priv->stats_lock);
1101219820Sjeff
1102257867Salfred		rx_pkt_diff = ((unsigned long) (rx_packets -
1103257867Salfred				priv->last_moder_packets[ring]));
1104257867Salfred		packets = rx_pkt_diff;
1105257867Salfred		rate = packets * HZ / period;
1106257867Salfred		avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
1107257867Salfred				priv->last_moder_bytes[ring])) / packets : 0;
1108219820Sjeff
1109257867Salfred		/* Apply auto-moderation only when packet rate
1110272407Shselasky		 * exceeds a rate that it matters */
1111257867Salfred		if (rate > (MLX4_EN_RX_RATE_THRESH / priv->rx_ring_num) &&
1112272407Shselasky		    avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
1113272407Shselasky			if (rate < priv->pkt_rate_low)
1114219820Sjeff				moder_time = priv->rx_usecs_low;
1115219820Sjeff			else if (rate > priv->pkt_rate_high)
1116219820Sjeff				moder_time = priv->rx_usecs_high;
1117219820Sjeff			else
1118219820Sjeff				moder_time = (rate - priv->pkt_rate_low) *
1119219820Sjeff					(priv->rx_usecs_high - priv->rx_usecs_low) /
1120219820Sjeff					(priv->pkt_rate_high - priv->pkt_rate_low) +
1121219820Sjeff					priv->rx_usecs_low;
1122257867Salfred		} else {
1123257867Salfred			moder_time = priv->rx_usecs_low;
1124219820Sjeff		}
1125219820Sjeff
1126257867Salfred		if (moder_time != priv->last_moder_time[ring]) {
1127257867Salfred			priv->last_moder_time[ring] = moder_time;
1128272407Shselasky			cq = priv->rx_cq[ring];
1129219820Sjeff			cq->moder_time = moder_time;
1130219820Sjeff			err = mlx4_en_set_cq_moder(priv, cq);
1131257867Salfred			if (err)
1132272407Shselasky				en_err(priv, "Failed modifying moderation for cq:%d\n",
1133272407Shselasky				       ring);
1134219820Sjeff		}
1135257867Salfred		priv->last_moder_packets[ring] = rx_packets;
1136257867Salfred		priv->last_moder_bytes[ring] = rx_bytes;
1137219820Sjeff	}
1138219820Sjeff
1139219820Sjeff	priv->last_moder_jiffies = jiffies;
1140219820Sjeff}
1141219820Sjeff
1142219820Sjeffstatic void mlx4_en_do_get_stats(struct work_struct *work)
1143219820Sjeff{
1144219820Sjeff	struct delayed_work *delay = to_delayed_work(work);
1145219820Sjeff	struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv,
1146219820Sjeff						 stats_task);
1147219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1148219820Sjeff	int err;
1149219820Sjeff
1150219820Sjeff	mutex_lock(&mdev->state_lock);
1151219820Sjeff	if (mdev->device_up) {
1152219820Sjeff		if (priv->port_up) {
1153272407Shselasky                        err = mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 0);
1154272407Shselasky			if (err)
1155272407Shselasky				en_dbg(HW, priv, "Could not update stats\n");
1156219820Sjeff
1157219820Sjeff			mlx4_en_auto_moderation(priv);
1158219820Sjeff		}
1159219820Sjeff
1160219820Sjeff		queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
1161219820Sjeff	}
1162219820Sjeff	mutex_unlock(&mdev->state_lock);
1163219820Sjeff}
1164219820Sjeff
1165272407Shselasky/* mlx4_en_service_task - Run service task for tasks that needed to be done
1166272407Shselasky * periodically
1167272407Shselasky */
1168272407Shselaskystatic void mlx4_en_service_task(struct work_struct *work)
1169272407Shselasky{
1170272407Shselasky	struct delayed_work *delay = to_delayed_work(work);
1171272407Shselasky	struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv,
1172272407Shselasky						 service_task);
1173272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
1174272407Shselasky
1175272407Shselasky	mutex_lock(&mdev->state_lock);
1176272407Shselasky	if (mdev->device_up) {
1177272407Shselasky		queue_delayed_work(mdev->workqueue, &priv->service_task,
1178272407Shselasky				   SERVICE_TASK_DELAY);
1179272407Shselasky	}
1180272407Shselasky	mutex_unlock(&mdev->state_lock);
1181272407Shselasky}
1182272407Shselasky
1183219820Sjeffstatic void mlx4_en_linkstate(struct work_struct *work)
1184219820Sjeff{
1185219820Sjeff	struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
1186219820Sjeff						 linkstate_task);
1187219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1188219820Sjeff	int linkstate = priv->link_state;
1189219820Sjeff
1190219820Sjeff	mutex_lock(&mdev->state_lock);
1191219820Sjeff	/* If observable port state changed set carrier state and
1192219820Sjeff	 * report to system log */
1193219820Sjeff	if (priv->last_link_state != linkstate) {
1194219820Sjeff		if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) {
1195272407Shselasky			en_info(priv, "Link Down\n");
1196219820Sjeff			if_link_state_change(priv->dev, LINK_STATE_DOWN);
1197273879Shselasky			/* update netif baudrate */
1198273879Shselasky			priv->dev->if_baudrate = 0;
1199273879Shselasky
1200292107Shselasky		/* make sure the port is up before notifying the OS.
1201292107Shselasky		 * This is tricky since we get here on INIT_PORT and
1202272407Shselasky		 * in such case we can't tell the OS the port is up.
1203272407Shselasky		 * To solve this there is a call to if_link_state_change
1204272407Shselasky		 * in set_rx_mode.
1205272407Shselasky		 * */
1206272407Shselasky		} else if (priv->port_up && (linkstate == MLX4_DEV_EVENT_PORT_UP)){
1207273879Shselasky			if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
1208273879Shselasky				en_info(priv, "Query port failed\n");
1209273879Shselasky			priv->dev->if_baudrate =
1210273879Shselasky			    IF_Mbps(priv->port_state.link_speed);
1211219820Sjeff			en_info(priv, "Link Up\n");
1212219820Sjeff			if_link_state_change(priv->dev, LINK_STATE_UP);
1213219820Sjeff		}
1214219820Sjeff	}
1215219820Sjeff	priv->last_link_state = linkstate;
1216219820Sjeff	mutex_unlock(&mdev->state_lock);
1217219820Sjeff}
1218219820Sjeff
1219219820Sjeff
1220272407Shselaskyint mlx4_en_start_port(struct net_device *dev)
1221219820Sjeff{
1222219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
1223219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1224219820Sjeff	struct mlx4_en_cq *cq;
1225219820Sjeff	struct mlx4_en_tx_ring *tx_ring;
1226219820Sjeff	int rx_index = 0;
1227219820Sjeff	int tx_index = 0;
1228219820Sjeff	int err = 0;
1229219820Sjeff	int i;
1230219820Sjeff	int j;
1231272407Shselasky	u8 mc_list[16] = {0};
1232219820Sjeff
1233272407Shselasky
1234219820Sjeff	if (priv->port_up) {
1235219820Sjeff		en_dbg(DRV, priv, "start port called while port already up\n");
1236219820Sjeff		return 0;
1237219820Sjeff	}
1238219820Sjeff
1239272407Shselasky	INIT_LIST_HEAD(&priv->mc_list);
1240272407Shselasky	INIT_LIST_HEAD(&priv->curr_list);
1241272407Shselasky	INIT_LIST_HEAD(&priv->ethtool_list);
1242272407Shselasky
1243219820Sjeff	/* Calculate Rx buf size */
1244219820Sjeff	dev->if_mtu = min(dev->if_mtu, priv->max_mtu);
1245272407Shselasky        mlx4_en_calc_rx_buf(dev);
1246219820Sjeff	en_dbg(DRV, priv, "Rx buf size:%d\n", priv->rx_mb_size);
1247219820Sjeff
1248219820Sjeff	/* Configure rx cq's and rings */
1249219820Sjeff	err = mlx4_en_activate_rx_rings(priv);
1250219820Sjeff	if (err) {
1251219820Sjeff		en_err(priv, "Failed to activate RX rings\n");
1252219820Sjeff		return err;
1253219820Sjeff	}
1254219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++) {
1255272407Shselasky		cq = priv->rx_cq[i];
1256219820Sjeff
1257272407Shselasky		mlx4_en_cq_init_lock(cq);
1258272407Shselasky		err = mlx4_en_activate_cq(priv, cq, i);
1259219820Sjeff		if (err) {
1260219820Sjeff			en_err(priv, "Failed activating Rx CQ\n");
1261219820Sjeff			goto cq_err;
1262219820Sjeff		}
1263219820Sjeff		for (j = 0; j < cq->size; j++)
1264219820Sjeff			cq->buf[j].owner_sr_opcode = MLX4_CQE_OWNER_MASK;
1265219820Sjeff		err = mlx4_en_set_cq_moder(priv, cq);
1266219820Sjeff		if (err) {
1267219820Sjeff			en_err(priv, "Failed setting cq moderation parameters");
1268219820Sjeff			mlx4_en_deactivate_cq(priv, cq);
1269219820Sjeff			goto cq_err;
1270219820Sjeff		}
1271219820Sjeff		mlx4_en_arm_cq(priv, cq);
1272272407Shselasky		priv->rx_ring[i]->cqn = cq->mcq.cqn;
1273219820Sjeff		++rx_index;
1274219820Sjeff	}
1275219820Sjeff
1276272407Shselasky	/* Set qp number */
1277272407Shselasky	en_dbg(DRV, priv, "Getting qp number for port %d\n", priv->port);
1278272407Shselasky	err = mlx4_en_get_qp(priv);
1279272407Shselasky	if (err) {
1280272407Shselasky		en_err(priv, "Failed getting eth qp\n");
1281272407Shselasky		goto cq_err;
1282272407Shselasky	}
1283272407Shselasky	mdev->mac_removed[priv->port] = 0;
1284272407Shselasky
1285272407Shselasky	/* gets default allocated counter index from func cap */
1286272407Shselasky	/* or sink counter index if no resources */
1287272407Shselasky	priv->counter_index = mdev->dev->caps.def_counter_index[priv->port - 1];
1288272407Shselasky
1289272407Shselasky	en_dbg(DRV, priv, "%s: default counter index %d for port %d\n",
1290272407Shselasky	       __func__, priv->counter_index, priv->port);
1291272407Shselasky
1292219820Sjeff	err = mlx4_en_config_rss_steer(priv);
1293219820Sjeff	if (err) {
1294219820Sjeff		en_err(priv, "Failed configuring rss steering\n");
1295272407Shselasky		goto mac_err;
1296219820Sjeff	}
1297219820Sjeff
1298272407Shselasky	err = mlx4_en_create_drop_qp(priv);
1299272407Shselasky	if (err)
1300272407Shselasky		goto rss_err;
1301272407Shselasky
1302219820Sjeff	/* Configure tx cq's and rings */
1303219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++) {
1304219820Sjeff		/* Configure cq */
1305272407Shselasky		cq = priv->tx_cq[i];
1306272407Shselasky		err = mlx4_en_activate_cq(priv, cq, i);
1307219820Sjeff		if (err) {
1308279731Shselasky			en_err(priv, "Failed activating Tx CQ\n");
1309219820Sjeff			goto tx_err;
1310219820Sjeff		}
1311219820Sjeff		err = mlx4_en_set_cq_moder(priv, cq);
1312219820Sjeff		if (err) {
1313219820Sjeff			en_err(priv, "Failed setting cq moderation parameters");
1314219820Sjeff			mlx4_en_deactivate_cq(priv, cq);
1315219820Sjeff			goto tx_err;
1316219820Sjeff		}
1317219820Sjeff		en_dbg(DRV, priv, "Resetting index of collapsed CQ:%d to -1\n", i);
1318219820Sjeff		cq->buf->wqe_index = cpu_to_be16(0xffff);
1319219820Sjeff
1320219820Sjeff		/* Configure ring */
1321272407Shselasky		tx_ring = priv->tx_ring[i];
1322272407Shselasky
1323272407Shselasky		err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn,
1324272407Shselasky					       i / priv->num_tx_rings_p_up);
1325219820Sjeff		if (err) {
1326279731Shselasky			en_err(priv, "Failed activating Tx ring %d\n", i);
1327219820Sjeff			mlx4_en_deactivate_cq(priv, cq);
1328219820Sjeff			goto tx_err;
1329219820Sjeff		}
1330272407Shselasky
1331272407Shselasky		/* Arm CQ for TX completions */
1332272407Shselasky		mlx4_en_arm_cq(priv, cq);
1333272407Shselasky
1334219820Sjeff		/* Set initial ownership of all Tx TXBBs to SW (1) */
1335219820Sjeff		for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE)
1336219820Sjeff			*((u32 *) (tx_ring->buf + j)) = 0xffffffff;
1337219820Sjeff		++tx_index;
1338219820Sjeff	}
1339219820Sjeff
1340219820Sjeff	/* Configure port */
1341219820Sjeff	err = mlx4_SET_PORT_general(mdev->dev, priv->port,
1342272407Shselasky				    priv->rx_mb_size,
1343219820Sjeff				    priv->prof->tx_pause,
1344219820Sjeff				    priv->prof->tx_ppp,
1345219820Sjeff				    priv->prof->rx_pause,
1346219820Sjeff				    priv->prof->rx_ppp);
1347219820Sjeff	if (err) {
1348272407Shselasky		en_err(priv, "Failed setting port general configurations for port %d, with error %d\n",
1349272407Shselasky		       priv->port, err);
1350219820Sjeff		goto tx_err;
1351219820Sjeff	}
1352219820Sjeff	/* Set default qp number */
1353219820Sjeff	err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, priv->base_qpn, 0);
1354219820Sjeff	if (err) {
1355219820Sjeff		en_err(priv, "Failed setting default qp numbers\n");
1356219820Sjeff		goto tx_err;
1357219820Sjeff	}
1358219820Sjeff
1359219820Sjeff	/* Init port */
1360219820Sjeff	en_dbg(HW, priv, "Initializing port\n");
1361219820Sjeff	err = mlx4_INIT_PORT(mdev->dev, priv->port);
1362219820Sjeff	if (err) {
1363219820Sjeff		en_err(priv, "Failed Initializing port\n");
1364272407Shselasky		goto tx_err;
1365219820Sjeff	}
1366219820Sjeff
1367272407Shselasky	/* Attach rx QP to bradcast address */
1368272407Shselasky	memset(&mc_list[10], 0xff, ETH_ALEN);
1369272407Shselasky	mc_list[5] = priv->port; /* needed for B0 steering support */
1370272407Shselasky	if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
1371272407Shselasky				  priv->port, 0, MLX4_PROT_ETH,
1372272407Shselasky				  &priv->broadcast_id))
1373272407Shselasky		mlx4_warn(mdev, "Failed Attaching Broadcast\n");
1374219820Sjeff
1375272407Shselasky	/* Must redo promiscuous mode setup. */
1376272407Shselasky	priv->flags &= ~(MLX4_EN_FLAG_PROMISC | MLX4_EN_FLAG_MC_PROMISC);
1377220016Sjeff
1378272407Shselasky	/* Schedule multicast task to populate multicast list */
1379272407Shselasky	queue_work(mdev->workqueue, &priv->rx_mode_task);
1380220016Sjeff
1381219820Sjeff	priv->port_up = true;
1382219820Sjeff
1383272407Shselasky        /* Enable the queues. */
1384272407Shselasky        dev->if_drv_flags &= ~IFF_DRV_OACTIVE;
1385272407Shselasky        dev->if_drv_flags |= IFF_DRV_RUNNING;
1386272407Shselasky#ifdef CONFIG_DEBUG_FS
1387272407Shselasky	mlx4_en_create_debug_files(priv);
1388272407Shselasky#endif
1389272407Shselasky        callout_reset(&priv->watchdog_timer, MLX4_EN_WATCHDOG_TIMEOUT,
1390272407Shselasky                    mlx4_en_watchdog_timeout, priv);
1391219820Sjeff
1392219820Sjeff
1393219820Sjeff	return 0;
1394219820Sjeff
1395219820Sjefftx_err:
1396219820Sjeff	while (tx_index--) {
1397272407Shselasky		mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[tx_index]);
1398272407Shselasky		mlx4_en_deactivate_cq(priv, priv->tx_cq[tx_index]);
1399219820Sjeff	}
1400272407Shselasky	mlx4_en_destroy_drop_qp(priv);
1401272407Shselaskyrss_err:
1402219820Sjeff	mlx4_en_release_rss_steer(priv);
1403272407Shselaskymac_err:
1404272407Shselasky	mlx4_en_put_qp(priv);
1405219820Sjeffcq_err:
1406219820Sjeff	while (rx_index--)
1407272407Shselasky		mlx4_en_deactivate_cq(priv, priv->rx_cq[rx_index]);
1408219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++)
1409272407Shselasky		mlx4_en_deactivate_rx_ring(priv, priv->rx_ring[i]);
1410219820Sjeff
1411219820Sjeff	return err; /* need to close devices */
1412219820Sjeff}
1413219820Sjeff
1414219820Sjeff
1415272407Shselaskyvoid mlx4_en_stop_port(struct net_device *dev)
1416219820Sjeff{
1417219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
1418219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1419272407Shselasky	struct mlx4_en_mc_list *mclist, *tmp;
1420219820Sjeff	int i;
1421272407Shselasky	u8 mc_list[16] = {0};
1422219820Sjeff
1423219820Sjeff	if (!priv->port_up) {
1424219820Sjeff		en_dbg(DRV, priv, "stop port called while port already down\n");
1425219820Sjeff		return;
1426219820Sjeff	}
1427219820Sjeff
1428272407Shselasky#ifdef CONFIG_DEBUG_FS
1429272407Shselasky	mlx4_en_delete_debug_files(priv);
1430272407Shselasky#endif
1431272407Shselasky
1432272407Shselasky	/* close port*/
1433272407Shselasky	mlx4_CLOSE_PORT(mdev->dev, priv->port);
1434272407Shselasky
1435219820Sjeff	/* Set port as not active */
1436219820Sjeff	priv->port_up = false;
1437272407Shselasky	if (priv->counter_index != 0xff) {
1438272407Shselasky		mlx4_counter_free(mdev->dev, priv->port, priv->counter_index);
1439272407Shselasky		priv->counter_index = 0xff;
1440272407Shselasky	}
1441219820Sjeff
1442272407Shselasky	/* Promsicuous mode */
1443272407Shselasky	if (mdev->dev->caps.steering_mode ==
1444272407Shselasky	    MLX4_STEERING_MODE_DEVICE_MANAGED) {
1445272407Shselasky		priv->flags &= ~(MLX4_EN_FLAG_PROMISC |
1446272407Shselasky				 MLX4_EN_FLAG_MC_PROMISC);
1447272407Shselasky		mlx4_flow_steer_promisc_remove(mdev->dev,
1448272407Shselasky					       priv->port,
1449272407Shselasky					       MLX4_FS_ALL_DEFAULT);
1450272407Shselasky		mlx4_flow_steer_promisc_remove(mdev->dev,
1451272407Shselasky					       priv->port,
1452272407Shselasky					       MLX4_FS_MC_DEFAULT);
1453272407Shselasky	} else if (priv->flags & MLX4_EN_FLAG_PROMISC) {
1454272407Shselasky		priv->flags &= ~MLX4_EN_FLAG_PROMISC;
1455219820Sjeff
1456272407Shselasky		/* Disable promiscouos mode */
1457272407Shselasky		mlx4_unicast_promisc_remove(mdev->dev, priv->base_qpn,
1458272407Shselasky					    priv->port);
1459272407Shselasky
1460272407Shselasky		/* Disable Multicast promisc */
1461272407Shselasky		if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
1462272407Shselasky			mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
1463272407Shselasky						      priv->port);
1464272407Shselasky			priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
1465272407Shselasky		}
1466272407Shselasky	}
1467272407Shselasky
1468272407Shselasky	/* Detach All multicasts */
1469272407Shselasky	memset(&mc_list[10], 0xff, ETH_ALEN);
1470272407Shselasky	mc_list[5] = priv->port; /* needed for B0 steering support */
1471272407Shselasky	mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
1472272407Shselasky			      MLX4_PROT_ETH, priv->broadcast_id);
1473272407Shselasky	list_for_each_entry(mclist, &priv->curr_list, list) {
1474272407Shselasky		memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
1475272407Shselasky		mc_list[5] = priv->port;
1476272407Shselasky		mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
1477272407Shselasky				      mc_list, MLX4_PROT_ETH, mclist->reg_id);
1478272407Shselasky	}
1479272407Shselasky	mlx4_en_clear_list(dev);
1480272407Shselasky	list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) {
1481272407Shselasky		list_del(&mclist->list);
1482272407Shselasky		kfree(mclist);
1483272407Shselasky	}
1484272407Shselasky
1485272407Shselasky	/* Flush multicast filter */
1486272407Shselasky	mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG);
1487272407Shselasky	mlx4_en_destroy_drop_qp(priv);
1488272407Shselasky
1489219820Sjeff	/* Free TX Rings */
1490219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++) {
1491272407Shselasky		mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[i]);
1492272407Shselasky		mlx4_en_deactivate_cq(priv, priv->tx_cq[i]);
1493219820Sjeff	}
1494219820Sjeff	msleep(10);
1495219820Sjeff
1496219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++)
1497272407Shselasky		mlx4_en_free_tx_buf(dev, priv->tx_ring[i]);
1498219820Sjeff
1499219820Sjeff	/* Free RSS qps */
1500219820Sjeff	mlx4_en_release_rss_steer(priv);
1501219820Sjeff
1502272407Shselasky	/* Unregister Mac address for the port */
1503272407Shselasky	mlx4_en_put_qp(priv);
1504272407Shselasky	mdev->mac_removed[priv->port] = 1;
1505272407Shselasky
1506219820Sjeff	/* Free RX Rings */
1507219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++) {
1508272407Shselasky		struct mlx4_en_cq *cq = priv->rx_cq[i];
1509272407Shselasky		mlx4_en_deactivate_rx_ring(priv, priv->rx_ring[i]);
1510272407Shselasky		mlx4_en_deactivate_cq(priv, cq);
1511219820Sjeff	}
1512219820Sjeff
1513272407Shselasky        callout_stop(&priv->watchdog_timer);
1514219820Sjeff
1515272407Shselasky        dev->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1516219820Sjeff}
1517219820Sjeff
1518219820Sjeffstatic void mlx4_en_restart(struct work_struct *work)
1519219820Sjeff{
1520219820Sjeff	struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
1521219820Sjeff						 watchdog_task);
1522219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1523219820Sjeff	struct net_device *dev = priv->dev;
1524219820Sjeff	struct mlx4_en_tx_ring *ring;
1525219820Sjeff	int i;
1526219820Sjeff
1527272407Shselasky
1528219820Sjeff	if (priv->blocked == 0 || priv->port_up == 0)
1529219820Sjeff		return;
1530219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++) {
1531272407Shselasky		ring = priv->tx_ring[i];
1532219820Sjeff		if (ring->blocked &&
1533272407Shselasky				ring->watchdog_time + MLX4_EN_WATCHDOG_TIMEOUT < ticks)
1534219820Sjeff			goto reset;
1535219820Sjeff	}
1536219820Sjeff	return;
1537219820Sjeff
1538219820Sjeffreset:
1539219820Sjeff	priv->port_stats.tx_timeout++;
1540219820Sjeff	en_dbg(DRV, priv, "Watchdog task called for port %d\n", priv->port);
1541219820Sjeff
1542219820Sjeff	mutex_lock(&mdev->state_lock);
1543219820Sjeff	if (priv->port_up) {
1544272407Shselasky		mlx4_en_stop_port(dev);
1545272407Shselasky                //for (i = 0; i < priv->tx_ring_num; i++)
1546272407Shselasky                //        netdev_tx_reset_queue(priv->tx_ring[i]->tx_queue);
1547272407Shselasky		if (mlx4_en_start_port(dev))
1548219820Sjeff			en_err(priv, "Failed restarting port %d\n", priv->port);
1549219820Sjeff	}
1550219820Sjeff	mutex_unlock(&mdev->state_lock);
1551219820Sjeff}
1552219820Sjeff
1553272407Shselaskystatic void mlx4_en_clear_stats(struct net_device *dev)
1554219820Sjeff{
1555272407Shselasky	struct mlx4_en_priv *priv = netdev_priv(dev);
1556272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
1557272407Shselasky	int i;
1558253774Sjhb
1559272407Shselasky	if (!mlx4_is_slave(mdev->dev))
1560272407Shselasky		if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
1561272407Shselasky			en_dbg(HW, priv, "Failed dumping statistics\n");
1562272407Shselasky
1563272407Shselasky	memset(&priv->pstats, 0, sizeof(priv->pstats));
1564272407Shselasky	memset(&priv->pkstats, 0, sizeof(priv->pkstats));
1565272407Shselasky	memset(&priv->port_stats, 0, sizeof(priv->port_stats));
1566272407Shselasky	memset(&priv->vport_stats, 0, sizeof(priv->vport_stats));
1567272407Shselasky
1568272407Shselasky	for (i = 0; i < priv->tx_ring_num; i++) {
1569272407Shselasky		priv->tx_ring[i]->bytes = 0;
1570272407Shselasky		priv->tx_ring[i]->packets = 0;
1571272407Shselasky		priv->tx_ring[i]->tx_csum = 0;
1572292107Shselasky		priv->tx_ring[i]->oversized_packets = 0;
1573272407Shselasky	}
1574272407Shselasky	for (i = 0; i < priv->rx_ring_num; i++) {
1575272407Shselasky		priv->rx_ring[i]->bytes = 0;
1576272407Shselasky		priv->rx_ring[i]->packets = 0;
1577272407Shselasky		priv->rx_ring[i]->csum_ok = 0;
1578272407Shselasky		priv->rx_ring[i]->csum_none = 0;
1579272407Shselasky	}
1580253774Sjhb}
1581253774Sjhb
1582272407Shselaskystatic void mlx4_en_open(void* arg)
1583253774Sjhb{
1584253774Sjhb
1585272407Shselasky        struct mlx4_en_priv *priv;
1586272407Shselasky        struct mlx4_en_dev *mdev;
1587272407Shselasky        struct net_device *dev;
1588272407Shselasky        int err = 0;
1589219820Sjeff
1590272407Shselasky        priv = arg;
1591272407Shselasky        mdev = priv->mdev;
1592272407Shselasky        dev = priv->dev;
1593219820Sjeff
1594272407Shselasky
1595272407Shselasky	mutex_lock(&mdev->state_lock);
1596272407Shselasky
1597219820Sjeff	if (!mdev->device_up) {
1598219820Sjeff		en_err(priv, "Cannot open - device down/disabled\n");
1599272407Shselasky		goto out;
1600219820Sjeff	}
1601219820Sjeff
1602272407Shselasky	/* Reset HW statistics and SW counters */
1603272407Shselasky	mlx4_en_clear_stats(dev);
1604219820Sjeff
1605272407Shselasky	err = mlx4_en_start_port(dev);
1606272407Shselasky	if (err)
1607272407Shselasky		en_err(priv, "Failed starting port:%d\n", priv->port);
1608219820Sjeff
1609272407Shselaskyout:
1610272407Shselasky	mutex_unlock(&mdev->state_lock);
1611272407Shselasky	return;
1612219820Sjeff}
1613219820Sjeff
1614219820Sjeffvoid mlx4_en_free_resources(struct mlx4_en_priv *priv)
1615219820Sjeff{
1616219820Sjeff	int i;
1617219820Sjeff
1618272407Shselasky#ifdef CONFIG_RFS_ACCEL
1619272407Shselasky	if (priv->dev->rx_cpu_rmap) {
1620272407Shselasky		free_irq_cpu_rmap(priv->dev->rx_cpu_rmap);
1621272407Shselasky		priv->dev->rx_cpu_rmap = NULL;
1622272407Shselasky	}
1623272407Shselasky#endif
1624272407Shselasky
1625219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++) {
1626272407Shselasky		if (priv->tx_ring && priv->tx_ring[i])
1627219820Sjeff			mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
1628272407Shselasky		if (priv->tx_cq && priv->tx_cq[i])
1629219820Sjeff			mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
1630219820Sjeff	}
1631219820Sjeff
1632219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++) {
1633272407Shselasky		if (priv->rx_ring[i])
1634272407Shselasky			mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i],
1635272407Shselasky				priv->prof->rx_ring_size, priv->stride);
1636272407Shselasky		if (priv->rx_cq[i])
1637219820Sjeff			mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
1638219820Sjeff	}
1639272407Shselasky
1640318540Shselasky	if (priv->stat_sysctl != NULL)
1641219820Sjeff		sysctl_ctx_free(&priv->stat_ctx);
1642219820Sjeff}
1643219820Sjeff
1644219820Sjeffint mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
1645219820Sjeff{
1646219820Sjeff	struct mlx4_en_port_profile *prof = priv->prof;
1647219820Sjeff	int i;
1648272407Shselasky	int node = 0;
1649219820Sjeff
1650272407Shselasky	/* Create rx Rings */
1651272407Shselasky	for (i = 0; i < priv->rx_ring_num; i++) {
1652272407Shselasky		if (mlx4_en_create_cq(priv, &priv->rx_cq[i],
1653272407Shselasky				      prof->rx_ring_size, i, RX, node))
1654219820Sjeff			goto err;
1655219820Sjeff
1656272407Shselasky		if (mlx4_en_create_rx_ring(priv, &priv->rx_ring[i],
1657272407Shselasky					   prof->rx_ring_size, node))
1658219820Sjeff			goto err;
1659219820Sjeff	}
1660219820Sjeff
1661272407Shselasky	/* Create tx Rings */
1662272407Shselasky	for (i = 0; i < priv->tx_ring_num; i++) {
1663272407Shselasky		if (mlx4_en_create_cq(priv, &priv->tx_cq[i],
1664272407Shselasky				      prof->tx_ring_size, i, TX, node))
1665219820Sjeff			goto err;
1666219820Sjeff
1667272407Shselasky		if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i],
1668272407Shselasky					   prof->tx_ring_size, TXBB_SIZE, node, i))
1669219820Sjeff			goto err;
1670219820Sjeff	}
1671219820Sjeff
1672272407Shselasky#ifdef CONFIG_RFS_ACCEL
1673272407Shselasky	priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->rx_ring_num);
1674272407Shselasky	if (!priv->dev->rx_cpu_rmap)
1675272407Shselasky		goto err;
1676272407Shselasky#endif
1677272407Shselasky        /* Re-create stat sysctls in case the number of rings changed. */
1678219820Sjeff	mlx4_en_sysctl_stat(priv);
1679219820Sjeff	return 0;
1680219820Sjeff
1681219820Sjefferr:
1682219820Sjeff	en_err(priv, "Failed to allocate NIC resources\n");
1683272407Shselasky	for (i = 0; i < priv->rx_ring_num; i++) {
1684272407Shselasky		if (priv->rx_ring[i])
1685272407Shselasky			mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i],
1686272407Shselasky						prof->rx_ring_size,
1687272407Shselasky						priv->stride);
1688272407Shselasky		if (priv->rx_cq[i])
1689272407Shselasky			mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
1690272407Shselasky	}
1691272407Shselasky	for (i = 0; i < priv->tx_ring_num; i++) {
1692272407Shselasky		if (priv->tx_ring[i])
1693272407Shselasky			mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
1694272407Shselasky		if (priv->tx_cq[i])
1695272407Shselasky			mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
1696272407Shselasky	}
1697272407Shselasky	priv->port_up = false;
1698219820Sjeff	return -ENOMEM;
1699219820Sjeff}
1700219820Sjeff
1701272407Shselaskystruct en_port_attribute {
1702272407Shselasky	struct attribute attr;
1703272407Shselasky	ssize_t (*show)(struct en_port *, struct en_port_attribute *, char *buf);
1704272407Shselasky	ssize_t (*store)(struct en_port *, struct en_port_attribute *, char *buf, size_t count);
1705272407Shselasky};
1706219820Sjeff
1707272407Shselasky#define PORT_ATTR_RO(_name) \
1708272407Shselaskystruct en_port_attribute en_port_attr_##_name = __ATTR_RO(_name)
1709272407Shselasky
1710272407Shselasky#define EN_PORT_ATTR(_name, _mode, _show, _store) \
1711272407Shselaskystruct en_port_attribute en_port_attr_##_name = __ATTR(_name, _mode, _show, _store)
1712272407Shselasky
1713219820Sjeffvoid mlx4_en_destroy_netdev(struct net_device *dev)
1714219820Sjeff{
1715219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
1716219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1717219820Sjeff
1718219820Sjeff	en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port);
1719219820Sjeff
1720272407Shselasky        if (priv->vlan_attach != NULL)
1721272407Shselasky                EVENTHANDLER_DEREGISTER(vlan_config, priv->vlan_attach);
1722272407Shselasky        if (priv->vlan_detach != NULL)
1723272407Shselasky                EVENTHANDLER_DEREGISTER(vlan_unconfig, priv->vlan_detach);
1724219820Sjeff
1725219820Sjeff	/* Unregister device - this will close the port if it was up */
1726292107Shselasky	if (priv->registered) {
1727292107Shselasky		mutex_lock(&mdev->state_lock);
1728219820Sjeff		ether_ifdetach(dev);
1729292107Shselasky		mutex_unlock(&mdev->state_lock);
1730292107Shselasky	}
1731219820Sjeff
1732253774Sjhb	mutex_lock(&mdev->state_lock);
1733272407Shselasky	mlx4_en_stop_port(dev);
1734253774Sjhb	mutex_unlock(&mdev->state_lock);
1735253774Sjhb
1736319567Shselasky	if (priv->allocated)
1737319567Shselasky		mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE);
1738272407Shselasky
1739219820Sjeff	cancel_delayed_work(&priv->stats_task);
1740272407Shselasky	cancel_delayed_work(&priv->service_task);
1741219820Sjeff	/* flush any pending task for this netdev */
1742219820Sjeff	flush_workqueue(mdev->workqueue);
1743272407Shselasky        callout_drain(&priv->watchdog_timer);
1744219820Sjeff
1745219820Sjeff	/* Detach the netdev so tasks would not attempt to access it */
1746219820Sjeff	mutex_lock(&mdev->state_lock);
1747219820Sjeff	mdev->pndev[priv->port] = NULL;
1748219820Sjeff	mutex_unlock(&mdev->state_lock);
1749219820Sjeff
1750272407Shselasky
1751219820Sjeff	mlx4_en_free_resources(priv);
1752255932Salfred
1753272407Shselasky	/* freeing the sysctl conf cannot be called from within mlx4_en_free_resources */
1754318540Shselasky	if (priv->conf_sysctl != NULL)
1755256810Salfred		sysctl_ctx_free(&priv->conf_ctx);
1756256810Salfred
1757272407Shselasky	kfree(priv->tx_ring);
1758272407Shselasky	kfree(priv->tx_cq);
1759272407Shselasky
1760272407Shselasky        kfree(priv);
1761272407Shselasky        if_free(dev);
1762272407Shselasky
1763219820Sjeff}
1764219820Sjeff
1765219820Sjeffstatic int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
1766219820Sjeff{
1767219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
1768219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1769219820Sjeff	int err = 0;
1770219820Sjeff
1771272407Shselasky	en_dbg(DRV, priv, "Change MTU called - current:%u new:%u\n",
1772272407Shselasky	       (unsigned)dev->if_mtu, (unsigned)new_mtu);
1773219820Sjeff
1774219820Sjeff	if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) {
1775322507Shselasky		en_err(priv, "Bad MTU size:%d, max %u.\n", new_mtu,
1776322507Shselasky		    priv->max_mtu);
1777219820Sjeff		return -EPERM;
1778219820Sjeff	}
1779219820Sjeff	mutex_lock(&mdev->state_lock);
1780219820Sjeff	dev->if_mtu = new_mtu;
1781219820Sjeff	if (dev->if_drv_flags & IFF_DRV_RUNNING) {
1782219820Sjeff		if (!mdev->device_up) {
1783219820Sjeff			/* NIC is probably restarting - let watchdog task reset
1784272407Shselasky			 *                          * the port */
1785219820Sjeff			en_dbg(DRV, priv, "Change MTU called with card down!?\n");
1786219820Sjeff		} else {
1787272407Shselasky			mlx4_en_stop_port(dev);
1788272407Shselasky			err = mlx4_en_start_port(dev);
1789219820Sjeff			if (err) {
1790219820Sjeff				en_err(priv, "Failed restarting port:%d\n",
1791272407Shselasky						priv->port);
1792219820Sjeff				queue_work(mdev->workqueue, &priv->watchdog_task);
1793219820Sjeff			}
1794219820Sjeff		}
1795219820Sjeff	}
1796219820Sjeff	mutex_unlock(&mdev->state_lock);
1797219820Sjeff	return 0;
1798219820Sjeff}
1799219820Sjeff
1800219820Sjeffstatic int mlx4_en_calc_media(struct mlx4_en_priv *priv)
1801219820Sjeff{
1802219820Sjeff	int trans_type;
1803219820Sjeff	int active;
1804219820Sjeff
1805219820Sjeff	active = IFM_ETHER;
1806219820Sjeff	if (priv->last_link_state == MLX4_DEV_EVENT_PORT_DOWN)
1807219820Sjeff		return (active);
1808219820Sjeff	active |= IFM_FDX;
1809219820Sjeff	trans_type = priv->port_state.transciver;
1810219820Sjeff	/* XXX I don't know all of the transceiver values. */
1811234099Sjhb	switch (priv->port_state.link_speed) {
1812234099Sjhb	case 1000:
1813219820Sjeff		active |= IFM_1000_T;
1814234099Sjhb		break;
1815234099Sjhb	case 10000:
1816234099Sjhb		if (trans_type > 0 && trans_type <= 0xC)
1817234099Sjhb			active |= IFM_10G_SR;
1818234099Sjhb		else if (trans_type == 0x80 || trans_type == 0)
1819234099Sjhb			active |= IFM_10G_CX4;
1820234099Sjhb		break;
1821234099Sjhb	case 40000:
1822234099Sjhb		active |= IFM_40G_CR4;
1823234099Sjhb		break;
1824234099Sjhb	}
1825219820Sjeff	if (priv->prof->tx_pause)
1826219820Sjeff		active |= IFM_ETH_TXPAUSE;
1827219820Sjeff	if (priv->prof->rx_pause)
1828219820Sjeff		active |= IFM_ETH_RXPAUSE;
1829219820Sjeff
1830219820Sjeff	return (active);
1831219820Sjeff}
1832219820Sjeff
1833219820Sjeffstatic void mlx4_en_media_status(struct ifnet *dev, struct ifmediareq *ifmr)
1834219820Sjeff{
1835219820Sjeff	struct mlx4_en_priv *priv;
1836219820Sjeff
1837219820Sjeff	priv = dev->if_softc;
1838219820Sjeff	ifmr->ifm_status = IFM_AVALID;
1839219820Sjeff	if (priv->last_link_state != MLX4_DEV_EVENT_PORT_DOWN)
1840219820Sjeff		ifmr->ifm_status |= IFM_ACTIVE;
1841219820Sjeff	ifmr->ifm_active = mlx4_en_calc_media(priv);
1842219820Sjeff
1843219820Sjeff	return;
1844219820Sjeff}
1845219820Sjeff
1846219820Sjeffstatic int mlx4_en_media_change(struct ifnet *dev)
1847219820Sjeff{
1848219820Sjeff	struct mlx4_en_priv *priv;
1849219820Sjeff        struct ifmedia *ifm;
1850219820Sjeff	int rxpause;
1851219820Sjeff	int txpause;
1852219820Sjeff	int error;
1853219820Sjeff
1854219820Sjeff	priv = dev->if_softc;
1855219820Sjeff	ifm = &priv->media;
1856219820Sjeff	rxpause = txpause = 0;
1857219820Sjeff	error = 0;
1858219820Sjeff
1859219820Sjeff	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
1860219820Sjeff		return (EINVAL);
1861219820Sjeff        switch (IFM_SUBTYPE(ifm->ifm_media)) {
1862219820Sjeff        case IFM_AUTO:
1863219820Sjeff		break;
1864219820Sjeff	case IFM_10G_SR:
1865219820Sjeff	case IFM_10G_CX4:
1866219820Sjeff	case IFM_1000_T:
1867272407Shselasky	case IFM_40G_CR4:
1868272407Shselasky		if ((IFM_SUBTYPE(ifm->ifm_media)
1869272407Shselasky			== IFM_SUBTYPE(mlx4_en_calc_media(priv)))
1870272407Shselasky			&& (ifm->ifm_media & IFM_FDX))
1871219820Sjeff			break;
1872219820Sjeff		/* Fallthrough */
1873219820Sjeff	default:
1874219820Sjeff                printf("%s: Only auto media type\n", if_name(dev));
1875219820Sjeff                return (EINVAL);
1876219820Sjeff	}
1877219820Sjeff	/* Allow user to set/clear pause */
1878219820Sjeff	if (IFM_OPTIONS(ifm->ifm_media) & IFM_ETH_RXPAUSE)
1879219820Sjeff		rxpause = 1;
1880219820Sjeff	if (IFM_OPTIONS(ifm->ifm_media) & IFM_ETH_TXPAUSE)
1881219820Sjeff		txpause = 1;
1882219820Sjeff	if (priv->prof->tx_pause != txpause || priv->prof->rx_pause != rxpause) {
1883219820Sjeff		priv->prof->tx_pause = txpause;
1884219820Sjeff		priv->prof->rx_pause = rxpause;
1885219820Sjeff		error = -mlx4_SET_PORT_general(priv->mdev->dev, priv->port,
1886219820Sjeff		     priv->rx_mb_size + ETHER_CRC_LEN, priv->prof->tx_pause,
1887219820Sjeff		     priv->prof->tx_ppp, priv->prof->rx_pause,
1888219820Sjeff		     priv->prof->rx_ppp);
1889219820Sjeff	}
1890219820Sjeff	return (error);
1891219820Sjeff}
1892219820Sjeff
1893219820Sjeffstatic int mlx4_en_ioctl(struct ifnet *dev, u_long command, caddr_t data)
1894219820Sjeff{
1895219820Sjeff	struct mlx4_en_priv *priv;
1896219820Sjeff	struct mlx4_en_dev *mdev;
1897219820Sjeff	struct ifreq *ifr;
1898219820Sjeff	int error;
1899219820Sjeff	int mask;
1900219820Sjeff
1901219820Sjeff	error = 0;
1902219820Sjeff	mask = 0;
1903219820Sjeff	priv = dev->if_softc;
1904219820Sjeff	mdev = priv->mdev;
1905219820Sjeff	ifr = (struct ifreq *) data;
1906219820Sjeff	switch (command) {
1907272407Shselasky
1908219820Sjeff	case SIOCSIFMTU:
1909219820Sjeff		error = -mlx4_en_change_mtu(dev, ifr->ifr_mtu);
1910219820Sjeff		break;
1911219820Sjeff	case SIOCSIFFLAGS:
1912219820Sjeff		if (dev->if_flags & IFF_UP) {
1913280018Shselasky			if ((dev->if_drv_flags & IFF_DRV_RUNNING) == 0) {
1914280018Shselasky				mutex_lock(&mdev->state_lock);
1915219820Sjeff				mlx4_en_start_port(dev);
1916280018Shselasky				mutex_unlock(&mdev->state_lock);
1917280018Shselasky			} else {
1918272407Shselasky				mlx4_en_set_rx_mode(dev);
1919280018Shselasky			}
1920219820Sjeff		} else {
1921280018Shselasky			mutex_lock(&mdev->state_lock);
1922219820Sjeff			if (dev->if_drv_flags & IFF_DRV_RUNNING) {
1923219820Sjeff				mlx4_en_stop_port(dev);
1924280018Shselasky				if_link_state_change(dev, LINK_STATE_DOWN);
1925219820Sjeff			}
1926280018Shselasky			mutex_unlock(&mdev->state_lock);
1927219820Sjeff		}
1928219820Sjeff		break;
1929219820Sjeff	case SIOCADDMULTI:
1930219820Sjeff	case SIOCDELMULTI:
1931272407Shselasky		mlx4_en_set_rx_mode(dev);
1932219820Sjeff		break;
1933219820Sjeff	case SIOCSIFMEDIA:
1934219820Sjeff	case SIOCGIFMEDIA:
1935219820Sjeff		error = ifmedia_ioctl(dev, ifr, &priv->media, command);
1936219820Sjeff		break;
1937219820Sjeff	case SIOCSIFCAP:
1938253774Sjhb		mutex_lock(&mdev->state_lock);
1939219820Sjeff		mask = ifr->ifr_reqcap ^ dev->if_capenable;
1940292107Shselasky		if (mask & IFCAP_TXCSUM) {
1941292107Shselasky			dev->if_capenable ^= IFCAP_TXCSUM;
1942292107Shselasky			dev->if_hwassist ^= (CSUM_TCP | CSUM_UDP | CSUM_IP);
1943292107Shselasky
1944292107Shselasky			if (IFCAP_TSO4 & dev->if_capenable &&
1945292107Shselasky			    !(IFCAP_TXCSUM & dev->if_capenable)) {
1946292107Shselasky				dev->if_capenable &= ~IFCAP_TSO4;
1947292107Shselasky				dev->if_hwassist &= ~CSUM_IP_TSO;
1948292107Shselasky				if_printf(dev,
1949292107Shselasky				    "tso4 disabled due to -txcsum.\n");
1950292107Shselasky			}
1951292107Shselasky		}
1952292107Shselasky		if (mask & IFCAP_TXCSUM_IPV6) {
1953292107Shselasky			dev->if_capenable ^= IFCAP_TXCSUM_IPV6;
1954292107Shselasky			dev->if_hwassist ^= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6);
1955292107Shselasky
1956292107Shselasky			if (IFCAP_TSO6 & dev->if_capenable &&
1957292107Shselasky			    !(IFCAP_TXCSUM_IPV6 & dev->if_capenable)) {
1958292107Shselasky				dev->if_capenable &= ~IFCAP_TSO6;
1959292107Shselasky				dev->if_hwassist &= ~CSUM_IP6_TSO;
1960292107Shselasky				if_printf(dev,
1961292107Shselasky				    "tso6 disabled due to -txcsum6.\n");
1962292107Shselasky			}
1963292107Shselasky		}
1964292107Shselasky		if (mask & IFCAP_RXCSUM)
1965292107Shselasky			dev->if_capenable ^= IFCAP_RXCSUM;
1966292107Shselasky		if (mask & IFCAP_RXCSUM_IPV6)
1967292107Shselasky			dev->if_capenable ^= IFCAP_RXCSUM_IPV6;
1968292107Shselasky
1969292107Shselasky		if (mask & IFCAP_TSO4) {
1970292107Shselasky			if (!(IFCAP_TSO4 & dev->if_capenable) &&
1971292107Shselasky			    !(IFCAP_TXCSUM & dev->if_capenable)) {
1972292107Shselasky				if_printf(dev, "enable txcsum first.\n");
1973292107Shselasky				error = EAGAIN;
1974292107Shselasky				goto out;
1975292107Shselasky			}
1976219820Sjeff			dev->if_capenable ^= IFCAP_TSO4;
1977292107Shselasky			dev->if_hwassist ^= CSUM_IP_TSO;
1978292107Shselasky		}
1979292107Shselasky		if (mask & IFCAP_TSO6) {
1980292107Shselasky			if (!(IFCAP_TSO6 & dev->if_capenable) &&
1981292107Shselasky			    !(IFCAP_TXCSUM_IPV6 & dev->if_capenable)) {
1982292107Shselasky				if_printf(dev, "enable txcsum6 first.\n");
1983292107Shselasky				error = EAGAIN;
1984292107Shselasky				goto out;
1985292107Shselasky			}
1986272407Shselasky			dev->if_capenable ^= IFCAP_TSO6;
1987292107Shselasky			dev->if_hwassist ^= CSUM_IP6_TSO;
1988292107Shselasky		}
1989219820Sjeff		if (mask & IFCAP_LRO)
1990219820Sjeff			dev->if_capenable ^= IFCAP_LRO;
1991219820Sjeff		if (mask & IFCAP_VLAN_HWTAGGING)
1992219820Sjeff			dev->if_capenable ^= IFCAP_VLAN_HWTAGGING;
1993219820Sjeff		if (mask & IFCAP_VLAN_HWFILTER)
1994219820Sjeff			dev->if_capenable ^= IFCAP_VLAN_HWFILTER;
1995220016Sjeff		if (mask & IFCAP_WOL_MAGIC)
1996220016Sjeff			dev->if_capenable ^= IFCAP_WOL_MAGIC;
1997219820Sjeff		if (dev->if_drv_flags & IFF_DRV_RUNNING)
1998272407Shselasky			mlx4_en_start_port(dev);
1999292107Shselaskyout:
2000253774Sjhb		mutex_unlock(&mdev->state_lock);
2001219820Sjeff		VLAN_CAPABILITIES(dev);
2002219820Sjeff		break;
2003292107Shselasky#if __FreeBSD_version >= 1100036
2004286841Sglebius	case SIOCGI2C: {
2005286841Sglebius		struct ifi2creq i2c;
2006286841Sglebius
2007286841Sglebius		error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));
2008286841Sglebius		if (error)
2009286841Sglebius			break;
2010286841Sglebius		if (i2c.len > sizeof(i2c.data)) {
2011286841Sglebius			error = EINVAL;
2012286841Sglebius			break;
2013286841Sglebius		}
2014286841Sglebius		/*
2015286841Sglebius		 * Note that we ignore i2c.addr here. The driver hardcodes
2016286841Sglebius		 * the address to 0x50, while standard expects it to be 0xA0.
2017286841Sglebius		 */
2018286841Sglebius		error = mlx4_get_module_info(mdev->dev, priv->port,
2019286841Sglebius		    i2c.offset, i2c.len, i2c.data);
2020286841Sglebius		if (error < 0) {
2021286841Sglebius			error = -error;
2022286841Sglebius			break;
2023286841Sglebius		}
2024286841Sglebius		error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
2025286841Sglebius		break;
2026286841Sglebius	}
2027292107Shselasky#endif
2028219820Sjeff	default:
2029219820Sjeff		error = ether_ioctl(dev, command, data);
2030219820Sjeff		break;
2031219820Sjeff	}
2032219820Sjeff
2033219820Sjeff	return (error);
2034219820Sjeff}
2035219820Sjeff
2036272407Shselasky
2037272407Shselaskyint mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
2038272407Shselasky			struct mlx4_en_port_profile *prof)
2039219820Sjeff{
2040272407Shselasky	struct net_device *dev;
2041272407Shselasky	struct mlx4_en_priv *priv;
2042272407Shselasky	uint8_t dev_addr[ETHER_ADDR_LEN];
2043272407Shselasky	int err;
2044272407Shselasky	int i;
2045219820Sjeff
2046272407Shselasky	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
2047272407Shselasky	dev = priv->dev = if_alloc(IFT_ETHER);
2048272407Shselasky	if (dev == NULL) {
2049272407Shselasky		en_err(priv, "Net device allocation failed\n");
2050272407Shselasky		kfree(priv);
2051272407Shselasky		return -ENOMEM;
2052272407Shselasky	}
2053272407Shselasky	dev->if_softc = priv;
2054320067Shselasky	if_initname(dev, "mlxen", (device_get_unit(
2055320067Shselasky	    mdev->pdev->dev.bsddev) * MLX4_MAX_PORTS) + port - 1);
2056272407Shselasky	dev->if_mtu = ETHERMTU;
2057272407Shselasky	dev->if_init = mlx4_en_open;
2058272407Shselasky	dev->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
2059272407Shselasky	dev->if_ioctl = mlx4_en_ioctl;
2060272407Shselasky	dev->if_transmit = mlx4_en_transmit;
2061272407Shselasky	dev->if_qflush = mlx4_en_qflush;
2062272407Shselasky	dev->if_snd.ifq_maxlen = prof->tx_ring_size;
2063219820Sjeff
2064272407Shselasky	/*
2065272407Shselasky	 * Initialize driver private data
2066272407Shselasky	 */
2067272407Shselasky	priv->counter_index = 0xff;
2068272407Shselasky	spin_lock_init(&priv->stats_lock);
2069272407Shselasky	INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode);
2070272407Shselasky	INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
2071272407Shselasky	INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
2072272407Shselasky	INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
2073272407Shselasky	INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task);
2074272407Shselasky	callout_init(&priv->watchdog_timer, 1);
2075272407Shselasky#ifdef CONFIG_RFS_ACCEL
2076272407Shselasky	INIT_LIST_HEAD(&priv->filters);
2077272407Shselasky	spin_lock_init(&priv->filters_lock);
2078272407Shselasky#endif
2079219820Sjeff
2080272407Shselasky	priv->msg_enable = MLX4_EN_MSG_LEVEL;
2081272407Shselasky	priv->dev = dev;
2082272407Shselasky	priv->mdev = mdev;
2083272407Shselasky	priv->ddev = &mdev->pdev->dev;
2084272407Shselasky	priv->prof = prof;
2085272407Shselasky	priv->port = port;
2086272407Shselasky	priv->port_up = false;
2087272407Shselasky	priv->flags = prof->flags;
2088272407Shselasky
2089272407Shselasky	priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up;
2090272407Shselasky	priv->tx_ring_num = prof->tx_ring_num;
2091272407Shselasky	priv->tx_ring = kcalloc(MAX_TX_RINGS,
2092272407Shselasky				sizeof(struct mlx4_en_tx_ring *), GFP_KERNEL);
2093272407Shselasky	if (!priv->tx_ring) {
2094272407Shselasky		err = -ENOMEM;
2095272407Shselasky		goto out;
2096219820Sjeff	}
2097272407Shselasky	priv->tx_cq = kcalloc(sizeof(struct mlx4_en_cq *), MAX_TX_RINGS,
2098272407Shselasky			GFP_KERNEL);
2099272407Shselasky	if (!priv->tx_cq) {
2100272407Shselasky		err = -ENOMEM;
2101272407Shselasky		goto out;
2102272407Shselasky	}
2103292107Shselasky
2104272407Shselasky	priv->rx_ring_num = prof->rx_ring_num;
2105272407Shselasky	priv->cqe_factor = (mdev->dev->caps.cqe_size == 64) ? 1 : 0;
2106272407Shselasky	priv->mac_index = -1;
2107272407Shselasky	priv->last_ifq_jiffies = 0;
2108272407Shselasky	priv->if_counters_rx_errors = 0;
2109272407Shselasky	priv->if_counters_rx_no_buffer = 0;
2110272407Shselasky#ifdef CONFIG_MLX4_EN_DCB
2111272407Shselasky	if (!mlx4_is_slave(priv->mdev->dev)) {
2112272407Shselasky		priv->dcbx_cap = DCB_CAP_DCBX_HOST;
2113272407Shselasky		priv->flags |= MLX4_EN_FLAG_DCB_ENABLED;
2114272407Shselasky		if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ETS_CFG) {
2115272407Shselasky			dev->dcbnl_ops = &mlx4_en_dcbnl_ops;
2116272407Shselasky		} else {
2117272407Shselasky			en_info(priv, "QoS disabled - no HW support\n");
2118272407Shselasky			dev->dcbnl_ops = &mlx4_en_dcbnl_pfc_ops;
2119272407Shselasky		}
2120272407Shselasky	}
2121272407Shselasky#endif
2122272407Shselasky
2123272407Shselasky	for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i)
2124272407Shselasky		INIT_HLIST_HEAD(&priv->mac_hash[i]);
2125272407Shselasky
2126272407Shselasky	/* Query for default mac and max mtu */
2127272407Shselasky	priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port];
2128272407Shselasky        priv->mac = mdev->dev->caps.def_mac[priv->port];
2129272407Shselasky        if (ILLEGAL_MAC(priv->mac)) {
2130272407Shselasky#if BITS_PER_LONG == 64
2131272407Shselasky                en_err(priv, "Port: %d, invalid mac burned: 0x%lx, quiting\n",
2132272407Shselasky                                priv->port, priv->mac);
2133272407Shselasky#elif BITS_PER_LONG == 32
2134272407Shselasky                en_err(priv, "Port: %d, invalid mac burned: 0x%llx, quiting\n",
2135272407Shselasky                                priv->port, priv->mac);
2136272407Shselasky#endif
2137272407Shselasky                err = -EINVAL;
2138272407Shselasky                goto out;
2139272407Shselasky        }
2140272407Shselasky
2141272407Shselasky	priv->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
2142272407Shselasky					  DS_SIZE);
2143272407Shselasky
2144272407Shselasky	mlx4_en_sysctl_conf(priv);
2145272407Shselasky
2146219820Sjeff	err = mlx4_en_alloc_resources(priv);
2147272407Shselasky	if (err)
2148272407Shselasky		goto out;
2149272407Shselasky
2150272407Shselasky	/* Allocate page for receive rings */
2151272407Shselasky	err = mlx4_alloc_hwq_res(mdev->dev, &priv->res,
2152272407Shselasky				MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE);
2153219820Sjeff	if (err) {
2154272407Shselasky		en_err(priv, "Failed to allocate page for rx qps\n");
2155219820Sjeff		goto out;
2156219820Sjeff	}
2157272407Shselasky	priv->allocated = 1;
2158272407Shselasky
2159272407Shselasky	/*
2160272407Shselasky	 * Set driver features
2161272407Shselasky	 */
2162292107Shselasky	dev->if_capabilities |= IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6;
2163272407Shselasky	dev->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
2164272407Shselasky	dev->if_capabilities |= IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWFILTER;
2165272407Shselasky	dev->if_capabilities |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU;
2166272407Shselasky	dev->if_capabilities |= IFCAP_LRO;
2167306955Shselasky	dev->if_capabilities |= IFCAP_HWSTATS;
2168272407Shselasky
2169272407Shselasky	if (mdev->LSO_support)
2170272407Shselasky		dev->if_capabilities |= IFCAP_TSO4 | IFCAP_TSO6 | IFCAP_VLAN_HWTSO;
2171274043Shselasky
2172272407Shselasky	/* set TSO limits so that we don't have to drop TX packets */
2173292107Shselasky	dev->if_hw_tsomax = MLX4_EN_TX_MAX_PAYLOAD_SIZE - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN) /* hdr */;
2174292107Shselasky	dev->if_hw_tsomaxsegcount = MLX4_EN_TX_MAX_MBUF_FRAGS - 1 /* hdr */;
2175292107Shselasky	dev->if_hw_tsomaxsegsize = MLX4_EN_TX_MAX_MBUF_SIZE;
2176274043Shselasky
2177272407Shselasky	dev->if_capenable = dev->if_capabilities;
2178272407Shselasky
2179272407Shselasky	dev->if_hwassist = 0;
2180272407Shselasky	if (dev->if_capenable & (IFCAP_TSO4 | IFCAP_TSO6))
2181272407Shselasky		dev->if_hwassist |= CSUM_TSO;
2182272407Shselasky	if (dev->if_capenable & IFCAP_TXCSUM)
2183272407Shselasky		dev->if_hwassist |= (CSUM_TCP | CSUM_UDP | CSUM_IP);
2184292107Shselasky	if (dev->if_capenable & IFCAP_TXCSUM_IPV6)
2185292107Shselasky		dev->if_hwassist |= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6);
2186272407Shselasky
2187272407Shselasky
2188272407Shselasky        /* Register for VLAN events */
2189272407Shselasky	priv->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
2190272407Shselasky            mlx4_en_vlan_rx_add_vid, priv, EVENTHANDLER_PRI_FIRST);
2191272407Shselasky	priv->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
2192272407Shselasky            mlx4_en_vlan_rx_kill_vid, priv, EVENTHANDLER_PRI_FIRST);
2193272407Shselasky
2194272407Shselasky	mdev->pndev[priv->port] = dev;
2195272407Shselasky
2196272407Shselasky	priv->last_link_state = MLX4_DEV_EVENT_PORT_DOWN;
2197272407Shselasky        mlx4_en_set_default_moderation(priv);
2198272407Shselasky
2199272407Shselasky	/* Set default MAC */
2200272407Shselasky	for (i = 0; i < ETHER_ADDR_LEN; i++)
2201272407Shselasky		dev_addr[ETHER_ADDR_LEN - 1 - i] = (u8) (priv->mac >> (8 * i));
2202272407Shselasky
2203272407Shselasky
2204272407Shselasky	ether_ifattach(dev, dev_addr);
2205272407Shselasky	if_link_state_change(dev, LINK_STATE_DOWN);
2206272407Shselasky	ifmedia_init(&priv->media, IFM_IMASK | IFM_ETH_FMASK,
2207272407Shselasky	    mlx4_en_media_change, mlx4_en_media_status);
2208272407Shselasky	ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_1000_T, 0, NULL);
2209272407Shselasky	ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_10G_SR, 0, NULL);
2210272407Shselasky	ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_10G_CX4, 0, NULL);
2211272407Shselasky	ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_40G_CR4, 0, NULL);
2212272407Shselasky	ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL);
2213272407Shselasky	ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO);
2214272407Shselasky
2215272407Shselasky	en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
2216272407Shselasky	en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
2217272407Shselasky
2218272407Shselasky	priv->registered = 1;
2219272407Shselasky
2220272407Shselasky        en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
2221272407Shselasky        en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
2222272407Shselasky
2223272407Shselasky
2224272407Shselasky	priv->rx_mb_size = dev->if_mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
2225272407Shselasky	err = mlx4_SET_PORT_general(mdev->dev, priv->port,
2226272407Shselasky				    priv->rx_mb_size,
2227272407Shselasky				    prof->tx_pause, prof->tx_ppp,
2228272407Shselasky				    prof->rx_pause, prof->rx_ppp);
2229272407Shselasky	if (err) {
2230272407Shselasky		en_err(priv, "Failed setting port general configurations "
2231272407Shselasky		       "for port %d, with error %d\n", priv->port, err);
2232272407Shselasky		goto out;
2233219820Sjeff	}
2234272407Shselasky
2235272407Shselasky	/* Init port */
2236272407Shselasky	en_warn(priv, "Initializing port\n");
2237272407Shselasky	err = mlx4_INIT_PORT(mdev->dev, priv->port);
2238272407Shselasky	if (err) {
2239272407Shselasky		en_err(priv, "Failed Initializing port\n");
2240272407Shselasky		goto out;
2241272407Shselasky	}
2242272407Shselasky
2243272407Shselasky	queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
2244272407Shselasky
2245272407Shselasky        if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
2246272407Shselasky                queue_delayed_work(mdev->workqueue, &priv->service_task, SERVICE_TASK_DELAY);
2247272407Shselasky
2248272407Shselasky	return 0;
2249272407Shselasky
2250219820Sjeffout:
2251272407Shselasky	mlx4_en_destroy_netdev(dev);
2252219820Sjeff	return err;
2253219820Sjeff}
2254279731Shselasky
2255272407Shselaskystatic int mlx4_en_set_ring_size(struct net_device *dev,
2256272407Shselasky    int rx_size, int tx_size)
2257272407Shselasky{
2258272407Shselasky        struct mlx4_en_priv *priv = netdev_priv(dev);
2259272407Shselasky        struct mlx4_en_dev *mdev = priv->mdev;
2260272407Shselasky        int port_up = 0;
2261272407Shselasky        int err = 0;
2262219820Sjeff
2263272407Shselasky        rx_size = roundup_pow_of_two(rx_size);
2264272407Shselasky        rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE);
2265272407Shselasky        rx_size = min_t(u32, rx_size, MLX4_EN_MAX_RX_SIZE);
2266272407Shselasky        tx_size = roundup_pow_of_two(tx_size);
2267272407Shselasky        tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
2268272407Shselasky        tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
2269272407Shselasky
2270272407Shselasky        if (rx_size == (priv->port_up ?
2271272407Shselasky            priv->rx_ring[0]->actual_size : priv->rx_ring[0]->size) &&
2272272407Shselasky            tx_size == priv->tx_ring[0]->size)
2273272407Shselasky                return 0;
2274272407Shselasky        mutex_lock(&mdev->state_lock);
2275272407Shselasky        if (priv->port_up) {
2276272407Shselasky                port_up = 1;
2277272407Shselasky                mlx4_en_stop_port(dev);
2278272407Shselasky        }
2279272407Shselasky        mlx4_en_free_resources(priv);
2280272407Shselasky        priv->prof->tx_ring_size = tx_size;
2281272407Shselasky        priv->prof->rx_ring_size = rx_size;
2282272407Shselasky        err = mlx4_en_alloc_resources(priv);
2283272407Shselasky        if (err) {
2284272407Shselasky                en_err(priv, "Failed reallocating port resources\n");
2285272407Shselasky                goto out;
2286272407Shselasky        }
2287272407Shselasky        if (port_up) {
2288272407Shselasky                err = mlx4_en_start_port(dev);
2289272407Shselasky                if (err)
2290272407Shselasky                        en_err(priv, "Failed starting port\n");
2291272407Shselasky        }
2292272407Shselaskyout:
2293272407Shselasky        mutex_unlock(&mdev->state_lock);
2294272407Shselasky        return err;
2295272407Shselasky}
2296219820Sjeffstatic int mlx4_en_set_rx_ring_size(SYSCTL_HANDLER_ARGS)
2297219820Sjeff{
2298272407Shselasky        struct mlx4_en_priv *priv;
2299272407Shselasky        int size;
2300272407Shselasky        int error;
2301219820Sjeff
2302272407Shselasky        priv = arg1;
2303272407Shselasky        size = priv->prof->rx_ring_size;
2304272407Shselasky        error = sysctl_handle_int(oidp, &size, 0, req);
2305272407Shselasky        if (error || !req->newptr)
2306272407Shselasky                return (error);
2307272407Shselasky        error = -mlx4_en_set_ring_size(priv->dev, size,
2308272407Shselasky            priv->prof->tx_ring_size);
2309272407Shselasky        return (error);
2310219820Sjeff}
2311219820Sjeff
2312219820Sjeffstatic int mlx4_en_set_tx_ring_size(SYSCTL_HANDLER_ARGS)
2313219820Sjeff{
2314272407Shselasky        struct mlx4_en_priv *priv;
2315272407Shselasky        int size;
2316272407Shselasky        int error;
2317219820Sjeff
2318272407Shselasky        priv = arg1;
2319272407Shselasky        size = priv->prof->tx_ring_size;
2320272407Shselasky        error = sysctl_handle_int(oidp, &size, 0, req);
2321272407Shselasky        if (error || !req->newptr)
2322272407Shselasky                return (error);
2323272407Shselasky        error = -mlx4_en_set_ring_size(priv->dev, priv->prof->rx_ring_size,
2324272407Shselasky            size);
2325219820Sjeff
2326272407Shselasky        return (error);
2327219820Sjeff}
2328219820Sjeff
2329292107Shselaskystatic int mlx4_en_get_module_info(struct net_device *dev,
2330292107Shselasky				   struct ethtool_modinfo *modinfo)
2331292107Shselasky{
2332292107Shselasky	struct mlx4_en_priv *priv = netdev_priv(dev);
2333292107Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
2334292107Shselasky	int ret;
2335292107Shselasky	u8 data[4];
2336292107Shselasky
2337292107Shselasky	/* Read first 2 bytes to get Module & REV ID */
2338292107Shselasky	ret = mlx4_get_module_info(mdev->dev, priv->port,
2339292107Shselasky				   0/*offset*/, 2/*size*/, data);
2340292107Shselasky
2341292107Shselasky	if (ret < 2) {
2342292107Shselasky		en_err(priv, "Failed to read eeprom module first two bytes, error: 0x%x\n", -ret);
2343292107Shselasky		return -EIO;
2344292107Shselasky	}
2345292107Shselasky
2346292107Shselasky	switch (data[0] /* identifier */) {
2347292107Shselasky	case MLX4_MODULE_ID_QSFP:
2348292107Shselasky		modinfo->type = ETH_MODULE_SFF_8436;
2349292107Shselasky		modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
2350292107Shselasky		break;
2351292107Shselasky	case MLX4_MODULE_ID_QSFP_PLUS:
2352292107Shselasky		if (data[1] >= 0x3) { /* revision id */
2353292107Shselasky			modinfo->type = ETH_MODULE_SFF_8636;
2354292107Shselasky			modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
2355292107Shselasky		} else {
2356292107Shselasky			modinfo->type = ETH_MODULE_SFF_8436;
2357292107Shselasky			modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
2358292107Shselasky		}
2359292107Shselasky		break;
2360292107Shselasky	case MLX4_MODULE_ID_QSFP28:
2361292107Shselasky		modinfo->type = ETH_MODULE_SFF_8636;
2362292107Shselasky		modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
2363292107Shselasky		break;
2364292107Shselasky	case MLX4_MODULE_ID_SFP:
2365292107Shselasky		modinfo->type = ETH_MODULE_SFF_8472;
2366292107Shselasky		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
2367292107Shselasky		break;
2368292107Shselasky	default:
2369292107Shselasky		en_err(priv, "mlx4_en_get_module_info :  Not recognized cable type\n");
2370292107Shselasky		return -EINVAL;
2371292107Shselasky	}
2372292107Shselasky
2373292107Shselasky	return 0;
2374292107Shselasky}
2375292107Shselasky
2376292107Shselaskystatic int mlx4_en_get_module_eeprom(struct net_device *dev,
2377292107Shselasky				     struct ethtool_eeprom *ee,
2378292107Shselasky				     u8 *data)
2379292107Shselasky{
2380292107Shselasky	struct mlx4_en_priv *priv = netdev_priv(dev);
2381292107Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
2382292107Shselasky	int offset = ee->offset;
2383292107Shselasky	int i = 0, ret;
2384292107Shselasky
2385292107Shselasky	if (ee->len == 0)
2386292107Shselasky		return -EINVAL;
2387292107Shselasky
2388292107Shselasky	memset(data, 0, ee->len);
2389292107Shselasky
2390292107Shselasky	while (i < ee->len) {
2391292107Shselasky		en_dbg(DRV, priv,
2392292107Shselasky		       "mlx4_get_module_info i(%d) offset(%d) len(%d)\n",
2393292107Shselasky		       i, offset, ee->len - i);
2394292107Shselasky
2395292107Shselasky		ret = mlx4_get_module_info(mdev->dev, priv->port,
2396292107Shselasky					   offset, ee->len - i, data + i);
2397292107Shselasky
2398292107Shselasky		if (!ret) /* Done reading */
2399292107Shselasky			return 0;
2400292107Shselasky
2401292107Shselasky		if (ret < 0) {
2402292107Shselasky			en_err(priv,
2403292107Shselasky			       "mlx4_get_module_info i(%d) offset(%d) bytes_to_read(%d) - FAILED (0x%x)\n",
2404292107Shselasky			       i, offset, ee->len - i, ret);
2405292107Shselasky			return -1;
2406292107Shselasky		}
2407292107Shselasky
2408292107Shselasky		i += ret;
2409292107Shselasky		offset += ret;
2410292107Shselasky	}
2411292107Shselasky	return 0;
2412292107Shselasky}
2413292107Shselasky
2414292107Shselaskystatic void mlx4_en_print_eeprom(u8 *data, __u32 len)
2415292107Shselasky{
2416292107Shselasky	int		i;
2417292107Shselasky	int		j = 0;
2418292107Shselasky	int		row = 0;
2419292107Shselasky	const int	NUM_OF_BYTES = 16;
2420292107Shselasky
2421292107Shselasky	printf("\nOffset\t\tValues\n");
2422292107Shselasky	printf("------\t\t------\n");
2423292107Shselasky	while(row < len){
2424292107Shselasky		printf("0x%04x\t\t",row);
2425292107Shselasky		for(i=0; i < NUM_OF_BYTES; i++){
2426292107Shselasky			printf("%02x ", data[j]);
2427292107Shselasky			row++;
2428292107Shselasky			j++;
2429292107Shselasky		}
2430292107Shselasky		printf("\n");
2431292107Shselasky	}
2432292107Shselasky}
2433292107Shselasky
2434292107Shselasky/* Read cable EEPROM module information by first inspecting the first
2435292107Shselasky * two bytes to get the length and then read the rest of the information.
2436292107Shselasky * The information is printed to dmesg. */
2437292107Shselaskystatic int mlx4_en_read_eeprom(SYSCTL_HANDLER_ARGS)
2438292107Shselasky{
2439292107Shselasky
2440292107Shselasky	u8*		data;
2441292107Shselasky	int		error;
2442292107Shselasky	int		result = 0;
2443292107Shselasky	struct		mlx4_en_priv *priv;
2444292107Shselasky	struct		net_device *dev;
2445292107Shselasky	struct		ethtool_modinfo modinfo;
2446292107Shselasky	struct		ethtool_eeprom ee;
2447292107Shselasky
2448292107Shselasky	error = sysctl_handle_int(oidp, &result, 0, req);
2449292107Shselasky	if (error || !req->newptr)
2450292107Shselasky		return (error);
2451292107Shselasky
2452292107Shselasky	if (result == 1) {
2453292107Shselasky		priv = arg1;
2454292107Shselasky		dev = priv->dev;
2455292107Shselasky		data = kmalloc(PAGE_SIZE, GFP_KERNEL);
2456292107Shselasky
2457292107Shselasky		error = mlx4_en_get_module_info(dev, &modinfo);
2458292107Shselasky		if (error) {
2459292107Shselasky			en_err(priv,
2460292107Shselasky			       "mlx4_en_get_module_info returned with error - FAILED (0x%x)\n",
2461292107Shselasky			       -error);
2462292107Shselasky			goto out;
2463292107Shselasky		}
2464292107Shselasky
2465292107Shselasky		ee.len = modinfo.eeprom_len;
2466292107Shselasky		ee.offset = 0;
2467292107Shselasky
2468292107Shselasky		error = mlx4_en_get_module_eeprom(dev, &ee, data);
2469292107Shselasky		if (error) {
2470292107Shselasky			en_err(priv,
2471292107Shselasky			       "mlx4_en_get_module_eeprom returned with error - FAILED (0x%x)\n",
2472292107Shselasky			       -error);
2473292107Shselasky			/* Continue printing partial information in case of an error */
2474292107Shselasky		}
2475292107Shselasky
2476292107Shselasky		/* EEPROM information will be printed in dmesg */
2477292107Shselasky		mlx4_en_print_eeprom(data, ee.len);
2478292107Shselaskyout:
2479292107Shselasky		kfree(data);
2480292107Shselasky	}
2481292107Shselasky	/* Return zero to prevent sysctl failure. */
2482292107Shselasky	return (0);
2483292107Shselasky}
2484292107Shselasky
2485219859Sjeffstatic int mlx4_en_set_tx_ppp(SYSCTL_HANDLER_ARGS)
2486219859Sjeff{
2487272407Shselasky        struct mlx4_en_priv *priv;
2488272407Shselasky        int ppp;
2489272407Shselasky        int error;
2490219859Sjeff
2491272407Shselasky        priv = arg1;
2492272407Shselasky        ppp = priv->prof->tx_ppp;
2493272407Shselasky        error = sysctl_handle_int(oidp, &ppp, 0, req);
2494272407Shselasky        if (error || !req->newptr)
2495272407Shselasky                return (error);
2496272407Shselasky        if (ppp > 0xff || ppp < 0)
2497272407Shselasky                return (-EINVAL);
2498272407Shselasky        priv->prof->tx_ppp = ppp;
2499272407Shselasky        error = -mlx4_SET_PORT_general(priv->mdev->dev, priv->port,
2500272407Shselasky                                       priv->rx_mb_size + ETHER_CRC_LEN,
2501272407Shselasky                                       priv->prof->tx_pause,
2502272407Shselasky                                       priv->prof->tx_ppp,
2503272407Shselasky                                       priv->prof->rx_pause,
2504272407Shselasky                                       priv->prof->rx_ppp);
2505219859Sjeff
2506272407Shselasky        return (error);
2507219859Sjeff}
2508219859Sjeff
2509219859Sjeffstatic int mlx4_en_set_rx_ppp(SYSCTL_HANDLER_ARGS)
2510219859Sjeff{
2511272407Shselasky        struct mlx4_en_priv *priv;
2512272407Shselasky        struct mlx4_en_dev *mdev;
2513272407Shselasky        int ppp;
2514272407Shselasky        int error;
2515272407Shselasky        int port_up;
2516219859Sjeff
2517272407Shselasky        port_up = 0;
2518272407Shselasky        priv = arg1;
2519272407Shselasky        mdev = priv->mdev;
2520272407Shselasky        ppp = priv->prof->rx_ppp;
2521272407Shselasky        error = sysctl_handle_int(oidp, &ppp, 0, req);
2522272407Shselasky        if (error || !req->newptr)
2523272407Shselasky                return (error);
2524272407Shselasky        if (ppp > 0xff || ppp < 0)
2525272407Shselasky                return (-EINVAL);
2526272407Shselasky        /* See if we have to change the number of tx queues. */
2527272407Shselasky        if (!ppp != !priv->prof->rx_ppp) {
2528272407Shselasky                mutex_lock(&mdev->state_lock);
2529272407Shselasky                if (priv->port_up) {
2530272407Shselasky                        port_up = 1;
2531272407Shselasky                        mlx4_en_stop_port(priv->dev);
2532272407Shselasky                }
2533272407Shselasky                mlx4_en_free_resources(priv);
2534272407Shselasky                priv->prof->rx_ppp = ppp;
2535272407Shselasky                error = -mlx4_en_alloc_resources(priv);
2536272407Shselasky                if (error)
2537272407Shselasky                        en_err(priv, "Failed reallocating port resources\n");
2538272407Shselasky                if (error == 0 && port_up) {
2539272407Shselasky                        error = -mlx4_en_start_port(priv->dev);
2540272407Shselasky                        if (error)
2541272407Shselasky                                en_err(priv, "Failed starting port\n");
2542272407Shselasky                }
2543272407Shselasky                mutex_unlock(&mdev->state_lock);
2544272407Shselasky                return (error);
2545219859Sjeff
2546272407Shselasky        }
2547272407Shselasky        priv->prof->rx_ppp = ppp;
2548272407Shselasky        error = -mlx4_SET_PORT_general(priv->mdev->dev, priv->port,
2549272407Shselasky                                       priv->rx_mb_size + ETHER_CRC_LEN,
2550272407Shselasky                                       priv->prof->tx_pause,
2551272407Shselasky                                       priv->prof->tx_ppp,
2552272407Shselasky                                       priv->prof->rx_pause,
2553272407Shselasky                                       priv->prof->rx_ppp);
2554219859Sjeff
2555272407Shselasky        return (error);
2556219859Sjeff}
2557219859Sjeff
2558219820Sjeffstatic void mlx4_en_sysctl_conf(struct mlx4_en_priv *priv)
2559219820Sjeff{
2560272407Shselasky        struct net_device *dev;
2561272407Shselasky        struct sysctl_ctx_list *ctx;
2562272407Shselasky        struct sysctl_oid *node;
2563272407Shselasky        struct sysctl_oid_list *node_list;
2564272407Shselasky        struct sysctl_oid *coal;
2565272407Shselasky        struct sysctl_oid_list *coal_list;
2566273246Shselasky	const char *pnameunit;
2567219820Sjeff
2568272407Shselasky        dev = priv->dev;
2569272407Shselasky        ctx = &priv->conf_ctx;
2570273246Shselasky	pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev);
2571219820Sjeff
2572272407Shselasky        sysctl_ctx_init(ctx);
2573318540Shselasky        priv->conf_sysctl = SYSCTL_ADD_NODE(ctx, SYSCTL_STATIC_CHILDREN(_hw),
2574272407Shselasky            OID_AUTO, dev->if_xname, CTLFLAG_RD, 0, "mlx4 10gig ethernet");
2575318540Shselasky        node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(priv->conf_sysctl), OID_AUTO,
2576272407Shselasky            "conf", CTLFLAG_RD, NULL, "Configuration");
2577272407Shselasky        node_list = SYSCTL_CHILDREN(node);
2578219820Sjeff
2579272407Shselasky        SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "msg_enable",
2580272407Shselasky            CTLFLAG_RW, &priv->msg_enable, 0,
2581272407Shselasky            "Driver message enable bitfield");
2582272407Shselasky        SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "rx_rings",
2583273246Shselasky            CTLFLAG_RD, &priv->rx_ring_num, 0,
2584272407Shselasky            "Number of receive rings");
2585272407Shselasky        SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "tx_rings",
2586273246Shselasky            CTLFLAG_RD, &priv->tx_ring_num, 0,
2587272407Shselasky            "Number of transmit rings");
2588272407Shselasky        SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "rx_size",
2589272407Shselasky            CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
2590272407Shselasky            mlx4_en_set_rx_ring_size, "I", "Receive ring size");
2591272407Shselasky        SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "tx_size",
2592272407Shselasky            CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
2593272407Shselasky            mlx4_en_set_tx_ring_size, "I", "Transmit ring size");
2594272407Shselasky        SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "tx_ppp",
2595272407Shselasky            CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
2596272407Shselasky            mlx4_en_set_tx_ppp, "I", "TX Per-priority pause");
2597272407Shselasky        SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "rx_ppp",
2598272407Shselasky            CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
2599272407Shselasky            mlx4_en_set_rx_ppp, "I", "RX Per-priority pause");
2600273246Shselasky        SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "port_num",
2601273246Shselasky            CTLFLAG_RD, &priv->port, 0,
2602273246Shselasky            "Port Number");
2603273246Shselasky        SYSCTL_ADD_STRING(ctx, node_list, OID_AUTO, "device_name",
2604273246Shselasky	    CTLFLAG_RD, __DECONST(void *, pnameunit), 0,
2605273246Shselasky	    "PCI device name");
2606219820Sjeff
2607272407Shselasky        /* Add coalescer configuration. */
2608272407Shselasky        coal = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO,
2609272407Shselasky            "coalesce", CTLFLAG_RD, NULL, "Interrupt coalesce configuration");
2610292107Shselasky        coal_list = SYSCTL_CHILDREN(coal);
2611272407Shselasky        SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "pkt_rate_low",
2612272407Shselasky            CTLFLAG_RW, &priv->pkt_rate_low, 0,
2613272407Shselasky            "Packets per-second for minimum delay");
2614272407Shselasky        SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "rx_usecs_low",
2615272407Shselasky            CTLFLAG_RW, &priv->rx_usecs_low, 0,
2616272407Shselasky            "Minimum RX delay in micro-seconds");
2617272407Shselasky        SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "pkt_rate_high",
2618272407Shselasky            CTLFLAG_RW, &priv->pkt_rate_high, 0,
2619272407Shselasky            "Packets per-second for maximum delay");
2620272407Shselasky        SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "rx_usecs_high",
2621272407Shselasky            CTLFLAG_RW, &priv->rx_usecs_high, 0,
2622272407Shselasky            "Maximum RX delay in micro-seconds");
2623272407Shselasky        SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "sample_interval",
2624272407Shselasky            CTLFLAG_RW, &priv->sample_interval, 0,
2625272407Shselasky            "adaptive frequency in units of HZ ticks");
2626272407Shselasky        SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "adaptive_rx_coal",
2627272407Shselasky            CTLFLAG_RW, &priv->adaptive_rx_coal, 0,
2628272407Shselasky            "Enable adaptive rx coalescing");
2629292107Shselasky	/* EEPROM support */
2630292107Shselasky	SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "eeprom_info",
2631292107Shselasky	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
2632292107Shselasky	    mlx4_en_read_eeprom, "I", "EEPROM information");
2633219820Sjeff}
2634219820Sjeff
2635219820Sjeffstatic void mlx4_en_sysctl_stat(struct mlx4_en_priv *priv)
2636219820Sjeff{
2637219820Sjeff	struct sysctl_ctx_list *ctx;
2638219820Sjeff	struct sysctl_oid_list *node_list;
2639219820Sjeff	struct sysctl_oid *ring_node;
2640219820Sjeff	struct sysctl_oid_list *ring_list;
2641219820Sjeff	struct mlx4_en_tx_ring *tx_ring;
2642219820Sjeff	struct mlx4_en_rx_ring *rx_ring;
2643219820Sjeff	char namebuf[128];
2644219820Sjeff	int i;
2645219820Sjeff
2646219820Sjeff	ctx = &priv->stat_ctx;
2647219820Sjeff	sysctl_ctx_init(ctx);
2648318540Shselasky	priv->stat_sysctl = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(priv->conf_sysctl), OID_AUTO,
2649219820Sjeff	    "stat", CTLFLAG_RD, NULL, "Statistics");
2650318540Shselasky	node_list = SYSCTL_CHILDREN(priv->stat_sysctl);
2651219820Sjeff
2652219820Sjeff#ifdef MLX4_EN_PERF_STAT
2653219820Sjeff	SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "tx_poll", CTLFLAG_RD,
2654219820Sjeff	    &priv->pstats.tx_poll, "TX Poll calls");
2655219820Sjeff	SYSCTL_ADD_QUAD(ctx, node_list, OID_AUTO, "tx_pktsz_avg", CTLFLAG_RD,
2656219820Sjeff	    &priv->pstats.tx_pktsz_avg, "TX average packet size");
2657219820Sjeff	SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "inflight_avg", CTLFLAG_RD,
2658219820Sjeff	    &priv->pstats.inflight_avg, "TX average packets in-flight");
2659219820Sjeff	SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "tx_coal_avg", CTLFLAG_RD,
2660219820Sjeff	    &priv->pstats.tx_coal_avg, "TX average coalesced completions");
2661219820Sjeff	SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "rx_coal_avg", CTLFLAG_RD,
2662219820Sjeff	    &priv->pstats.rx_coal_avg, "RX average coalesced completions");
2663219820Sjeff#endif
2664219820Sjeff
2665219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tso_packets", CTLFLAG_RD,
2666219820Sjeff	    &priv->port_stats.tso_packets, "TSO packets sent");
2667219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "queue_stopped", CTLFLAG_RD,
2668219820Sjeff	    &priv->port_stats.queue_stopped, "Queue full");
2669219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "wake_queue", CTLFLAG_RD,
2670219820Sjeff	    &priv->port_stats.wake_queue, "Queue resumed after full");
2671219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_timeout", CTLFLAG_RD,
2672219820Sjeff	    &priv->port_stats.tx_timeout, "Transmit timeouts");
2673292107Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_oversized_packets", CTLFLAG_RD,
2674292107Shselasky	    &priv->port_stats.oversized_packets, "TX oversized packets, m_defrag failed");
2675219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_alloc_failed", CTLFLAG_RD,
2676219820Sjeff	    &priv->port_stats.rx_alloc_failed, "RX failed to allocate mbuf");
2677219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_chksum_good", CTLFLAG_RD,
2678219820Sjeff	    &priv->port_stats.rx_chksum_good, "RX checksum offload success");
2679219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_chksum_none", CTLFLAG_RD,
2680219820Sjeff	    &priv->port_stats.rx_chksum_none, "RX without checksum offload");
2681219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_chksum_offload",
2682219820Sjeff	    CTLFLAG_RD, &priv->port_stats.tx_chksum_offload,
2683219820Sjeff	    "TX checksum offloads");
2684322531Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "defrag_attempts", CTLFLAG_RD,
2685322531Shselasky	    &priv->port_stats.defrag_attempts, "Oversized chains defragged");
2686219820Sjeff
2687219820Sjeff	/* Could strdup the names and add in a loop.  This is simpler. */
2688272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_bytes", CTLFLAG_RD,
2689272407Shselasky	    &priv->pkstats.rx_bytes, "RX Bytes");
2690272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_packets", CTLFLAG_RD,
2691272407Shselasky	    &priv->pkstats.rx_packets, "RX packets");
2692272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_multicast_packets", CTLFLAG_RD,
2693272407Shselasky	    &priv->pkstats.rx_multicast_packets, "RX Multicast Packets");
2694272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_broadcast_packets", CTLFLAG_RD,
2695272407Shselasky	    &priv->pkstats.rx_broadcast_packets, "RX Broadcast Packets");
2696272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_errors", CTLFLAG_RD,
2697272407Shselasky	    &priv->pkstats.rx_errors, "RX Errors");
2698272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_dropped", CTLFLAG_RD,
2699272407Shselasky	    &priv->pkstats.rx_dropped, "RX Dropped");
2700272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_length_errors", CTLFLAG_RD,
2701272407Shselasky	    &priv->pkstats.rx_length_errors, "RX Length Errors");
2702272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_over_errors", CTLFLAG_RD,
2703272407Shselasky	    &priv->pkstats.rx_over_errors, "RX Over Errors");
2704272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_crc_errors", CTLFLAG_RD,
2705272407Shselasky	    &priv->pkstats.rx_crc_errors, "RX CRC Errors");
2706272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_jabbers", CTLFLAG_RD,
2707272407Shselasky	    &priv->pkstats.rx_jabbers, "RX Jabbers");
2708219820Sjeff
2709272407Shselasky
2710272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_in_range_length_error", CTLFLAG_RD,
2711272407Shselasky	    &priv->pkstats.rx_in_range_length_error, "RX IN_Range Length Error");
2712272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_out_range_length_error",
2713272407Shselasky		CTLFLAG_RD, &priv->pkstats.rx_out_range_length_error,
2714272407Shselasky		"RX Out Range Length Error");
2715272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_lt_64_bytes_packets", CTLFLAG_RD,
2716272407Shselasky	    &priv->pkstats.rx_lt_64_bytes_packets, "RX Lt 64 Bytes Packets");
2717272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_127_bytes_packets", CTLFLAG_RD,
2718272407Shselasky	    &priv->pkstats.rx_127_bytes_packets, "RX 127 bytes Packets");
2719272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_255_bytes_packets", CTLFLAG_RD,
2720272407Shselasky	    &priv->pkstats.rx_255_bytes_packets, "RX 255 bytes Packets");
2721272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_511_bytes_packets", CTLFLAG_RD,
2722272407Shselasky	    &priv->pkstats.rx_511_bytes_packets, "RX 511 bytes Packets");
2723272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1023_bytes_packets", CTLFLAG_RD,
2724272407Shselasky	    &priv->pkstats.rx_1023_bytes_packets, "RX 1023 bytes Packets");
2725272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1518_bytes_packets", CTLFLAG_RD,
2726272407Shselasky	    &priv->pkstats.rx_1518_bytes_packets, "RX 1518 bytes Packets");
2727272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1522_bytes_packets", CTLFLAG_RD,
2728272407Shselasky	    &priv->pkstats.rx_1522_bytes_packets, "RX 1522 bytes Packets");
2729272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1548_bytes_packets", CTLFLAG_RD,
2730272407Shselasky	    &priv->pkstats.rx_1548_bytes_packets, "RX 1548 bytes Packets");
2731272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_gt_1548_bytes_packets", CTLFLAG_RD,
2732272407Shselasky	    &priv->pkstats.rx_gt_1548_bytes_packets,
2733272407Shselasky	    "RX Greater Then 1548 bytes Packets");
2734272407Shselasky
2735272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_packets", CTLFLAG_RD,
2736272407Shselasky	    &priv->pkstats.tx_packets, "TX packets");
2737272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_bytes", CTLFLAG_RD,
2738292107Shselasky	    &priv->pkstats.tx_bytes, "TX Bytes");
2739272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_multicast_packets", CTLFLAG_RD,
2740272407Shselasky	    &priv->pkstats.tx_multicast_packets, "TX Multicast Packets");
2741272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_broadcast_packets", CTLFLAG_RD,
2742272407Shselasky	    &priv->pkstats.tx_broadcast_packets, "TX Broadcast Packets");
2743272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_errors", CTLFLAG_RD,
2744272407Shselasky	    &priv->pkstats.tx_errors, "TX Errors");
2745272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_dropped", CTLFLAG_RD,
2746272407Shselasky	    &priv->pkstats.tx_dropped, "TX Dropped");
2747272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_lt_64_bytes_packets", CTLFLAG_RD,
2748272407Shselasky	    &priv->pkstats.tx_lt_64_bytes_packets, "TX Less Then 64 Bytes Packets");
2749272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_127_bytes_packets", CTLFLAG_RD,
2750272407Shselasky	    &priv->pkstats.tx_127_bytes_packets, "TX 127 Bytes Packets");
2751272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_255_bytes_packets", CTLFLAG_RD,
2752272407Shselasky	    &priv->pkstats.tx_255_bytes_packets, "TX 255 Bytes Packets");
2753272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_511_bytes_packets", CTLFLAG_RD,
2754272407Shselasky	    &priv->pkstats.tx_511_bytes_packets, "TX 511 Bytes Packets");
2755272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1023_bytes_packets", CTLFLAG_RD,
2756272407Shselasky	    &priv->pkstats.tx_1023_bytes_packets, "TX 1023 Bytes Packets");
2757272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1518_bytes_packets", CTLFLAG_RD,
2758272407Shselasky	    &priv->pkstats.tx_1518_bytes_packets, "TX 1518 Bytes Packets");
2759272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1522_bytes_packets", CTLFLAG_RD,
2760272407Shselasky	    &priv->pkstats.tx_1522_bytes_packets, "TX 1522 Bytes Packets");
2761272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1548_bytes_packets", CTLFLAG_RD,
2762272407Shselasky	    &priv->pkstats.tx_1548_bytes_packets, "TX 1548 Bytes Packets");
2763272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_gt_1548_bytes_packets", CTLFLAG_RD,
2764272407Shselasky	    &priv->pkstats.tx_gt_1548_bytes_packets,
2765272407Shselasky	    "TX Greater Then 1548 Bytes Packets");
2766272407Shselasky
2767272407Shselasky
2768272407Shselasky
2769219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++) {
2770272407Shselasky		tx_ring = priv->tx_ring[i];
2771219820Sjeff		snprintf(namebuf, sizeof(namebuf), "tx_ring%d", i);
2772219820Sjeff		ring_node = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO, namebuf,
2773219820Sjeff		    CTLFLAG_RD, NULL, "TX Ring");
2774219820Sjeff		ring_list = SYSCTL_CHILDREN(ring_node);
2775219820Sjeff		SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "packets",
2776219820Sjeff		    CTLFLAG_RD, &tx_ring->packets, "TX packets");
2777219820Sjeff		SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "bytes",
2778219820Sjeff		    CTLFLAG_RD, &tx_ring->bytes, "TX bytes");
2779322531Shselasky		SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "tso_packets",
2780322531Shselasky		    CTLFLAG_RD, &tx_ring->tso_packets, "TSO packets");
2781322531Shselasky		SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "defrag_attempts",
2782322531Shselasky		    CTLFLAG_RD, &tx_ring->defrag_attempts, "Oversized chains defragged");
2783292107Shselasky	}
2784219820Sjeff
2785219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++) {
2786272407Shselasky		rx_ring = priv->rx_ring[i];
2787219820Sjeff		snprintf(namebuf, sizeof(namebuf), "rx_ring%d", i);
2788219820Sjeff		ring_node = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO, namebuf,
2789219820Sjeff		    CTLFLAG_RD, NULL, "RX Ring");
2790219820Sjeff		ring_list = SYSCTL_CHILDREN(ring_node);
2791219820Sjeff		SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "packets",
2792219820Sjeff		    CTLFLAG_RD, &rx_ring->packets, "RX packets");
2793219820Sjeff		SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "bytes",
2794219820Sjeff		    CTLFLAG_RD, &rx_ring->bytes, "RX bytes");
2795219820Sjeff		SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "error",
2796219820Sjeff		    CTLFLAG_RD, &rx_ring->errors, "RX soft errors");
2797219820Sjeff	}
2798219820Sjeff}
2799