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);
57272407Shselaskystatic int mlx4_en_unit;
58219820Sjeff
59272407Shselasky#ifdef CONFIG_NET_RX_BUSY_POLL
60272407Shselasky/* must be called with local_bh_disable()d */
61272407Shselaskystatic int mlx4_en_low_latency_recv(struct napi_struct *napi)
62272407Shselasky{
63272407Shselasky	struct mlx4_en_cq *cq = container_of(napi, struct mlx4_en_cq, napi);
64272407Shselasky	struct net_device *dev = cq->dev;
65272407Shselasky	struct mlx4_en_priv *priv = netdev_priv(dev);
66272407Shselasky	struct mlx4_en_rx_ring *rx_ring = priv->rx_ring[cq->ring];
67272407Shselasky	int done;
68272407Shselasky
69272407Shselasky	if (!priv->port_up)
70272407Shselasky		return LL_FLUSH_FAILED;
71272407Shselasky
72272407Shselasky	if (!mlx4_en_cq_lock_poll(cq))
73272407Shselasky		return LL_FLUSH_BUSY;
74272407Shselasky
75272407Shselasky	done = mlx4_en_process_rx_cq(dev, cq, 4);
76272407Shselasky#ifdef LL_EXTENDED_STATS
77272407Shselasky	if (done)
78272407Shselasky		rx_ring->cleaned += done;
79272407Shselasky	else
80272407Shselasky		rx_ring->misses++;
81272407Shselasky#endif
82272407Shselasky
83272407Shselasky	mlx4_en_cq_unlock_poll(cq);
84272407Shselasky
85272407Shselasky	return done;
86272407Shselasky}
87272407Shselasky#endif	/* CONFIG_NET_RX_BUSY_POLL */
88272407Shselasky
89272407Shselasky#ifdef CONFIG_RFS_ACCEL
90272407Shselasky
91272407Shselaskystruct mlx4_en_filter {
92272407Shselasky	struct list_head next;
93272407Shselasky	struct work_struct work;
94272407Shselasky
95272407Shselasky	u8     ip_proto;
96272407Shselasky	__be32 src_ip;
97272407Shselasky	__be32 dst_ip;
98272407Shselasky	__be16 src_port;
99272407Shselasky	__be16 dst_port;
100272407Shselasky
101272407Shselasky	int rxq_index;
102272407Shselasky	struct mlx4_en_priv *priv;
103272407Shselasky	u32 flow_id;			/* RFS infrastructure id */
104272407Shselasky	int id;				/* mlx4_en driver id */
105272407Shselasky	u64 reg_id;			/* Flow steering API id */
106272407Shselasky	u8 activated;			/* Used to prevent expiry before filter
107272407Shselasky					 * is attached
108272407Shselasky					 */
109272407Shselasky	struct hlist_node filter_chain;
110272407Shselasky};
111272407Shselasky
112272407Shselaskystatic void mlx4_en_filter_rfs_expire(struct mlx4_en_priv *priv);
113272407Shselasky
114272407Shselaskystatic enum mlx4_net_trans_rule_id mlx4_ip_proto_to_trans_rule_id(u8 ip_proto)
115272407Shselasky{
116272407Shselasky	switch (ip_proto) {
117272407Shselasky	case IPPROTO_UDP:
118272407Shselasky		return MLX4_NET_TRANS_RULE_ID_UDP;
119272407Shselasky	case IPPROTO_TCP:
120272407Shselasky		return MLX4_NET_TRANS_RULE_ID_TCP;
121272407Shselasky	default:
122272407Shselasky		return -EPROTONOSUPPORT;
123272407Shselasky	}
124272407Shselasky};
125272407Shselasky
126272407Shselaskystatic void mlx4_en_filter_work(struct work_struct *work)
127272407Shselasky{
128272407Shselasky	struct mlx4_en_filter *filter = container_of(work,
129272407Shselasky						     struct mlx4_en_filter,
130272407Shselasky						     work);
131272407Shselasky	struct mlx4_en_priv *priv = filter->priv;
132272407Shselasky	struct mlx4_spec_list spec_tcp_udp = {
133272407Shselasky		.id = mlx4_ip_proto_to_trans_rule_id(filter->ip_proto),
134272407Shselasky		{
135272407Shselasky			.tcp_udp = {
136272407Shselasky				.dst_port = filter->dst_port,
137272407Shselasky				.dst_port_msk = (__force __be16)-1,
138272407Shselasky				.src_port = filter->src_port,
139272407Shselasky				.src_port_msk = (__force __be16)-1,
140272407Shselasky			},
141272407Shselasky		},
142272407Shselasky	};
143272407Shselasky	struct mlx4_spec_list spec_ip = {
144272407Shselasky		.id = MLX4_NET_TRANS_RULE_ID_IPV4,
145272407Shselasky		{
146272407Shselasky			.ipv4 = {
147272407Shselasky				.dst_ip = filter->dst_ip,
148272407Shselasky				.dst_ip_msk = (__force __be32)-1,
149272407Shselasky				.src_ip = filter->src_ip,
150272407Shselasky				.src_ip_msk = (__force __be32)-1,
151272407Shselasky			},
152272407Shselasky		},
153272407Shselasky	};
154272407Shselasky	struct mlx4_spec_list spec_eth = {
155272407Shselasky		.id = MLX4_NET_TRANS_RULE_ID_ETH,
156272407Shselasky	};
157272407Shselasky	struct mlx4_net_trans_rule rule = {
158272407Shselasky		.list = LIST_HEAD_INIT(rule.list),
159272407Shselasky		.queue_mode = MLX4_NET_TRANS_Q_LIFO,
160272407Shselasky		.exclusive = 1,
161272407Shselasky		.allow_loopback = 1,
162272407Shselasky		.promisc_mode = MLX4_FS_REGULAR,
163272407Shselasky		.port = priv->port,
164272407Shselasky		.priority = MLX4_DOMAIN_RFS,
165272407Shselasky	};
166272407Shselasky	int rc;
167272407Shselasky	__be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
168272407Shselasky
169272407Shselasky	if (spec_tcp_udp.id < 0) {
170272407Shselasky		en_warn(priv, "RFS: ignoring unsupported ip protocol (%d)\n",
171272407Shselasky			filter->ip_proto);
172272407Shselasky		goto ignore;
173272407Shselasky	}
174272407Shselasky	list_add_tail(&spec_eth.list, &rule.list);
175272407Shselasky	list_add_tail(&spec_ip.list, &rule.list);
176272407Shselasky	list_add_tail(&spec_tcp_udp.list, &rule.list);
177272407Shselasky
178272407Shselasky	rule.qpn = priv->rss_map.qps[filter->rxq_index].qpn;
179272407Shselasky	memcpy(spec_eth.eth.dst_mac, priv->dev->dev_addr, ETH_ALEN);
180272407Shselasky	memcpy(spec_eth.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
181272407Shselasky
182272407Shselasky	filter->activated = 0;
183272407Shselasky
184272407Shselasky	if (filter->reg_id) {
185272407Shselasky		rc = mlx4_flow_detach(priv->mdev->dev, filter->reg_id);
186272407Shselasky		if (rc && rc != -ENOENT)
187272407Shselasky			en_err(priv, "Error detaching flow. rc = %d\n", rc);
188272407Shselasky	}
189272407Shselasky
190272407Shselasky	rc = mlx4_flow_attach(priv->mdev->dev, &rule, &filter->reg_id);
191272407Shselasky	if (rc)
192272407Shselasky		en_err(priv, "Error attaching flow. err = %d\n", rc);
193272407Shselasky
194272407Shselaskyignore:
195272407Shselasky	mlx4_en_filter_rfs_expire(priv);
196272407Shselasky
197272407Shselasky	filter->activated = 1;
198272407Shselasky}
199272407Shselasky
200272407Shselaskystatic inline struct hlist_head *
201272407Shselaskyfilter_hash_bucket(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip,
202272407Shselasky		   __be16 src_port, __be16 dst_port)
203272407Shselasky{
204272407Shselasky	unsigned long l;
205272407Shselasky	int bucket_idx;
206272407Shselasky
207272407Shselasky	l = (__force unsigned long)src_port |
208272407Shselasky	    ((__force unsigned long)dst_port << 2);
209272407Shselasky	l ^= (__force unsigned long)(src_ip ^ dst_ip);
210272407Shselasky
211272407Shselasky	bucket_idx = hash_long(l, MLX4_EN_FILTER_HASH_SHIFT);
212272407Shselasky
213272407Shselasky	return &priv->filter_hash[bucket_idx];
214272407Shselasky}
215272407Shselasky
216272407Shselaskystatic struct mlx4_en_filter *
217272407Shselaskymlx4_en_filter_alloc(struct mlx4_en_priv *priv, int rxq_index, __be32 src_ip,
218272407Shselasky		     __be32 dst_ip, u8 ip_proto, __be16 src_port,
219272407Shselasky		     __be16 dst_port, u32 flow_id)
220272407Shselasky{
221272407Shselasky	struct mlx4_en_filter *filter = NULL;
222272407Shselasky
223272407Shselasky	filter = kzalloc(sizeof(struct mlx4_en_filter), GFP_ATOMIC);
224272407Shselasky	if (!filter)
225272407Shselasky		return NULL;
226272407Shselasky
227272407Shselasky	filter->priv = priv;
228272407Shselasky	filter->rxq_index = rxq_index;
229272407Shselasky	INIT_WORK(&filter->work, mlx4_en_filter_work);
230272407Shselasky
231272407Shselasky	filter->src_ip = src_ip;
232272407Shselasky	filter->dst_ip = dst_ip;
233272407Shselasky	filter->ip_proto = ip_proto;
234272407Shselasky	filter->src_port = src_port;
235272407Shselasky	filter->dst_port = dst_port;
236272407Shselasky
237272407Shselasky	filter->flow_id = flow_id;
238272407Shselasky
239272407Shselasky	filter->id = priv->last_filter_id++ % RPS_NO_FILTER;
240272407Shselasky
241272407Shselasky	list_add_tail(&filter->next, &priv->filters);
242272407Shselasky	hlist_add_head(&filter->filter_chain,
243272407Shselasky		       filter_hash_bucket(priv, src_ip, dst_ip, src_port,
244272407Shselasky					  dst_port));
245272407Shselasky
246272407Shselasky	return filter;
247272407Shselasky}
248272407Shselasky
249272407Shselaskystatic void mlx4_en_filter_free(struct mlx4_en_filter *filter)
250272407Shselasky{
251272407Shselasky	struct mlx4_en_priv *priv = filter->priv;
252272407Shselasky	int rc;
253272407Shselasky
254272407Shselasky	list_del(&filter->next);
255272407Shselasky
256272407Shselasky	rc = mlx4_flow_detach(priv->mdev->dev, filter->reg_id);
257272407Shselasky	if (rc && rc != -ENOENT)
258272407Shselasky		en_err(priv, "Error detaching flow. rc = %d\n", rc);
259272407Shselasky
260272407Shselasky	kfree(filter);
261272407Shselasky}
262272407Shselasky
263272407Shselaskystatic inline struct mlx4_en_filter *
264272407Shselaskymlx4_en_filter_find(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip,
265272407Shselasky		    u8 ip_proto, __be16 src_port, __be16 dst_port)
266272407Shselasky{
267272407Shselasky	struct hlist_node *elem;
268272407Shselasky	struct mlx4_en_filter *filter;
269272407Shselasky	struct mlx4_en_filter *ret = NULL;
270272407Shselasky
271272407Shselasky	hlist_for_each_entry(filter, elem,
272272407Shselasky			     filter_hash_bucket(priv, src_ip, dst_ip,
273272407Shselasky						src_port, dst_port),
274272407Shselasky			     filter_chain) {
275272407Shselasky		if (filter->src_ip == src_ip &&
276272407Shselasky		    filter->dst_ip == dst_ip &&
277272407Shselasky		    filter->ip_proto == ip_proto &&
278272407Shselasky		    filter->src_port == src_port &&
279272407Shselasky		    filter->dst_port == dst_port) {
280272407Shselasky			ret = filter;
281272407Shselasky			break;
282272407Shselasky		}
283272407Shselasky	}
284272407Shselasky
285272407Shselasky	return ret;
286272407Shselasky}
287272407Shselasky
288272407Shselaskystatic int
289272407Shselaskymlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
290272407Shselasky		   u16 rxq_index, u32 flow_id)
291272407Shselasky{
292272407Shselasky	struct mlx4_en_priv *priv = netdev_priv(net_dev);
293272407Shselasky	struct mlx4_en_filter *filter;
294272407Shselasky	const struct iphdr *ip;
295272407Shselasky	const __be16 *ports;
296272407Shselasky	u8 ip_proto;
297272407Shselasky	__be32 src_ip;
298272407Shselasky	__be32 dst_ip;
299272407Shselasky	__be16 src_port;
300272407Shselasky	__be16 dst_port;
301272407Shselasky	int nhoff = skb_network_offset(skb);
302272407Shselasky	int ret = 0;
303272407Shselasky
304272407Shselasky	if (skb->protocol != htons(ETH_P_IP))
305272407Shselasky		return -EPROTONOSUPPORT;
306272407Shselasky
307272407Shselasky	ip = (const struct iphdr *)(skb->data + nhoff);
308272407Shselasky	if (ip_is_fragment(ip))
309272407Shselasky		return -EPROTONOSUPPORT;
310272407Shselasky
311272407Shselasky	if ((ip->protocol != IPPROTO_TCP) && (ip->protocol != IPPROTO_UDP))
312272407Shselasky		return -EPROTONOSUPPORT;
313272407Shselasky	ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
314272407Shselasky
315272407Shselasky	ip_proto = ip->protocol;
316272407Shselasky	src_ip = ip->saddr;
317272407Shselasky	dst_ip = ip->daddr;
318272407Shselasky	src_port = ports[0];
319272407Shselasky	dst_port = ports[1];
320272407Shselasky
321272407Shselasky	spin_lock_bh(&priv->filters_lock);
322272407Shselasky	filter = mlx4_en_filter_find(priv, src_ip, dst_ip, ip_proto,
323272407Shselasky				     src_port, dst_port);
324272407Shselasky	if (filter) {
325272407Shselasky		if (filter->rxq_index == rxq_index)
326272407Shselasky			goto out;
327272407Shselasky
328272407Shselasky		filter->rxq_index = rxq_index;
329272407Shselasky	} else {
330272407Shselasky		filter = mlx4_en_filter_alloc(priv, rxq_index,
331272407Shselasky					      src_ip, dst_ip, ip_proto,
332272407Shselasky					      src_port, dst_port, flow_id);
333272407Shselasky		if (!filter) {
334272407Shselasky			ret = -ENOMEM;
335272407Shselasky			goto err;
336272407Shselasky		}
337272407Shselasky	}
338272407Shselasky
339272407Shselasky	queue_work(priv->mdev->workqueue, &filter->work);
340272407Shselasky
341272407Shselaskyout:
342272407Shselasky	ret = filter->id;
343272407Shselaskyerr:
344272407Shselasky	spin_unlock_bh(&priv->filters_lock);
345272407Shselasky
346272407Shselasky	return ret;
347272407Shselasky}
348272407Shselasky
349272407Shselaskyvoid mlx4_en_cleanup_filters(struct mlx4_en_priv *priv,
350272407Shselasky			     struct mlx4_en_rx_ring *rx_ring)
351272407Shselasky{
352272407Shselasky	struct mlx4_en_filter *filter, *tmp;
353272407Shselasky	LIST_HEAD(del_list);
354272407Shselasky
355272407Shselasky	spin_lock_bh(&priv->filters_lock);
356272407Shselasky	list_for_each_entry_safe(filter, tmp, &priv->filters, next) {
357272407Shselasky		list_move(&filter->next, &del_list);
358272407Shselasky		hlist_del(&filter->filter_chain);
359272407Shselasky	}
360272407Shselasky	spin_unlock_bh(&priv->filters_lock);
361272407Shselasky
362272407Shselasky	list_for_each_entry_safe(filter, tmp, &del_list, next) {
363272407Shselasky		cancel_work_sync(&filter->work);
364272407Shselasky		mlx4_en_filter_free(filter);
365272407Shselasky	}
366272407Shselasky}
367272407Shselasky
368272407Shselaskystatic void mlx4_en_filter_rfs_expire(struct mlx4_en_priv *priv)
369272407Shselasky{
370272407Shselasky	struct mlx4_en_filter *filter = NULL, *tmp, *last_filter = NULL;
371272407Shselasky	LIST_HEAD(del_list);
372272407Shselasky	int i = 0;
373272407Shselasky
374272407Shselasky	spin_lock_bh(&priv->filters_lock);
375272407Shselasky	list_for_each_entry_safe(filter, tmp, &priv->filters, next) {
376272407Shselasky		if (i > MLX4_EN_FILTER_EXPIRY_QUOTA)
377272407Shselasky			break;
378272407Shselasky
379272407Shselasky		if (filter->activated &&
380272407Shselasky		    !work_pending(&filter->work) &&
381272407Shselasky		    rps_may_expire_flow(priv->dev,
382272407Shselasky					filter->rxq_index, filter->flow_id,
383272407Shselasky					filter->id)) {
384272407Shselasky			list_move(&filter->next, &del_list);
385272407Shselasky			hlist_del(&filter->filter_chain);
386272407Shselasky		} else
387272407Shselasky			last_filter = filter;
388272407Shselasky
389272407Shselasky		i++;
390272407Shselasky	}
391272407Shselasky
392272407Shselasky	if (last_filter && (&last_filter->next != priv->filters.next))
393272407Shselasky		list_move(&priv->filters, &last_filter->next);
394272407Shselasky
395272407Shselasky	spin_unlock_bh(&priv->filters_lock);
396272407Shselasky
397272407Shselasky	list_for_each_entry_safe(filter, tmp, &del_list, next)
398272407Shselasky		mlx4_en_filter_free(filter);
399272407Shselasky}
400272407Shselasky#endif
401272407Shselasky
402219820Sjeffstatic void mlx4_en_vlan_rx_add_vid(void *arg, struct net_device *dev, u16 vid)
403219820Sjeff{
404219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
405272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
406272407Shselasky	int err;
407219820Sjeff	int idx;
408219820Sjeff
409258280Salfred	if (arg != priv)
410258280Salfred		return;
411258280Salfred
412219820Sjeff	en_dbg(HW, priv, "adding VLAN:%d\n", vid);
413272407Shselasky
414272407Shselasky	set_bit(vid, priv->active_vlans);
415272407Shselasky
416272407Shselasky	/* Add VID to port VLAN filter */
417272407Shselasky	mutex_lock(&mdev->state_lock);
418272407Shselasky	if (mdev->device_up && priv->port_up) {
419272407Shselasky		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
420272407Shselasky		if (err)
421272407Shselasky			en_err(priv, "Failed configuring VLAN filter\n");
422272407Shselasky	}
423272407Shselasky	if (mlx4_register_vlan(mdev->dev, priv->port, vid, &idx))
424272407Shselasky		en_dbg(HW, priv, "failed adding vlan %d\n", vid);
425272407Shselasky	mutex_unlock(&mdev->state_lock);
426272407Shselasky
427219820Sjeff}
428219820Sjeff
429219820Sjeffstatic void mlx4_en_vlan_rx_kill_vid(void *arg, struct net_device *dev, u16 vid)
430219820Sjeff{
431219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
432272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
433272407Shselasky	int err;
434219820Sjeff
435258280Salfred	if (arg != priv)
436258280Salfred		return;
437258280Salfred
438219820Sjeff	en_dbg(HW, priv, "Killing VID:%d\n", vid);
439272407Shselasky
440272407Shselasky	clear_bit(vid, priv->active_vlans);
441272407Shselasky
442272407Shselasky	/* Remove VID from port VLAN filter */
443272407Shselasky	mutex_lock(&mdev->state_lock);
444272407Shselasky	mlx4_unregister_vlan(mdev->dev, priv->port, vid);
445272407Shselasky
446272407Shselasky	if (mdev->device_up && priv->port_up) {
447272407Shselasky		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
448272407Shselasky		if (err)
449272407Shselasky			en_err(priv, "Failed configuring VLAN filter\n");
450272407Shselasky	}
451272407Shselasky	mutex_unlock(&mdev->state_lock);
452272407Shselasky
453219820Sjeff}
454219820Sjeff
455272407Shselaskystatic int mlx4_en_uc_steer_add(struct mlx4_en_priv *priv,
456272407Shselasky				unsigned char *mac, int *qpn, u64 *reg_id)
457219820Sjeff{
458272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
459272407Shselasky	struct mlx4_dev *dev = mdev->dev;
460272407Shselasky	int err;
461219820Sjeff
462272407Shselasky	switch (dev->caps.steering_mode) {
463272407Shselasky	case MLX4_STEERING_MODE_B0: {
464272407Shselasky		struct mlx4_qp qp;
465272407Shselasky		u8 gid[16] = {0};
466272407Shselasky
467272407Shselasky		qp.qpn = *qpn;
468272407Shselasky		memcpy(&gid[10], mac, ETH_ALEN);
469272407Shselasky		gid[5] = priv->port;
470272407Shselasky
471272407Shselasky		err = mlx4_unicast_attach(dev, &qp, gid, 0, MLX4_PROT_ETH);
472272407Shselasky		break;
473219820Sjeff	}
474272407Shselasky	case MLX4_STEERING_MODE_DEVICE_MANAGED: {
475272407Shselasky		struct mlx4_spec_list spec_eth = { {NULL} };
476272407Shselasky		__be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
477272407Shselasky
478272407Shselasky		struct mlx4_net_trans_rule rule = {
479272407Shselasky			.queue_mode = MLX4_NET_TRANS_Q_FIFO,
480272407Shselasky			.exclusive = 0,
481272407Shselasky			.allow_loopback = 1,
482272407Shselasky			.promisc_mode = MLX4_FS_REGULAR,
483272407Shselasky			.priority = MLX4_DOMAIN_NIC,
484272407Shselasky		};
485272407Shselasky
486272407Shselasky		rule.port = priv->port;
487272407Shselasky		rule.qpn = *qpn;
488272407Shselasky		INIT_LIST_HEAD(&rule.list);
489272407Shselasky
490272407Shselasky		spec_eth.id = MLX4_NET_TRANS_RULE_ID_ETH;
491272407Shselasky		memcpy(spec_eth.eth.dst_mac, mac, ETH_ALEN);
492272407Shselasky		memcpy(spec_eth.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
493272407Shselasky		list_add_tail(&spec_eth.list, &rule.list);
494272407Shselasky
495272407Shselasky		err = mlx4_flow_attach(dev, &rule, reg_id);
496272407Shselasky		break;
497272407Shselasky	}
498272407Shselasky	default:
499272407Shselasky		return -EINVAL;
500272407Shselasky	}
501272407Shselasky	if (err)
502272407Shselasky		en_warn(priv, "Failed Attaching Unicast\n");
503272407Shselasky
504272407Shselasky	return err;
505219820Sjeff}
506219820Sjeff
507272407Shselaskystatic void mlx4_en_uc_steer_release(struct mlx4_en_priv *priv,
508272407Shselasky				     unsigned char *mac, int qpn, u64 reg_id)
509219820Sjeff{
510272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
511272407Shselasky	struct mlx4_dev *dev = mdev->dev;
512219820Sjeff
513272407Shselasky	switch (dev->caps.steering_mode) {
514272407Shselasky	case MLX4_STEERING_MODE_B0: {
515272407Shselasky		struct mlx4_qp qp;
516272407Shselasky		u8 gid[16] = {0};
517272407Shselasky
518272407Shselasky		qp.qpn = qpn;
519272407Shselasky		memcpy(&gid[10], mac, ETH_ALEN);
520272407Shselasky		gid[5] = priv->port;
521272407Shselasky
522272407Shselasky		mlx4_unicast_detach(dev, &qp, gid, MLX4_PROT_ETH);
523272407Shselasky		break;
524219820Sjeff	}
525272407Shselasky	case MLX4_STEERING_MODE_DEVICE_MANAGED: {
526272407Shselasky		mlx4_flow_detach(dev, reg_id);
527272407Shselasky		break;
528272407Shselasky	}
529272407Shselasky	default:
530272407Shselasky		en_err(priv, "Invalid steering mode.\n");
531272407Shselasky	}
532272407Shselasky}
533272407Shselasky
534272407Shselaskystatic int mlx4_en_get_qp(struct mlx4_en_priv *priv)
535272407Shselasky{
536272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
537272407Shselasky	struct mlx4_dev *dev = mdev->dev;
538272407Shselasky	struct mlx4_mac_entry *entry;
539272407Shselasky	int index = 0;
540272407Shselasky	int err = 0;
541272407Shselasky	u64 reg_id;
542272407Shselasky	int *qpn = &priv->base_qpn;
543272407Shselasky	u64 mac = mlx4_mac_to_u64(IF_LLADDR(priv->dev));
544272407Shselasky
545272407Shselasky	en_dbg(DRV, priv, "Registering MAC: %pM for adding\n",
546272407Shselasky	       IF_LLADDR(priv->dev));
547272407Shselasky	index = mlx4_register_mac(dev, priv->port, mac);
548272407Shselasky	if (index < 0) {
549272407Shselasky		err = index;
550272407Shselasky		en_err(priv, "Failed adding MAC: %pM\n",
551272407Shselasky		       IF_LLADDR(priv->dev));
552272407Shselasky		return err;
553272407Shselasky	}
554272407Shselasky
555272407Shselasky	if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
556272407Shselasky		int base_qpn = mlx4_get_base_qpn(dev, priv->port);
557272407Shselasky		*qpn = base_qpn + index;
558272407Shselasky		return 0;
559272407Shselasky	}
560272407Shselasky
561272407Shselasky	err = mlx4_qp_reserve_range(dev, 1, 1, qpn, 0);
562272407Shselasky	en_dbg(DRV, priv, "Reserved qp %d\n", *qpn);
563272407Shselasky	if (err) {
564272407Shselasky		en_err(priv, "Failed to reserve qp for mac registration\n");
565272407Shselasky		goto qp_err;
566272407Shselasky	}
567272407Shselasky
568272407Shselasky	err = mlx4_en_uc_steer_add(priv, IF_LLADDR(priv->dev), qpn, &reg_id);
569272407Shselasky	if (err)
570272407Shselasky		goto steer_err;
571272407Shselasky
572272407Shselasky	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
573272407Shselasky	if (!entry) {
574272407Shselasky		err = -ENOMEM;
575272407Shselasky		goto alloc_err;
576272407Shselasky	}
577272407Shselasky	memcpy(entry->mac, IF_LLADDR(priv->dev), sizeof(entry->mac));
578272407Shselasky	entry->reg_id = reg_id;
579272407Shselasky
580272407Shselasky	hlist_add_head(&entry->hlist,
581272407Shselasky			   &priv->mac_hash[entry->mac[MLX4_EN_MAC_HASH_IDX]]);
582272407Shselasky
583272407Shselasky	return 0;
584272407Shselasky
585272407Shselaskyalloc_err:
586272407Shselasky	mlx4_en_uc_steer_release(priv, IF_LLADDR(priv->dev), *qpn, reg_id);
587272407Shselasky
588272407Shselaskysteer_err:
589272407Shselasky	mlx4_qp_release_range(dev, *qpn, 1);
590272407Shselasky
591272407Shselaskyqp_err:
592272407Shselasky	mlx4_unregister_mac(dev, priv->port, mac);
593272407Shselasky	return err;
594272407Shselasky}
595272407Shselasky
596272407Shselaskystatic void mlx4_en_put_qp(struct mlx4_en_priv *priv)
597272407Shselasky{
598272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
599272407Shselasky	struct mlx4_dev *dev = mdev->dev;
600272407Shselasky	int qpn = priv->base_qpn;
601272407Shselasky	u64 mac;
602272407Shselasky
603272407Shselasky	if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
604272407Shselasky		mac = mlx4_mac_to_u64(IF_LLADDR(priv->dev));
605272407Shselasky		en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
606272407Shselasky		       IF_LLADDR(priv->dev));
607272407Shselasky		mlx4_unregister_mac(dev, priv->port, mac);
608272407Shselasky	} else {
609272407Shselasky		struct mlx4_mac_entry *entry;
610272407Shselasky		struct hlist_node *n, *tmp;
611272407Shselasky		struct hlist_head *bucket;
612272407Shselasky		unsigned int i;
613272407Shselasky
614272407Shselasky		for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) {
615272407Shselasky			bucket = &priv->mac_hash[i];
616272407Shselasky			hlist_for_each_entry_safe(entry, n, tmp, bucket, hlist) {
617272407Shselasky				mac = mlx4_mac_to_u64(entry->mac);
618272407Shselasky				en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
619272407Shselasky				       entry->mac);
620272407Shselasky				mlx4_en_uc_steer_release(priv, entry->mac,
621272407Shselasky							 qpn, entry->reg_id);
622272407Shselasky
623272407Shselasky				mlx4_unregister_mac(dev, priv->port, mac);
624272407Shselasky				hlist_del(&entry->hlist);
625272407Shselasky				kfree(entry);
626272407Shselasky			}
627219820Sjeff		}
628272407Shselasky
629272407Shselasky		en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n",
630272407Shselasky		       priv->port, qpn);
631272407Shselasky		mlx4_qp_release_range(dev, qpn, 1);
632272407Shselasky		priv->flags &= ~MLX4_EN_FLAG_FORCE_PROMISC;
633219820Sjeff	}
634219820Sjeff}
635219820Sjeff
636272407Shselaskystatic void mlx4_en_clear_list(struct net_device *dev)
637259608Salfred{
638259608Salfred	struct mlx4_en_priv *priv = netdev_priv(dev);
639272407Shselasky	struct mlx4_en_mc_list *tmp, *mc_to_del;
640272407Shselasky
641272407Shselasky	list_for_each_entry_safe(mc_to_del, tmp, &priv->mc_list, list) {
642272407Shselasky		list_del(&mc_to_del->list);
643272407Shselasky		kfree(mc_to_del);
644272407Shselasky	}
645259608Salfred}
646219820Sjeff
647272407Shselaskystatic void mlx4_en_cache_mclist(struct net_device *dev)
648259608Salfred{
649272407Shselasky        struct ifmultiaddr *ifma;
650272407Shselasky	struct mlx4_en_mc_list *tmp;
651259608Salfred	struct mlx4_en_priv *priv = netdev_priv(dev);
652259608Salfred
653283175Shselasky        if_maddr_rlock(dev);
654272407Shselasky        TAILQ_FOREACH(ifma, &dev->if_multiaddrs, ifma_link) {
655272407Shselasky                if (ifma->ifma_addr->sa_family != AF_LINK)
656272407Shselasky                        continue;
657272407Shselasky                if (((struct sockaddr_dl *)ifma->ifma_addr)->sdl_alen !=
658272407Shselasky                                ETHER_ADDR_LEN)
659272407Shselasky                        continue;
660272407Shselasky                /* Make sure the list didn't grow. */
661272407Shselasky		tmp = kzalloc(sizeof(struct mlx4_en_mc_list), GFP_ATOMIC);
662292107Shselasky		if (tmp == NULL) {
663292107Shselasky			en_err(priv, "Failed to allocate multicast list\n");
664283175Shselasky			break;
665292107Shselasky		}
666272407Shselasky		memcpy(tmp->addr,
667272407Shselasky			LLADDR((struct sockaddr_dl *)ifma->ifma_addr), ETH_ALEN);
668272407Shselasky		list_add_tail(&tmp->list, &priv->mc_list);
669272407Shselasky        }
670283175Shselasky        if_maddr_runlock(dev);
671259608Salfred}
672259608Salfred
673272407Shselaskystatic void update_mclist_flags(struct mlx4_en_priv *priv,
674272407Shselasky				struct list_head *dst,
675272407Shselasky				struct list_head *src)
676219820Sjeff{
677272407Shselasky	struct mlx4_en_mc_list *dst_tmp, *src_tmp, *new_mc;
678272407Shselasky	bool found;
679272407Shselasky
680272407Shselasky	/* Find all the entries that should be removed from dst,
681272407Shselasky	 * These are the entries that are not found in src
682272407Shselasky	 */
683272407Shselasky	list_for_each_entry(dst_tmp, dst, list) {
684272407Shselasky		found = false;
685272407Shselasky		list_for_each_entry(src_tmp, src, list) {
686272407Shselasky			if (!memcmp(dst_tmp->addr, src_tmp->addr, ETH_ALEN)) {
687272407Shselasky				found = true;
688272407Shselasky				break;
689272407Shselasky			}
690272407Shselasky		}
691272407Shselasky		if (!found)
692272407Shselasky			dst_tmp->action = MCLIST_REM;
693272407Shselasky	}
694272407Shselasky
695272407Shselasky	/* Add entries that exist in src but not in dst
696272407Shselasky	 * mark them as need to add
697272407Shselasky	 */
698272407Shselasky	list_for_each_entry(src_tmp, src, list) {
699272407Shselasky		found = false;
700272407Shselasky		list_for_each_entry(dst_tmp, dst, list) {
701272407Shselasky			if (!memcmp(dst_tmp->addr, src_tmp->addr, ETH_ALEN)) {
702272407Shselasky				dst_tmp->action = MCLIST_NONE;
703272407Shselasky				found = true;
704272407Shselasky				break;
705272407Shselasky			}
706272407Shselasky		}
707272407Shselasky		if (!found) {
708272407Shselasky			new_mc = kmalloc(sizeof(struct mlx4_en_mc_list),
709272407Shselasky					 GFP_KERNEL);
710272407Shselasky			if (!new_mc) {
711272407Shselasky				en_err(priv, "Failed to allocate current multicast list\n");
712272407Shselasky				return;
713272407Shselasky			}
714272407Shselasky			memcpy(new_mc, src_tmp,
715272407Shselasky			       sizeof(struct mlx4_en_mc_list));
716272407Shselasky			new_mc->action = MCLIST_ADD;
717272407Shselasky			list_add_tail(&new_mc->list, dst);
718272407Shselasky		}
719272407Shselasky	}
720272407Shselasky}
721272407Shselasky
722272407Shselaskystatic void mlx4_en_set_rx_mode(struct net_device *dev)
723272407Shselasky{
724219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
725219820Sjeff
726219820Sjeff	if (!priv->port_up)
727219820Sjeff		return;
728219820Sjeff
729272407Shselasky	queue_work(priv->mdev->workqueue, &priv->rx_mode_task);
730219820Sjeff}
731219820Sjeff
732272407Shselaskystatic void mlx4_en_set_promisc_mode(struct mlx4_en_priv *priv,
733272407Shselasky				     struct mlx4_en_dev *mdev)
734219820Sjeff{
735272407Shselasky	int err = 0;
736272407Shselasky	if (!(priv->flags & MLX4_EN_FLAG_PROMISC)) {
737272407Shselasky		priv->flags |= MLX4_EN_FLAG_PROMISC;
738219820Sjeff
739272407Shselasky		/* Enable promiscouos mode */
740272407Shselasky		switch (mdev->dev->caps.steering_mode) {
741272407Shselasky		case MLX4_STEERING_MODE_DEVICE_MANAGED:
742272407Shselasky			err = mlx4_flow_steer_promisc_add(mdev->dev,
743272407Shselasky							  priv->port,
744272407Shselasky							  priv->base_qpn,
745272407Shselasky							  MLX4_FS_ALL_DEFAULT);
746219820Sjeff			if (err)
747272407Shselasky				en_err(priv, "Failed enabling promiscuous mode\n");
748272407Shselasky			priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
749272407Shselasky			break;
750219820Sjeff
751272407Shselasky		case MLX4_STEERING_MODE_B0:
752272407Shselasky			err = mlx4_unicast_promisc_add(mdev->dev,
753272407Shselasky						       priv->base_qpn,
754272407Shselasky						       priv->port);
755219820Sjeff			if (err)
756272407Shselasky				en_err(priv, "Failed enabling unicast promiscuous mode\n");
757219820Sjeff
758272407Shselasky			/* Add the default qp number as multicast
759272407Shselasky			 * promisc
760272407Shselasky			 */
761272407Shselasky			if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
762272407Shselasky				err = mlx4_multicast_promisc_add(mdev->dev,
763272407Shselasky								 priv->base_qpn,
764272407Shselasky								 priv->port);
765272407Shselasky				if (err)
766272407Shselasky					en_err(priv, "Failed enabling multicast promiscuous mode\n");
767272407Shselasky				priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
768272407Shselasky			}
769272407Shselasky			break;
770272407Shselasky
771272407Shselasky		case MLX4_STEERING_MODE_A0:
772272407Shselasky			err = mlx4_SET_PORT_qpn_calc(mdev->dev,
773272407Shselasky						     priv->port,
774272407Shselasky						     priv->base_qpn,
775272407Shselasky						     1);
776219820Sjeff			if (err)
777272407Shselasky				en_err(priv, "Failed enabling promiscuous mode\n");
778272407Shselasky			break;
779219820Sjeff		}
780272407Shselasky
781272407Shselasky		/* Disable port multicast filter (unconditionally) */
782272407Shselasky		err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
783272407Shselasky					  0, MLX4_MCAST_DISABLE);
784272407Shselasky		if (err)
785272407Shselasky			en_err(priv, "Failed disabling multicast filter\n");
786219820Sjeff	}
787272407Shselasky}
788219820Sjeff
789272407Shselaskystatic void mlx4_en_clear_promisc_mode(struct mlx4_en_priv *priv,
790272407Shselasky				       struct mlx4_en_dev *mdev)
791272407Shselasky{
792272407Shselasky	int err = 0;
793219820Sjeff
794272407Shselasky	priv->flags &= ~MLX4_EN_FLAG_PROMISC;
795219820Sjeff
796272407Shselasky	/* Disable promiscouos mode */
797272407Shselasky	switch (mdev->dev->caps.steering_mode) {
798272407Shselasky	case MLX4_STEERING_MODE_DEVICE_MANAGED:
799272407Shselasky		err = mlx4_flow_steer_promisc_remove(mdev->dev,
800272407Shselasky						     priv->port,
801272407Shselasky						     MLX4_FS_ALL_DEFAULT);
802219820Sjeff		if (err)
803272407Shselasky			en_err(priv, "Failed disabling promiscuous mode\n");
804272407Shselasky		priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
805272407Shselasky		break;
806219820Sjeff
807272407Shselasky	case MLX4_STEERING_MODE_B0:
808272407Shselasky		err = mlx4_unicast_promisc_remove(mdev->dev,
809272407Shselasky						  priv->base_qpn,
810272407Shselasky						  priv->port);
811219820Sjeff		if (err)
812272407Shselasky			en_err(priv, "Failed disabling unicast promiscuous mode\n");
813272407Shselasky		/* Disable Multicast promisc */
814272407Shselasky		if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
815272407Shselasky			err = mlx4_multicast_promisc_remove(mdev->dev,
816272407Shselasky							    priv->base_qpn,
817272407Shselasky							    priv->port);
818272407Shselasky			if (err)
819272407Shselasky				en_err(priv, "Failed disabling multicast promiscuous mode\n");
820272407Shselasky			priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
821272407Shselasky		}
822272407Shselasky		break;
823272407Shselasky
824272407Shselasky	case MLX4_STEERING_MODE_A0:
825272407Shselasky		err = mlx4_SET_PORT_qpn_calc(mdev->dev,
826272407Shselasky					     priv->port,
827272407Shselasky					     priv->base_qpn, 0);
828272407Shselasky		if (err)
829272407Shselasky			en_err(priv, "Failed disabling promiscuous mode\n");
830272407Shselasky		break;
831219820Sjeff	}
832272407Shselasky}
833219820Sjeff
834272407Shselaskystatic void mlx4_en_do_multicast(struct mlx4_en_priv *priv,
835272407Shselasky				 struct net_device *dev,
836272407Shselasky				 struct mlx4_en_dev *mdev)
837272407Shselasky{
838272407Shselasky	struct mlx4_en_mc_list *mclist, *tmp;
839272407Shselasky	u8 mc_list[16] = {0};
840272407Shselasky	int err = 0;
841272407Shselasky	u64 mcast_addr = 0;
842272407Shselasky
843272407Shselasky
844219820Sjeff	/* Enable/disable the multicast filter according to IFF_ALLMULTI */
845219820Sjeff	if (dev->if_flags & IFF_ALLMULTI) {
846219820Sjeff		err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
847219820Sjeff					  0, MLX4_MCAST_DISABLE);
848219820Sjeff		if (err)
849219820Sjeff			en_err(priv, "Failed disabling multicast filter\n");
850272407Shselasky
851272407Shselasky		/* Add the default qp number as multicast promisc */
852272407Shselasky		if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
853272407Shselasky			switch (mdev->dev->caps.steering_mode) {
854272407Shselasky			case MLX4_STEERING_MODE_DEVICE_MANAGED:
855272407Shselasky				err = mlx4_flow_steer_promisc_add(mdev->dev,
856272407Shselasky								  priv->port,
857272407Shselasky								  priv->base_qpn,
858272407Shselasky								  MLX4_FS_MC_DEFAULT);
859272407Shselasky				break;
860272407Shselasky
861272407Shselasky			case MLX4_STEERING_MODE_B0:
862272407Shselasky				err = mlx4_multicast_promisc_add(mdev->dev,
863272407Shselasky								 priv->base_qpn,
864272407Shselasky								 priv->port);
865272407Shselasky				break;
866272407Shselasky
867272407Shselasky			case MLX4_STEERING_MODE_A0:
868272407Shselasky				break;
869272407Shselasky			}
870272407Shselasky			if (err)
871272407Shselasky				en_err(priv, "Failed entering multicast promisc mode\n");
872272407Shselasky			priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
873272407Shselasky		}
874219820Sjeff	} else {
875272407Shselasky		/* Disable Multicast promisc */
876272407Shselasky		if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
877272407Shselasky			switch (mdev->dev->caps.steering_mode) {
878272407Shselasky			case MLX4_STEERING_MODE_DEVICE_MANAGED:
879272407Shselasky				err = mlx4_flow_steer_promisc_remove(mdev->dev,
880272407Shselasky								     priv->port,
881272407Shselasky								     MLX4_FS_MC_DEFAULT);
882272407Shselasky				break;
883219820Sjeff
884272407Shselasky			case MLX4_STEERING_MODE_B0:
885272407Shselasky				err = mlx4_multicast_promisc_remove(mdev->dev,
886272407Shselasky								    priv->base_qpn,
887272407Shselasky								    priv->port);
888272407Shselasky				break;
889272407Shselasky
890272407Shselasky			case MLX4_STEERING_MODE_A0:
891272407Shselasky				break;
892272407Shselasky			}
893272407Shselasky			if (err)
894272407Shselasky				en_err(priv, "Failed disabling multicast promiscuous mode\n");
895272407Shselasky			priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
896272407Shselasky		}
897272407Shselasky
898219820Sjeff		err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
899219820Sjeff					  0, MLX4_MCAST_DISABLE);
900219820Sjeff		if (err)
901219820Sjeff			en_err(priv, "Failed disabling multicast filter\n");
902219820Sjeff
903219820Sjeff		/* Flush mcast filter and init it with broadcast address */
904219820Sjeff		mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST,
905219820Sjeff				    1, MLX4_MCAST_CONFIG);
906219820Sjeff
907219820Sjeff		/* Update multicast list - we cache all addresses so they won't
908219820Sjeff		 * change while HW is updated holding the command semaphor */
909272407Shselasky		mlx4_en_cache_mclist(dev);
910272407Shselasky		list_for_each_entry(mclist, &priv->mc_list, list) {
911272407Shselasky			mcast_addr = mlx4_mac_to_u64(mclist->addr);
912219820Sjeff			mlx4_SET_MCAST_FLTR(mdev->dev, priv->port,
913272407Shselasky					mcast_addr, 0, MLX4_MCAST_CONFIG);
914272407Shselasky		}
915219820Sjeff		err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
916219820Sjeff					  0, MLX4_MCAST_ENABLE);
917219820Sjeff		if (err)
918219820Sjeff			en_err(priv, "Failed enabling multicast filter\n");
919219820Sjeff
920272407Shselasky		update_mclist_flags(priv, &priv->curr_list, &priv->mc_list);
921272407Shselasky		list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) {
922272407Shselasky			if (mclist->action == MCLIST_REM) {
923272407Shselasky				/* detach this address and delete from list */
924272407Shselasky				memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
925272407Shselasky				mc_list[5] = priv->port;
926272407Shselasky				err = mlx4_multicast_detach(mdev->dev,
927272407Shselasky							    &priv->rss_map.indir_qp,
928272407Shselasky							    mc_list,
929272407Shselasky							    MLX4_PROT_ETH,
930272407Shselasky							    mclist->reg_id);
931272407Shselasky				if (err)
932272407Shselasky					en_err(priv, "Fail to detach multicast address\n");
933272407Shselasky
934272407Shselasky				/* remove from list */
935272407Shselasky				list_del(&mclist->list);
936272407Shselasky				kfree(mclist);
937272407Shselasky			} else if (mclist->action == MCLIST_ADD) {
938272407Shselasky				/* attach the address */
939272407Shselasky				memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
940272407Shselasky				/* needed for B0 steering support */
941272407Shselasky				mc_list[5] = priv->port;
942272407Shselasky				err = mlx4_multicast_attach(mdev->dev,
943272407Shselasky							    &priv->rss_map.indir_qp,
944272407Shselasky							    mc_list,
945272407Shselasky							    priv->port, 0,
946272407Shselasky							    MLX4_PROT_ETH,
947272407Shselasky							    &mclist->reg_id);
948272407Shselasky				if (err)
949272407Shselasky					en_err(priv, "Fail to attach multicast address\n");
950272407Shselasky
951272407Shselasky			}
952272407Shselasky		}
953219820Sjeff	}
954272407Shselasky}
955272407Shselasky
956272407Shselaskystatic void mlx4_en_do_set_rx_mode(struct work_struct *work)
957272407Shselasky{
958272407Shselasky	struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
959272407Shselasky						 rx_mode_task);
960272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
961272407Shselasky	struct net_device *dev = priv->dev;
962272407Shselasky
963272407Shselasky
964272407Shselasky	mutex_lock(&mdev->state_lock);
965272407Shselasky	if (!mdev->device_up) {
966272407Shselasky		en_dbg(HW, priv, "Card is not up, ignoring rx mode change.\n");
967272407Shselasky		goto out;
968272407Shselasky	}
969272407Shselasky	if (!priv->port_up) {
970272407Shselasky		en_dbg(HW, priv, "Port is down, ignoring rx mode change.\n");
971272407Shselasky		goto out;
972272407Shselasky	}
973272407Shselasky	if (!mlx4_en_QUERY_PORT(mdev, priv->port)) {
974272407Shselasky		if (priv->port_state.link_state) {
975272407Shselasky			priv->last_link_state = MLX4_DEV_EVENT_PORT_UP;
976292107Shselasky			/* update netif baudrate */
977292107Shselasky			priv->dev->if_baudrate =
978292107Shselasky			    IF_Mbps(priv->port_state.link_speed);
979272407Shselasky			/* Important note: the following call for if_link_state_change
980272407Shselasky			 * is needed for interface up scenario (start port, link state
981272407Shselasky			 * change) */
982272407Shselasky			if_link_state_change(priv->dev, LINK_STATE_UP);
983272407Shselasky			en_dbg(HW, priv, "Link Up\n");
984272407Shselasky		}
985272407Shselasky	}
986272407Shselasky
987272407Shselasky	/* Promsicuous mode: disable all filters */
988272407Shselasky	if ((dev->if_flags & IFF_PROMISC) ||
989272407Shselasky	    (priv->flags & MLX4_EN_FLAG_FORCE_PROMISC)) {
990272407Shselasky		mlx4_en_set_promisc_mode(priv, mdev);
991272407Shselasky		goto out;
992272407Shselasky	}
993272407Shselasky
994272407Shselasky	/* Not in promiscuous mode */
995272407Shselasky	if (priv->flags & MLX4_EN_FLAG_PROMISC)
996272407Shselasky		mlx4_en_clear_promisc_mode(priv, mdev);
997272407Shselasky
998272407Shselasky	mlx4_en_do_multicast(priv, dev, mdev);
999219820Sjeffout:
1000219820Sjeff	mutex_unlock(&mdev->state_lock);
1001219820Sjeff}
1002219820Sjeff
1003219820Sjeff#ifdef CONFIG_NET_POLL_CONTROLLER
1004219820Sjeffstatic void mlx4_en_netpoll(struct net_device *dev)
1005219820Sjeff{
1006219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
1007219820Sjeff	struct mlx4_en_cq *cq;
1008219820Sjeff	unsigned long flags;
1009219820Sjeff	int i;
1010219820Sjeff
1011219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++) {
1012272407Shselasky		cq = priv->rx_cq[i];
1013219820Sjeff		spin_lock_irqsave(&cq->lock, flags);
1014219820Sjeff		napi_synchronize(&cq->napi);
1015219859Sjeff		mlx4_en_process_rx_cq(dev, cq, 0);
1016219820Sjeff		spin_unlock_irqrestore(&cq->lock, flags);
1017219820Sjeff	}
1018219820Sjeff}
1019219820Sjeff#endif
1020219820Sjeff
1021219820Sjeffstatic void mlx4_en_watchdog_timeout(void *arg)
1022219820Sjeff{
1023272407Shselasky        struct mlx4_en_priv *priv = arg;
1024272407Shselasky        struct mlx4_en_dev *mdev = priv->mdev;
1025219820Sjeff
1026272407Shselasky        en_dbg(DRV, priv, "Scheduling watchdog\n");
1027272407Shselasky        queue_work(mdev->workqueue, &priv->watchdog_task);
1028272407Shselasky        if (priv->port_up)
1029272407Shselasky                callout_reset(&priv->watchdog_timer, MLX4_EN_WATCHDOG_TIMEOUT,
1030272407Shselasky                                mlx4_en_watchdog_timeout, priv);
1031219820Sjeff}
1032219820Sjeff
1033219820Sjeff
1034272407Shselasky
1035219820Sjeffstatic void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
1036219820Sjeff{
1037219820Sjeff	struct mlx4_en_cq *cq;
1038219820Sjeff	int i;
1039219820Sjeff
1040219820Sjeff	/* If we haven't received a specific coalescing setting
1041272407Shselasky	 * (module param), we set the moderation parameters as follows:
1042219820Sjeff	 * - moder_cnt is set to the number of mtu sized packets to
1043219820Sjeff	 *   satisfy our coelsing target.
1044219820Sjeff	 * - moder_time is set to a fixed value.
1045219820Sjeff	 */
1046219820Sjeff	priv->rx_frames = MLX4_EN_RX_COAL_TARGET / priv->dev->if_mtu + 1;
1047219820Sjeff	priv->rx_usecs = MLX4_EN_RX_COAL_TIME;
1048272407Shselasky	priv->tx_frames = MLX4_EN_TX_COAL_PKTS;
1049272407Shselasky	priv->tx_usecs = MLX4_EN_TX_COAL_TIME;
1050272407Shselasky	en_dbg(INTR, priv, "Default coalesing params for mtu: %u - "
1051272407Shselasky	       "rx_frames:%d rx_usecs:%d\n",
1052272407Shselasky	       (unsigned)priv->dev->if_mtu, priv->rx_frames, priv->rx_usecs);
1053219820Sjeff
1054219820Sjeff	/* Setup cq moderation params */
1055219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++) {
1056272407Shselasky		cq = priv->rx_cq[i];
1057219820Sjeff		cq->moder_cnt = priv->rx_frames;
1058219820Sjeff		cq->moder_time = priv->rx_usecs;
1059257867Salfred		priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
1060257867Salfred		priv->last_moder_packets[i] = 0;
1061257867Salfred		priv->last_moder_bytes[i] = 0;
1062219820Sjeff	}
1063219820Sjeff
1064219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++) {
1065272407Shselasky		cq = priv->tx_cq[i];
1066272407Shselasky		cq->moder_cnt = priv->tx_frames;
1067272407Shselasky		cq->moder_time = priv->tx_usecs;
1068219820Sjeff	}
1069219820Sjeff
1070219820Sjeff	/* Reset auto-moderation params */
1071219820Sjeff	priv->pkt_rate_low = MLX4_EN_RX_RATE_LOW;
1072219820Sjeff	priv->rx_usecs_low = MLX4_EN_RX_COAL_TIME_LOW;
1073219820Sjeff	priv->pkt_rate_high = MLX4_EN_RX_RATE_HIGH;
1074219820Sjeff	priv->rx_usecs_high = MLX4_EN_RX_COAL_TIME_HIGH;
1075219820Sjeff	priv->sample_interval = MLX4_EN_SAMPLE_INTERVAL;
1076219820Sjeff	priv->adaptive_rx_coal = 1;
1077219820Sjeff	priv->last_moder_jiffies = 0;
1078219820Sjeff	priv->last_moder_tx_packets = 0;
1079219820Sjeff}
1080219820Sjeff
1081219820Sjeffstatic void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
1082219820Sjeff{
1083219820Sjeff	unsigned long period = (unsigned long) (jiffies - priv->last_moder_jiffies);
1084219820Sjeff	struct mlx4_en_cq *cq;
1085219820Sjeff	unsigned long packets;
1086219820Sjeff	unsigned long rate;
1087219820Sjeff	unsigned long avg_pkt_size;
1088219820Sjeff	unsigned long rx_packets;
1089219820Sjeff	unsigned long rx_bytes;
1090219820Sjeff	unsigned long rx_pkt_diff;
1091219820Sjeff	int moder_time;
1092257867Salfred	int ring, err;
1093219820Sjeff
1094219820Sjeff	if (!priv->adaptive_rx_coal || period < priv->sample_interval * HZ)
1095219820Sjeff		return;
1096272407Shselasky
1097257867Salfred	for (ring = 0; ring < priv->rx_ring_num; ring++) {
1098272407Shselasky                spin_lock(&priv->stats_lock);
1099272407Shselasky		rx_packets = priv->rx_ring[ring]->packets;
1100272407Shselasky		rx_bytes = priv->rx_ring[ring]->bytes;
1101257867Salfred		spin_unlock(&priv->stats_lock);
1102219820Sjeff
1103257867Salfred		rx_pkt_diff = ((unsigned long) (rx_packets -
1104257867Salfred				priv->last_moder_packets[ring]));
1105257867Salfred		packets = rx_pkt_diff;
1106257867Salfred		rate = packets * HZ / period;
1107257867Salfred		avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
1108257867Salfred				priv->last_moder_bytes[ring])) / packets : 0;
1109219820Sjeff
1110257867Salfred		/* Apply auto-moderation only when packet rate
1111272407Shselasky		 * exceeds a rate that it matters */
1112257867Salfred		if (rate > (MLX4_EN_RX_RATE_THRESH / priv->rx_ring_num) &&
1113272407Shselasky		    avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
1114272407Shselasky			if (rate < priv->pkt_rate_low)
1115219820Sjeff				moder_time = priv->rx_usecs_low;
1116219820Sjeff			else if (rate > priv->pkt_rate_high)
1117219820Sjeff				moder_time = priv->rx_usecs_high;
1118219820Sjeff			else
1119219820Sjeff				moder_time = (rate - priv->pkt_rate_low) *
1120219820Sjeff					(priv->rx_usecs_high - priv->rx_usecs_low) /
1121219820Sjeff					(priv->pkt_rate_high - priv->pkt_rate_low) +
1122219820Sjeff					priv->rx_usecs_low;
1123257867Salfred		} else {
1124257867Salfred			moder_time = priv->rx_usecs_low;
1125219820Sjeff		}
1126219820Sjeff
1127257867Salfred		if (moder_time != priv->last_moder_time[ring]) {
1128257867Salfred			priv->last_moder_time[ring] = moder_time;
1129272407Shselasky			cq = priv->rx_cq[ring];
1130219820Sjeff			cq->moder_time = moder_time;
1131219820Sjeff			err = mlx4_en_set_cq_moder(priv, cq);
1132257867Salfred			if (err)
1133272407Shselasky				en_err(priv, "Failed modifying moderation for cq:%d\n",
1134272407Shselasky				       ring);
1135219820Sjeff		}
1136257867Salfred		priv->last_moder_packets[ring] = rx_packets;
1137257867Salfred		priv->last_moder_bytes[ring] = rx_bytes;
1138219820Sjeff	}
1139219820Sjeff
1140219820Sjeff	priv->last_moder_jiffies = jiffies;
1141219820Sjeff}
1142219820Sjeff
1143219820Sjeffstatic void mlx4_en_do_get_stats(struct work_struct *work)
1144219820Sjeff{
1145219820Sjeff	struct delayed_work *delay = to_delayed_work(work);
1146219820Sjeff	struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv,
1147219820Sjeff						 stats_task);
1148219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1149219820Sjeff	int err;
1150219820Sjeff
1151219820Sjeff	mutex_lock(&mdev->state_lock);
1152219820Sjeff	if (mdev->device_up) {
1153219820Sjeff		if (priv->port_up) {
1154272407Shselasky                        err = mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 0);
1155272407Shselasky			if (err)
1156272407Shselasky				en_dbg(HW, priv, "Could not update stats\n");
1157219820Sjeff
1158219820Sjeff			mlx4_en_auto_moderation(priv);
1159219820Sjeff		}
1160219820Sjeff
1161219820Sjeff		queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
1162219820Sjeff	}
1163219820Sjeff	mutex_unlock(&mdev->state_lock);
1164219820Sjeff}
1165219820Sjeff
1166272407Shselasky/* mlx4_en_service_task - Run service task for tasks that needed to be done
1167272407Shselasky * periodically
1168272407Shselasky */
1169272407Shselaskystatic void mlx4_en_service_task(struct work_struct *work)
1170272407Shselasky{
1171272407Shselasky	struct delayed_work *delay = to_delayed_work(work);
1172272407Shselasky	struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv,
1173272407Shselasky						 service_task);
1174272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
1175272407Shselasky
1176272407Shselasky	mutex_lock(&mdev->state_lock);
1177272407Shselasky	if (mdev->device_up) {
1178272407Shselasky		queue_delayed_work(mdev->workqueue, &priv->service_task,
1179272407Shselasky				   SERVICE_TASK_DELAY);
1180272407Shselasky	}
1181272407Shselasky	mutex_unlock(&mdev->state_lock);
1182272407Shselasky}
1183272407Shselasky
1184219820Sjeffstatic void mlx4_en_linkstate(struct work_struct *work)
1185219820Sjeff{
1186219820Sjeff	struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
1187219820Sjeff						 linkstate_task);
1188219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1189219820Sjeff	int linkstate = priv->link_state;
1190219820Sjeff
1191219820Sjeff	mutex_lock(&mdev->state_lock);
1192219820Sjeff	/* If observable port state changed set carrier state and
1193219820Sjeff	 * report to system log */
1194219820Sjeff	if (priv->last_link_state != linkstate) {
1195219820Sjeff		if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) {
1196272407Shselasky			en_info(priv, "Link Down\n");
1197219820Sjeff			if_link_state_change(priv->dev, LINK_STATE_DOWN);
1198273879Shselasky			/* update netif baudrate */
1199273879Shselasky			priv->dev->if_baudrate = 0;
1200273879Shselasky
1201292107Shselasky		/* make sure the port is up before notifying the OS.
1202292107Shselasky		 * This is tricky since we get here on INIT_PORT and
1203272407Shselasky		 * in such case we can't tell the OS the port is up.
1204272407Shselasky		 * To solve this there is a call to if_link_state_change
1205272407Shselasky		 * in set_rx_mode.
1206272407Shselasky		 * */
1207272407Shselasky		} else if (priv->port_up && (linkstate == MLX4_DEV_EVENT_PORT_UP)){
1208273879Shselasky			if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
1209273879Shselasky				en_info(priv, "Query port failed\n");
1210273879Shselasky			priv->dev->if_baudrate =
1211273879Shselasky			    IF_Mbps(priv->port_state.link_speed);
1212219820Sjeff			en_info(priv, "Link Up\n");
1213219820Sjeff			if_link_state_change(priv->dev, LINK_STATE_UP);
1214219820Sjeff		}
1215219820Sjeff	}
1216219820Sjeff	priv->last_link_state = linkstate;
1217219820Sjeff	mutex_unlock(&mdev->state_lock);
1218219820Sjeff}
1219219820Sjeff
1220219820Sjeff
1221272407Shselaskyint mlx4_en_start_port(struct net_device *dev)
1222219820Sjeff{
1223219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
1224219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1225219820Sjeff	struct mlx4_en_cq *cq;
1226219820Sjeff	struct mlx4_en_tx_ring *tx_ring;
1227219820Sjeff	int rx_index = 0;
1228219820Sjeff	int tx_index = 0;
1229219820Sjeff	int err = 0;
1230219820Sjeff	int i;
1231219820Sjeff	int j;
1232272407Shselasky	u8 mc_list[16] = {0};
1233219820Sjeff
1234272407Shselasky
1235219820Sjeff	if (priv->port_up) {
1236219820Sjeff		en_dbg(DRV, priv, "start port called while port already up\n");
1237219820Sjeff		return 0;
1238219820Sjeff	}
1239219820Sjeff
1240272407Shselasky	INIT_LIST_HEAD(&priv->mc_list);
1241272407Shselasky	INIT_LIST_HEAD(&priv->curr_list);
1242272407Shselasky	INIT_LIST_HEAD(&priv->ethtool_list);
1243272407Shselasky
1244219820Sjeff	/* Calculate Rx buf size */
1245219820Sjeff	dev->if_mtu = min(dev->if_mtu, priv->max_mtu);
1246272407Shselasky        mlx4_en_calc_rx_buf(dev);
1247272407Shselasky	priv->rx_alloc_size = max_t(int, 2 * roundup_pow_of_two(priv->rx_mb_size),
1248272407Shselasky				    PAGE_SIZE);
1249272407Shselasky	priv->rx_alloc_order = get_order(priv->rx_alloc_size);
1250272407Shselasky	priv->rx_buf_size = roundup_pow_of_two(priv->rx_mb_size);
1251219820Sjeff	en_dbg(DRV, priv, "Rx buf size:%d\n", priv->rx_mb_size);
1252219820Sjeff
1253219820Sjeff	/* Configure rx cq's and rings */
1254219820Sjeff	err = mlx4_en_activate_rx_rings(priv);
1255219820Sjeff	if (err) {
1256219820Sjeff		en_err(priv, "Failed to activate RX rings\n");
1257219820Sjeff		return err;
1258219820Sjeff	}
1259219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++) {
1260272407Shselasky		cq = priv->rx_cq[i];
1261219820Sjeff
1262272407Shselasky		mlx4_en_cq_init_lock(cq);
1263272407Shselasky		err = mlx4_en_activate_cq(priv, cq, i);
1264219820Sjeff		if (err) {
1265219820Sjeff			en_err(priv, "Failed activating Rx CQ\n");
1266219820Sjeff			goto cq_err;
1267219820Sjeff		}
1268219820Sjeff		for (j = 0; j < cq->size; j++)
1269219820Sjeff			cq->buf[j].owner_sr_opcode = MLX4_CQE_OWNER_MASK;
1270219820Sjeff		err = mlx4_en_set_cq_moder(priv, cq);
1271219820Sjeff		if (err) {
1272219820Sjeff			en_err(priv, "Failed setting cq moderation parameters");
1273219820Sjeff			mlx4_en_deactivate_cq(priv, cq);
1274219820Sjeff			goto cq_err;
1275219820Sjeff		}
1276219820Sjeff		mlx4_en_arm_cq(priv, cq);
1277272407Shselasky		priv->rx_ring[i]->cqn = cq->mcq.cqn;
1278219820Sjeff		++rx_index;
1279219820Sjeff	}
1280219820Sjeff
1281272407Shselasky	/* Set qp number */
1282272407Shselasky	en_dbg(DRV, priv, "Getting qp number for port %d\n", priv->port);
1283272407Shselasky	err = mlx4_en_get_qp(priv);
1284272407Shselasky	if (err) {
1285272407Shselasky		en_err(priv, "Failed getting eth qp\n");
1286272407Shselasky		goto cq_err;
1287272407Shselasky	}
1288272407Shselasky	mdev->mac_removed[priv->port] = 0;
1289272407Shselasky
1290272407Shselasky	/* gets default allocated counter index from func cap */
1291272407Shselasky	/* or sink counter index if no resources */
1292272407Shselasky	priv->counter_index = mdev->dev->caps.def_counter_index[priv->port - 1];
1293272407Shselasky
1294272407Shselasky	en_dbg(DRV, priv, "%s: default counter index %d for port %d\n",
1295272407Shselasky	       __func__, priv->counter_index, priv->port);
1296272407Shselasky
1297219820Sjeff	err = mlx4_en_config_rss_steer(priv);
1298219820Sjeff	if (err) {
1299219820Sjeff		en_err(priv, "Failed configuring rss steering\n");
1300272407Shselasky		goto mac_err;
1301219820Sjeff	}
1302219820Sjeff
1303272407Shselasky	err = mlx4_en_create_drop_qp(priv);
1304272407Shselasky	if (err)
1305272407Shselasky		goto rss_err;
1306272407Shselasky
1307219820Sjeff	/* Configure tx cq's and rings */
1308219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++) {
1309219820Sjeff		/* Configure cq */
1310272407Shselasky		cq = priv->tx_cq[i];
1311272407Shselasky		err = mlx4_en_activate_cq(priv, cq, i);
1312219820Sjeff		if (err) {
1313279731Shselasky			en_err(priv, "Failed activating Tx CQ\n");
1314219820Sjeff			goto tx_err;
1315219820Sjeff		}
1316219820Sjeff		err = mlx4_en_set_cq_moder(priv, cq);
1317219820Sjeff		if (err) {
1318219820Sjeff			en_err(priv, "Failed setting cq moderation parameters");
1319219820Sjeff			mlx4_en_deactivate_cq(priv, cq);
1320219820Sjeff			goto tx_err;
1321219820Sjeff		}
1322219820Sjeff		en_dbg(DRV, priv, "Resetting index of collapsed CQ:%d to -1\n", i);
1323219820Sjeff		cq->buf->wqe_index = cpu_to_be16(0xffff);
1324219820Sjeff
1325219820Sjeff		/* Configure ring */
1326272407Shselasky		tx_ring = priv->tx_ring[i];
1327272407Shselasky
1328272407Shselasky		err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn,
1329272407Shselasky					       i / priv->num_tx_rings_p_up);
1330219820Sjeff		if (err) {
1331279731Shselasky			en_err(priv, "Failed activating Tx ring %d\n", i);
1332219820Sjeff			mlx4_en_deactivate_cq(priv, cq);
1333219820Sjeff			goto tx_err;
1334219820Sjeff		}
1335272407Shselasky
1336272407Shselasky		/* Arm CQ for TX completions */
1337272407Shselasky		mlx4_en_arm_cq(priv, cq);
1338272407Shselasky
1339219820Sjeff		/* Set initial ownership of all Tx TXBBs to SW (1) */
1340219820Sjeff		for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE)
1341219820Sjeff			*((u32 *) (tx_ring->buf + j)) = 0xffffffff;
1342219820Sjeff		++tx_index;
1343219820Sjeff	}
1344219820Sjeff
1345219820Sjeff	/* Configure port */
1346219820Sjeff	err = mlx4_SET_PORT_general(mdev->dev, priv->port,
1347272407Shselasky				    priv->rx_mb_size,
1348219820Sjeff				    priv->prof->tx_pause,
1349219820Sjeff				    priv->prof->tx_ppp,
1350219820Sjeff				    priv->prof->rx_pause,
1351219820Sjeff				    priv->prof->rx_ppp);
1352219820Sjeff	if (err) {
1353272407Shselasky		en_err(priv, "Failed setting port general configurations for port %d, with error %d\n",
1354272407Shselasky		       priv->port, err);
1355219820Sjeff		goto tx_err;
1356219820Sjeff	}
1357219820Sjeff	/* Set default qp number */
1358219820Sjeff	err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, priv->base_qpn, 0);
1359219820Sjeff	if (err) {
1360219820Sjeff		en_err(priv, "Failed setting default qp numbers\n");
1361219820Sjeff		goto tx_err;
1362219820Sjeff	}
1363219820Sjeff
1364219820Sjeff	/* Init port */
1365219820Sjeff	en_dbg(HW, priv, "Initializing port\n");
1366219820Sjeff	err = mlx4_INIT_PORT(mdev->dev, priv->port);
1367219820Sjeff	if (err) {
1368219820Sjeff		en_err(priv, "Failed Initializing port\n");
1369272407Shselasky		goto tx_err;
1370219820Sjeff	}
1371219820Sjeff
1372272407Shselasky	/* Attach rx QP to bradcast address */
1373272407Shselasky	memset(&mc_list[10], 0xff, ETH_ALEN);
1374272407Shselasky	mc_list[5] = priv->port; /* needed for B0 steering support */
1375272407Shselasky	if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
1376272407Shselasky				  priv->port, 0, MLX4_PROT_ETH,
1377272407Shselasky				  &priv->broadcast_id))
1378272407Shselasky		mlx4_warn(mdev, "Failed Attaching Broadcast\n");
1379219820Sjeff
1380272407Shselasky	/* Must redo promiscuous mode setup. */
1381272407Shselasky	priv->flags &= ~(MLX4_EN_FLAG_PROMISC | MLX4_EN_FLAG_MC_PROMISC);
1382220016Sjeff
1383272407Shselasky	/* Schedule multicast task to populate multicast list */
1384272407Shselasky	queue_work(mdev->workqueue, &priv->rx_mode_task);
1385220016Sjeff
1386272407Shselasky	mlx4_set_stats_bitmap(mdev->dev, priv->stats_bitmap);
1387272407Shselasky
1388219820Sjeff	priv->port_up = true;
1389219820Sjeff
1390272407Shselasky        /* Enable the queues. */
1391272407Shselasky        dev->if_drv_flags &= ~IFF_DRV_OACTIVE;
1392272407Shselasky        dev->if_drv_flags |= IFF_DRV_RUNNING;
1393272407Shselasky#ifdef CONFIG_DEBUG_FS
1394272407Shselasky	mlx4_en_create_debug_files(priv);
1395272407Shselasky#endif
1396272407Shselasky        callout_reset(&priv->watchdog_timer, MLX4_EN_WATCHDOG_TIMEOUT,
1397272407Shselasky                    mlx4_en_watchdog_timeout, priv);
1398219820Sjeff
1399219820Sjeff
1400219820Sjeff	return 0;
1401219820Sjeff
1402219820Sjefftx_err:
1403219820Sjeff	while (tx_index--) {
1404272407Shselasky		mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[tx_index]);
1405272407Shselasky		mlx4_en_deactivate_cq(priv, priv->tx_cq[tx_index]);
1406219820Sjeff	}
1407272407Shselasky	mlx4_en_destroy_drop_qp(priv);
1408272407Shselaskyrss_err:
1409219820Sjeff	mlx4_en_release_rss_steer(priv);
1410272407Shselaskymac_err:
1411272407Shselasky	mlx4_en_put_qp(priv);
1412219820Sjeffcq_err:
1413219820Sjeff	while (rx_index--)
1414272407Shselasky		mlx4_en_deactivate_cq(priv, priv->rx_cq[rx_index]);
1415219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++)
1416272407Shselasky		mlx4_en_deactivate_rx_ring(priv, priv->rx_ring[i]);
1417219820Sjeff
1418219820Sjeff	return err; /* need to close devices */
1419219820Sjeff}
1420219820Sjeff
1421219820Sjeff
1422272407Shselaskyvoid mlx4_en_stop_port(struct net_device *dev)
1423219820Sjeff{
1424219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
1425219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1426272407Shselasky	struct mlx4_en_mc_list *mclist, *tmp;
1427219820Sjeff	int i;
1428272407Shselasky	u8 mc_list[16] = {0};
1429219820Sjeff
1430219820Sjeff	if (!priv->port_up) {
1431219820Sjeff		en_dbg(DRV, priv, "stop port called while port already down\n");
1432219820Sjeff		return;
1433219820Sjeff	}
1434219820Sjeff
1435272407Shselasky#ifdef CONFIG_DEBUG_FS
1436272407Shselasky	mlx4_en_delete_debug_files(priv);
1437272407Shselasky#endif
1438272407Shselasky
1439272407Shselasky	/* close port*/
1440272407Shselasky	mlx4_CLOSE_PORT(mdev->dev, priv->port);
1441272407Shselasky
1442219820Sjeff	/* Set port as not active */
1443219820Sjeff	priv->port_up = false;
1444272407Shselasky	if (priv->counter_index != 0xff) {
1445272407Shselasky		mlx4_counter_free(mdev->dev, priv->port, priv->counter_index);
1446272407Shselasky		priv->counter_index = 0xff;
1447272407Shselasky	}
1448219820Sjeff
1449272407Shselasky	/* Promsicuous mode */
1450272407Shselasky	if (mdev->dev->caps.steering_mode ==
1451272407Shselasky	    MLX4_STEERING_MODE_DEVICE_MANAGED) {
1452272407Shselasky		priv->flags &= ~(MLX4_EN_FLAG_PROMISC |
1453272407Shselasky				 MLX4_EN_FLAG_MC_PROMISC);
1454272407Shselasky		mlx4_flow_steer_promisc_remove(mdev->dev,
1455272407Shselasky					       priv->port,
1456272407Shselasky					       MLX4_FS_ALL_DEFAULT);
1457272407Shselasky		mlx4_flow_steer_promisc_remove(mdev->dev,
1458272407Shselasky					       priv->port,
1459272407Shselasky					       MLX4_FS_MC_DEFAULT);
1460272407Shselasky	} else if (priv->flags & MLX4_EN_FLAG_PROMISC) {
1461272407Shselasky		priv->flags &= ~MLX4_EN_FLAG_PROMISC;
1462219820Sjeff
1463272407Shselasky		/* Disable promiscouos mode */
1464272407Shselasky		mlx4_unicast_promisc_remove(mdev->dev, priv->base_qpn,
1465272407Shselasky					    priv->port);
1466272407Shselasky
1467272407Shselasky		/* Disable Multicast promisc */
1468272407Shselasky		if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
1469272407Shselasky			mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
1470272407Shselasky						      priv->port);
1471272407Shselasky			priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
1472272407Shselasky		}
1473272407Shselasky	}
1474272407Shselasky
1475272407Shselasky	/* Detach All multicasts */
1476272407Shselasky	memset(&mc_list[10], 0xff, ETH_ALEN);
1477272407Shselasky	mc_list[5] = priv->port; /* needed for B0 steering support */
1478272407Shselasky	mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
1479272407Shselasky			      MLX4_PROT_ETH, priv->broadcast_id);
1480272407Shselasky	list_for_each_entry(mclist, &priv->curr_list, list) {
1481272407Shselasky		memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
1482272407Shselasky		mc_list[5] = priv->port;
1483272407Shselasky		mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
1484272407Shselasky				      mc_list, MLX4_PROT_ETH, mclist->reg_id);
1485272407Shselasky	}
1486272407Shselasky	mlx4_en_clear_list(dev);
1487272407Shselasky	list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) {
1488272407Shselasky		list_del(&mclist->list);
1489272407Shselasky		kfree(mclist);
1490272407Shselasky	}
1491272407Shselasky
1492272407Shselasky	/* Flush multicast filter */
1493272407Shselasky	mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG);
1494272407Shselasky	mlx4_en_destroy_drop_qp(priv);
1495272407Shselasky
1496219820Sjeff	/* Free TX Rings */
1497219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++) {
1498272407Shselasky		mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[i]);
1499272407Shselasky		mlx4_en_deactivate_cq(priv, priv->tx_cq[i]);
1500219820Sjeff	}
1501219820Sjeff	msleep(10);
1502219820Sjeff
1503219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++)
1504272407Shselasky		mlx4_en_free_tx_buf(dev, priv->tx_ring[i]);
1505219820Sjeff
1506219820Sjeff	/* Free RSS qps */
1507219820Sjeff	mlx4_en_release_rss_steer(priv);
1508219820Sjeff
1509272407Shselasky	/* Unregister Mac address for the port */
1510272407Shselasky	mlx4_en_put_qp(priv);
1511272407Shselasky	mdev->mac_removed[priv->port] = 1;
1512272407Shselasky
1513219820Sjeff	/* Free RX Rings */
1514219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++) {
1515272407Shselasky		struct mlx4_en_cq *cq = priv->rx_cq[i];
1516272407Shselasky		mlx4_en_deactivate_rx_ring(priv, priv->rx_ring[i]);
1517272407Shselasky		mlx4_en_deactivate_cq(priv, cq);
1518219820Sjeff	}
1519219820Sjeff
1520272407Shselasky        callout_stop(&priv->watchdog_timer);
1521219820Sjeff
1522272407Shselasky        dev->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1523219820Sjeff}
1524219820Sjeff
1525219820Sjeffstatic void mlx4_en_restart(struct work_struct *work)
1526219820Sjeff{
1527219820Sjeff	struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
1528219820Sjeff						 watchdog_task);
1529219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1530219820Sjeff	struct net_device *dev = priv->dev;
1531219820Sjeff	struct mlx4_en_tx_ring *ring;
1532219820Sjeff	int i;
1533219820Sjeff
1534272407Shselasky
1535219820Sjeff	if (priv->blocked == 0 || priv->port_up == 0)
1536219820Sjeff		return;
1537219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++) {
1538272407Shselasky		ring = priv->tx_ring[i];
1539219820Sjeff		if (ring->blocked &&
1540272407Shselasky				ring->watchdog_time + MLX4_EN_WATCHDOG_TIMEOUT < ticks)
1541219820Sjeff			goto reset;
1542219820Sjeff	}
1543219820Sjeff	return;
1544219820Sjeff
1545219820Sjeffreset:
1546219820Sjeff	priv->port_stats.tx_timeout++;
1547219820Sjeff	en_dbg(DRV, priv, "Watchdog task called for port %d\n", priv->port);
1548219820Sjeff
1549219820Sjeff	mutex_lock(&mdev->state_lock);
1550219820Sjeff	if (priv->port_up) {
1551272407Shselasky		mlx4_en_stop_port(dev);
1552272407Shselasky                //for (i = 0; i < priv->tx_ring_num; i++)
1553272407Shselasky                //        netdev_tx_reset_queue(priv->tx_ring[i]->tx_queue);
1554272407Shselasky		if (mlx4_en_start_port(dev))
1555219820Sjeff			en_err(priv, "Failed restarting port %d\n", priv->port);
1556219820Sjeff	}
1557219820Sjeff	mutex_unlock(&mdev->state_lock);
1558219820Sjeff}
1559219820Sjeff
1560272407Shselaskystatic void mlx4_en_clear_stats(struct net_device *dev)
1561219820Sjeff{
1562272407Shselasky	struct mlx4_en_priv *priv = netdev_priv(dev);
1563272407Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
1564272407Shselasky	int i;
1565253774Sjhb
1566272407Shselasky	if (!mlx4_is_slave(mdev->dev))
1567272407Shselasky		if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
1568272407Shselasky			en_dbg(HW, priv, "Failed dumping statistics\n");
1569272407Shselasky
1570272407Shselasky	memset(&priv->pstats, 0, sizeof(priv->pstats));
1571272407Shselasky	memset(&priv->pkstats, 0, sizeof(priv->pkstats));
1572272407Shselasky	memset(&priv->port_stats, 0, sizeof(priv->port_stats));
1573272407Shselasky	memset(&priv->vport_stats, 0, sizeof(priv->vport_stats));
1574272407Shselasky
1575272407Shselasky	for (i = 0; i < priv->tx_ring_num; i++) {
1576272407Shselasky		priv->tx_ring[i]->bytes = 0;
1577272407Shselasky		priv->tx_ring[i]->packets = 0;
1578272407Shselasky		priv->tx_ring[i]->tx_csum = 0;
1579292107Shselasky		priv->tx_ring[i]->oversized_packets = 0;
1580272407Shselasky	}
1581272407Shselasky	for (i = 0; i < priv->rx_ring_num; i++) {
1582272407Shselasky		priv->rx_ring[i]->bytes = 0;
1583272407Shselasky		priv->rx_ring[i]->packets = 0;
1584272407Shselasky		priv->rx_ring[i]->csum_ok = 0;
1585272407Shselasky		priv->rx_ring[i]->csum_none = 0;
1586272407Shselasky	}
1587253774Sjhb}
1588253774Sjhb
1589272407Shselaskystatic void mlx4_en_open(void* arg)
1590253774Sjhb{
1591253774Sjhb
1592272407Shselasky        struct mlx4_en_priv *priv;
1593272407Shselasky        struct mlx4_en_dev *mdev;
1594272407Shselasky        struct net_device *dev;
1595272407Shselasky        int err = 0;
1596219820Sjeff
1597272407Shselasky        priv = arg;
1598272407Shselasky        mdev = priv->mdev;
1599272407Shselasky        dev = priv->dev;
1600219820Sjeff
1601272407Shselasky
1602272407Shselasky	mutex_lock(&mdev->state_lock);
1603272407Shselasky
1604219820Sjeff	if (!mdev->device_up) {
1605219820Sjeff		en_err(priv, "Cannot open - device down/disabled\n");
1606272407Shselasky		goto out;
1607219820Sjeff	}
1608219820Sjeff
1609272407Shselasky	/* Reset HW statistics and SW counters */
1610272407Shselasky	mlx4_en_clear_stats(dev);
1611219820Sjeff
1612272407Shselasky	err = mlx4_en_start_port(dev);
1613272407Shselasky	if (err)
1614272407Shselasky		en_err(priv, "Failed starting port:%d\n", priv->port);
1615219820Sjeff
1616272407Shselaskyout:
1617272407Shselasky	mutex_unlock(&mdev->state_lock);
1618272407Shselasky	return;
1619219820Sjeff}
1620219820Sjeff
1621219820Sjeffvoid mlx4_en_free_resources(struct mlx4_en_priv *priv)
1622219820Sjeff{
1623219820Sjeff	int i;
1624219820Sjeff
1625272407Shselasky#ifdef CONFIG_RFS_ACCEL
1626272407Shselasky	if (priv->dev->rx_cpu_rmap) {
1627272407Shselasky		free_irq_cpu_rmap(priv->dev->rx_cpu_rmap);
1628272407Shselasky		priv->dev->rx_cpu_rmap = NULL;
1629272407Shselasky	}
1630272407Shselasky#endif
1631272407Shselasky
1632219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++) {
1633272407Shselasky		if (priv->tx_ring && priv->tx_ring[i])
1634219820Sjeff			mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
1635272407Shselasky		if (priv->tx_cq && priv->tx_cq[i])
1636219820Sjeff			mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
1637219820Sjeff	}
1638219820Sjeff
1639219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++) {
1640272407Shselasky		if (priv->rx_ring[i])
1641272407Shselasky			mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i],
1642272407Shselasky				priv->prof->rx_ring_size, priv->stride);
1643272407Shselasky		if (priv->rx_cq[i])
1644219820Sjeff			mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
1645219820Sjeff	}
1646272407Shselasky
1647219820Sjeff	if (priv->sysctl)
1648219820Sjeff		sysctl_ctx_free(&priv->stat_ctx);
1649219820Sjeff}
1650219820Sjeff
1651219820Sjeffint mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
1652219820Sjeff{
1653219820Sjeff	struct mlx4_en_port_profile *prof = priv->prof;
1654219820Sjeff	int i;
1655272407Shselasky	int node = 0;
1656219820Sjeff
1657272407Shselasky	/* Create rx Rings */
1658272407Shselasky	for (i = 0; i < priv->rx_ring_num; i++) {
1659272407Shselasky		if (mlx4_en_create_cq(priv, &priv->rx_cq[i],
1660272407Shselasky				      prof->rx_ring_size, i, RX, node))
1661219820Sjeff			goto err;
1662219820Sjeff
1663272407Shselasky		if (mlx4_en_create_rx_ring(priv, &priv->rx_ring[i],
1664272407Shselasky					   prof->rx_ring_size, node))
1665219820Sjeff			goto err;
1666219820Sjeff	}
1667219820Sjeff
1668272407Shselasky	/* Create tx Rings */
1669272407Shselasky	for (i = 0; i < priv->tx_ring_num; i++) {
1670272407Shselasky		if (mlx4_en_create_cq(priv, &priv->tx_cq[i],
1671272407Shselasky				      prof->tx_ring_size, i, TX, node))
1672219820Sjeff			goto err;
1673219820Sjeff
1674272407Shselasky		if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i],
1675272407Shselasky					   prof->tx_ring_size, TXBB_SIZE, node, i))
1676219820Sjeff			goto err;
1677219820Sjeff	}
1678219820Sjeff
1679272407Shselasky#ifdef CONFIG_RFS_ACCEL
1680272407Shselasky	priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->rx_ring_num);
1681272407Shselasky	if (!priv->dev->rx_cpu_rmap)
1682272407Shselasky		goto err;
1683272407Shselasky#endif
1684272407Shselasky        /* Re-create stat sysctls in case the number of rings changed. */
1685219820Sjeff	mlx4_en_sysctl_stat(priv);
1686219820Sjeff	return 0;
1687219820Sjeff
1688219820Sjefferr:
1689219820Sjeff	en_err(priv, "Failed to allocate NIC resources\n");
1690272407Shselasky	for (i = 0; i < priv->rx_ring_num; i++) {
1691272407Shselasky		if (priv->rx_ring[i])
1692272407Shselasky			mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i],
1693272407Shselasky						prof->rx_ring_size,
1694272407Shselasky						priv->stride);
1695272407Shselasky		if (priv->rx_cq[i])
1696272407Shselasky			mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
1697272407Shselasky	}
1698272407Shselasky	for (i = 0; i < priv->tx_ring_num; i++) {
1699272407Shselasky		if (priv->tx_ring[i])
1700272407Shselasky			mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
1701272407Shselasky		if (priv->tx_cq[i])
1702272407Shselasky			mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
1703272407Shselasky	}
1704272407Shselasky	priv->port_up = false;
1705219820Sjeff	return -ENOMEM;
1706219820Sjeff}
1707219820Sjeff
1708272407Shselaskystruct en_port_attribute {
1709272407Shselasky	struct attribute attr;
1710272407Shselasky	ssize_t (*show)(struct en_port *, struct en_port_attribute *, char *buf);
1711272407Shselasky	ssize_t (*store)(struct en_port *, struct en_port_attribute *, char *buf, size_t count);
1712272407Shselasky};
1713219820Sjeff
1714272407Shselasky#define PORT_ATTR_RO(_name) \
1715272407Shselaskystruct en_port_attribute en_port_attr_##_name = __ATTR_RO(_name)
1716272407Shselasky
1717272407Shselasky#define EN_PORT_ATTR(_name, _mode, _show, _store) \
1718272407Shselaskystruct en_port_attribute en_port_attr_##_name = __ATTR(_name, _mode, _show, _store)
1719272407Shselasky
1720219820Sjeffvoid mlx4_en_destroy_netdev(struct net_device *dev)
1721219820Sjeff{
1722219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
1723219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1724219820Sjeff
1725219820Sjeff	en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port);
1726219820Sjeff
1727272407Shselasky        if (priv->vlan_attach != NULL)
1728272407Shselasky                EVENTHANDLER_DEREGISTER(vlan_config, priv->vlan_attach);
1729272407Shselasky        if (priv->vlan_detach != NULL)
1730272407Shselasky                EVENTHANDLER_DEREGISTER(vlan_unconfig, priv->vlan_detach);
1731219820Sjeff
1732219820Sjeff	/* Unregister device - this will close the port if it was up */
1733292107Shselasky	if (priv->registered) {
1734292107Shselasky		mutex_lock(&mdev->state_lock);
1735219820Sjeff		ether_ifdetach(dev);
1736292107Shselasky		mutex_unlock(&mdev->state_lock);
1737292107Shselasky	}
1738219820Sjeff
1739219820Sjeff	if (priv->allocated)
1740219820Sjeff		mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE);
1741219820Sjeff
1742253774Sjhb	mutex_lock(&mdev->state_lock);
1743272407Shselasky	mlx4_en_stop_port(dev);
1744253774Sjhb	mutex_unlock(&mdev->state_lock);
1745253774Sjhb
1746272407Shselasky
1747219820Sjeff	cancel_delayed_work(&priv->stats_task);
1748272407Shselasky	cancel_delayed_work(&priv->service_task);
1749219820Sjeff	/* flush any pending task for this netdev */
1750219820Sjeff	flush_workqueue(mdev->workqueue);
1751272407Shselasky        callout_drain(&priv->watchdog_timer);
1752219820Sjeff
1753219820Sjeff	/* Detach the netdev so tasks would not attempt to access it */
1754219820Sjeff	mutex_lock(&mdev->state_lock);
1755219820Sjeff	mdev->pndev[priv->port] = NULL;
1756219820Sjeff	mutex_unlock(&mdev->state_lock);
1757219820Sjeff
1758272407Shselasky
1759219820Sjeff	mlx4_en_free_resources(priv);
1760255932Salfred
1761272407Shselasky	/* freeing the sysctl conf cannot be called from within mlx4_en_free_resources */
1762256810Salfred	if (priv->sysctl)
1763256810Salfred		sysctl_ctx_free(&priv->conf_ctx);
1764256810Salfred
1765272407Shselasky	kfree(priv->tx_ring);
1766272407Shselasky	kfree(priv->tx_cq);
1767272407Shselasky
1768272407Shselasky        kfree(priv);
1769272407Shselasky        if_free(dev);
1770272407Shselasky
1771219820Sjeff}
1772219820Sjeff
1773219820Sjeffstatic int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
1774219820Sjeff{
1775219820Sjeff	struct mlx4_en_priv *priv = netdev_priv(dev);
1776219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
1777219820Sjeff	int err = 0;
1778219820Sjeff
1779272407Shselasky	en_dbg(DRV, priv, "Change MTU called - current:%u new:%u\n",
1780272407Shselasky	       (unsigned)dev->if_mtu, (unsigned)new_mtu);
1781219820Sjeff
1782219820Sjeff	if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) {
1783219820Sjeff		en_err(priv, "Bad MTU size:%d.\n", new_mtu);
1784219820Sjeff		return -EPERM;
1785219820Sjeff	}
1786219820Sjeff	mutex_lock(&mdev->state_lock);
1787219820Sjeff	dev->if_mtu = new_mtu;
1788219820Sjeff	if (dev->if_drv_flags & IFF_DRV_RUNNING) {
1789219820Sjeff		if (!mdev->device_up) {
1790219820Sjeff			/* NIC is probably restarting - let watchdog task reset
1791272407Shselasky			 *                          * the port */
1792219820Sjeff			en_dbg(DRV, priv, "Change MTU called with card down!?\n");
1793219820Sjeff		} else {
1794272407Shselasky			mlx4_en_stop_port(dev);
1795272407Shselasky			err = mlx4_en_start_port(dev);
1796219820Sjeff			if (err) {
1797219820Sjeff				en_err(priv, "Failed restarting port:%d\n",
1798272407Shselasky						priv->port);
1799219820Sjeff				queue_work(mdev->workqueue, &priv->watchdog_task);
1800219820Sjeff			}
1801219820Sjeff		}
1802219820Sjeff	}
1803219820Sjeff	mutex_unlock(&mdev->state_lock);
1804219820Sjeff	return 0;
1805219820Sjeff}
1806219820Sjeff
1807219820Sjeffstatic int mlx4_en_calc_media(struct mlx4_en_priv *priv)
1808219820Sjeff{
1809219820Sjeff	int trans_type;
1810219820Sjeff	int active;
1811219820Sjeff
1812219820Sjeff	active = IFM_ETHER;
1813219820Sjeff	if (priv->last_link_state == MLX4_DEV_EVENT_PORT_DOWN)
1814219820Sjeff		return (active);
1815219820Sjeff	active |= IFM_FDX;
1816219820Sjeff	trans_type = priv->port_state.transciver;
1817219820Sjeff	/* XXX I don't know all of the transceiver values. */
1818234099Sjhb	switch (priv->port_state.link_speed) {
1819234099Sjhb	case 1000:
1820219820Sjeff		active |= IFM_1000_T;
1821234099Sjhb		break;
1822234099Sjhb	case 10000:
1823234099Sjhb		if (trans_type > 0 && trans_type <= 0xC)
1824234099Sjhb			active |= IFM_10G_SR;
1825234099Sjhb		else if (trans_type == 0x80 || trans_type == 0)
1826234099Sjhb			active |= IFM_10G_CX4;
1827234099Sjhb		break;
1828234099Sjhb	case 40000:
1829234099Sjhb		active |= IFM_40G_CR4;
1830234099Sjhb		break;
1831234099Sjhb	}
1832219820Sjeff	if (priv->prof->tx_pause)
1833219820Sjeff		active |= IFM_ETH_TXPAUSE;
1834219820Sjeff	if (priv->prof->rx_pause)
1835219820Sjeff		active |= IFM_ETH_RXPAUSE;
1836219820Sjeff
1837219820Sjeff	return (active);
1838219820Sjeff}
1839219820Sjeff
1840219820Sjeffstatic void mlx4_en_media_status(struct ifnet *dev, struct ifmediareq *ifmr)
1841219820Sjeff{
1842219820Sjeff	struct mlx4_en_priv *priv;
1843219820Sjeff
1844219820Sjeff	priv = dev->if_softc;
1845219820Sjeff	ifmr->ifm_status = IFM_AVALID;
1846219820Sjeff	if (priv->last_link_state != MLX4_DEV_EVENT_PORT_DOWN)
1847219820Sjeff		ifmr->ifm_status |= IFM_ACTIVE;
1848219820Sjeff	ifmr->ifm_active = mlx4_en_calc_media(priv);
1849219820Sjeff
1850219820Sjeff	return;
1851219820Sjeff}
1852219820Sjeff
1853219820Sjeffstatic int mlx4_en_media_change(struct ifnet *dev)
1854219820Sjeff{
1855219820Sjeff	struct mlx4_en_priv *priv;
1856219820Sjeff        struct ifmedia *ifm;
1857219820Sjeff	int rxpause;
1858219820Sjeff	int txpause;
1859219820Sjeff	int error;
1860219820Sjeff
1861219820Sjeff	priv = dev->if_softc;
1862219820Sjeff	ifm = &priv->media;
1863219820Sjeff	rxpause = txpause = 0;
1864219820Sjeff	error = 0;
1865219820Sjeff
1866219820Sjeff	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
1867219820Sjeff		return (EINVAL);
1868219820Sjeff        switch (IFM_SUBTYPE(ifm->ifm_media)) {
1869219820Sjeff        case IFM_AUTO:
1870219820Sjeff		break;
1871219820Sjeff	case IFM_10G_SR:
1872219820Sjeff	case IFM_10G_CX4:
1873219820Sjeff	case IFM_1000_T:
1874272407Shselasky	case IFM_40G_CR4:
1875272407Shselasky		if ((IFM_SUBTYPE(ifm->ifm_media)
1876272407Shselasky			== IFM_SUBTYPE(mlx4_en_calc_media(priv)))
1877272407Shselasky			&& (ifm->ifm_media & IFM_FDX))
1878219820Sjeff			break;
1879219820Sjeff		/* Fallthrough */
1880219820Sjeff	default:
1881219820Sjeff                printf("%s: Only auto media type\n", if_name(dev));
1882219820Sjeff                return (EINVAL);
1883219820Sjeff	}
1884219820Sjeff	/* Allow user to set/clear pause */
1885219820Sjeff	if (IFM_OPTIONS(ifm->ifm_media) & IFM_ETH_RXPAUSE)
1886219820Sjeff		rxpause = 1;
1887219820Sjeff	if (IFM_OPTIONS(ifm->ifm_media) & IFM_ETH_TXPAUSE)
1888219820Sjeff		txpause = 1;
1889219820Sjeff	if (priv->prof->tx_pause != txpause || priv->prof->rx_pause != rxpause) {
1890219820Sjeff		priv->prof->tx_pause = txpause;
1891219820Sjeff		priv->prof->rx_pause = rxpause;
1892219820Sjeff		error = -mlx4_SET_PORT_general(priv->mdev->dev, priv->port,
1893219820Sjeff		     priv->rx_mb_size + ETHER_CRC_LEN, priv->prof->tx_pause,
1894219820Sjeff		     priv->prof->tx_ppp, priv->prof->rx_pause,
1895219820Sjeff		     priv->prof->rx_ppp);
1896219820Sjeff	}
1897219820Sjeff	return (error);
1898219820Sjeff}
1899219820Sjeff
1900219820Sjeffstatic int mlx4_en_ioctl(struct ifnet *dev, u_long command, caddr_t data)
1901219820Sjeff{
1902219820Sjeff	struct mlx4_en_priv *priv;
1903219820Sjeff	struct mlx4_en_dev *mdev;
1904219820Sjeff	struct ifreq *ifr;
1905219820Sjeff	int error;
1906219820Sjeff	int mask;
1907219820Sjeff
1908219820Sjeff	error = 0;
1909219820Sjeff	mask = 0;
1910219820Sjeff	priv = dev->if_softc;
1911219820Sjeff	mdev = priv->mdev;
1912219820Sjeff	ifr = (struct ifreq *) data;
1913219820Sjeff	switch (command) {
1914272407Shselasky
1915219820Sjeff	case SIOCSIFMTU:
1916219820Sjeff		error = -mlx4_en_change_mtu(dev, ifr->ifr_mtu);
1917219820Sjeff		break;
1918219820Sjeff	case SIOCSIFFLAGS:
1919219820Sjeff		if (dev->if_flags & IFF_UP) {
1920280018Shselasky			if ((dev->if_drv_flags & IFF_DRV_RUNNING) == 0) {
1921280018Shselasky				mutex_lock(&mdev->state_lock);
1922219820Sjeff				mlx4_en_start_port(dev);
1923280018Shselasky				mutex_unlock(&mdev->state_lock);
1924280018Shselasky			} else {
1925272407Shselasky				mlx4_en_set_rx_mode(dev);
1926280018Shselasky			}
1927219820Sjeff		} else {
1928280018Shselasky			mutex_lock(&mdev->state_lock);
1929219820Sjeff			if (dev->if_drv_flags & IFF_DRV_RUNNING) {
1930219820Sjeff				mlx4_en_stop_port(dev);
1931280018Shselasky				if_link_state_change(dev, LINK_STATE_DOWN);
1932219820Sjeff			}
1933280018Shselasky			mutex_unlock(&mdev->state_lock);
1934219820Sjeff		}
1935219820Sjeff		break;
1936219820Sjeff	case SIOCADDMULTI:
1937219820Sjeff	case SIOCDELMULTI:
1938272407Shselasky		mlx4_en_set_rx_mode(dev);
1939219820Sjeff		break;
1940219820Sjeff	case SIOCSIFMEDIA:
1941219820Sjeff	case SIOCGIFMEDIA:
1942219820Sjeff		error = ifmedia_ioctl(dev, ifr, &priv->media, command);
1943219820Sjeff		break;
1944219820Sjeff	case SIOCSIFCAP:
1945253774Sjhb		mutex_lock(&mdev->state_lock);
1946219820Sjeff		mask = ifr->ifr_reqcap ^ dev->if_capenable;
1947292107Shselasky		if (mask & IFCAP_TXCSUM) {
1948292107Shselasky			dev->if_capenable ^= IFCAP_TXCSUM;
1949292107Shselasky			dev->if_hwassist ^= (CSUM_TCP | CSUM_UDP | CSUM_IP);
1950292107Shselasky
1951292107Shselasky			if (IFCAP_TSO4 & dev->if_capenable &&
1952292107Shselasky			    !(IFCAP_TXCSUM & dev->if_capenable)) {
1953292107Shselasky				dev->if_capenable &= ~IFCAP_TSO4;
1954292107Shselasky				dev->if_hwassist &= ~CSUM_IP_TSO;
1955292107Shselasky				if_printf(dev,
1956292107Shselasky				    "tso4 disabled due to -txcsum.\n");
1957292107Shselasky			}
1958292107Shselasky		}
1959292107Shselasky		if (mask & IFCAP_TXCSUM_IPV6) {
1960292107Shselasky			dev->if_capenable ^= IFCAP_TXCSUM_IPV6;
1961292107Shselasky			dev->if_hwassist ^= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6);
1962292107Shselasky
1963292107Shselasky			if (IFCAP_TSO6 & dev->if_capenable &&
1964292107Shselasky			    !(IFCAP_TXCSUM_IPV6 & dev->if_capenable)) {
1965292107Shselasky				dev->if_capenable &= ~IFCAP_TSO6;
1966292107Shselasky				dev->if_hwassist &= ~CSUM_IP6_TSO;
1967292107Shselasky				if_printf(dev,
1968292107Shselasky				    "tso6 disabled due to -txcsum6.\n");
1969292107Shselasky			}
1970292107Shselasky		}
1971292107Shselasky		if (mask & IFCAP_RXCSUM)
1972292107Shselasky			dev->if_capenable ^= IFCAP_RXCSUM;
1973292107Shselasky		if (mask & IFCAP_RXCSUM_IPV6)
1974292107Shselasky			dev->if_capenable ^= IFCAP_RXCSUM_IPV6;
1975292107Shselasky
1976292107Shselasky		if (mask & IFCAP_TSO4) {
1977292107Shselasky			if (!(IFCAP_TSO4 & dev->if_capenable) &&
1978292107Shselasky			    !(IFCAP_TXCSUM & dev->if_capenable)) {
1979292107Shselasky				if_printf(dev, "enable txcsum first.\n");
1980292107Shselasky				error = EAGAIN;
1981292107Shselasky				goto out;
1982292107Shselasky			}
1983219820Sjeff			dev->if_capenable ^= IFCAP_TSO4;
1984292107Shselasky			dev->if_hwassist ^= CSUM_IP_TSO;
1985292107Shselasky		}
1986292107Shselasky		if (mask & IFCAP_TSO6) {
1987292107Shselasky			if (!(IFCAP_TSO6 & dev->if_capenable) &&
1988292107Shselasky			    !(IFCAP_TXCSUM_IPV6 & dev->if_capenable)) {
1989292107Shselasky				if_printf(dev, "enable txcsum6 first.\n");
1990292107Shselasky				error = EAGAIN;
1991292107Shselasky				goto out;
1992292107Shselasky			}
1993272407Shselasky			dev->if_capenable ^= IFCAP_TSO6;
1994292107Shselasky			dev->if_hwassist ^= CSUM_IP6_TSO;
1995292107Shselasky		}
1996219820Sjeff		if (mask & IFCAP_LRO)
1997219820Sjeff			dev->if_capenable ^= IFCAP_LRO;
1998219820Sjeff		if (mask & IFCAP_VLAN_HWTAGGING)
1999219820Sjeff			dev->if_capenable ^= IFCAP_VLAN_HWTAGGING;
2000219820Sjeff		if (mask & IFCAP_VLAN_HWFILTER)
2001219820Sjeff			dev->if_capenable ^= IFCAP_VLAN_HWFILTER;
2002220016Sjeff		if (mask & IFCAP_WOL_MAGIC)
2003220016Sjeff			dev->if_capenable ^= IFCAP_WOL_MAGIC;
2004219820Sjeff		if (dev->if_drv_flags & IFF_DRV_RUNNING)
2005272407Shselasky			mlx4_en_start_port(dev);
2006292107Shselaskyout:
2007253774Sjhb		mutex_unlock(&mdev->state_lock);
2008219820Sjeff		VLAN_CAPABILITIES(dev);
2009219820Sjeff		break;
2010292107Shselasky#if __FreeBSD_version >= 1100036
2011286841Sglebius	case SIOCGI2C: {
2012286841Sglebius		struct ifi2creq i2c;
2013286841Sglebius
2014286841Sglebius		error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));
2015286841Sglebius		if (error)
2016286841Sglebius			break;
2017286841Sglebius		if (i2c.len > sizeof(i2c.data)) {
2018286841Sglebius			error = EINVAL;
2019286841Sglebius			break;
2020286841Sglebius		}
2021286841Sglebius		/*
2022286841Sglebius		 * Note that we ignore i2c.addr here. The driver hardcodes
2023286841Sglebius		 * the address to 0x50, while standard expects it to be 0xA0.
2024286841Sglebius		 */
2025286841Sglebius		error = mlx4_get_module_info(mdev->dev, priv->port,
2026286841Sglebius		    i2c.offset, i2c.len, i2c.data);
2027286841Sglebius		if (error < 0) {
2028286841Sglebius			error = -error;
2029286841Sglebius			break;
2030286841Sglebius		}
2031286841Sglebius		error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
2032286841Sglebius		break;
2033286841Sglebius	}
2034292107Shselasky#endif
2035219820Sjeff	default:
2036219820Sjeff		error = ether_ioctl(dev, command, data);
2037219820Sjeff		break;
2038219820Sjeff	}
2039219820Sjeff
2040219820Sjeff	return (error);
2041219820Sjeff}
2042219820Sjeff
2043272407Shselasky
2044272407Shselaskyint mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
2045272407Shselasky			struct mlx4_en_port_profile *prof)
2046219820Sjeff{
2047272407Shselasky	struct net_device *dev;
2048272407Shselasky	struct mlx4_en_priv *priv;
2049272407Shselasky	uint8_t dev_addr[ETHER_ADDR_LEN];
2050272407Shselasky	int err;
2051272407Shselasky	int i;
2052219820Sjeff
2053272407Shselasky	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
2054272407Shselasky	dev = priv->dev = if_alloc(IFT_ETHER);
2055272407Shselasky	if (dev == NULL) {
2056272407Shselasky		en_err(priv, "Net device allocation failed\n");
2057272407Shselasky		kfree(priv);
2058272407Shselasky		return -ENOMEM;
2059272407Shselasky	}
2060272407Shselasky	dev->if_softc = priv;
2061272407Shselasky	if_initname(dev, "mlxen", atomic_fetchadd_int(&mlx4_en_unit, 1));
2062272407Shselasky	dev->if_mtu = ETHERMTU;
2063272407Shselasky	dev->if_init = mlx4_en_open;
2064272407Shselasky	dev->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
2065272407Shselasky	dev->if_ioctl = mlx4_en_ioctl;
2066272407Shselasky	dev->if_transmit = mlx4_en_transmit;
2067272407Shselasky	dev->if_qflush = mlx4_en_qflush;
2068272407Shselasky	dev->if_snd.ifq_maxlen = prof->tx_ring_size;
2069219820Sjeff
2070272407Shselasky	/*
2071272407Shselasky	 * Initialize driver private data
2072272407Shselasky	 */
2073272407Shselasky	priv->counter_index = 0xff;
2074272407Shselasky	spin_lock_init(&priv->stats_lock);
2075272407Shselasky	INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode);
2076272407Shselasky	INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
2077272407Shselasky	INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
2078272407Shselasky	INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
2079272407Shselasky	INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task);
2080272407Shselasky	callout_init(&priv->watchdog_timer, 1);
2081272407Shselasky#ifdef CONFIG_RFS_ACCEL
2082272407Shselasky	INIT_LIST_HEAD(&priv->filters);
2083272407Shselasky	spin_lock_init(&priv->filters_lock);
2084272407Shselasky#endif
2085219820Sjeff
2086272407Shselasky	priv->msg_enable = MLX4_EN_MSG_LEVEL;
2087272407Shselasky	priv->dev = dev;
2088272407Shselasky	priv->mdev = mdev;
2089272407Shselasky	priv->ddev = &mdev->pdev->dev;
2090272407Shselasky	priv->prof = prof;
2091272407Shselasky	priv->port = port;
2092272407Shselasky	priv->port_up = false;
2093272407Shselasky	priv->flags = prof->flags;
2094272407Shselasky
2095272407Shselasky	priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up;
2096272407Shselasky	priv->tx_ring_num = prof->tx_ring_num;
2097272407Shselasky	priv->tx_ring = kcalloc(MAX_TX_RINGS,
2098272407Shselasky				sizeof(struct mlx4_en_tx_ring *), GFP_KERNEL);
2099272407Shselasky	if (!priv->tx_ring) {
2100272407Shselasky		err = -ENOMEM;
2101272407Shselasky		goto out;
2102219820Sjeff	}
2103272407Shselasky	priv->tx_cq = kcalloc(sizeof(struct mlx4_en_cq *), MAX_TX_RINGS,
2104272407Shselasky			GFP_KERNEL);
2105272407Shselasky	if (!priv->tx_cq) {
2106272407Shselasky		err = -ENOMEM;
2107272407Shselasky		goto out;
2108272407Shselasky	}
2109292107Shselasky
2110272407Shselasky	priv->rx_ring_num = prof->rx_ring_num;
2111272407Shselasky	priv->cqe_factor = (mdev->dev->caps.cqe_size == 64) ? 1 : 0;
2112272407Shselasky	priv->mac_index = -1;
2113272407Shselasky	priv->last_ifq_jiffies = 0;
2114272407Shselasky	priv->if_counters_rx_errors = 0;
2115272407Shselasky	priv->if_counters_rx_no_buffer = 0;
2116272407Shselasky#ifdef CONFIG_MLX4_EN_DCB
2117272407Shselasky	if (!mlx4_is_slave(priv->mdev->dev)) {
2118272407Shselasky		priv->dcbx_cap = DCB_CAP_DCBX_HOST;
2119272407Shselasky		priv->flags |= MLX4_EN_FLAG_DCB_ENABLED;
2120272407Shselasky		if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ETS_CFG) {
2121272407Shselasky			dev->dcbnl_ops = &mlx4_en_dcbnl_ops;
2122272407Shselasky		} else {
2123272407Shselasky			en_info(priv, "QoS disabled - no HW support\n");
2124272407Shselasky			dev->dcbnl_ops = &mlx4_en_dcbnl_pfc_ops;
2125272407Shselasky		}
2126272407Shselasky	}
2127272407Shselasky#endif
2128272407Shselasky
2129272407Shselasky	for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i)
2130272407Shselasky		INIT_HLIST_HEAD(&priv->mac_hash[i]);
2131272407Shselasky
2132272407Shselasky	/* Query for default mac and max mtu */
2133272407Shselasky	priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port];
2134272407Shselasky        priv->mac = mdev->dev->caps.def_mac[priv->port];
2135272407Shselasky        if (ILLEGAL_MAC(priv->mac)) {
2136272407Shselasky#if BITS_PER_LONG == 64
2137272407Shselasky                en_err(priv, "Port: %d, invalid mac burned: 0x%lx, quiting\n",
2138272407Shselasky                                priv->port, priv->mac);
2139272407Shselasky#elif BITS_PER_LONG == 32
2140272407Shselasky                en_err(priv, "Port: %d, invalid mac burned: 0x%llx, quiting\n",
2141272407Shselasky                                priv->port, priv->mac);
2142272407Shselasky#endif
2143272407Shselasky                err = -EINVAL;
2144272407Shselasky                goto out;
2145272407Shselasky        }
2146272407Shselasky
2147272407Shselasky	priv->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
2148272407Shselasky					  DS_SIZE);
2149272407Shselasky
2150272407Shselasky	mlx4_en_sysctl_conf(priv);
2151272407Shselasky
2152219820Sjeff	err = mlx4_en_alloc_resources(priv);
2153272407Shselasky	if (err)
2154272407Shselasky		goto out;
2155272407Shselasky
2156272407Shselasky	/* Allocate page for receive rings */
2157272407Shselasky	err = mlx4_alloc_hwq_res(mdev->dev, &priv->res,
2158272407Shselasky				MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE);
2159219820Sjeff	if (err) {
2160272407Shselasky		en_err(priv, "Failed to allocate page for rx qps\n");
2161219820Sjeff		goto out;
2162219820Sjeff	}
2163272407Shselasky	priv->allocated = 1;
2164272407Shselasky
2165272407Shselasky	/*
2166272407Shselasky	 * Set driver features
2167272407Shselasky	 */
2168292107Shselasky	dev->if_capabilities |= IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6;
2169272407Shselasky	dev->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
2170272407Shselasky	dev->if_capabilities |= IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWFILTER;
2171272407Shselasky	dev->if_capabilities |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU;
2172272407Shselasky	dev->if_capabilities |= IFCAP_LRO;
2173272407Shselasky
2174272407Shselasky	if (mdev->LSO_support)
2175272407Shselasky		dev->if_capabilities |= IFCAP_TSO4 | IFCAP_TSO6 | IFCAP_VLAN_HWTSO;
2176274043Shselasky
2177272407Shselasky	/* set TSO limits so that we don't have to drop TX packets */
2178292107Shselasky	dev->if_hw_tsomax = MLX4_EN_TX_MAX_PAYLOAD_SIZE - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN) /* hdr */;
2179292107Shselasky	dev->if_hw_tsomaxsegcount = MLX4_EN_TX_MAX_MBUF_FRAGS - 1 /* hdr */;
2180292107Shselasky	dev->if_hw_tsomaxsegsize = MLX4_EN_TX_MAX_MBUF_SIZE;
2181274043Shselasky
2182272407Shselasky	dev->if_capenable = dev->if_capabilities;
2183272407Shselasky
2184272407Shselasky	dev->if_hwassist = 0;
2185272407Shselasky	if (dev->if_capenable & (IFCAP_TSO4 | IFCAP_TSO6))
2186272407Shselasky		dev->if_hwassist |= CSUM_TSO;
2187272407Shselasky	if (dev->if_capenable & IFCAP_TXCSUM)
2188272407Shselasky		dev->if_hwassist |= (CSUM_TCP | CSUM_UDP | CSUM_IP);
2189292107Shselasky	if (dev->if_capenable & IFCAP_TXCSUM_IPV6)
2190292107Shselasky		dev->if_hwassist |= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6);
2191272407Shselasky
2192272407Shselasky
2193272407Shselasky        /* Register for VLAN events */
2194272407Shselasky	priv->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
2195272407Shselasky            mlx4_en_vlan_rx_add_vid, priv, EVENTHANDLER_PRI_FIRST);
2196272407Shselasky	priv->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
2197272407Shselasky            mlx4_en_vlan_rx_kill_vid, priv, EVENTHANDLER_PRI_FIRST);
2198272407Shselasky
2199272407Shselasky	mdev->pndev[priv->port] = dev;
2200272407Shselasky
2201272407Shselasky	priv->last_link_state = MLX4_DEV_EVENT_PORT_DOWN;
2202272407Shselasky        mlx4_en_set_default_moderation(priv);
2203272407Shselasky
2204272407Shselasky	/* Set default MAC */
2205272407Shselasky	for (i = 0; i < ETHER_ADDR_LEN; i++)
2206272407Shselasky		dev_addr[ETHER_ADDR_LEN - 1 - i] = (u8) (priv->mac >> (8 * i));
2207272407Shselasky
2208272407Shselasky
2209272407Shselasky	ether_ifattach(dev, dev_addr);
2210272407Shselasky	if_link_state_change(dev, LINK_STATE_DOWN);
2211272407Shselasky	ifmedia_init(&priv->media, IFM_IMASK | IFM_ETH_FMASK,
2212272407Shselasky	    mlx4_en_media_change, mlx4_en_media_status);
2213272407Shselasky	ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_1000_T, 0, NULL);
2214272407Shselasky	ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_10G_SR, 0, NULL);
2215272407Shselasky	ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_10G_CX4, 0, NULL);
2216272407Shselasky	ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_40G_CR4, 0, NULL);
2217272407Shselasky	ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL);
2218272407Shselasky	ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO);
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	priv->registered = 1;
2224272407Shselasky
2225272407Shselasky        en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
2226272407Shselasky        en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
2227272407Shselasky
2228272407Shselasky
2229272407Shselasky	priv->rx_mb_size = dev->if_mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
2230272407Shselasky	err = mlx4_SET_PORT_general(mdev->dev, priv->port,
2231272407Shselasky				    priv->rx_mb_size,
2232272407Shselasky				    prof->tx_pause, prof->tx_ppp,
2233272407Shselasky				    prof->rx_pause, prof->rx_ppp);
2234272407Shselasky	if (err) {
2235272407Shselasky		en_err(priv, "Failed setting port general configurations "
2236272407Shselasky		       "for port %d, with error %d\n", priv->port, err);
2237272407Shselasky		goto out;
2238219820Sjeff	}
2239272407Shselasky
2240272407Shselasky	/* Init port */
2241272407Shselasky	en_warn(priv, "Initializing port\n");
2242272407Shselasky	err = mlx4_INIT_PORT(mdev->dev, priv->port);
2243272407Shselasky	if (err) {
2244272407Shselasky		en_err(priv, "Failed Initializing port\n");
2245272407Shselasky		goto out;
2246272407Shselasky	}
2247272407Shselasky
2248272407Shselasky	queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
2249272407Shselasky
2250272407Shselasky        if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
2251272407Shselasky                queue_delayed_work(mdev->workqueue, &priv->service_task, SERVICE_TASK_DELAY);
2252272407Shselasky
2253272407Shselasky	return 0;
2254272407Shselasky
2255219820Sjeffout:
2256272407Shselasky	mlx4_en_destroy_netdev(dev);
2257219820Sjeff	return err;
2258219820Sjeff}
2259279731Shselasky
2260272407Shselaskystatic int mlx4_en_set_ring_size(struct net_device *dev,
2261272407Shselasky    int rx_size, int tx_size)
2262272407Shselasky{
2263272407Shselasky        struct mlx4_en_priv *priv = netdev_priv(dev);
2264272407Shselasky        struct mlx4_en_dev *mdev = priv->mdev;
2265272407Shselasky        int port_up = 0;
2266272407Shselasky        int err = 0;
2267219820Sjeff
2268272407Shselasky        rx_size = roundup_pow_of_two(rx_size);
2269272407Shselasky        rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE);
2270272407Shselasky        rx_size = min_t(u32, rx_size, MLX4_EN_MAX_RX_SIZE);
2271272407Shselasky        tx_size = roundup_pow_of_two(tx_size);
2272272407Shselasky        tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
2273272407Shselasky        tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
2274272407Shselasky
2275272407Shselasky        if (rx_size == (priv->port_up ?
2276272407Shselasky            priv->rx_ring[0]->actual_size : priv->rx_ring[0]->size) &&
2277272407Shselasky            tx_size == priv->tx_ring[0]->size)
2278272407Shselasky                return 0;
2279272407Shselasky        mutex_lock(&mdev->state_lock);
2280272407Shselasky        if (priv->port_up) {
2281272407Shselasky                port_up = 1;
2282272407Shselasky                mlx4_en_stop_port(dev);
2283272407Shselasky        }
2284272407Shselasky        mlx4_en_free_resources(priv);
2285272407Shselasky        priv->prof->tx_ring_size = tx_size;
2286272407Shselasky        priv->prof->rx_ring_size = rx_size;
2287272407Shselasky        err = mlx4_en_alloc_resources(priv);
2288272407Shselasky        if (err) {
2289272407Shselasky                en_err(priv, "Failed reallocating port resources\n");
2290272407Shselasky                goto out;
2291272407Shselasky        }
2292272407Shselasky        if (port_up) {
2293272407Shselasky                err = mlx4_en_start_port(dev);
2294272407Shselasky                if (err)
2295272407Shselasky                        en_err(priv, "Failed starting port\n");
2296272407Shselasky        }
2297272407Shselaskyout:
2298272407Shselasky        mutex_unlock(&mdev->state_lock);
2299272407Shselasky        return err;
2300272407Shselasky}
2301219820Sjeffstatic int mlx4_en_set_rx_ring_size(SYSCTL_HANDLER_ARGS)
2302219820Sjeff{
2303272407Shselasky        struct mlx4_en_priv *priv;
2304272407Shselasky        int size;
2305272407Shselasky        int error;
2306219820Sjeff
2307272407Shselasky        priv = arg1;
2308272407Shselasky        size = priv->prof->rx_ring_size;
2309272407Shselasky        error = sysctl_handle_int(oidp, &size, 0, req);
2310272407Shselasky        if (error || !req->newptr)
2311272407Shselasky                return (error);
2312272407Shselasky        error = -mlx4_en_set_ring_size(priv->dev, size,
2313272407Shselasky            priv->prof->tx_ring_size);
2314272407Shselasky        return (error);
2315219820Sjeff}
2316219820Sjeff
2317219820Sjeffstatic int mlx4_en_set_tx_ring_size(SYSCTL_HANDLER_ARGS)
2318219820Sjeff{
2319272407Shselasky        struct mlx4_en_priv *priv;
2320272407Shselasky        int size;
2321272407Shselasky        int error;
2322219820Sjeff
2323272407Shselasky        priv = arg1;
2324272407Shselasky        size = priv->prof->tx_ring_size;
2325272407Shselasky        error = sysctl_handle_int(oidp, &size, 0, req);
2326272407Shselasky        if (error || !req->newptr)
2327272407Shselasky                return (error);
2328272407Shselasky        error = -mlx4_en_set_ring_size(priv->dev, priv->prof->rx_ring_size,
2329272407Shselasky            size);
2330219820Sjeff
2331272407Shselasky        return (error);
2332219820Sjeff}
2333219820Sjeff
2334292107Shselaskystatic int mlx4_en_get_module_info(struct net_device *dev,
2335292107Shselasky				   struct ethtool_modinfo *modinfo)
2336292107Shselasky{
2337292107Shselasky	struct mlx4_en_priv *priv = netdev_priv(dev);
2338292107Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
2339292107Shselasky	int ret;
2340292107Shselasky	u8 data[4];
2341292107Shselasky
2342292107Shselasky	/* Read first 2 bytes to get Module & REV ID */
2343292107Shselasky	ret = mlx4_get_module_info(mdev->dev, priv->port,
2344292107Shselasky				   0/*offset*/, 2/*size*/, data);
2345292107Shselasky
2346292107Shselasky	if (ret < 2) {
2347292107Shselasky		en_err(priv, "Failed to read eeprom module first two bytes, error: 0x%x\n", -ret);
2348292107Shselasky		return -EIO;
2349292107Shselasky	}
2350292107Shselasky
2351292107Shselasky	switch (data[0] /* identifier */) {
2352292107Shselasky	case MLX4_MODULE_ID_QSFP:
2353292107Shselasky		modinfo->type = ETH_MODULE_SFF_8436;
2354292107Shselasky		modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
2355292107Shselasky		break;
2356292107Shselasky	case MLX4_MODULE_ID_QSFP_PLUS:
2357292107Shselasky		if (data[1] >= 0x3) { /* revision id */
2358292107Shselasky			modinfo->type = ETH_MODULE_SFF_8636;
2359292107Shselasky			modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
2360292107Shselasky		} else {
2361292107Shselasky			modinfo->type = ETH_MODULE_SFF_8436;
2362292107Shselasky			modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
2363292107Shselasky		}
2364292107Shselasky		break;
2365292107Shselasky	case MLX4_MODULE_ID_QSFP28:
2366292107Shselasky		modinfo->type = ETH_MODULE_SFF_8636;
2367292107Shselasky		modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
2368292107Shselasky		break;
2369292107Shselasky	case MLX4_MODULE_ID_SFP:
2370292107Shselasky		modinfo->type = ETH_MODULE_SFF_8472;
2371292107Shselasky		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
2372292107Shselasky		break;
2373292107Shselasky	default:
2374292107Shselasky		en_err(priv, "mlx4_en_get_module_info :  Not recognized cable type\n");
2375292107Shselasky		return -EINVAL;
2376292107Shselasky	}
2377292107Shselasky
2378292107Shselasky	return 0;
2379292107Shselasky}
2380292107Shselasky
2381292107Shselaskystatic int mlx4_en_get_module_eeprom(struct net_device *dev,
2382292107Shselasky				     struct ethtool_eeprom *ee,
2383292107Shselasky				     u8 *data)
2384292107Shselasky{
2385292107Shselasky	struct mlx4_en_priv *priv = netdev_priv(dev);
2386292107Shselasky	struct mlx4_en_dev *mdev = priv->mdev;
2387292107Shselasky	int offset = ee->offset;
2388292107Shselasky	int i = 0, ret;
2389292107Shselasky
2390292107Shselasky	if (ee->len == 0)
2391292107Shselasky		return -EINVAL;
2392292107Shselasky
2393292107Shselasky	memset(data, 0, ee->len);
2394292107Shselasky
2395292107Shselasky	while (i < ee->len) {
2396292107Shselasky		en_dbg(DRV, priv,
2397292107Shselasky		       "mlx4_get_module_info i(%d) offset(%d) len(%d)\n",
2398292107Shselasky		       i, offset, ee->len - i);
2399292107Shselasky
2400292107Shselasky		ret = mlx4_get_module_info(mdev->dev, priv->port,
2401292107Shselasky					   offset, ee->len - i, data + i);
2402292107Shselasky
2403292107Shselasky		if (!ret) /* Done reading */
2404292107Shselasky			return 0;
2405292107Shselasky
2406292107Shselasky		if (ret < 0) {
2407292107Shselasky			en_err(priv,
2408292107Shselasky			       "mlx4_get_module_info i(%d) offset(%d) bytes_to_read(%d) - FAILED (0x%x)\n",
2409292107Shselasky			       i, offset, ee->len - i, ret);
2410292107Shselasky			return -1;
2411292107Shselasky		}
2412292107Shselasky
2413292107Shselasky		i += ret;
2414292107Shselasky		offset += ret;
2415292107Shselasky	}
2416292107Shselasky	return 0;
2417292107Shselasky}
2418292107Shselasky
2419292107Shselaskystatic void mlx4_en_print_eeprom(u8 *data, __u32 len)
2420292107Shselasky{
2421292107Shselasky	int		i;
2422292107Shselasky	int		j = 0;
2423292107Shselasky	int		row = 0;
2424292107Shselasky	const int	NUM_OF_BYTES = 16;
2425292107Shselasky
2426292107Shselasky	printf("\nOffset\t\tValues\n");
2427292107Shselasky	printf("------\t\t------\n");
2428292107Shselasky	while(row < len){
2429292107Shselasky		printf("0x%04x\t\t",row);
2430292107Shselasky		for(i=0; i < NUM_OF_BYTES; i++){
2431292107Shselasky			printf("%02x ", data[j]);
2432292107Shselasky			row++;
2433292107Shselasky			j++;
2434292107Shselasky		}
2435292107Shselasky		printf("\n");
2436292107Shselasky	}
2437292107Shselasky}
2438292107Shselasky
2439292107Shselasky/* Read cable EEPROM module information by first inspecting the first
2440292107Shselasky * two bytes to get the length and then read the rest of the information.
2441292107Shselasky * The information is printed to dmesg. */
2442292107Shselaskystatic int mlx4_en_read_eeprom(SYSCTL_HANDLER_ARGS)
2443292107Shselasky{
2444292107Shselasky
2445292107Shselasky	u8*		data;
2446292107Shselasky	int		error;
2447292107Shselasky	int		result = 0;
2448292107Shselasky	struct		mlx4_en_priv *priv;
2449292107Shselasky	struct		net_device *dev;
2450292107Shselasky	struct		ethtool_modinfo modinfo;
2451292107Shselasky	struct		ethtool_eeprom ee;
2452292107Shselasky
2453292107Shselasky	error = sysctl_handle_int(oidp, &result, 0, req);
2454292107Shselasky	if (error || !req->newptr)
2455292107Shselasky		return (error);
2456292107Shselasky
2457292107Shselasky	if (result == 1) {
2458292107Shselasky		priv = arg1;
2459292107Shselasky		dev = priv->dev;
2460292107Shselasky		data = kmalloc(PAGE_SIZE, GFP_KERNEL);
2461292107Shselasky
2462292107Shselasky		error = mlx4_en_get_module_info(dev, &modinfo);
2463292107Shselasky		if (error) {
2464292107Shselasky			en_err(priv,
2465292107Shselasky			       "mlx4_en_get_module_info returned with error - FAILED (0x%x)\n",
2466292107Shselasky			       -error);
2467292107Shselasky			goto out;
2468292107Shselasky		}
2469292107Shselasky
2470292107Shselasky		ee.len = modinfo.eeprom_len;
2471292107Shselasky		ee.offset = 0;
2472292107Shselasky
2473292107Shselasky		error = mlx4_en_get_module_eeprom(dev, &ee, data);
2474292107Shselasky		if (error) {
2475292107Shselasky			en_err(priv,
2476292107Shselasky			       "mlx4_en_get_module_eeprom returned with error - FAILED (0x%x)\n",
2477292107Shselasky			       -error);
2478292107Shselasky			/* Continue printing partial information in case of an error */
2479292107Shselasky		}
2480292107Shselasky
2481292107Shselasky		/* EEPROM information will be printed in dmesg */
2482292107Shselasky		mlx4_en_print_eeprom(data, ee.len);
2483292107Shselaskyout:
2484292107Shselasky		kfree(data);
2485292107Shselasky	}
2486292107Shselasky	/* Return zero to prevent sysctl failure. */
2487292107Shselasky	return (0);
2488292107Shselasky}
2489292107Shselasky
2490219859Sjeffstatic int mlx4_en_set_tx_ppp(SYSCTL_HANDLER_ARGS)
2491219859Sjeff{
2492272407Shselasky        struct mlx4_en_priv *priv;
2493272407Shselasky        int ppp;
2494272407Shselasky        int error;
2495219859Sjeff
2496272407Shselasky        priv = arg1;
2497272407Shselasky        ppp = priv->prof->tx_ppp;
2498272407Shselasky        error = sysctl_handle_int(oidp, &ppp, 0, req);
2499272407Shselasky        if (error || !req->newptr)
2500272407Shselasky                return (error);
2501272407Shselasky        if (ppp > 0xff || ppp < 0)
2502272407Shselasky                return (-EINVAL);
2503272407Shselasky        priv->prof->tx_ppp = ppp;
2504272407Shselasky        error = -mlx4_SET_PORT_general(priv->mdev->dev, priv->port,
2505272407Shselasky                                       priv->rx_mb_size + ETHER_CRC_LEN,
2506272407Shselasky                                       priv->prof->tx_pause,
2507272407Shselasky                                       priv->prof->tx_ppp,
2508272407Shselasky                                       priv->prof->rx_pause,
2509272407Shselasky                                       priv->prof->rx_ppp);
2510219859Sjeff
2511272407Shselasky        return (error);
2512219859Sjeff}
2513219859Sjeff
2514219859Sjeffstatic int mlx4_en_set_rx_ppp(SYSCTL_HANDLER_ARGS)
2515219859Sjeff{
2516272407Shselasky        struct mlx4_en_priv *priv;
2517272407Shselasky        struct mlx4_en_dev *mdev;
2518272407Shselasky        int ppp;
2519272407Shselasky        int error;
2520272407Shselasky        int port_up;
2521219859Sjeff
2522272407Shselasky        port_up = 0;
2523272407Shselasky        priv = arg1;
2524272407Shselasky        mdev = priv->mdev;
2525272407Shselasky        ppp = priv->prof->rx_ppp;
2526272407Shselasky        error = sysctl_handle_int(oidp, &ppp, 0, req);
2527272407Shselasky        if (error || !req->newptr)
2528272407Shselasky                return (error);
2529272407Shselasky        if (ppp > 0xff || ppp < 0)
2530272407Shselasky                return (-EINVAL);
2531272407Shselasky        /* See if we have to change the number of tx queues. */
2532272407Shselasky        if (!ppp != !priv->prof->rx_ppp) {
2533272407Shselasky                mutex_lock(&mdev->state_lock);
2534272407Shselasky                if (priv->port_up) {
2535272407Shselasky                        port_up = 1;
2536272407Shselasky                        mlx4_en_stop_port(priv->dev);
2537272407Shselasky                }
2538272407Shselasky                mlx4_en_free_resources(priv);
2539272407Shselasky                priv->prof->rx_ppp = ppp;
2540272407Shselasky                error = -mlx4_en_alloc_resources(priv);
2541272407Shselasky                if (error)
2542272407Shselasky                        en_err(priv, "Failed reallocating port resources\n");
2543272407Shselasky                if (error == 0 && port_up) {
2544272407Shselasky                        error = -mlx4_en_start_port(priv->dev);
2545272407Shselasky                        if (error)
2546272407Shselasky                                en_err(priv, "Failed starting port\n");
2547272407Shselasky                }
2548272407Shselasky                mutex_unlock(&mdev->state_lock);
2549272407Shselasky                return (error);
2550219859Sjeff
2551272407Shselasky        }
2552272407Shselasky        priv->prof->rx_ppp = ppp;
2553272407Shselasky        error = -mlx4_SET_PORT_general(priv->mdev->dev, priv->port,
2554272407Shselasky                                       priv->rx_mb_size + ETHER_CRC_LEN,
2555272407Shselasky                                       priv->prof->tx_pause,
2556272407Shselasky                                       priv->prof->tx_ppp,
2557272407Shselasky                                       priv->prof->rx_pause,
2558272407Shselasky                                       priv->prof->rx_ppp);
2559219859Sjeff
2560272407Shselasky        return (error);
2561219859Sjeff}
2562219859Sjeff
2563219820Sjeffstatic void mlx4_en_sysctl_conf(struct mlx4_en_priv *priv)
2564219820Sjeff{
2565272407Shselasky        struct net_device *dev;
2566272407Shselasky        struct sysctl_ctx_list *ctx;
2567272407Shselasky        struct sysctl_oid *node;
2568272407Shselasky        struct sysctl_oid_list *node_list;
2569272407Shselasky        struct sysctl_oid *coal;
2570272407Shselasky        struct sysctl_oid_list *coal_list;
2571273246Shselasky	const char *pnameunit;
2572219820Sjeff
2573272407Shselasky        dev = priv->dev;
2574272407Shselasky        ctx = &priv->conf_ctx;
2575273246Shselasky	pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev);
2576219820Sjeff
2577272407Shselasky        sysctl_ctx_init(ctx);
2578272407Shselasky        priv->sysctl = SYSCTL_ADD_NODE(ctx, SYSCTL_STATIC_CHILDREN(_hw),
2579272407Shselasky            OID_AUTO, dev->if_xname, CTLFLAG_RD, 0, "mlx4 10gig ethernet");
2580272407Shselasky        node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(priv->sysctl), OID_AUTO,
2581272407Shselasky            "conf", CTLFLAG_RD, NULL, "Configuration");
2582272407Shselasky        node_list = SYSCTL_CHILDREN(node);
2583219820Sjeff
2584272407Shselasky        SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "msg_enable",
2585272407Shselasky            CTLFLAG_RW, &priv->msg_enable, 0,
2586272407Shselasky            "Driver message enable bitfield");
2587272407Shselasky        SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "rx_rings",
2588273246Shselasky            CTLFLAG_RD, &priv->rx_ring_num, 0,
2589272407Shselasky            "Number of receive rings");
2590272407Shselasky        SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "tx_rings",
2591273246Shselasky            CTLFLAG_RD, &priv->tx_ring_num, 0,
2592272407Shselasky            "Number of transmit rings");
2593272407Shselasky        SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "rx_size",
2594272407Shselasky            CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
2595272407Shselasky            mlx4_en_set_rx_ring_size, "I", "Receive ring size");
2596272407Shselasky        SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "tx_size",
2597272407Shselasky            CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
2598272407Shselasky            mlx4_en_set_tx_ring_size, "I", "Transmit ring size");
2599272407Shselasky        SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "tx_ppp",
2600272407Shselasky            CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
2601272407Shselasky            mlx4_en_set_tx_ppp, "I", "TX Per-priority pause");
2602272407Shselasky        SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "rx_ppp",
2603272407Shselasky            CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
2604272407Shselasky            mlx4_en_set_rx_ppp, "I", "RX Per-priority pause");
2605273246Shselasky        SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "port_num",
2606273246Shselasky            CTLFLAG_RD, &priv->port, 0,
2607273246Shselasky            "Port Number");
2608273246Shselasky        SYSCTL_ADD_STRING(ctx, node_list, OID_AUTO, "device_name",
2609273246Shselasky	    CTLFLAG_RD, __DECONST(void *, pnameunit), 0,
2610273246Shselasky	    "PCI device name");
2611219820Sjeff
2612272407Shselasky        /* Add coalescer configuration. */
2613272407Shselasky        coal = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO,
2614272407Shselasky            "coalesce", CTLFLAG_RD, NULL, "Interrupt coalesce configuration");
2615292107Shselasky        coal_list = SYSCTL_CHILDREN(coal);
2616272407Shselasky        SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "pkt_rate_low",
2617272407Shselasky            CTLFLAG_RW, &priv->pkt_rate_low, 0,
2618272407Shselasky            "Packets per-second for minimum delay");
2619272407Shselasky        SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "rx_usecs_low",
2620272407Shselasky            CTLFLAG_RW, &priv->rx_usecs_low, 0,
2621272407Shselasky            "Minimum RX delay in micro-seconds");
2622272407Shselasky        SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "pkt_rate_high",
2623272407Shselasky            CTLFLAG_RW, &priv->pkt_rate_high, 0,
2624272407Shselasky            "Packets per-second for maximum delay");
2625272407Shselasky        SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "rx_usecs_high",
2626272407Shselasky            CTLFLAG_RW, &priv->rx_usecs_high, 0,
2627272407Shselasky            "Maximum RX delay in micro-seconds");
2628272407Shselasky        SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "sample_interval",
2629272407Shselasky            CTLFLAG_RW, &priv->sample_interval, 0,
2630272407Shselasky            "adaptive frequency in units of HZ ticks");
2631272407Shselasky        SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "adaptive_rx_coal",
2632272407Shselasky            CTLFLAG_RW, &priv->adaptive_rx_coal, 0,
2633272407Shselasky            "Enable adaptive rx coalescing");
2634292107Shselasky	/* EEPROM support */
2635292107Shselasky	SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "eeprom_info",
2636292107Shselasky	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
2637292107Shselasky	    mlx4_en_read_eeprom, "I", "EEPROM information");
2638219820Sjeff}
2639219820Sjeff
2640219820Sjeffstatic void mlx4_en_sysctl_stat(struct mlx4_en_priv *priv)
2641219820Sjeff{
2642219820Sjeff	struct sysctl_ctx_list *ctx;
2643219820Sjeff	struct sysctl_oid *node;
2644219820Sjeff	struct sysctl_oid_list *node_list;
2645219820Sjeff	struct sysctl_oid *ring_node;
2646219820Sjeff	struct sysctl_oid_list *ring_list;
2647219820Sjeff	struct mlx4_en_tx_ring *tx_ring;
2648219820Sjeff	struct mlx4_en_rx_ring *rx_ring;
2649219820Sjeff	char namebuf[128];
2650219820Sjeff	int i;
2651219820Sjeff
2652219820Sjeff	ctx = &priv->stat_ctx;
2653219820Sjeff	sysctl_ctx_init(ctx);
2654219820Sjeff	node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(priv->sysctl), OID_AUTO,
2655219820Sjeff	    "stat", CTLFLAG_RD, NULL, "Statistics");
2656219820Sjeff	node_list = SYSCTL_CHILDREN(node);
2657219820Sjeff
2658219820Sjeff#ifdef MLX4_EN_PERF_STAT
2659219820Sjeff	SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "tx_poll", CTLFLAG_RD,
2660219820Sjeff	    &priv->pstats.tx_poll, "TX Poll calls");
2661219820Sjeff	SYSCTL_ADD_QUAD(ctx, node_list, OID_AUTO, "tx_pktsz_avg", CTLFLAG_RD,
2662219820Sjeff	    &priv->pstats.tx_pktsz_avg, "TX average packet size");
2663219820Sjeff	SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "inflight_avg", CTLFLAG_RD,
2664219820Sjeff	    &priv->pstats.inflight_avg, "TX average packets in-flight");
2665219820Sjeff	SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "tx_coal_avg", CTLFLAG_RD,
2666219820Sjeff	    &priv->pstats.tx_coal_avg, "TX average coalesced completions");
2667219820Sjeff	SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "rx_coal_avg", CTLFLAG_RD,
2668219820Sjeff	    &priv->pstats.rx_coal_avg, "RX average coalesced completions");
2669219820Sjeff#endif
2670219820Sjeff
2671219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tso_packets", CTLFLAG_RD,
2672219820Sjeff	    &priv->port_stats.tso_packets, "TSO packets sent");
2673219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "queue_stopped", CTLFLAG_RD,
2674219820Sjeff	    &priv->port_stats.queue_stopped, "Queue full");
2675219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "wake_queue", CTLFLAG_RD,
2676219820Sjeff	    &priv->port_stats.wake_queue, "Queue resumed after full");
2677219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_timeout", CTLFLAG_RD,
2678219820Sjeff	    &priv->port_stats.tx_timeout, "Transmit timeouts");
2679292107Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_oversized_packets", CTLFLAG_RD,
2680292107Shselasky	    &priv->port_stats.oversized_packets, "TX oversized packets, m_defrag failed");
2681219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_alloc_failed", CTLFLAG_RD,
2682219820Sjeff	    &priv->port_stats.rx_alloc_failed, "RX failed to allocate mbuf");
2683219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_chksum_good", CTLFLAG_RD,
2684219820Sjeff	    &priv->port_stats.rx_chksum_good, "RX checksum offload success");
2685219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_chksum_none", CTLFLAG_RD,
2686219820Sjeff	    &priv->port_stats.rx_chksum_none, "RX without checksum offload");
2687219820Sjeff	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_chksum_offload",
2688219820Sjeff	    CTLFLAG_RD, &priv->port_stats.tx_chksum_offload,
2689219820Sjeff	    "TX checksum offloads");
2690219820Sjeff
2691219820Sjeff	/* Could strdup the names and add in a loop.  This is simpler. */
2692272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_bytes", CTLFLAG_RD,
2693272407Shselasky	    &priv->pkstats.rx_bytes, "RX Bytes");
2694272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_packets", CTLFLAG_RD,
2695272407Shselasky	    &priv->pkstats.rx_packets, "RX packets");
2696272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_multicast_packets", CTLFLAG_RD,
2697272407Shselasky	    &priv->pkstats.rx_multicast_packets, "RX Multicast Packets");
2698272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_broadcast_packets", CTLFLAG_RD,
2699272407Shselasky	    &priv->pkstats.rx_broadcast_packets, "RX Broadcast Packets");
2700272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_errors", CTLFLAG_RD,
2701272407Shselasky	    &priv->pkstats.rx_errors, "RX Errors");
2702272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_dropped", CTLFLAG_RD,
2703272407Shselasky	    &priv->pkstats.rx_dropped, "RX Dropped");
2704272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_length_errors", CTLFLAG_RD,
2705272407Shselasky	    &priv->pkstats.rx_length_errors, "RX Length Errors");
2706272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_over_errors", CTLFLAG_RD,
2707272407Shselasky	    &priv->pkstats.rx_over_errors, "RX Over Errors");
2708272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_crc_errors", CTLFLAG_RD,
2709272407Shselasky	    &priv->pkstats.rx_crc_errors, "RX CRC Errors");
2710272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_jabbers", CTLFLAG_RD,
2711272407Shselasky	    &priv->pkstats.rx_jabbers, "RX Jabbers");
2712219820Sjeff
2713272407Shselasky
2714272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_in_range_length_error", CTLFLAG_RD,
2715272407Shselasky	    &priv->pkstats.rx_in_range_length_error, "RX IN_Range Length Error");
2716272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_out_range_length_error",
2717272407Shselasky		CTLFLAG_RD, &priv->pkstats.rx_out_range_length_error,
2718272407Shselasky		"RX Out Range Length Error");
2719272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_lt_64_bytes_packets", CTLFLAG_RD,
2720272407Shselasky	    &priv->pkstats.rx_lt_64_bytes_packets, "RX Lt 64 Bytes Packets");
2721272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_127_bytes_packets", CTLFLAG_RD,
2722272407Shselasky	    &priv->pkstats.rx_127_bytes_packets, "RX 127 bytes Packets");
2723272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_255_bytes_packets", CTLFLAG_RD,
2724272407Shselasky	    &priv->pkstats.rx_255_bytes_packets, "RX 255 bytes Packets");
2725272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_511_bytes_packets", CTLFLAG_RD,
2726272407Shselasky	    &priv->pkstats.rx_511_bytes_packets, "RX 511 bytes Packets");
2727272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1023_bytes_packets", CTLFLAG_RD,
2728272407Shselasky	    &priv->pkstats.rx_1023_bytes_packets, "RX 1023 bytes Packets");
2729272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1518_bytes_packets", CTLFLAG_RD,
2730272407Shselasky	    &priv->pkstats.rx_1518_bytes_packets, "RX 1518 bytes Packets");
2731272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1522_bytes_packets", CTLFLAG_RD,
2732272407Shselasky	    &priv->pkstats.rx_1522_bytes_packets, "RX 1522 bytes Packets");
2733272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1548_bytes_packets", CTLFLAG_RD,
2734272407Shselasky	    &priv->pkstats.rx_1548_bytes_packets, "RX 1548 bytes Packets");
2735272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_gt_1548_bytes_packets", CTLFLAG_RD,
2736272407Shselasky	    &priv->pkstats.rx_gt_1548_bytes_packets,
2737272407Shselasky	    "RX Greater Then 1548 bytes Packets");
2738272407Shselasky
2739272407Shselaskystruct mlx4_en_pkt_stats {
2740272407Shselasky	unsigned long tx_packets;
2741272407Shselasky	unsigned long tx_bytes;
2742272407Shselasky	unsigned long tx_multicast_packets;
2743272407Shselasky	unsigned long tx_broadcast_packets;
2744272407Shselasky	unsigned long tx_errors;
2745272407Shselasky	unsigned long tx_dropped;
2746272407Shselasky	unsigned long tx_lt_64_bytes_packets;
2747272407Shselasky	unsigned long tx_127_bytes_packets;
2748272407Shselasky	unsigned long tx_255_bytes_packets;
2749272407Shselasky	unsigned long tx_511_bytes_packets;
2750272407Shselasky	unsigned long tx_1023_bytes_packets;
2751272407Shselasky	unsigned long tx_1518_bytes_packets;
2752272407Shselasky	unsigned long tx_1522_bytes_packets;
2753272407Shselasky	unsigned long tx_1548_bytes_packets;
2754272407Shselasky	unsigned long tx_gt_1548_bytes_packets;
2755272407Shselasky	unsigned long rx_prio[NUM_PRIORITIES][NUM_PRIORITY_STATS];
2756272407Shselasky	unsigned long tx_prio[NUM_PRIORITIES][NUM_PRIORITY_STATS];
2757272407Shselasky#define NUM_PKT_STATS		72
2758272407Shselasky};
2759272407Shselasky
2760272407Shselasky
2761272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_packets", CTLFLAG_RD,
2762272407Shselasky	    &priv->pkstats.tx_packets, "TX packets");
2763272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_bytes", CTLFLAG_RD,
2764292107Shselasky	    &priv->pkstats.tx_bytes, "TX Bytes");
2765272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_multicast_packets", CTLFLAG_RD,
2766272407Shselasky	    &priv->pkstats.tx_multicast_packets, "TX Multicast Packets");
2767272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_broadcast_packets", CTLFLAG_RD,
2768272407Shselasky	    &priv->pkstats.tx_broadcast_packets, "TX Broadcast Packets");
2769272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_errors", CTLFLAG_RD,
2770272407Shselasky	    &priv->pkstats.tx_errors, "TX Errors");
2771272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_dropped", CTLFLAG_RD,
2772272407Shselasky	    &priv->pkstats.tx_dropped, "TX Dropped");
2773272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_lt_64_bytes_packets", CTLFLAG_RD,
2774272407Shselasky	    &priv->pkstats.tx_lt_64_bytes_packets, "TX Less Then 64 Bytes Packets");
2775272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_127_bytes_packets", CTLFLAG_RD,
2776272407Shselasky	    &priv->pkstats.tx_127_bytes_packets, "TX 127 Bytes Packets");
2777272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_255_bytes_packets", CTLFLAG_RD,
2778272407Shselasky	    &priv->pkstats.tx_255_bytes_packets, "TX 255 Bytes Packets");
2779272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_511_bytes_packets", CTLFLAG_RD,
2780272407Shselasky	    &priv->pkstats.tx_511_bytes_packets, "TX 511 Bytes Packets");
2781272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1023_bytes_packets", CTLFLAG_RD,
2782272407Shselasky	    &priv->pkstats.tx_1023_bytes_packets, "TX 1023 Bytes Packets");
2783272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1518_bytes_packets", CTLFLAG_RD,
2784272407Shselasky	    &priv->pkstats.tx_1518_bytes_packets, "TX 1518 Bytes Packets");
2785272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1522_bytes_packets", CTLFLAG_RD,
2786272407Shselasky	    &priv->pkstats.tx_1522_bytes_packets, "TX 1522 Bytes Packets");
2787272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1548_bytes_packets", CTLFLAG_RD,
2788272407Shselasky	    &priv->pkstats.tx_1548_bytes_packets, "TX 1548 Bytes Packets");
2789272407Shselasky	SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_gt_1548_bytes_packets", CTLFLAG_RD,
2790272407Shselasky	    &priv->pkstats.tx_gt_1548_bytes_packets,
2791272407Shselasky	    "TX Greater Then 1548 Bytes Packets");
2792272407Shselasky
2793272407Shselasky
2794272407Shselasky
2795219820Sjeff	for (i = 0; i < priv->tx_ring_num; i++) {
2796272407Shselasky		tx_ring = priv->tx_ring[i];
2797219820Sjeff		snprintf(namebuf, sizeof(namebuf), "tx_ring%d", i);
2798219820Sjeff		ring_node = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO, namebuf,
2799219820Sjeff		    CTLFLAG_RD, NULL, "TX Ring");
2800219820Sjeff		ring_list = SYSCTL_CHILDREN(ring_node);
2801219820Sjeff		SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "packets",
2802219820Sjeff		    CTLFLAG_RD, &tx_ring->packets, "TX packets");
2803219820Sjeff		SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "bytes",
2804219820Sjeff		    CTLFLAG_RD, &tx_ring->bytes, "TX bytes");
2805292107Shselasky	}
2806219820Sjeff
2807219820Sjeff	for (i = 0; i < priv->rx_ring_num; i++) {
2808272407Shselasky		rx_ring = priv->rx_ring[i];
2809219820Sjeff		snprintf(namebuf, sizeof(namebuf), "rx_ring%d", i);
2810219820Sjeff		ring_node = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO, namebuf,
2811219820Sjeff		    CTLFLAG_RD, NULL, "RX Ring");
2812219820Sjeff		ring_list = SYSCTL_CHILDREN(ring_node);
2813219820Sjeff		SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "packets",
2814219820Sjeff		    CTLFLAG_RD, &rx_ring->packets, "RX packets");
2815219820Sjeff		SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "bytes",
2816219820Sjeff		    CTLFLAG_RD, &rx_ring->bytes, "RX bytes");
2817219820Sjeff		SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "error",
2818219820Sjeff		    CTLFLAG_RD, &rx_ring->errors, "RX soft errors");
2819219820Sjeff	}
2820219820Sjeff}
2821