en_main.c 127.8 KB
Newer Older
1
/*
2
 * Copyright (c) 2015-2016, Mellanox Technologies. All rights reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

33 34
#include <net/tc_act/tc_gact.h>
#include <net/pkt_cls.h>
35
#include <linux/mlx5/fs.h>
36
#include <net/vxlan.h>
37
#include <linux/bpf.h>
38
#include <net/page_pool.h>
39
#include "eswitch.h"
40
#include "en.h"
41
#include "en_tc.h"
42
#include "en_rep.h"
43
#include "en_accel/ipsec.h"
44
#include "en_accel/ipsec_rxtx.h"
45
#include "en_accel/tls.h"
46
#include "accel/ipsec.h"
47
#include "accel/tls.h"
48
#include "vxlan.h"
49
#include "en/port.h"
50
#include "en/xdp.h"
51 52

struct mlx5e_rq_param {
53 54
	u32			rqc[MLX5_ST_SZ_DW(rqc)];
	struct mlx5_wq_param	wq;
55
	struct mlx5e_rq_frags_info frags_info;
56 57 58 59 60 61 62 63 64 65 66
};

struct mlx5e_sq_param {
	u32                        sqc[MLX5_ST_SZ_DW(sqc)];
	struct mlx5_wq_param       wq;
};

struct mlx5e_cq_param {
	u32                        cqc[MLX5_ST_SZ_DW(cqc)];
	struct mlx5_wq_param       wq;
	u16                        eq_ix;
T
Tariq Toukan 已提交
67
	u8                         cq_period_mode;
68 69 70 71 72
};

struct mlx5e_channel_param {
	struct mlx5e_rq_param      rq;
	struct mlx5e_sq_param      sq;
73
	struct mlx5e_sq_param      xdp_sq;
T
Tariq Toukan 已提交
74
	struct mlx5e_sq_param      icosq;
75 76
	struct mlx5e_cq_param      rx_cq;
	struct mlx5e_cq_param      tx_cq;
T
Tariq Toukan 已提交
77
	struct mlx5e_cq_param      icosq_cq;
78 79
};

80
bool mlx5e_check_fragmented_striding_rq_cap(struct mlx5_core_dev *mdev)
81
{
82
	bool striding_rq_umr = MLX5_CAP_GEN(mdev, striding_rq) &&
83 84
		MLX5_CAP_GEN(mdev, umr_ptr_rlky) &&
		MLX5_CAP_ETH(mdev, reg_umr_sq);
85 86 87 88 89 90 91 92 93 94 95
	u16 max_wqe_sz_cap = MLX5_CAP_GEN(mdev, max_wqe_sz_sq);
	bool inline_umr = MLX5E_UMR_WQE_INLINE_SZ <= max_wqe_sz_cap;

	if (!striding_rq_umr)
		return false;
	if (!inline_umr) {
		mlx5_core_warn(mdev, "Cannot support Striding RQ: UMR WQE size (%d) exceeds maximum supported (%d).\n",
			       (int)MLX5E_UMR_WQE_INLINE_SZ, max_wqe_sz_cap);
		return false;
	}
	return true;
96 97
}

98
static u32 mlx5e_rx_get_linear_frag_sz(struct mlx5e_params *params)
99
{
100 101 102 103
	u16 hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu);
	u16 linear_rq_headroom = params->xdp_prog ?
		XDP_PACKET_HEADROOM : MLX5_RX_HEADROOM;
	u32 frag_sz;
104

105
	linear_rq_headroom += NET_IP_ALIGN;
106

107 108 109 110 111 112
	frag_sz = MLX5_SKB_FRAG_SZ(linear_rq_headroom + hw_mtu);

	if (params->xdp_prog && frag_sz < PAGE_SIZE)
		frag_sz = PAGE_SIZE;

	return frag_sz;
113 114 115 116
}

static u8 mlx5e_mpwqe_log_pkts_per_wqe(struct mlx5e_params *params)
{
117
	u32 linear_frag_sz = mlx5e_rx_get_linear_frag_sz(params);
118 119 120 121

	return MLX5_MPWRQ_LOG_WQE_SZ - order_base_2(linear_frag_sz);
}

122 123 124 125 126 127 128 129
static bool mlx5e_rx_is_linear_skb(struct mlx5_core_dev *mdev,
				   struct mlx5e_params *params)
{
	u32 frag_sz = mlx5e_rx_get_linear_frag_sz(params);

	return !params->lro_en && frag_sz <= PAGE_SIZE;
}

130 131 132
static bool mlx5e_rx_mpwqe_is_linear_skb(struct mlx5_core_dev *mdev,
					 struct mlx5e_params *params)
{
133
	u32 frag_sz = mlx5e_rx_get_linear_frag_sz(params);
134 135 136
	s8 signed_log_num_strides_param;
	u8 log_num_strides;

137
	if (!mlx5e_rx_is_linear_skb(mdev, params))
138 139 140 141 142 143 144 145 146 147 148 149
		return false;

	if (MLX5_CAP_GEN(mdev, ext_stride_num_range))
		return true;

	log_num_strides = MLX5_MPWRQ_LOG_WQE_SZ - order_base_2(frag_sz);
	signed_log_num_strides_param =
		(s8)log_num_strides - MLX5_MPWQE_LOG_NUM_STRIDES_BASE;

	return signed_log_num_strides_param >= 0;
}

150 151 152 153 154 155 156 157 158 159 160
static u8 mlx5e_mpwqe_get_log_rq_size(struct mlx5e_params *params)
{
	if (params->log_rq_mtu_frames <
	    mlx5e_mpwqe_log_pkts_per_wqe(params) + MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE_MPW)
		return MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE_MPW;

	return params->log_rq_mtu_frames - mlx5e_mpwqe_log_pkts_per_wqe(params);
}

static u8 mlx5e_mpwqe_get_log_stride_size(struct mlx5_core_dev *mdev,
					  struct mlx5e_params *params)
161
{
162
	if (mlx5e_rx_mpwqe_is_linear_skb(mdev, params))
163
		return order_base_2(mlx5e_rx_get_linear_frag_sz(params));
164

165 166 167 168
	return MLX5E_MPWQE_STRIDE_SZ(mdev,
		MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS));
}

169 170
static u8 mlx5e_mpwqe_get_log_num_strides(struct mlx5_core_dev *mdev,
					  struct mlx5e_params *params)
171 172 173 174 175
{
	return MLX5_MPWRQ_LOG_WQE_SZ -
		mlx5e_mpwqe_get_log_stride_size(mdev, params);
}

176 177
static u16 mlx5e_get_rq_headroom(struct mlx5_core_dev *mdev,
				 struct mlx5e_params *params)
178 179 180
{
	u16 linear_rq_headroom = params->xdp_prog ?
		XDP_PACKET_HEADROOM : MLX5_RX_HEADROOM;
181
	bool is_linear_skb;
182 183 184

	linear_rq_headroom += NET_IP_ALIGN;

185 186 187
	is_linear_skb = (params->rq_wq_type == MLX5_WQ_TYPE_CYCLIC) ?
		mlx5e_rx_is_linear_skb(mdev, params) :
		mlx5e_rx_mpwqe_is_linear_skb(mdev, params);
188

189
	return is_linear_skb ? linear_rq_headroom : 0;
190 191
}

192
void mlx5e_init_rq_type_params(struct mlx5_core_dev *mdev,
193
			       struct mlx5e_params *params)
194
{
195
	params->lro_wqe_sz = MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
196 197 198
	params->log_rq_mtu_frames = is_kdump_kernel() ?
		MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE :
		MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE;
199

200 201
	mlx5_core_info(mdev, "MLX5E: StrdRq(%d) RqSz(%ld) StrdSz(%ld) RxCqeCmprss(%d)\n",
		       params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ,
202 203
		       params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ ?
		       BIT(mlx5e_mpwqe_get_log_rq_size(params)) :
204
		       BIT(params->log_rq_mtu_frames),
205
		       BIT(mlx5e_mpwqe_get_log_stride_size(mdev, params)),
206
		       MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS));
207 208
}

209 210 211 212
bool mlx5e_striding_rq_possible(struct mlx5_core_dev *mdev,
				struct mlx5e_params *params)
{
	return mlx5e_check_fragmented_striding_rq_cap(mdev) &&
213 214
		!MLX5_IPSEC_DEV(mdev) &&
		!(params->xdp_prog && !mlx5e_rx_mpwqe_is_linear_skb(mdev, params));
215
}
216

217
void mlx5e_set_rq_type(struct mlx5_core_dev *mdev, struct mlx5e_params *params)
218
{
219 220
	params->rq_wq_type = mlx5e_striding_rq_possible(mdev, params) &&
		MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_STRIDING_RQ) ?
221
		MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ :
222
		MLX5_WQ_TYPE_CYCLIC;
223 224
}

225 226 227 228 229 230
static void mlx5e_update_carrier(struct mlx5e_priv *priv)
{
	struct mlx5_core_dev *mdev = priv->mdev;
	u8 port_state;

	port_state = mlx5_query_vport_state(mdev,
231 232
					    MLX5_QUERY_VPORT_STATE_IN_OP_MOD_VNIC_VPORT,
					    0);
233

234 235
	if (port_state == VPORT_STATE_UP) {
		netdev_info(priv->netdev, "Link up\n");
236
		netif_carrier_on(priv->netdev);
237 238
	} else {
		netdev_info(priv->netdev, "Link down\n");
239
		netif_carrier_off(priv->netdev);
240
	}
241 242 243 244 245 246 247 248 249
}

static void mlx5e_update_carrier_work(struct work_struct *work)
{
	struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
					       update_carrier_work);

	mutex_lock(&priv->state_lock);
	if (test_bit(MLX5E_STATE_OPENED, &priv->state))
250 251
		if (priv->profile->update_carrier)
			priv->profile->update_carrier(priv);
252 253 254
	mutex_unlock(&priv->state_lock);
}

255
void mlx5e_update_stats(struct mlx5e_priv *priv)
256
{
257
	int i;
258

259 260 261
	for (i = mlx5e_num_stats_grps - 1; i >= 0; i--)
		if (mlx5e_stats_grps[i].update_stats)
			mlx5e_stats_grps[i].update_stats(priv);
262 263
}

264 265
static void mlx5e_update_ndo_stats(struct mlx5e_priv *priv)
{
266 267 268 269 270 271
	int i;

	for (i = mlx5e_num_stats_grps - 1; i >= 0; i--)
		if (mlx5e_stats_grps[i].update_stats_mask &
		    MLX5E_NDO_UPDATE_STATS)
			mlx5e_stats_grps[i].update_stats(priv);
272 273
}

274
void mlx5e_update_stats_work(struct work_struct *work)
275 276 277 278
{
	struct delayed_work *dwork = to_delayed_work(work);
	struct mlx5e_priv *priv = container_of(dwork, struct mlx5e_priv,
					       update_stats_work);
279

280
	mutex_lock(&priv->state_lock);
281
	priv->profile->update_stats(priv);
282 283 284
	mutex_unlock(&priv->state_lock);
}

285 286
static void mlx5e_async_event(struct mlx5_core_dev *mdev, void *vpriv,
			      enum mlx5_dev_event event, unsigned long param)
287
{
288 289
	struct mlx5e_priv *priv = vpriv;

290
	if (!test_bit(MLX5E_STATE_ASYNC_EVENTS_ENABLED, &priv->state))
291 292
		return;

293 294 295
	switch (event) {
	case MLX5_DEV_EVENT_PORT_UP:
	case MLX5_DEV_EVENT_PORT_DOWN:
296
		queue_work(priv->wq, &priv->update_carrier_work);
297 298 299 300 301 302 303 304
		break;
	default:
		break;
	}
}

static void mlx5e_enable_async_events(struct mlx5e_priv *priv)
{
305
	set_bit(MLX5E_STATE_ASYNC_EVENTS_ENABLED, &priv->state);
306 307 308 309
}

static void mlx5e_disable_async_events(struct mlx5e_priv *priv)
{
310
	clear_bit(MLX5E_STATE_ASYNC_EVENTS_ENABLED, &priv->state);
311
	synchronize_irq(pci_irq_vector(priv->mdev->pdev, MLX5_EQ_VEC_ASYNC));
312 313
}

S
Saeed Mahameed 已提交
314 315
static inline void mlx5e_build_umr_wqe(struct mlx5e_rq *rq,
				       struct mlx5e_icosq *sq,
316
				       struct mlx5e_umr_wqe *wqe)
317 318 319
{
	struct mlx5_wqe_ctrl_seg      *cseg = &wqe->ctrl;
	struct mlx5_wqe_umr_ctrl_seg *ucseg = &wqe->uctrl;
320
	u8 ds_cnt = DIV_ROUND_UP(MLX5E_UMR_WQE_INLINE_SZ, MLX5_SEND_WQE_DS);
321 322 323 324 325 326

	cseg->qpn_ds    = cpu_to_be32((sq->sqn << MLX5_WQE_CTRL_QPN_SHIFT) |
				      ds_cnt);
	cseg->fm_ce_se  = MLX5_WQE_CTRL_CQ_UPDATE;
	cseg->imm       = rq->mkey_be;

327
	ucseg->flags = MLX5_UMR_TRANSLATION_OFFSET_EN | MLX5_UMR_INLINE;
328
	ucseg->xlt_octowords =
329 330 331 332
		cpu_to_be16(MLX5_MTT_OCTW(MLX5_MPWRQ_PAGES_PER_WQE));
	ucseg->mkey_mask     = cpu_to_be64(MLX5_MKEY_MASK_FREE);
}

333 334 335 336 337 338
static u32 mlx5e_rqwq_get_size(struct mlx5e_rq *rq)
{
	switch (rq->wq_type) {
	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
		return mlx5_wq_ll_get_size(&rq->mpwqe.wq);
	default:
339
		return mlx5_wq_cyc_get_size(&rq->wqe.wq);
340 341 342 343 344 345 346 347 348 349 350 351 352
	}
}

static u32 mlx5e_rqwq_get_cur_sz(struct mlx5e_rq *rq)
{
	switch (rq->wq_type) {
	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
		return rq->mpwqe.wq.cur_sz;
	default:
		return rq->wqe.wq.cur_sz;
	}
}

353 354 355
static int mlx5e_rq_alloc_mpwqe_info(struct mlx5e_rq *rq,
				     struct mlx5e_channel *c)
{
356
	int wq_sz = mlx5_wq_ll_get_size(&rq->mpwqe.wq);
357

358 359
	rq->mpwqe.info = kvzalloc_node(array_size(wq_sz,
						  sizeof(*rq->mpwqe.info)),
360
				       GFP_KERNEL, cpu_to_node(c->cpu));
361
	if (!rq->mpwqe.info)
362
		return -ENOMEM;
363

364
	mlx5e_build_umr_wqe(rq, &c->icosq, &rq->mpwqe.umr_wqe);
365 366 367 368

	return 0;
}

369
static int mlx5e_create_umr_mkey(struct mlx5_core_dev *mdev,
T
Tariq Toukan 已提交
370 371
				 u64 npages, u8 page_shift,
				 struct mlx5_core_mkey *umr_mkey)
372 373 374 375 376 377
{
	int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
	void *mkc;
	u32 *in;
	int err;

378
	in = kvzalloc(inlen, GFP_KERNEL);
379 380 381 382 383 384 385 386 387
	if (!in)
		return -ENOMEM;

	mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);

	MLX5_SET(mkc, mkc, free, 1);
	MLX5_SET(mkc, mkc, umr_en, 1);
	MLX5_SET(mkc, mkc, lw, 1);
	MLX5_SET(mkc, mkc, lr, 1);
388
	MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_MTT);
389 390 391

	MLX5_SET(mkc, mkc, qpn, 0xffffff);
	MLX5_SET(mkc, mkc, pd, mdev->mlx5e_res.pdn);
T
Tariq Toukan 已提交
392
	MLX5_SET64(mkc, mkc, len, npages << page_shift);
393 394
	MLX5_SET(mkc, mkc, translations_octword_size,
		 MLX5_MTT_OCTW(npages));
T
Tariq Toukan 已提交
395
	MLX5_SET(mkc, mkc, log_page_size, page_shift);
396

T
Tariq Toukan 已提交
397
	err = mlx5_core_create_mkey(mdev, umr_mkey, in, inlen);
398 399 400 401 402

	kvfree(in);
	return err;
}

403
static int mlx5e_create_rq_umr_mkey(struct mlx5_core_dev *mdev, struct mlx5e_rq *rq)
T
Tariq Toukan 已提交
404
{
405
	u64 num_mtts = MLX5E_REQUIRED_MTTS(mlx5_wq_ll_get_size(&rq->mpwqe.wq));
T
Tariq Toukan 已提交
406

407
	return mlx5e_create_umr_mkey(mdev, num_mtts, PAGE_SHIFT, &rq->umr_mkey);
T
Tariq Toukan 已提交
408 409
}

410 411 412 413 414
static inline u64 mlx5e_get_mpwqe_offset(struct mlx5e_rq *rq, u16 wqe_ix)
{
	return (wqe_ix << MLX5E_LOG_ALIGNED_MPWQE_PPW) << PAGE_SHIFT;
}

415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
static void mlx5e_init_frags_partition(struct mlx5e_rq *rq)
{
	struct mlx5e_wqe_frag_info next_frag, *prev;
	int i;

	next_frag.di = &rq->wqe.di[0];
	next_frag.offset = 0;
	prev = NULL;

	for (i = 0; i < mlx5_wq_cyc_get_size(&rq->wqe.wq); i++) {
		struct mlx5e_rq_frag_info *frag_info = &rq->wqe.info.arr[0];
		struct mlx5e_wqe_frag_info *frag =
			&rq->wqe.frags[i << rq->wqe.info.log_num_frags];
		int f;

		for (f = 0; f < rq->wqe.info.num_frags; f++, frag++) {
			if (next_frag.offset + frag_info[f].frag_stride > PAGE_SIZE) {
				next_frag.di++;
				next_frag.offset = 0;
				if (prev)
					prev->last_in_page = true;
			}
			*frag = next_frag;

			/* prepare next */
			next_frag.offset += frag_info[f].frag_stride;
			prev = frag;
		}
	}

	if (prev)
		prev->last_in_page = true;
}

static int mlx5e_init_di_list(struct mlx5e_rq *rq,
			      struct mlx5e_params *params,
			      int wq_sz, int cpu)
{
	int len = wq_sz << rq->wqe.info.log_num_frags;

455
	rq->wqe.di = kvzalloc_node(array_size(len, sizeof(*rq->wqe.di)),
456 457 458 459 460 461 462 463 464 465 466 467 468 469
				   GFP_KERNEL, cpu_to_node(cpu));
	if (!rq->wqe.di)
		return -ENOMEM;

	mlx5e_init_frags_partition(rq);

	return 0;
}

static void mlx5e_free_di_list(struct mlx5e_rq *rq)
{
	kvfree(rq->wqe.di);
}

470
static int mlx5e_alloc_rq(struct mlx5e_channel *c,
471 472
			  struct mlx5e_params *params,
			  struct mlx5e_rq_param *rqp,
473
			  struct mlx5e_rq *rq)
474
{
475
	struct page_pool_params pp_params = { 0 };
476
	struct mlx5_core_dev *mdev = c->mdev;
477
	void *rqc = rqp->rqc;
478
	void *rqc_wq = MLX5_ADDR_OF(rqc, rqc, wq);
479
	u32 pool_size;
480 481 482 483
	int wq_sz;
	int err;
	int i;

484
	rqp->wq.db_numa_node = cpu_to_node(c->cpu);
485

486
	rq->wq_type = params->rq_wq_type;
487 488
	rq->pdev    = c->pdev;
	rq->netdev  = c->netdev;
489
	rq->tstamp  = c->tstamp;
490
	rq->clock   = &mdev->clock;
491 492
	rq->channel = c;
	rq->ix      = c->ix;
493
	rq->mdev    = mdev;
494
	rq->stats   = &c->priv->channel_stats[c->ix].rq;
495

496
	rq->xdp_prog = params->xdp_prog ? bpf_prog_inc(params->xdp_prog) : NULL;
497 498 499 500 501
	if (IS_ERR(rq->xdp_prog)) {
		err = PTR_ERR(rq->xdp_prog);
		rq->xdp_prog = NULL;
		goto err_rq_wq_destroy;
	}
502

503 504
	err = xdp_rxq_info_reg(&rq->xdp_rxq, rq->netdev, rq->ix);
	if (err < 0)
505 506
		goto err_rq_wq_destroy;

507
	rq->buff.map_dir = rq->xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;
508
	rq->buff.headroom = mlx5e_get_rq_headroom(mdev, params);
509
	pool_size = 1 << params->log_rq_mtu_frames;
510

511
	switch (rq->wq_type) {
512
	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
513 514 515 516 517 518 519 520
		err = mlx5_wq_ll_create(mdev, &rqp->wq, rqc_wq, &rq->mpwqe.wq,
					&rq->wq_ctrl);
		if (err)
			return err;

		rq->mpwqe.wq.db = &rq->mpwqe.wq.db[MLX5_RCV_DBR];

		wq_sz = mlx5_wq_ll_get_size(&rq->mpwqe.wq);
521 522

		pool_size = MLX5_MPWRQ_PAGES_PER_WQE << mlx5e_mpwqe_get_log_rq_size(params);
523

524
		rq->post_wqes = mlx5e_post_rx_mpwqes;
525
		rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe;
526

527
		rq->handle_rx_cqe = c->priv->profile->rx_handlers.handle_rx_cqe_mpwqe;
528 529 530 531 532 533 534
#ifdef CONFIG_MLX5_EN_IPSEC
		if (MLX5_IPSEC_DEV(mdev)) {
			err = -EINVAL;
			netdev_err(c->netdev, "MPWQE RQ with IPSec offload not supported\n");
			goto err_rq_wq_destroy;
		}
#endif
535 536 537 538 539 540
		if (!rq->handle_rx_cqe) {
			err = -EINVAL;
			netdev_err(c->netdev, "RX handler of MPWQE RQ is not set, err %d\n", err);
			goto err_rq_wq_destroy;
		}

541 542 543 544
		rq->mpwqe.skb_from_cqe_mpwrq =
			mlx5e_rx_mpwqe_is_linear_skb(mdev, params) ?
			mlx5e_skb_from_cqe_mpwrq_linear :
			mlx5e_skb_from_cqe_mpwrq_nonlinear;
545 546
		rq->mpwqe.log_stride_sz = mlx5e_mpwqe_get_log_stride_size(mdev, params);
		rq->mpwqe.num_strides = BIT(mlx5e_mpwqe_get_log_num_strides(mdev, params));
547

548
		err = mlx5e_create_rq_umr_mkey(mdev, rq);
549 550
		if (err)
			goto err_rq_wq_destroy;
T
Tariq Toukan 已提交
551 552 553 554
		rq->mkey_be = cpu_to_be32(rq->umr_mkey.key);

		err = mlx5e_rq_alloc_mpwqe_info(rq, c);
		if (err)
555
			goto err_free;
556
		break;
557 558 559
	default: /* MLX5_WQ_TYPE_CYCLIC */
		err = mlx5_wq_cyc_create(mdev, &rqp->wq, rqc_wq, &rq->wqe.wq,
					 &rq->wq_ctrl);
560 561 562 563 564
		if (err)
			return err;

		rq->wqe.wq.db = &rq->wqe.wq.db[MLX5_RCV_DBR];

565
		wq_sz = mlx5_wq_cyc_get_size(&rq->wqe.wq);
566

567 568
		rq->wqe.info = rqp->frags_info;
		rq->wqe.frags =
569 570
			kvzalloc_node(array_size(sizeof(*rq->wqe.frags),
					(wq_sz << rq->wqe.info.log_num_frags)),
571
				      GFP_KERNEL, cpu_to_node(c->cpu));
572 573
		if (!rq->wqe.frags) {
			err = -ENOMEM;
574
			goto err_free;
575
		}
576 577 578 579

		err = mlx5e_init_di_list(rq, params, wq_sz, c->cpu);
		if (err)
			goto err_free;
580
		rq->post_wqes = mlx5e_post_rx_wqes;
581
		rq->dealloc_wqe = mlx5e_dealloc_rx_wqe;
582

583 584 585 586 587 588
#ifdef CONFIG_MLX5_EN_IPSEC
		if (c->priv->ipsec)
			rq->handle_rx_cqe = mlx5e_ipsec_handle_rx_cqe;
		else
#endif
			rq->handle_rx_cqe = c->priv->profile->rx_handlers.handle_rx_cqe;
589 590 591
		if (!rq->handle_rx_cqe) {
			err = -EINVAL;
			netdev_err(c->netdev, "RX handler of RQ is not set, err %d\n", err);
592
			goto err_free;
593 594
		}

595 596 597
		rq->wqe.skb_from_cqe = mlx5e_rx_is_linear_skb(mdev, params) ?
			mlx5e_skb_from_cqe_linear :
			mlx5e_skb_from_cqe_nonlinear;
598
		rq->mkey_be = c->mkey_be;
599
	}
600

601
	/* Create a page_pool and register it with rxq */
602
	pp_params.order     = 0;
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617
	pp_params.flags     = 0; /* No-internal DMA mapping in page_pool */
	pp_params.pool_size = pool_size;
	pp_params.nid       = cpu_to_node(c->cpu);
	pp_params.dev       = c->pdev;
	pp_params.dma_dir   = rq->buff.map_dir;

	/* page_pool can be used even when there is no rq->xdp_prog,
	 * given page_pool does not handle DMA mapping there is no
	 * required state to clear. And page_pool gracefully handle
	 * elevated refcnt.
	 */
	rq->page_pool = page_pool_create(&pp_params);
	if (IS_ERR(rq->page_pool)) {
		err = PTR_ERR(rq->page_pool);
		rq->page_pool = NULL;
618
		goto err_free;
619
	}
620 621 622
	err = xdp_rxq_info_reg_mem_model(&rq->xdp_rxq,
					 MEM_TYPE_PAGE_POOL, rq->page_pool);
	if (err)
623
		goto err_free;
624

625
	for (i = 0; i < wq_sz; i++) {
626
		if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
627
			struct mlx5e_rx_wqe_ll *wqe =
628
				mlx5_wq_ll_get_wqe(&rq->mpwqe.wq, i);
629 630
			u32 byte_count =
				rq->mpwqe.num_strides << rq->mpwqe.log_stride_sz;
631
			u64 dma_offset = mlx5e_get_mpwqe_offset(rq, i);
632

633 634 635
			wqe->data[0].addr = cpu_to_be64(dma_offset + rq->buff.headroom);
			wqe->data[0].byte_count = cpu_to_be32(byte_count);
			wqe->data[0].lkey = rq->mkey_be;
636
		} else {
637 638
			struct mlx5e_rx_wqe_cyc *wqe =
				mlx5_wq_cyc_get_wqe(&rq->wqe.wq, i);
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653
			int f;

			for (f = 0; f < rq->wqe.info.num_frags; f++) {
				u32 frag_size = rq->wqe.info.arr[f].frag_size |
					MLX5_HW_START_PADDING;

				wqe->data[f].byte_count = cpu_to_be32(frag_size);
				wqe->data[f].lkey = rq->mkey_be;
			}
			/* check if num_frags is not a pow of two */
			if (rq->wqe.info.num_frags < (1 << rq->wqe.info.log_num_frags)) {
				wqe->data[f].byte_count = 0;
				wqe->data[f].lkey = cpu_to_be32(MLX5_INVALID_LKEY);
				wqe->data[f].addr = 0;
			}
654
		}
655 656
	}

657 658 659 660 661 662 663 664 665 666 667
	INIT_WORK(&rq->dim.work, mlx5e_rx_dim_work);

	switch (params->rx_cq_moderation.cq_period_mode) {
	case MLX5_CQ_PERIOD_MODE_START_FROM_CQE:
		rq->dim.mode = NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE;
		break;
	case MLX5_CQ_PERIOD_MODE_START_FROM_EQE:
	default:
		rq->dim.mode = NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE;
	}

668 669 670
	rq->page_cache.head = 0;
	rq->page_cache.tail = 0;

671 672
	return 0;

673 674 675
err_free:
	switch (rq->wq_type) {
	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
676
		kvfree(rq->mpwqe.info);
677 678 679 680 681 682
		mlx5_core_destroy_mkey(mdev, &rq->umr_mkey);
		break;
	default: /* MLX5_WQ_TYPE_CYCLIC */
		kvfree(rq->wqe.frags);
		mlx5e_free_di_list(rq);
	}
T
Tariq Toukan 已提交
683

684
err_rq_wq_destroy:
685 686
	if (rq->xdp_prog)
		bpf_prog_put(rq->xdp_prog);
687
	xdp_rxq_info_unreg(&rq->xdp_rxq);
688 689
	if (rq->page_pool)
		page_pool_destroy(rq->page_pool);
690 691 692 693 694
	mlx5_wq_destroy(&rq->wq_ctrl);

	return err;
}

695
static void mlx5e_free_rq(struct mlx5e_rq *rq)
696
{
697 698
	int i;

699 700 701
	if (rq->xdp_prog)
		bpf_prog_put(rq->xdp_prog);

702
	xdp_rxq_info_unreg(&rq->xdp_rxq);
703 704
	if (rq->page_pool)
		page_pool_destroy(rq->page_pool);
705

706 707
	switch (rq->wq_type) {
	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
708
		kvfree(rq->mpwqe.info);
709
		mlx5_core_destroy_mkey(rq->mdev, &rq->umr_mkey);
710
		break;
711
	default: /* MLX5_WQ_TYPE_CYCLIC */
712 713
		kvfree(rq->wqe.frags);
		mlx5e_free_di_list(rq);
714 715
	}

716 717 718 719 720 721
	for (i = rq->page_cache.head; i != rq->page_cache.tail;
	     i = (i + 1) & (MLX5E_CACHE_SIZE - 1)) {
		struct mlx5e_dma_info *dma_info = &rq->page_cache.page_cache[i];

		mlx5e_page_release(rq, dma_info, false);
	}
722 723 724
	mlx5_wq_destroy(&rq->wq_ctrl);
}

725 726
static int mlx5e_create_rq(struct mlx5e_rq *rq,
			   struct mlx5e_rq_param *param)
727
{
728
	struct mlx5_core_dev *mdev = rq->mdev;
729 730 731 732 733 734 735 736 737

	void *in;
	void *rqc;
	void *wq;
	int inlen;
	int err;

	inlen = MLX5_ST_SZ_BYTES(create_rq_in) +
		sizeof(u64) * rq->wq_ctrl.buf.npages;
738
	in = kvzalloc(inlen, GFP_KERNEL);
739 740 741 742 743 744 745 746
	if (!in)
		return -ENOMEM;

	rqc = MLX5_ADDR_OF(create_rq_in, in, ctx);
	wq  = MLX5_ADDR_OF(rqc, rqc, wq);

	memcpy(rqc, param->rqc, sizeof(param->rqc));

747
	MLX5_SET(rqc,  rqc, cqn,		rq->cq.mcq.cqn);
748 749
	MLX5_SET(rqc,  rqc, state,		MLX5_RQC_STATE_RST);
	MLX5_SET(wq,   wq,  log_wq_pg_sz,	rq->wq_ctrl.buf.page_shift -
750
						MLX5_ADAPTER_PAGE_SHIFT);
751 752
	MLX5_SET64(wq, wq,  dbr_addr,		rq->wq_ctrl.db.dma);

753 754
	mlx5_fill_page_frag_array(&rq->wq_ctrl.buf,
				  (__be64 *)MLX5_ADDR_OF(wq, wq, pas));
755

756
	err = mlx5_core_create_rq(mdev, in, inlen, &rq->rqn);
757 758 759 760 761 762

	kvfree(in);

	return err;
}

763 764
static int mlx5e_modify_rq_state(struct mlx5e_rq *rq, int curr_state,
				 int next_state)
765
{
766
	struct mlx5_core_dev *mdev = rq->mdev;
767 768 769 770 771 772 773

	void *in;
	void *rqc;
	int inlen;
	int err;

	inlen = MLX5_ST_SZ_BYTES(modify_rq_in);
774
	in = kvzalloc(inlen, GFP_KERNEL);
775 776 777 778 779 780 781 782
	if (!in)
		return -ENOMEM;

	rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);

	MLX5_SET(modify_rq_in, in, rq_state, curr_state);
	MLX5_SET(rqc, rqc, state, next_state);

783
	err = mlx5_core_modify_rq(mdev, rq->rqn, in, inlen);
784 785 786 787 788 789

	kvfree(in);

	return err;
}

790 791 792 793 794 795 796 797 798 799 800 801
static int mlx5e_modify_rq_scatter_fcs(struct mlx5e_rq *rq, bool enable)
{
	struct mlx5e_channel *c = rq->channel;
	struct mlx5e_priv *priv = c->priv;
	struct mlx5_core_dev *mdev = priv->mdev;

	void *in;
	void *rqc;
	int inlen;
	int err;

	inlen = MLX5_ST_SZ_BYTES(modify_rq_in);
802
	in = kvzalloc(inlen, GFP_KERNEL);
803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
	if (!in)
		return -ENOMEM;

	rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);

	MLX5_SET(modify_rq_in, in, rq_state, MLX5_RQC_STATE_RDY);
	MLX5_SET64(modify_rq_in, in, modify_bitmask,
		   MLX5_MODIFY_RQ_IN_MODIFY_BITMASK_SCATTER_FCS);
	MLX5_SET(rqc, rqc, scatter_fcs, enable);
	MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RDY);

	err = mlx5_core_modify_rq(mdev, rq->rqn, in, inlen);

	kvfree(in);

	return err;
}

821 822 823
static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd)
{
	struct mlx5e_channel *c = rq->channel;
824
	struct mlx5_core_dev *mdev = c->mdev;
825 826 827 828 829 830
	void *in;
	void *rqc;
	int inlen;
	int err;

	inlen = MLX5_ST_SZ_BYTES(modify_rq_in);
831
	in = kvzalloc(inlen, GFP_KERNEL);
832 833 834 835 836 837
	if (!in)
		return -ENOMEM;

	rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);

	MLX5_SET(modify_rq_in, in, rq_state, MLX5_RQC_STATE_RDY);
838 839
	MLX5_SET64(modify_rq_in, in, modify_bitmask,
		   MLX5_MODIFY_RQ_IN_MODIFY_BITMASK_VSD);
840 841 842 843 844 845 846 847 848 849
	MLX5_SET(rqc, rqc, vsd, vsd);
	MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RDY);

	err = mlx5_core_modify_rq(mdev, rq->rqn, in, inlen);

	kvfree(in);

	return err;
}

850
static void mlx5e_destroy_rq(struct mlx5e_rq *rq)
851
{
852
	mlx5_core_destroy_rq(rq->mdev, rq->rqn);
853 854
}

855
static int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq, int wait_time)
856
{
857
	unsigned long exp_time = jiffies + msecs_to_jiffies(wait_time);
858
	struct mlx5e_channel *c = rq->channel;
859

860
	u16 min_wqes = mlx5_min_rx_wqes(rq->wq_type, mlx5e_rqwq_get_size(rq));
861

862
	do {
863
		if (mlx5e_rqwq_get_cur_sz(rq) >= min_wqes)
864 865 866
			return 0;

		msleep(20);
867 868 869
	} while (time_before(jiffies, exp_time));

	netdev_warn(c->netdev, "Failed to get min RX wqes on Channel[%d] RQN[0x%x] wq cur_sz(%d) min_rx_wqes(%d)\n",
870
		    c->ix, rq->rqn, mlx5e_rqwq_get_cur_sz(rq), min_wqes);
871 872 873 874

	return -ETIMEDOUT;
}

875 876 877 878 879
static void mlx5e_free_rx_descs(struct mlx5e_rq *rq)
{
	__be16 wqe_ix_be;
	u16 wqe_ix;

880 881 882
	if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
		struct mlx5_wq_ll *wq = &rq->mpwqe.wq;

883
		/* UMR WQE (if in progress) is always at wq->head */
884
		if (rq->mpwqe.umr_in_progress)
885
			rq->dealloc_wqe(rq, wq->head);
886 887

		while (!mlx5_wq_ll_is_empty(wq)) {
888
			struct mlx5e_rx_wqe_ll *wqe;
889 890 891 892 893 894 895 896 897

			wqe_ix_be = *wq->tail_next;
			wqe_ix    = be16_to_cpu(wqe_ix_be);
			wqe       = mlx5_wq_ll_get_wqe(wq, wqe_ix);
			rq->dealloc_wqe(rq, wqe_ix);
			mlx5_wq_ll_pop(wq, wqe_ix_be,
				       &wqe->next.next_wqe_index);
		}
	} else {
898
		struct mlx5_wq_cyc *wq = &rq->wqe.wq;
899

900 901
		while (!mlx5_wq_cyc_is_empty(wq)) {
			wqe_ix = mlx5_wq_cyc_get_tail(wq);
902
			rq->dealloc_wqe(rq, wqe_ix);
903
			mlx5_wq_cyc_pop(wq);
904
		}
905
	}
906

907 908
}

909
static int mlx5e_open_rq(struct mlx5e_channel *c,
910
			 struct mlx5e_params *params,
911 912 913 914 915
			 struct mlx5e_rq_param *param,
			 struct mlx5e_rq *rq)
{
	int err;

916
	err = mlx5e_alloc_rq(c, params, param, rq);
917 918 919
	if (err)
		return err;

920
	err = mlx5e_create_rq(rq, param);
921
	if (err)
922
		goto err_free_rq;
923

924
	err = mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY);
925
	if (err)
926
		goto err_destroy_rq;
927

928
	if (params->rx_dim_enabled)
929
		__set_bit(MLX5E_RQ_STATE_AM, &c->rq.state);
930

931 932 933 934
	return 0;

err_destroy_rq:
	mlx5e_destroy_rq(rq);
935 936
err_free_rq:
	mlx5e_free_rq(rq);
937 938 939 940

	return err;
}

941 942 943
static void mlx5e_activate_rq(struct mlx5e_rq *rq)
{
	struct mlx5e_icosq *sq = &rq->channel->icosq;
944
	struct mlx5_wq_cyc *wq = &sq->wq;
945 946
	struct mlx5e_tx_wqe *nopwqe;

947 948
	u16 pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc);

949 950
	set_bit(MLX5E_RQ_STATE_ENABLED, &rq->state);
	sq->db.ico_wqe[pi].opcode     = MLX5_OPCODE_NOP;
951 952
	nopwqe = mlx5e_post_nop(wq, sq->sqn, &sq->pc);
	mlx5e_notify_hw(wq, sq->pc, sq->uar_map, &nopwqe->ctrl);
953 954 955
}

static void mlx5e_deactivate_rq(struct mlx5e_rq *rq)
956
{
957
	clear_bit(MLX5E_RQ_STATE_ENABLED, &rq->state);
958
	napi_synchronize(&rq->channel->napi); /* prevent mlx5e_post_rx_wqes */
959
}
960

961 962
static void mlx5e_close_rq(struct mlx5e_rq *rq)
{
963
	cancel_work_sync(&rq->dim.work);
964
	mlx5e_destroy_rq(rq);
965 966
	mlx5e_free_rx_descs(rq);
	mlx5e_free_rq(rq);
967 968
}

S
Saeed Mahameed 已提交
969
static void mlx5e_free_xdpsq_db(struct mlx5e_xdpsq *sq)
970
{
971
	kvfree(sq->db.xdpi);
972 973
}

S
Saeed Mahameed 已提交
974
static int mlx5e_alloc_xdpsq_db(struct mlx5e_xdpsq *sq, int numa)
975 976 977
{
	int wq_sz = mlx5_wq_cyc_get_size(&sq->wq);

978 979 980
	sq->db.xdpi = kvzalloc_node(array_size(wq_sz, sizeof(*sq->db.xdpi)),
				    GFP_KERNEL, numa);
	if (!sq->db.xdpi) {
S
Saeed Mahameed 已提交
981
		mlx5e_free_xdpsq_db(sq);
982 983 984 985 986 987
		return -ENOMEM;
	}

	return 0;
}

S
Saeed Mahameed 已提交
988
static int mlx5e_alloc_xdpsq(struct mlx5e_channel *c,
989
			     struct mlx5e_params *params,
S
Saeed Mahameed 已提交
990
			     struct mlx5e_sq_param *param,
991 992
			     struct mlx5e_xdpsq *sq,
			     bool is_redirect)
S
Saeed Mahameed 已提交
993 994
{
	void *sqc_wq               = MLX5_ADDR_OF(sqc, param->sqc, wq);
995
	struct mlx5_core_dev *mdev = c->mdev;
996
	struct mlx5_wq_cyc *wq = &sq->wq;
S
Saeed Mahameed 已提交
997 998 999 1000 1001 1002
	int err;

	sq->pdev      = c->pdev;
	sq->mkey_be   = c->mkey_be;
	sq->channel   = c;
	sq->uar_map   = mdev->mlx5e_res.bfreg.map;
1003
	sq->min_inline_mode = params->tx_min_inline_mode;
1004
	sq->hw_mtu    = MLX5E_SW2HW_MTU(params, params->sw_mtu);
1005 1006 1007
	sq->stats     = is_redirect ?
		&c->priv->channel_stats[c->ix].xdpsq :
		&c->priv->channel_stats[c->ix].rq_xdpsq;
S
Saeed Mahameed 已提交
1008

1009
	param->wq.db_numa_node = cpu_to_node(c->cpu);
1010
	err = mlx5_wq_cyc_create(mdev, &param->wq, sqc_wq, wq, &sq->wq_ctrl);
S
Saeed Mahameed 已提交
1011 1012
	if (err)
		return err;
1013
	wq->db = &wq->db[MLX5_SND_DBR];
S
Saeed Mahameed 已提交
1014

1015
	err = mlx5e_alloc_xdpsq_db(sq, cpu_to_node(c->cpu));
S
Saeed Mahameed 已提交
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
	if (err)
		goto err_sq_wq_destroy;

	return 0;

err_sq_wq_destroy:
	mlx5_wq_destroy(&sq->wq_ctrl);

	return err;
}

static void mlx5e_free_xdpsq(struct mlx5e_xdpsq *sq)
{
	mlx5e_free_xdpsq_db(sq);
	mlx5_wq_destroy(&sq->wq_ctrl);
}

static void mlx5e_free_icosq_db(struct mlx5e_icosq *sq)
1034
{
1035
	kvfree(sq->db.ico_wqe);
1036 1037
}

S
Saeed Mahameed 已提交
1038
static int mlx5e_alloc_icosq_db(struct mlx5e_icosq *sq, int numa)
1039 1040 1041
{
	u8 wq_sz = mlx5_wq_cyc_get_size(&sq->wq);

1042 1043
	sq->db.ico_wqe = kvzalloc_node(array_size(wq_sz,
						  sizeof(*sq->db.ico_wqe)),
1044
				       GFP_KERNEL, numa);
1045 1046 1047 1048 1049 1050
	if (!sq->db.ico_wqe)
		return -ENOMEM;

	return 0;
}

S
Saeed Mahameed 已提交
1051 1052 1053
static int mlx5e_alloc_icosq(struct mlx5e_channel *c,
			     struct mlx5e_sq_param *param,
			     struct mlx5e_icosq *sq)
1054
{
S
Saeed Mahameed 已提交
1055
	void *sqc_wq               = MLX5_ADDR_OF(sqc, param->sqc, wq);
1056
	struct mlx5_core_dev *mdev = c->mdev;
1057
	struct mlx5_wq_cyc *wq = &sq->wq;
S
Saeed Mahameed 已提交
1058
	int err;
1059

S
Saeed Mahameed 已提交
1060 1061
	sq->channel   = c;
	sq->uar_map   = mdev->mlx5e_res.bfreg.map;
1062

1063
	param->wq.db_numa_node = cpu_to_node(c->cpu);
1064
	err = mlx5_wq_cyc_create(mdev, &param->wq, sqc_wq, wq, &sq->wq_ctrl);
S
Saeed Mahameed 已提交
1065 1066
	if (err)
		return err;
1067
	wq->db = &wq->db[MLX5_SND_DBR];
1068

1069
	err = mlx5e_alloc_icosq_db(sq, cpu_to_node(c->cpu));
S
Saeed Mahameed 已提交
1070 1071 1072
	if (err)
		goto err_sq_wq_destroy;

1073
	return 0;
S
Saeed Mahameed 已提交
1074 1075 1076 1077 1078

err_sq_wq_destroy:
	mlx5_wq_destroy(&sq->wq_ctrl);

	return err;
1079 1080
}

S
Saeed Mahameed 已提交
1081
static void mlx5e_free_icosq(struct mlx5e_icosq *sq)
1082
{
S
Saeed Mahameed 已提交
1083 1084
	mlx5e_free_icosq_db(sq);
	mlx5_wq_destroy(&sq->wq_ctrl);
1085 1086
}

S
Saeed Mahameed 已提交
1087
static void mlx5e_free_txqsq_db(struct mlx5e_txqsq *sq)
1088
{
1089 1090
	kvfree(sq->db.wqe_info);
	kvfree(sq->db.dma_fifo);
1091 1092
}

S
Saeed Mahameed 已提交
1093
static int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa)
1094
{
S
Saeed Mahameed 已提交
1095 1096 1097
	int wq_sz = mlx5_wq_cyc_get_size(&sq->wq);
	int df_sz = wq_sz * MLX5_SEND_WQEBB_NUM_DS;

1098 1099
	sq->db.dma_fifo = kvzalloc_node(array_size(df_sz,
						   sizeof(*sq->db.dma_fifo)),
1100
					GFP_KERNEL, numa);
1101 1102
	sq->db.wqe_info = kvzalloc_node(array_size(wq_sz,
						   sizeof(*sq->db.wqe_info)),
1103
					GFP_KERNEL, numa);
S
Saeed Mahameed 已提交
1104
	if (!sq->db.dma_fifo || !sq->db.wqe_info) {
S
Saeed Mahameed 已提交
1105 1106
		mlx5e_free_txqsq_db(sq);
		return -ENOMEM;
1107
	}
S
Saeed Mahameed 已提交
1108 1109 1110 1111

	sq->dma_fifo_mask = df_sz - 1;

	return 0;
1112 1113
}

1114
static void mlx5e_sq_recover(struct work_struct *work);
S
Saeed Mahameed 已提交
1115
static int mlx5e_alloc_txqsq(struct mlx5e_channel *c,
1116
			     int txq_ix,
1117
			     struct mlx5e_params *params,
S
Saeed Mahameed 已提交
1118
			     struct mlx5e_sq_param *param,
1119 1120
			     struct mlx5e_txqsq *sq,
			     int tc)
1121
{
S
Saeed Mahameed 已提交
1122
	void *sqc_wq               = MLX5_ADDR_OF(sqc, param->sqc, wq);
1123
	struct mlx5_core_dev *mdev = c->mdev;
1124
	struct mlx5_wq_cyc *wq = &sq->wq;
1125 1126
	int err;

1127
	sq->pdev      = c->pdev;
1128
	sq->tstamp    = c->tstamp;
1129
	sq->clock     = &mdev->clock;
1130 1131
	sq->mkey_be   = c->mkey_be;
	sq->channel   = c;
1132
	sq->txq_ix    = txq_ix;
1133
	sq->uar_map   = mdev->mlx5e_res.bfreg.map;
1134
	sq->min_inline_mode = params->tx_min_inline_mode;
1135
	sq->stats     = &c->priv->channel_stats[c->ix].sq[tc];
1136
	INIT_WORK(&sq->recover.recover_work, mlx5e_sq_recover);
1137 1138
	if (MLX5_IPSEC_DEV(c->priv->mdev))
		set_bit(MLX5E_SQ_STATE_IPSEC, &sq->state);
1139 1140
	if (mlx5_accel_is_tls_device(c->priv->mdev))
		set_bit(MLX5E_SQ_STATE_TLS, &sq->state);
1141

1142
	param->wq.db_numa_node = cpu_to_node(c->cpu);
1143
	err = mlx5_wq_cyc_create(mdev, &param->wq, sqc_wq, wq, &sq->wq_ctrl);
1144
	if (err)
1145
		return err;
1146
	wq->db    = &wq->db[MLX5_SND_DBR];
1147

1148
	err = mlx5e_alloc_txqsq_db(sq, cpu_to_node(c->cpu));
D
Dan Carpenter 已提交
1149
	if (err)
1150 1151
		goto err_sq_wq_destroy;

1152 1153 1154
	INIT_WORK(&sq->dim.work, mlx5e_tx_dim_work);
	sq->dim.mode = params->tx_cq_moderation.cq_period_mode;

1155 1156 1157 1158 1159 1160 1161 1162
	return 0;

err_sq_wq_destroy:
	mlx5_wq_destroy(&sq->wq_ctrl);

	return err;
}

S
Saeed Mahameed 已提交
1163
static void mlx5e_free_txqsq(struct mlx5e_txqsq *sq)
1164
{
S
Saeed Mahameed 已提交
1165
	mlx5e_free_txqsq_db(sq);
1166 1167 1168
	mlx5_wq_destroy(&sq->wq_ctrl);
}

1169 1170 1171 1172 1173 1174 1175 1176
struct mlx5e_create_sq_param {
	struct mlx5_wq_ctrl        *wq_ctrl;
	u32                         cqn;
	u32                         tisn;
	u8                          tis_lst_sz;
	u8                          min_inline_mode;
};

1177
static int mlx5e_create_sq(struct mlx5_core_dev *mdev,
1178 1179 1180
			   struct mlx5e_sq_param *param,
			   struct mlx5e_create_sq_param *csp,
			   u32 *sqn)
1181 1182 1183 1184 1185 1186 1187 1188
{
	void *in;
	void *sqc;
	void *wq;
	int inlen;
	int err;

	inlen = MLX5_ST_SZ_BYTES(create_sq_in) +
1189
		sizeof(u64) * csp->wq_ctrl->buf.npages;
1190
	in = kvzalloc(inlen, GFP_KERNEL);
1191 1192 1193 1194 1195 1196 1197
	if (!in)
		return -ENOMEM;

	sqc = MLX5_ADDR_OF(create_sq_in, in, ctx);
	wq = MLX5_ADDR_OF(sqc, sqc, wq);

	memcpy(sqc, param->sqc, sizeof(param->sqc));
1198 1199 1200
	MLX5_SET(sqc,  sqc, tis_lst_sz, csp->tis_lst_sz);
	MLX5_SET(sqc,  sqc, tis_num_0, csp->tisn);
	MLX5_SET(sqc,  sqc, cqn, csp->cqn);
1201 1202

	if (MLX5_CAP_ETH(mdev, wqe_inline_mode) == MLX5_CAP_INLINE_MODE_VPORT_CONTEXT)
1203
		MLX5_SET(sqc,  sqc, min_wqe_inline_mode, csp->min_inline_mode);
1204

1205
	MLX5_SET(sqc,  sqc, state, MLX5_SQC_STATE_RST);
1206
	MLX5_SET(sqc,  sqc, flush_in_error_en, 1);
1207 1208

	MLX5_SET(wq,   wq, wq_type,       MLX5_WQ_TYPE_CYCLIC);
1209
	MLX5_SET(wq,   wq, uar_page,      mdev->mlx5e_res.bfreg.index);
1210
	MLX5_SET(wq,   wq, log_wq_pg_sz,  csp->wq_ctrl->buf.page_shift -
1211
					  MLX5_ADAPTER_PAGE_SHIFT);
1212
	MLX5_SET64(wq, wq, dbr_addr,      csp->wq_ctrl->db.dma);
1213

1214 1215
	mlx5_fill_page_frag_array(&csp->wq_ctrl->buf,
				  (__be64 *)MLX5_ADDR_OF(wq, wq, pas));
1216

1217
	err = mlx5_core_create_sq(mdev, in, inlen, sqn);
1218 1219 1220 1221 1222 1223

	kvfree(in);

	return err;
}

1224 1225 1226 1227 1228 1229 1230
struct mlx5e_modify_sq_param {
	int curr_state;
	int next_state;
	bool rl_update;
	int rl_index;
};

1231
static int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn,
1232
			   struct mlx5e_modify_sq_param *p)
1233 1234 1235 1236 1237 1238 1239
{
	void *in;
	void *sqc;
	int inlen;
	int err;

	inlen = MLX5_ST_SZ_BYTES(modify_sq_in);
1240
	in = kvzalloc(inlen, GFP_KERNEL);
1241 1242 1243 1244 1245
	if (!in)
		return -ENOMEM;

	sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx);

1246 1247 1248
	MLX5_SET(modify_sq_in, in, sq_state, p->curr_state);
	MLX5_SET(sqc, sqc, state, p->next_state);
	if (p->rl_update && p->next_state == MLX5_SQC_STATE_RDY) {
1249
		MLX5_SET64(modify_sq_in, in, modify_bitmask, 1);
1250
		MLX5_SET(sqc,  sqc, packet_pacing_rate_limit_index, p->rl_index);
1251
	}
1252

1253
	err = mlx5_core_modify_sq(mdev, sqn, in, inlen);
1254 1255 1256 1257 1258 1259

	kvfree(in);

	return err;
}

1260
static void mlx5e_destroy_sq(struct mlx5_core_dev *mdev, u32 sqn)
1261
{
1262
	mlx5_core_destroy_sq(mdev, sqn);
1263 1264
}

1265
static int mlx5e_create_sq_rdy(struct mlx5_core_dev *mdev,
S
Saeed Mahameed 已提交
1266 1267 1268
			       struct mlx5e_sq_param *param,
			       struct mlx5e_create_sq_param *csp,
			       u32 *sqn)
1269
{
1270
	struct mlx5e_modify_sq_param msp = {0};
S
Saeed Mahameed 已提交
1271 1272
	int err;

1273
	err = mlx5e_create_sq(mdev, param, csp, sqn);
S
Saeed Mahameed 已提交
1274 1275 1276 1277 1278
	if (err)
		return err;

	msp.curr_state = MLX5_SQC_STATE_RST;
	msp.next_state = MLX5_SQC_STATE_RDY;
1279
	err = mlx5e_modify_sq(mdev, *sqn, &msp);
S
Saeed Mahameed 已提交
1280
	if (err)
1281
		mlx5e_destroy_sq(mdev, *sqn);
S
Saeed Mahameed 已提交
1282 1283 1284 1285

	return err;
}

1286 1287 1288
static int mlx5e_set_sq_maxrate(struct net_device *dev,
				struct mlx5e_txqsq *sq, u32 rate);

S
Saeed Mahameed 已提交
1289
static int mlx5e_open_txqsq(struct mlx5e_channel *c,
1290
			    u32 tisn,
1291
			    int txq_ix,
1292
			    struct mlx5e_params *params,
S
Saeed Mahameed 已提交
1293
			    struct mlx5e_sq_param *param,
1294 1295
			    struct mlx5e_txqsq *sq,
			    int tc)
S
Saeed Mahameed 已提交
1296 1297
{
	struct mlx5e_create_sq_param csp = {};
1298
	u32 tx_rate;
1299 1300
	int err;

1301
	err = mlx5e_alloc_txqsq(c, txq_ix, params, param, sq, tc);
1302 1303 1304
	if (err)
		return err;

1305
	csp.tisn            = tisn;
S
Saeed Mahameed 已提交
1306
	csp.tis_lst_sz      = 1;
1307 1308 1309
	csp.cqn             = sq->cq.mcq.cqn;
	csp.wq_ctrl         = &sq->wq_ctrl;
	csp.min_inline_mode = sq->min_inline_mode;
1310
	err = mlx5e_create_sq_rdy(c->mdev, param, &csp, &sq->sqn);
1311
	if (err)
S
Saeed Mahameed 已提交
1312
		goto err_free_txqsq;
1313

1314
	tx_rate = c->priv->tx_rates[sq->txq_ix];
1315
	if (tx_rate)
1316
		mlx5e_set_sq_maxrate(c->netdev, sq, tx_rate);
1317

1318 1319 1320
	if (params->tx_dim_enabled)
		sq->state |= BIT(MLX5E_SQ_STATE_AM);

1321 1322
	return 0;

S
Saeed Mahameed 已提交
1323
err_free_txqsq:
1324
	clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
S
Saeed Mahameed 已提交
1325
	mlx5e_free_txqsq(sq);
1326 1327 1328 1329

	return err;
}

1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
static void mlx5e_reset_txqsq_cc_pc(struct mlx5e_txqsq *sq)
{
	WARN_ONCE(sq->cc != sq->pc,
		  "SQ 0x%x: cc (0x%x) != pc (0x%x)\n",
		  sq->sqn, sq->cc, sq->pc);
	sq->cc = 0;
	sq->dma_fifo_cc = 0;
	sq->pc = 0;
}

1340 1341
static void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq)
{
1342
	sq->txq = netdev_get_tx_queue(sq->channel->netdev, sq->txq_ix);
1343
	clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
1344 1345 1346 1347 1348
	set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
	netdev_tx_reset_queue(sq->txq);
	netif_tx_start_queue(sq->txq);
}

1349 1350 1351 1352 1353 1354 1355
static inline void netif_tx_disable_queue(struct netdev_queue *txq)
{
	__netif_tx_lock_bh(txq);
	netif_tx_stop_queue(txq);
	__netif_tx_unlock_bh(txq);
}

1356
static void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq)
1357
{
1358
	struct mlx5e_channel *c = sq->channel;
1359
	struct mlx5_wq_cyc *wq = &sq->wq;
1360

1361
	clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
1362
	/* prevent netif_tx_wake_queue */
1363
	napi_synchronize(&c->napi);
1364

S
Saeed Mahameed 已提交
1365
	netif_tx_disable_queue(sq->txq);
1366

S
Saeed Mahameed 已提交
1367
	/* last doorbell out, godspeed .. */
1368 1369
	if (mlx5e_wqc_has_room_for(wq, sq->cc, sq->pc, 1)) {
		u16 pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc);
S
Saeed Mahameed 已提交
1370
		struct mlx5e_tx_wqe *nop;
1371

1372 1373 1374
		sq->db.wqe_info[pi].skb = NULL;
		nop = mlx5e_post_nop(wq, sq->sqn, &sq->pc);
		mlx5e_notify_hw(wq, sq->pc, sq->uar_map, &nop->ctrl);
1375
	}
1376 1377 1378 1379 1380
}

static void mlx5e_close_txqsq(struct mlx5e_txqsq *sq)
{
	struct mlx5e_channel *c = sq->channel;
1381
	struct mlx5_core_dev *mdev = c->mdev;
1382
	struct mlx5_rate_limit rl = {0};
1383

1384
	mlx5e_destroy_sq(mdev, sq->sqn);
1385 1386 1387 1388
	if (sq->rate_limit) {
		rl.rate = sq->rate_limit;
		mlx5_rl_remove_rate(mdev, &rl);
	}
S
Saeed Mahameed 已提交
1389 1390 1391 1392
	mlx5e_free_txqsq_descs(sq);
	mlx5e_free_txqsq(sq);
}

1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq)
{
	unsigned long exp_time = jiffies + msecs_to_jiffies(2000);

	while (time_before(jiffies, exp_time)) {
		if (sq->cc == sq->pc)
			return 0;

		msleep(20);
	}

	netdev_err(sq->channel->netdev,
		   "Wait for SQ 0x%x flush timeout (sq cc = 0x%x, sq pc = 0x%x)\n",
		   sq->sqn, sq->cc, sq->pc);

	return -ETIMEDOUT;
}

static int mlx5e_sq_to_ready(struct mlx5e_txqsq *sq, int curr_state)
{
	struct mlx5_core_dev *mdev = sq->channel->mdev;
	struct net_device *dev = sq->channel->netdev;
	struct mlx5e_modify_sq_param msp = {0};
	int err;

	msp.curr_state = curr_state;
	msp.next_state = MLX5_SQC_STATE_RST;

	err = mlx5e_modify_sq(mdev, sq->sqn, &msp);
	if (err) {
		netdev_err(dev, "Failed to move sq 0x%x to reset\n", sq->sqn);
		return err;
	}

	memset(&msp, 0, sizeof(msp));
	msp.curr_state = MLX5_SQC_STATE_RST;
	msp.next_state = MLX5_SQC_STATE_RDY;

	err = mlx5e_modify_sq(mdev, sq->sqn, &msp);
	if (err) {
		netdev_err(dev, "Failed to move sq 0x%x to ready\n", sq->sqn);
		return err;
	}

	return 0;
}

static void mlx5e_sq_recover(struct work_struct *work)
{
	struct mlx5e_txqsq_recover *recover =
		container_of(work, struct mlx5e_txqsq_recover,
			     recover_work);
	struct mlx5e_txqsq *sq = container_of(recover, struct mlx5e_txqsq,
					      recover);
	struct mlx5_core_dev *mdev = sq->channel->mdev;
	struct net_device *dev = sq->channel->netdev;
	u8 state;
	int err;

	err = mlx5_core_query_sq_state(mdev, sq->sqn, &state);
	if (err) {
		netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n",
			   sq->sqn, err);
		return;
	}

	if (state != MLX5_RQC_STATE_ERR) {
		netdev_err(dev, "SQ 0x%x not in ERROR state\n", sq->sqn);
		return;
	}

	netif_tx_disable_queue(sq->txq);

	if (mlx5e_wait_for_sq_flush(sq))
		return;

	/* If the interval between two consecutive recovers per SQ is too
	 * short, don't recover to avoid infinite loop of ERR_CQE -> recover.
	 * If we reached this state, there is probably a bug that needs to be
	 * fixed. let's keep the queue close and let tx timeout cleanup.
	 */
	if (jiffies_to_msecs(jiffies - recover->last_recover) <
	    MLX5E_SQ_RECOVER_MIN_INTERVAL) {
		netdev_err(dev, "Recover SQ 0x%x canceled, too many error CQEs\n",
			   sq->sqn);
		return;
	}

	/* At this point, no new packets will arrive from the stack as TXQ is
	 * marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all
	 * pending WQEs.  SQ can safely reset the SQ.
	 */
	if (mlx5e_sq_to_ready(sq, state))
		return;

	mlx5e_reset_txqsq_cc_pc(sq);
1489
	sq->stats->recover++;
1490 1491 1492 1493
	recover->last_recover = jiffies;
	mlx5e_activate_txqsq(sq);
}

S
Saeed Mahameed 已提交
1494
static int mlx5e_open_icosq(struct mlx5e_channel *c,
1495
			    struct mlx5e_params *params,
S
Saeed Mahameed 已提交
1496 1497 1498 1499 1500 1501
			    struct mlx5e_sq_param *param,
			    struct mlx5e_icosq *sq)
{
	struct mlx5e_create_sq_param csp = {};
	int err;

1502
	err = mlx5e_alloc_icosq(c, param, sq);
S
Saeed Mahameed 已提交
1503 1504 1505 1506 1507
	if (err)
		return err;

	csp.cqn             = sq->cq.mcq.cqn;
	csp.wq_ctrl         = &sq->wq_ctrl;
1508
	csp.min_inline_mode = params->tx_min_inline_mode;
S
Saeed Mahameed 已提交
1509
	set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
1510
	err = mlx5e_create_sq_rdy(c->mdev, param, &csp, &sq->sqn);
S
Saeed Mahameed 已提交
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529
	if (err)
		goto err_free_icosq;

	return 0;

err_free_icosq:
	clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
	mlx5e_free_icosq(sq);

	return err;
}

static void mlx5e_close_icosq(struct mlx5e_icosq *sq)
{
	struct mlx5e_channel *c = sq->channel;

	clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
	napi_synchronize(&c->napi);

1530
	mlx5e_destroy_sq(c->mdev, sq->sqn);
S
Saeed Mahameed 已提交
1531 1532 1533 1534
	mlx5e_free_icosq(sq);
}

static int mlx5e_open_xdpsq(struct mlx5e_channel *c,
1535
			    struct mlx5e_params *params,
S
Saeed Mahameed 已提交
1536
			    struct mlx5e_sq_param *param,
1537 1538
			    struct mlx5e_xdpsq *sq,
			    bool is_redirect)
S
Saeed Mahameed 已提交
1539 1540 1541 1542 1543 1544 1545
{
	unsigned int ds_cnt = MLX5E_XDP_TX_DS_COUNT;
	struct mlx5e_create_sq_param csp = {};
	unsigned int inline_hdr_sz = 0;
	int err;
	int i;

1546
	err = mlx5e_alloc_xdpsq(c, params, param, sq, is_redirect);
S
Saeed Mahameed 已提交
1547 1548 1549 1550
	if (err)
		return err;

	csp.tis_lst_sz      = 1;
1551
	csp.tisn            = c->priv->tisn[0]; /* tc = 0 */
S
Saeed Mahameed 已提交
1552 1553 1554
	csp.cqn             = sq->cq.mcq.cqn;
	csp.wq_ctrl         = &sq->wq_ctrl;
	csp.min_inline_mode = sq->min_inline_mode;
1555 1556
	if (is_redirect)
		set_bit(MLX5E_SQ_STATE_REDIRECT, &sq->state);
S
Saeed Mahameed 已提交
1557
	set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
1558
	err = mlx5e_create_sq_rdy(c->mdev, param, &csp, &sq->sqn);
S
Saeed Mahameed 已提交
1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596
	if (err)
		goto err_free_xdpsq;

	if (sq->min_inline_mode != MLX5_INLINE_MODE_NONE) {
		inline_hdr_sz = MLX5E_XDP_MIN_INLINE;
		ds_cnt++;
	}

	/* Pre initialize fixed WQE fields */
	for (i = 0; i < mlx5_wq_cyc_get_size(&sq->wq); i++) {
		struct mlx5e_tx_wqe      *wqe  = mlx5_wq_cyc_get_wqe(&sq->wq, i);
		struct mlx5_wqe_ctrl_seg *cseg = &wqe->ctrl;
		struct mlx5_wqe_eth_seg  *eseg = &wqe->eth;
		struct mlx5_wqe_data_seg *dseg;

		cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt);
		eseg->inline_hdr.sz = cpu_to_be16(inline_hdr_sz);

		dseg = (struct mlx5_wqe_data_seg *)cseg + (ds_cnt - 1);
		dseg->lkey = sq->mkey_be;
	}

	return 0;

err_free_xdpsq:
	clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
	mlx5e_free_xdpsq(sq);

	return err;
}

static void mlx5e_close_xdpsq(struct mlx5e_xdpsq *sq)
{
	struct mlx5e_channel *c = sq->channel;

	clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
	napi_synchronize(&c->napi);

1597
	mlx5e_destroy_sq(c->mdev, sq->sqn);
S
Saeed Mahameed 已提交
1598 1599
	mlx5e_free_xdpsq_descs(sq);
	mlx5e_free_xdpsq(sq);
1600 1601
}

1602 1603 1604
static int mlx5e_alloc_cq_common(struct mlx5_core_dev *mdev,
				 struct mlx5e_cq_param *param,
				 struct mlx5e_cq *cq)
1605 1606 1607
{
	struct mlx5_core_cq *mcq = &cq->mcq;
	int eqn_not_used;
1608
	unsigned int irqn;
1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
	int err;
	u32 i;

	err = mlx5_cqwq_create(mdev, &param->wq, param->cqc, &cq->wq,
			       &cq->wq_ctrl);
	if (err)
		return err;

	mlx5_vector2eqn(mdev, param->eq_ix, &eqn_not_used, &irqn);

	mcq->cqe_sz     = 64;
	mcq->set_ci_db  = cq->wq_ctrl.db.db;
	mcq->arm_db     = cq->wq_ctrl.db.db + 1;
	*mcq->set_ci_db = 0;
	*mcq->arm_db    = 0;
	mcq->vector     = param->eq_ix;
	mcq->comp       = mlx5e_completion_event;
	mcq->event      = mlx5e_cq_error_event;
	mcq->irqn       = irqn;

	for (i = 0; i < mlx5_cqwq_get_size(&cq->wq); i++) {
		struct mlx5_cqe64 *cqe = mlx5_cqwq_get_wqe(&cq->wq, i);

		cqe->op_own = 0xf1;
	}

1635
	cq->mdev = mdev;
1636 1637 1638 1639

	return 0;
}

1640 1641 1642 1643 1644 1645 1646
static int mlx5e_alloc_cq(struct mlx5e_channel *c,
			  struct mlx5e_cq_param *param,
			  struct mlx5e_cq *cq)
{
	struct mlx5_core_dev *mdev = c->priv->mdev;
	int err;

1647 1648
	param->wq.buf_numa_node = cpu_to_node(c->cpu);
	param->wq.db_numa_node  = cpu_to_node(c->cpu);
1649 1650 1651 1652 1653 1654 1655 1656 1657 1658
	param->eq_ix   = c->ix;

	err = mlx5e_alloc_cq_common(mdev, param, cq);

	cq->napi    = &c->napi;
	cq->channel = c;

	return err;
}

1659
static void mlx5e_free_cq(struct mlx5e_cq *cq)
1660
{
1661
	mlx5_wq_destroy(&cq->wq_ctrl);
1662 1663
}

1664
static int mlx5e_create_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
1665
{
1666
	struct mlx5_core_dev *mdev = cq->mdev;
1667 1668 1669 1670 1671
	struct mlx5_core_cq *mcq = &cq->mcq;

	void *in;
	void *cqc;
	int inlen;
1672
	unsigned int irqn_not_used;
1673 1674 1675 1676
	int eqn;
	int err;

	inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
1677
		sizeof(u64) * cq->wq_ctrl.buf.npages;
1678
	in = kvzalloc(inlen, GFP_KERNEL);
1679 1680 1681 1682 1683 1684 1685
	if (!in)
		return -ENOMEM;

	cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context);

	memcpy(cqc, param->cqc, sizeof(param->cqc));

1686
	mlx5_fill_page_frag_array(&cq->wq_ctrl.buf,
1687
				  (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas));
1688 1689 1690

	mlx5_vector2eqn(mdev, param->eq_ix, &eqn, &irqn_not_used);

T
Tariq Toukan 已提交
1691
	MLX5_SET(cqc,   cqc, cq_period_mode, param->cq_period_mode);
1692
	MLX5_SET(cqc,   cqc, c_eqn,         eqn);
E
Eli Cohen 已提交
1693
	MLX5_SET(cqc,   cqc, uar_page,      mdev->priv.uar->index);
1694
	MLX5_SET(cqc,   cqc, log_page_size, cq->wq_ctrl.buf.page_shift -
1695
					    MLX5_ADAPTER_PAGE_SHIFT);
1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709
	MLX5_SET64(cqc, cqc, dbr_addr,      cq->wq_ctrl.db.dma);

	err = mlx5_core_create_cq(mdev, mcq, in, inlen);

	kvfree(in);

	if (err)
		return err;

	mlx5e_cq_arm(cq);

	return 0;
}

1710
static void mlx5e_destroy_cq(struct mlx5e_cq *cq)
1711
{
1712
	mlx5_core_destroy_cq(cq->mdev, &cq->mcq);
1713 1714 1715
}

static int mlx5e_open_cq(struct mlx5e_channel *c,
1716
			 struct net_dim_cq_moder moder,
1717
			 struct mlx5e_cq_param *param,
1718
			 struct mlx5e_cq *cq)
1719
{
1720
	struct mlx5_core_dev *mdev = c->mdev;
1721 1722
	int err;

1723
	err = mlx5e_alloc_cq(c, param, cq);
1724 1725 1726
	if (err)
		return err;

1727
	err = mlx5e_create_cq(cq, param);
1728
	if (err)
1729
		goto err_free_cq;
1730

1731
	if (MLX5_CAP_GEN(mdev, cq_moderation))
1732
		mlx5_core_modify_cq_moderation(mdev, &cq->mcq, moder.usec, moder.pkts);
1733 1734
	return 0;

1735 1736
err_free_cq:
	mlx5e_free_cq(cq);
1737 1738 1739 1740 1741 1742 1743

	return err;
}

static void mlx5e_close_cq(struct mlx5e_cq *cq)
{
	mlx5e_destroy_cq(cq);
1744
	mlx5e_free_cq(cq);
1745 1746
}

1747 1748 1749 1750 1751
static int mlx5e_get_cpu(struct mlx5e_priv *priv, int ix)
{
	return cpumask_first(priv->mdev->priv.irq_info[ix].mask);
}

1752
static int mlx5e_open_tx_cqs(struct mlx5e_channel *c,
1753
			     struct mlx5e_params *params,
1754 1755 1756 1757 1758 1759
			     struct mlx5e_channel_param *cparam)
{
	int err;
	int tc;

	for (tc = 0; tc < c->num_tc; tc++) {
1760 1761
		err = mlx5e_open_cq(c, params->tx_cq_moderation,
				    &cparam->tx_cq, &c->sq[tc].cq);
1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783
		if (err)
			goto err_close_tx_cqs;
	}

	return 0;

err_close_tx_cqs:
	for (tc--; tc >= 0; tc--)
		mlx5e_close_cq(&c->sq[tc].cq);

	return err;
}

static void mlx5e_close_tx_cqs(struct mlx5e_channel *c)
{
	int tc;

	for (tc = 0; tc < c->num_tc; tc++)
		mlx5e_close_cq(&c->sq[tc].cq);
}

static int mlx5e_open_sqs(struct mlx5e_channel *c,
1784
			  struct mlx5e_params *params,
1785 1786
			  struct mlx5e_channel_param *cparam)
{
1787 1788
	struct mlx5e_priv *priv = c->priv;
	int err, tc, max_nch = priv->profile->max_nch(priv->mdev);
1789

1790
	for (tc = 0; tc < params->num_tc; tc++) {
1791
		int txq_ix = c->ix + tc * max_nch;
1792

1793
		err = mlx5e_open_txqsq(c, c->priv->tisn[tc], txq_ix,
1794
				       params, &cparam->sq, &c->sq[tc], tc);
1795 1796 1797 1798 1799 1800 1801 1802
		if (err)
			goto err_close_sqs;
	}

	return 0;

err_close_sqs:
	for (tc--; tc >= 0; tc--)
S
Saeed Mahameed 已提交
1803
		mlx5e_close_txqsq(&c->sq[tc]);
1804 1805 1806 1807 1808 1809 1810 1811 1812

	return err;
}

static void mlx5e_close_sqs(struct mlx5e_channel *c)
{
	int tc;

	for (tc = 0; tc < c->num_tc; tc++)
S
Saeed Mahameed 已提交
1813
		mlx5e_close_txqsq(&c->sq[tc]);
1814 1815
}

1816
static int mlx5e_set_sq_maxrate(struct net_device *dev,
S
Saeed Mahameed 已提交
1817
				struct mlx5e_txqsq *sq, u32 rate)
1818 1819 1820
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev = priv->mdev;
1821
	struct mlx5e_modify_sq_param msp = {0};
1822
	struct mlx5_rate_limit rl = {0};
1823 1824 1825 1826 1827 1828 1829
	u16 rl_index = 0;
	int err;

	if (rate == sq->rate_limit)
		/* nothing to do */
		return 0;

1830 1831
	if (sq->rate_limit) {
		rl.rate = sq->rate_limit;
1832
		/* remove current rl index to free space to next ones */
1833 1834
		mlx5_rl_remove_rate(mdev, &rl);
	}
1835 1836 1837 1838

	sq->rate_limit = 0;

	if (rate) {
1839 1840
		rl.rate = rate;
		err = mlx5_rl_add_rate(mdev, &rl_index, &rl);
1841 1842 1843 1844 1845 1846 1847
		if (err) {
			netdev_err(dev, "Failed configuring rate %u: %d\n",
				   rate, err);
			return err;
		}
	}

1848 1849 1850 1851
	msp.curr_state = MLX5_SQC_STATE_RDY;
	msp.next_state = MLX5_SQC_STATE_RDY;
	msp.rl_index   = rl_index;
	msp.rl_update  = true;
1852
	err = mlx5e_modify_sq(mdev, sq->sqn, &msp);
1853 1854 1855 1856 1857
	if (err) {
		netdev_err(dev, "Failed configuring rate %u: %d\n",
			   rate, err);
		/* remove the rate from the table */
		if (rate)
1858
			mlx5_rl_remove_rate(mdev, &rl);
1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869
		return err;
	}

	sq->rate_limit = rate;
	return 0;
}

static int mlx5e_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev = priv->mdev;
1870
	struct mlx5e_txqsq *sq = priv->txq2sq[index];
1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896
	int err = 0;

	if (!mlx5_rl_is_supported(mdev)) {
		netdev_err(dev, "Rate limiting is not supported on this device\n");
		return -EINVAL;
	}

	/* rate is given in Mb/sec, HW config is in Kb/sec */
	rate = rate << 10;

	/* Check whether rate in valid range, 0 is always valid */
	if (rate && !mlx5_rl_is_in_range(mdev, rate)) {
		netdev_err(dev, "TX rate %u, is not in range\n", rate);
		return -ERANGE;
	}

	mutex_lock(&priv->state_lock);
	if (test_bit(MLX5E_STATE_OPENED, &priv->state))
		err = mlx5e_set_sq_maxrate(dev, sq, rate);
	if (!err)
		priv->tx_rates[index] = rate;
	mutex_unlock(&priv->state_lock);

	return err;
}

1897
static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
1898
			      struct mlx5e_params *params,
1899 1900 1901
			      struct mlx5e_channel_param *cparam,
			      struct mlx5e_channel **cp)
{
1902
	struct net_dim_cq_moder icocq_moder = {0, 0};
1903
	struct net_device *netdev = priv->netdev;
1904
	int cpu = mlx5e_get_cpu(priv, ix);
1905
	struct mlx5e_channel *c;
1906
	unsigned int irq;
1907
	int err;
1908
	int eqn;
1909

1910
	c = kvzalloc_node(sizeof(*c), GFP_KERNEL, cpu_to_node(cpu));
1911 1912 1913 1914
	if (!c)
		return -ENOMEM;

	c->priv     = priv;
1915 1916
	c->mdev     = priv->mdev;
	c->tstamp   = &priv->tstamp;
1917
	c->ix       = ix;
1918
	c->cpu      = cpu;
1919 1920
	c->pdev     = &priv->mdev->pdev->dev;
	c->netdev   = priv->netdev;
1921
	c->mkey_be  = cpu_to_be32(priv->mdev->mlx5e_res.mkey.key);
1922 1923
	c->num_tc   = params->num_tc;
	c->xdp      = !!params->xdp_prog;
1924
	c->stats    = &priv->channel_stats[ix].ch;
1925

1926 1927 1928
	mlx5_vector2eqn(priv->mdev, ix, &eqn, &irq);
	c->irq_desc = irq_to_desc(irq);

1929 1930
	netif_napi_add(netdev, &c->napi, mlx5e_napi_poll, 64);

1931
	err = mlx5e_open_cq(c, icocq_moder, &cparam->icosq_cq, &c->icosq.cq);
1932 1933 1934
	if (err)
		goto err_napi_del;

1935
	err = mlx5e_open_tx_cqs(c, params, cparam);
T
Tariq Toukan 已提交
1936 1937 1938
	if (err)
		goto err_close_icosq_cq;

1939
	err = mlx5e_open_cq(c, params->tx_cq_moderation, &cparam->tx_cq, &c->xdpsq.cq);
1940 1941 1942
	if (err)
		goto err_close_tx_cqs;

1943 1944 1945 1946
	err = mlx5e_open_cq(c, params->rx_cq_moderation, &cparam->rx_cq, &c->rq.cq);
	if (err)
		goto err_close_xdp_tx_cqs;

1947
	/* XDP SQ CQ params are same as normal TXQ sq CQ params */
1948 1949
	err = c->xdp ? mlx5e_open_cq(c, params->tx_cq_moderation,
				     &cparam->tx_cq, &c->rq.xdpsq.cq) : 0;
1950 1951 1952
	if (err)
		goto err_close_rx_cq;

1953 1954
	napi_enable(&c->napi);

1955
	err = mlx5e_open_icosq(c, params, &cparam->icosq, &c->icosq);
1956 1957 1958
	if (err)
		goto err_disable_napi;

1959
	err = mlx5e_open_sqs(c, params, cparam);
T
Tariq Toukan 已提交
1960 1961 1962
	if (err)
		goto err_close_icosq;

1963
	err = c->xdp ? mlx5e_open_xdpsq(c, params, &cparam->xdp_sq, &c->rq.xdpsq, false) : 0;
1964 1965
	if (err)
		goto err_close_sqs;
1966

1967
	err = mlx5e_open_rq(c, params, &cparam->rq, &c->rq);
1968
	if (err)
1969
		goto err_close_xdp_sq;
1970

1971 1972 1973 1974
	err = mlx5e_open_xdpsq(c, params, &cparam->xdp_sq, &c->xdpsq, true);
	if (err)
		goto err_close_rq;

1975 1976 1977
	*cp = c;

	return 0;
1978 1979 1980 1981

err_close_rq:
	mlx5e_close_rq(&c->rq);

1982
err_close_xdp_sq:
1983
	if (c->xdp)
S
Saeed Mahameed 已提交
1984
		mlx5e_close_xdpsq(&c->rq.xdpsq);
1985 1986 1987 1988

err_close_sqs:
	mlx5e_close_sqs(c);

T
Tariq Toukan 已提交
1989
err_close_icosq:
S
Saeed Mahameed 已提交
1990
	mlx5e_close_icosq(&c->icosq);
T
Tariq Toukan 已提交
1991

1992 1993
err_disable_napi:
	napi_disable(&c->napi);
1994
	if (c->xdp)
1995
		mlx5e_close_cq(&c->rq.xdpsq.cq);
1996 1997

err_close_rx_cq:
1998 1999
	mlx5e_close_cq(&c->rq.cq);

2000 2001 2002
err_close_xdp_tx_cqs:
	mlx5e_close_cq(&c->xdpsq.cq);

2003 2004 2005
err_close_tx_cqs:
	mlx5e_close_tx_cqs(c);

T
Tariq Toukan 已提交
2006 2007 2008
err_close_icosq_cq:
	mlx5e_close_cq(&c->icosq.cq);

2009 2010
err_napi_del:
	netif_napi_del(&c->napi);
2011
	kvfree(c);
2012 2013 2014 2015

	return err;
}

2016 2017 2018 2019 2020 2021 2022
static void mlx5e_activate_channel(struct mlx5e_channel *c)
{
	int tc;

	for (tc = 0; tc < c->num_tc; tc++)
		mlx5e_activate_txqsq(&c->sq[tc]);
	mlx5e_activate_rq(&c->rq);
2023
	netif_set_xps_queue(c->netdev, get_cpu_mask(c->cpu), c->ix);
2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034
}

static void mlx5e_deactivate_channel(struct mlx5e_channel *c)
{
	int tc;

	mlx5e_deactivate_rq(&c->rq);
	for (tc = 0; tc < c->num_tc; tc++)
		mlx5e_deactivate_txqsq(&c->sq[tc]);
}

2035 2036
static void mlx5e_close_channel(struct mlx5e_channel *c)
{
2037
	mlx5e_close_xdpsq(&c->xdpsq);
2038
	mlx5e_close_rq(&c->rq);
2039
	if (c->xdp)
S
Saeed Mahameed 已提交
2040
		mlx5e_close_xdpsq(&c->rq.xdpsq);
2041
	mlx5e_close_sqs(c);
S
Saeed Mahameed 已提交
2042
	mlx5e_close_icosq(&c->icosq);
2043
	napi_disable(&c->napi);
2044
	if (c->xdp)
2045
		mlx5e_close_cq(&c->rq.xdpsq.cq);
2046
	mlx5e_close_cq(&c->rq.cq);
2047
	mlx5e_close_cq(&c->xdpsq.cq);
2048
	mlx5e_close_tx_cqs(c);
T
Tariq Toukan 已提交
2049
	mlx5e_close_cq(&c->icosq.cq);
2050
	netif_napi_del(&c->napi);
E
Eric Dumazet 已提交
2051

2052
	kvfree(c);
2053 2054
}

2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109
#define DEFAULT_FRAG_SIZE (2048)

static void mlx5e_build_rq_frags_info(struct mlx5_core_dev *mdev,
				      struct mlx5e_params *params,
				      struct mlx5e_rq_frags_info *info)
{
	u32 byte_count = MLX5E_SW2HW_MTU(params, params->sw_mtu);
	int frag_size_max = DEFAULT_FRAG_SIZE;
	u32 buf_size = 0;
	int i;

#ifdef CONFIG_MLX5_EN_IPSEC
	if (MLX5_IPSEC_DEV(mdev))
		byte_count += MLX5E_METADATA_ETHER_LEN;
#endif

	if (mlx5e_rx_is_linear_skb(mdev, params)) {
		int frag_stride;

		frag_stride = mlx5e_rx_get_linear_frag_sz(params);
		frag_stride = roundup_pow_of_two(frag_stride);

		info->arr[0].frag_size = byte_count;
		info->arr[0].frag_stride = frag_stride;
		info->num_frags = 1;
		info->wqe_bulk = PAGE_SIZE / frag_stride;
		goto out;
	}

	if (byte_count > PAGE_SIZE +
	    (MLX5E_MAX_RX_FRAGS - 1) * frag_size_max)
		frag_size_max = PAGE_SIZE;

	i = 0;
	while (buf_size < byte_count) {
		int frag_size = byte_count - buf_size;

		if (i < MLX5E_MAX_RX_FRAGS - 1)
			frag_size = min(frag_size, frag_size_max);

		info->arr[i].frag_size = frag_size;
		info->arr[i].frag_stride = roundup_pow_of_two(frag_size);

		buf_size += frag_size;
		i++;
	}
	info->num_frags = i;
	/* number of different wqes sharing a page */
	info->wqe_bulk = 1 + (info->num_frags % 2);

out:
	info->wqe_bulk = max_t(u8, info->wqe_bulk, 8);
	info->log_num_frags = order_base_2(info->num_frags);
}

2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124
static inline u8 mlx5e_get_rqwq_log_stride(u8 wq_type, int ndsegs)
{
	int sz = sizeof(struct mlx5_wqe_data_seg) * ndsegs;

	switch (wq_type) {
	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
		sz += sizeof(struct mlx5e_rx_wqe_ll);
		break;
	default: /* MLX5_WQ_TYPE_CYCLIC */
		sz += sizeof(struct mlx5e_rx_wqe_cyc);
	}

	return order_base_2(sz);
}

2125
static void mlx5e_build_rq_param(struct mlx5e_priv *priv,
2126
				 struct mlx5e_params *params,
2127 2128
				 struct mlx5e_rq_param *param)
{
2129
	struct mlx5_core_dev *mdev = priv->mdev;
2130 2131
	void *rqc = param->rqc;
	void *wq = MLX5_ADDR_OF(rqc, rqc, wq);
2132
	int ndsegs = 1;
2133

2134
	switch (params->rq_wq_type) {
2135
	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
2136
		MLX5_SET(wq, wq, log_wqe_num_of_strides,
2137 2138
			 mlx5e_mpwqe_get_log_num_strides(mdev, params) -
			 MLX5_MPWQE_LOG_NUM_STRIDES_BASE);
2139
		MLX5_SET(wq, wq, log_wqe_stride_size,
2140 2141
			 mlx5e_mpwqe_get_log_stride_size(mdev, params) -
			 MLX5_MPWQE_LOG_STRIDE_SZ_BASE);
2142
		MLX5_SET(wq, wq, log_wq_sz, mlx5e_mpwqe_get_log_rq_size(params));
2143
		break;
2144
	default: /* MLX5_WQ_TYPE_CYCLIC */
2145
		MLX5_SET(wq, wq, log_wq_sz, params->log_rq_mtu_frames);
2146 2147
		mlx5e_build_rq_frags_info(mdev, params, &param->frags_info);
		ndsegs = param->frags_info.num_frags;
2148 2149
	}

2150
	MLX5_SET(wq, wq, wq_type,          params->rq_wq_type);
2151
	MLX5_SET(wq, wq, end_padding_mode, MLX5_WQ_END_PAD_MODE_ALIGN);
2152 2153
	MLX5_SET(wq, wq, log_wq_stride,
		 mlx5e_get_rqwq_log_stride(params->rq_wq_type, ndsegs));
2154
	MLX5_SET(wq, wq, pd,               mdev->mlx5e_res.pdn);
2155
	MLX5_SET(rqc, rqc, counter_set_id, priv->q_counter);
2156
	MLX5_SET(rqc, rqc, vsd,            params->vlan_strip_disable);
2157
	MLX5_SET(rqc, rqc, scatter_fcs,    params->scatter_fcs_en);
2158

2159
	param->wq.buf_numa_node = dev_to_node(&mdev->pdev->dev);
2160 2161
}

2162
static void mlx5e_build_drop_rq_param(struct mlx5e_priv *priv,
2163
				      struct mlx5e_rq_param *param)
2164
{
2165
	struct mlx5_core_dev *mdev = priv->mdev;
2166 2167 2168
	void *rqc = param->rqc;
	void *wq = MLX5_ADDR_OF(rqc, rqc, wq);

2169 2170 2171
	MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC);
	MLX5_SET(wq, wq, log_wq_stride,
		 mlx5e_get_rqwq_log_stride(MLX5_WQ_TYPE_CYCLIC, 1));
2172
	MLX5_SET(rqc, rqc, counter_set_id, priv->drop_rq_q_counter);
2173 2174

	param->wq.buf_numa_node = dev_to_node(&mdev->pdev->dev);
2175 2176
}

T
Tariq Toukan 已提交
2177 2178
static void mlx5e_build_sq_param_common(struct mlx5e_priv *priv,
					struct mlx5e_sq_param *param)
2179 2180 2181 2182 2183
{
	void *sqc = param->sqc;
	void *wq = MLX5_ADDR_OF(sqc, sqc, wq);

	MLX5_SET(wq, wq, log_wq_stride, ilog2(MLX5_SEND_WQE_BB));
2184
	MLX5_SET(wq, wq, pd,            priv->mdev->mlx5e_res.pdn);
2185

2186
	param->wq.buf_numa_node = dev_to_node(&priv->mdev->pdev->dev);
T
Tariq Toukan 已提交
2187 2188 2189
}

static void mlx5e_build_sq_param(struct mlx5e_priv *priv,
2190
				 struct mlx5e_params *params,
T
Tariq Toukan 已提交
2191 2192 2193 2194 2195 2196
				 struct mlx5e_sq_param *param)
{
	void *sqc = param->sqc;
	void *wq = MLX5_ADDR_OF(sqc, sqc, wq);

	mlx5e_build_sq_param_common(priv, param);
2197
	MLX5_SET(wq, wq, log_wq_sz, params->log_sq_size);
2198
	MLX5_SET(sqc, sqc, allow_swp, !!MLX5_IPSEC_DEV(priv->mdev));
2199 2200 2201 2202 2203 2204 2205
}

static void mlx5e_build_common_cq_param(struct mlx5e_priv *priv,
					struct mlx5e_cq_param *param)
{
	void *cqc = param->cqc;

E
Eli Cohen 已提交
2206
	MLX5_SET(cqc, cqc, uar_page, priv->mdev->priv.uar->index);
2207 2208 2209
}

static void mlx5e_build_rx_cq_param(struct mlx5e_priv *priv,
2210
				    struct mlx5e_params *params,
2211 2212
				    struct mlx5e_cq_param *param)
{
2213
	struct mlx5_core_dev *mdev = priv->mdev;
2214
	void *cqc = param->cqc;
2215
	u8 log_cq_size;
2216

2217
	switch (params->rq_wq_type) {
2218
	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
2219 2220
		log_cq_size = mlx5e_mpwqe_get_log_rq_size(params) +
			mlx5e_mpwqe_get_log_num_strides(mdev, params);
2221
		break;
2222
	default: /* MLX5_WQ_TYPE_CYCLIC */
2223
		log_cq_size = params->log_rq_mtu_frames;
2224 2225 2226
	}

	MLX5_SET(cqc, cqc, log_cq_size, log_cq_size);
2227
	if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
T
Tariq Toukan 已提交
2228 2229 2230
		MLX5_SET(cqc, cqc, mini_cqe_res_format, MLX5_CQE_FORMAT_CSUM);
		MLX5_SET(cqc, cqc, cqe_comp_en, 1);
	}
2231 2232

	mlx5e_build_common_cq_param(priv, param);
2233
	param->cq_period_mode = params->rx_cq_moderation.cq_period_mode;
2234 2235 2236
}

static void mlx5e_build_tx_cq_param(struct mlx5e_priv *priv,
2237
				    struct mlx5e_params *params,
2238 2239 2240 2241
				    struct mlx5e_cq_param *param)
{
	void *cqc = param->cqc;

2242
	MLX5_SET(cqc, cqc, log_cq_size, params->log_sq_size);
2243 2244

	mlx5e_build_common_cq_param(priv, param);
2245
	param->cq_period_mode = params->tx_cq_moderation.cq_period_mode;
2246 2247
}

T
Tariq Toukan 已提交
2248
static void mlx5e_build_ico_cq_param(struct mlx5e_priv *priv,
2249 2250
				     u8 log_wq_size,
				     struct mlx5e_cq_param *param)
T
Tariq Toukan 已提交
2251 2252 2253 2254 2255 2256
{
	void *cqc = param->cqc;

	MLX5_SET(cqc, cqc, log_cq_size, log_wq_size);

	mlx5e_build_common_cq_param(priv, param);
T
Tariq Toukan 已提交
2257

2258
	param->cq_period_mode = NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE;
T
Tariq Toukan 已提交
2259 2260 2261
}

static void mlx5e_build_icosq_param(struct mlx5e_priv *priv,
2262 2263
				    u8 log_wq_size,
				    struct mlx5e_sq_param *param)
T
Tariq Toukan 已提交
2264 2265 2266 2267 2268 2269 2270
{
	void *sqc = param->sqc;
	void *wq = MLX5_ADDR_OF(sqc, sqc, wq);

	mlx5e_build_sq_param_common(priv, param);

	MLX5_SET(wq, wq, log_wq_sz, log_wq_size);
2271
	MLX5_SET(sqc, sqc, reg_umr, MLX5_CAP_ETH(priv->mdev, reg_umr_sq));
T
Tariq Toukan 已提交
2272 2273
}

2274
static void mlx5e_build_xdpsq_param(struct mlx5e_priv *priv,
2275
				    struct mlx5e_params *params,
2276 2277 2278 2279 2280 2281
				    struct mlx5e_sq_param *param)
{
	void *sqc = param->sqc;
	void *wq = MLX5_ADDR_OF(sqc, sqc, wq);

	mlx5e_build_sq_param_common(priv, param);
2282
	MLX5_SET(wq, wq, log_wq_sz, params->log_sq_size);
2283 2284
}

2285 2286 2287
static void mlx5e_build_channel_param(struct mlx5e_priv *priv,
				      struct mlx5e_params *params,
				      struct mlx5e_channel_param *cparam)
2288
{
2289
	u8 icosq_log_wq_sz = MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE;
T
Tariq Toukan 已提交
2290

2291 2292 2293 2294 2295 2296 2297
	mlx5e_build_rq_param(priv, params, &cparam->rq);
	mlx5e_build_sq_param(priv, params, &cparam->sq);
	mlx5e_build_xdpsq_param(priv, params, &cparam->xdp_sq);
	mlx5e_build_icosq_param(priv, icosq_log_wq_sz, &cparam->icosq);
	mlx5e_build_rx_cq_param(priv, params, &cparam->rx_cq);
	mlx5e_build_tx_cq_param(priv, params, &cparam->tx_cq);
	mlx5e_build_ico_cq_param(priv, icosq_log_wq_sz, &cparam->icosq_cq);
2298 2299
}

2300 2301
int mlx5e_open_channels(struct mlx5e_priv *priv,
			struct mlx5e_channels *chs)
2302
{
2303
	struct mlx5e_channel_param *cparam;
2304
	int err = -ENOMEM;
2305 2306
	int i;

2307
	chs->num = chs->params.num_channels;
2308

2309
	chs->c = kcalloc(chs->num, sizeof(struct mlx5e_channel *), GFP_KERNEL);
2310
	cparam = kvzalloc(sizeof(struct mlx5e_channel_param), GFP_KERNEL);
2311 2312
	if (!chs->c || !cparam)
		goto err_free;
2313

2314
	mlx5e_build_channel_param(priv, &chs->params, cparam);
2315
	for (i = 0; i < chs->num; i++) {
2316
		err = mlx5e_open_channel(priv, i, &chs->params, cparam, &chs->c[i]);
2317 2318 2319 2320
		if (err)
			goto err_close_channels;
	}

2321
	kvfree(cparam);
2322 2323 2324 2325
	return 0;

err_close_channels:
	for (i--; i >= 0; i--)
2326
		mlx5e_close_channel(chs->c[i]);
2327

2328
err_free:
2329
	kfree(chs->c);
2330
	kvfree(cparam);
2331
	chs->num = 0;
2332 2333 2334
	return err;
}

2335
static void mlx5e_activate_channels(struct mlx5e_channels *chs)
2336 2337 2338
{
	int i;

2339 2340 2341 2342 2343 2344 2345 2346 2347
	for (i = 0; i < chs->num; i++)
		mlx5e_activate_channel(chs->c[i]);
}

static int mlx5e_wait_channels_min_rx_wqes(struct mlx5e_channels *chs)
{
	int err = 0;
	int i;

2348 2349 2350
	for (i = 0; i < chs->num; i++)
		err |= mlx5e_wait_for_min_rx_wqes(&chs->c[i]->rq,
						  err ? 0 : 20000);
2351

2352
	return err ? -ETIMEDOUT : 0;
2353 2354 2355 2356 2357 2358 2359 2360 2361 2362
}

static void mlx5e_deactivate_channels(struct mlx5e_channels *chs)
{
	int i;

	for (i = 0; i < chs->num; i++)
		mlx5e_deactivate_channel(chs->c[i]);
}

2363
void mlx5e_close_channels(struct mlx5e_channels *chs)
2364 2365
{
	int i;
2366

2367 2368
	for (i = 0; i < chs->num; i++)
		mlx5e_close_channel(chs->c[i]);
2369

2370 2371
	kfree(chs->c);
	chs->num = 0;
2372 2373
}

2374 2375
static int
mlx5e_create_rqt(struct mlx5e_priv *priv, int sz, struct mlx5e_rqt *rqt)
2376 2377 2378 2379 2380
{
	struct mlx5_core_dev *mdev = priv->mdev;
	void *rqtc;
	int inlen;
	int err;
T
Tariq Toukan 已提交
2381
	u32 *in;
2382
	int i;
2383 2384

	inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * sz;
2385
	in = kvzalloc(inlen, GFP_KERNEL);
2386 2387 2388 2389 2390 2391 2392 2393
	if (!in)
		return -ENOMEM;

	rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context);

	MLX5_SET(rqtc, rqtc, rqt_actual_size, sz);
	MLX5_SET(rqtc, rqtc, rqt_max_size, sz);

2394 2395
	for (i = 0; i < sz; i++)
		MLX5_SET(rqtc, rqtc, rq_num[i], priv->drop_rq.rqn);
2396

2397 2398 2399
	err = mlx5_core_create_rqt(mdev, in, inlen, &rqt->rqtn);
	if (!err)
		rqt->enabled = true;
2400 2401

	kvfree(in);
T
Tariq Toukan 已提交
2402 2403 2404
	return err;
}

2405
void mlx5e_destroy_rqt(struct mlx5e_priv *priv, struct mlx5e_rqt *rqt)
T
Tariq Toukan 已提交
2406
{
2407 2408
	rqt->enabled = false;
	mlx5_core_destroy_rqt(priv->mdev, rqt->rqtn);
T
Tariq Toukan 已提交
2409 2410
}

2411
int mlx5e_create_indirect_rqt(struct mlx5e_priv *priv)
2412 2413
{
	struct mlx5e_rqt *rqt = &priv->indir_rqt;
2414
	int err;
2415

2416 2417 2418 2419
	err = mlx5e_create_rqt(priv, MLX5E_INDIR_RQT_SIZE, rqt);
	if (err)
		mlx5_core_warn(priv->mdev, "create indirect rqts failed, %d\n", err);
	return err;
2420 2421
}

2422
int mlx5e_create_direct_rqts(struct mlx5e_priv *priv)
T
Tariq Toukan 已提交
2423
{
2424
	struct mlx5e_rqt *rqt;
T
Tariq Toukan 已提交
2425 2426 2427
	int err;
	int ix;

2428
	for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) {
2429
		rqt = &priv->direct_tir[ix].rqt;
2430
		err = mlx5e_create_rqt(priv, 1 /*size */, rqt);
T
Tariq Toukan 已提交
2431 2432 2433 2434 2435 2436 2437
		if (err)
			goto err_destroy_rqts;
	}

	return 0;

err_destroy_rqts:
2438
	mlx5_core_warn(priv->mdev, "create direct rqts failed, %d\n", err);
T
Tariq Toukan 已提交
2439
	for (ix--; ix >= 0; ix--)
2440
		mlx5e_destroy_rqt(priv, &priv->direct_tir[ix].rqt);
T
Tariq Toukan 已提交
2441

2442 2443 2444
	return err;
}

2445 2446 2447 2448 2449 2450 2451 2452
void mlx5e_destroy_direct_rqts(struct mlx5e_priv *priv)
{
	int i;

	for (i = 0; i < priv->profile->max_nch(priv->mdev); i++)
		mlx5e_destroy_rqt(priv, &priv->direct_tir[i].rqt);
}

2453 2454 2455 2456 2457 2458 2459
static int mlx5e_rx_hash_fn(int hfunc)
{
	return (hfunc == ETH_RSS_HASH_TOP) ?
	       MLX5_RX_HASH_FN_TOEPLITZ :
	       MLX5_RX_HASH_FN_INVERTED_XOR8;
}

2460
int mlx5e_bits_invert(unsigned long a, int size)
2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484
{
	int inv = 0;
	int i;

	for (i = 0; i < size; i++)
		inv |= (test_bit(size - i - 1, &a) ? 1 : 0) << i;

	return inv;
}

static void mlx5e_fill_rqt_rqns(struct mlx5e_priv *priv, int sz,
				struct mlx5e_redirect_rqt_param rrp, void *rqtc)
{
	int i;

	for (i = 0; i < sz; i++) {
		u32 rqn;

		if (rrp.is_rss) {
			int ix = i;

			if (rrp.rss.hfunc == ETH_RSS_HASH_XOR)
				ix = mlx5e_bits_invert(i, ilog2(sz));

2485
			ix = priv->channels.params.indirection_rqt[ix];
2486 2487 2488 2489 2490 2491 2492 2493 2494 2495
			rqn = rrp.rss.channels->c[ix]->rq.rqn;
		} else {
			rqn = rrp.rqn;
		}
		MLX5_SET(rqtc, rqtc, rq_num[i], rqn);
	}
}

int mlx5e_redirect_rqt(struct mlx5e_priv *priv, u32 rqtn, int sz,
		       struct mlx5e_redirect_rqt_param rrp)
2496 2497 2498 2499
{
	struct mlx5_core_dev *mdev = priv->mdev;
	void *rqtc;
	int inlen;
T
Tariq Toukan 已提交
2500
	u32 *in;
2501 2502 2503
	int err;

	inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + sizeof(u32) * sz;
2504
	in = kvzalloc(inlen, GFP_KERNEL);
2505 2506 2507 2508 2509 2510 2511
	if (!in)
		return -ENOMEM;

	rqtc = MLX5_ADDR_OF(modify_rqt_in, in, ctx);

	MLX5_SET(rqtc, rqtc, rqt_actual_size, sz);
	MLX5_SET(modify_rqt_in, in, bitmask.rqn_list, 1);
2512
	mlx5e_fill_rqt_rqns(priv, sz, rrp, rqtc);
T
Tariq Toukan 已提交
2513
	err = mlx5_core_modify_rqt(mdev, rqtn, in, inlen);
2514 2515 2516 2517 2518

	kvfree(in);
	return err;
}

2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532
static u32 mlx5e_get_direct_rqn(struct mlx5e_priv *priv, int ix,
				struct mlx5e_redirect_rqt_param rrp)
{
	if (!rrp.is_rss)
		return rrp.rqn;

	if (ix >= rrp.rss.channels->num)
		return priv->drop_rq.rqn;

	return rrp.rss.channels->c[ix]->rq.rqn;
}

static void mlx5e_redirect_rqts(struct mlx5e_priv *priv,
				struct mlx5e_redirect_rqt_param rrp)
2533
{
T
Tariq Toukan 已提交
2534 2535 2536
	u32 rqtn;
	int ix;

2537
	if (priv->indir_rqt.enabled) {
2538
		/* RSS RQ table */
2539
		rqtn = priv->indir_rqt.rqtn;
2540
		mlx5e_redirect_rqt(priv, rqtn, MLX5E_INDIR_RQT_SIZE, rrp);
2541 2542
	}

2543 2544 2545
	for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) {
		struct mlx5e_redirect_rqt_param direct_rrp = {
			.is_rss = false,
2546 2547 2548
			{
				.rqn    = mlx5e_get_direct_rqn(priv, ix, rrp)
			},
2549 2550 2551
		};

		/* Direct RQ Tables */
2552 2553
		if (!priv->direct_tir[ix].rqt.enabled)
			continue;
2554

2555
		rqtn = priv->direct_tir[ix].rqt.rqtn;
2556
		mlx5e_redirect_rqt(priv, rqtn, 1, direct_rrp);
T
Tariq Toukan 已提交
2557
	}
2558 2559
}

2560 2561 2562 2563 2564
static void mlx5e_redirect_rqts_to_channels(struct mlx5e_priv *priv,
					    struct mlx5e_channels *chs)
{
	struct mlx5e_redirect_rqt_param rrp = {
		.is_rss        = true,
2565 2566 2567 2568 2569 2570
		{
			.rss = {
				.channels  = chs,
				.hfunc     = chs->params.rss_hfunc,
			}
		},
2571 2572 2573 2574 2575 2576 2577 2578 2579
	};

	mlx5e_redirect_rqts(priv, rrp);
}

static void mlx5e_redirect_rqts_to_drop(struct mlx5e_priv *priv)
{
	struct mlx5e_redirect_rqt_param drop_rrp = {
		.is_rss = false,
2580 2581 2582
		{
			.rqn = priv->drop_rq.rqn,
		},
2583 2584 2585 2586 2587
	};

	mlx5e_redirect_rqts(priv, drop_rrp);
}

2588
static void mlx5e_build_tir_ctx_lro(struct mlx5e_params *params, void *tirc)
2589
{
2590
	if (!params->lro_en)
2591 2592 2593 2594 2595 2596 2597 2598
		return;

#define ROUGH_MAX_L2_L3_HDR_SZ 256

	MLX5_SET(tirc, tirc, lro_enable_mask,
		 MLX5_TIRC_LRO_ENABLE_MASK_IPV4_LRO |
		 MLX5_TIRC_LRO_ENABLE_MASK_IPV6_LRO);
	MLX5_SET(tirc, tirc, lro_max_ip_payload_size,
2599 2600
		 (params->lro_wqe_sz - ROUGH_MAX_L2_L3_HDR_SZ) >> 8);
	MLX5_SET(tirc, tirc, lro_timeout_period_usecs, params->lro_timeout);
2601 2602
}

2603 2604
void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_params *params,
				    enum mlx5e_traffic_types tt,
2605
				    void *tirc, bool inner)
2606
{
2607 2608
	void *hfso = inner ? MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_inner) :
			     MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621

#define MLX5_HASH_IP            (MLX5_HASH_FIELD_SEL_SRC_IP   |\
				 MLX5_HASH_FIELD_SEL_DST_IP)

#define MLX5_HASH_IP_L4PORTS    (MLX5_HASH_FIELD_SEL_SRC_IP   |\
				 MLX5_HASH_FIELD_SEL_DST_IP   |\
				 MLX5_HASH_FIELD_SEL_L4_SPORT |\
				 MLX5_HASH_FIELD_SEL_L4_DPORT)

#define MLX5_HASH_IP_IPSEC_SPI  (MLX5_HASH_FIELD_SEL_SRC_IP   |\
				 MLX5_HASH_FIELD_SEL_DST_IP   |\
				 MLX5_HASH_FIELD_SEL_IPSEC_SPI)

2622 2623
	MLX5_SET(tirc, tirc, rx_hash_fn, mlx5e_rx_hash_fn(params->rss_hfunc));
	if (params->rss_hfunc == ETH_RSS_HASH_TOP) {
2624 2625 2626 2627 2628 2629
		void *rss_key = MLX5_ADDR_OF(tirc, tirc,
					     rx_hash_toeplitz_key);
		size_t len = MLX5_FLD_SZ_BYTES(tirc,
					       rx_hash_toeplitz_key);

		MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
2630
		memcpy(rss_key, params->toeplitz_hash_key, len);
2631
	}
2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713

	switch (tt) {
	case MLX5E_TT_IPV4_TCP:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV4);
		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
			 MLX5_L4_PROT_TYPE_TCP);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_L4PORTS);
		break;

	case MLX5E_TT_IPV6_TCP:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV6);
		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
			 MLX5_L4_PROT_TYPE_TCP);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_L4PORTS);
		break;

	case MLX5E_TT_IPV4_UDP:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV4);
		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
			 MLX5_L4_PROT_TYPE_UDP);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_L4PORTS);
		break;

	case MLX5E_TT_IPV6_UDP:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV6);
		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
			 MLX5_L4_PROT_TYPE_UDP);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_L4PORTS);
		break;

	case MLX5E_TT_IPV4_IPSEC_AH:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV4);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_IPSEC_SPI);
		break;

	case MLX5E_TT_IPV6_IPSEC_AH:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV6);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_IPSEC_SPI);
		break;

	case MLX5E_TT_IPV4_IPSEC_ESP:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV4);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_IPSEC_SPI);
		break;

	case MLX5E_TT_IPV6_IPSEC_ESP:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV6);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP_IPSEC_SPI);
		break;

	case MLX5E_TT_IPV4:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV4);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP);
		break;

	case MLX5E_TT_IPV6:
		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
			 MLX5_L3_PROT_TYPE_IPV6);
		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
			 MLX5_HASH_IP);
		break;
	default:
		WARN_ONCE(true, "%s: bad traffic type!\n", __func__);
	}
2714 2715
}

T
Tariq Toukan 已提交
2716
static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
2717 2718 2719 2720 2721 2722 2723
{
	struct mlx5_core_dev *mdev = priv->mdev;

	void *in;
	void *tirc;
	int inlen;
	int err;
T
Tariq Toukan 已提交
2724
	int tt;
T
Tariq Toukan 已提交
2725
	int ix;
2726 2727

	inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
2728
	in = kvzalloc(inlen, GFP_KERNEL);
2729 2730 2731 2732 2733 2734
	if (!in)
		return -ENOMEM;

	MLX5_SET(modify_tir_in, in, bitmask.lro, 1);
	tirc = MLX5_ADDR_OF(modify_tir_in, in, ctx);

2735
	mlx5e_build_tir_ctx_lro(&priv->channels.params, tirc);
2736

T
Tariq Toukan 已提交
2737
	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
2738
		err = mlx5_core_modify_tir(mdev, priv->indir_tir[tt].tirn, in,
T
Tariq Toukan 已提交
2739
					   inlen);
T
Tariq Toukan 已提交
2740
		if (err)
T
Tariq Toukan 已提交
2741
			goto free_in;
T
Tariq Toukan 已提交
2742
	}
2743

2744
	for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) {
T
Tariq Toukan 已提交
2745 2746 2747 2748 2749 2750 2751
		err = mlx5_core_modify_tir(mdev, priv->direct_tir[ix].tirn,
					   in, inlen);
		if (err)
			goto free_in;
	}

free_in:
2752 2753 2754 2755 2756
	kvfree(in);

	return err;
}

2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771
static void mlx5e_build_inner_indir_tir_ctx(struct mlx5e_priv *priv,
					    enum mlx5e_traffic_types tt,
					    u32 *tirc)
{
	MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.td.tdn);

	mlx5e_build_tir_ctx_lro(&priv->channels.params, tirc);

	MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
	MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqt.rqtn);
	MLX5_SET(tirc, tirc, tunneled_offload_en, 0x1);

	mlx5e_build_indir_tir_ctx_hash(&priv->channels.params, tt, tirc, true);
}

2772 2773
static int mlx5e_set_mtu(struct mlx5_core_dev *mdev,
			 struct mlx5e_params *params, u16 mtu)
2774
{
2775
	u16 hw_mtu = MLX5E_SW2HW_MTU(params, mtu);
2776 2777
	int err;

2778
	err = mlx5_set_port_mtu(mdev, hw_mtu, 1);
2779 2780 2781
	if (err)
		return err;

2782 2783 2784 2785
	/* Update vport context MTU */
	mlx5_modify_nic_vport_mtu(mdev, hw_mtu);
	return 0;
}
2786

2787 2788
static void mlx5e_query_mtu(struct mlx5_core_dev *mdev,
			    struct mlx5e_params *params, u16 *mtu)
2789 2790 2791
{
	u16 hw_mtu = 0;
	int err;
2792

2793 2794 2795 2796
	err = mlx5_query_nic_vport_mtu(mdev, &hw_mtu);
	if (err || !hw_mtu) /* fallback to port oper mtu */
		mlx5_query_port_oper_mtu(mdev, &hw_mtu, 1);

2797
	*mtu = MLX5E_HW2SW_MTU(params, hw_mtu);
2798 2799
}

2800
static int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv)
2801
{
2802
	struct mlx5e_params *params = &priv->channels.params;
2803
	struct net_device *netdev = priv->netdev;
2804
	struct mlx5_core_dev *mdev = priv->mdev;
2805 2806 2807
	u16 mtu;
	int err;

2808
	err = mlx5e_set_mtu(mdev, params, params->sw_mtu);
2809 2810
	if (err)
		return err;
2811

2812 2813
	mlx5e_query_mtu(mdev, params, &mtu);
	if (mtu != params->sw_mtu)
2814
		netdev_warn(netdev, "%s: VPort MTU %d is different than netdev mtu %d\n",
2815
			    __func__, mtu, params->sw_mtu);
2816

2817
	params->sw_mtu = mtu;
2818 2819 2820
	return 0;
}

2821 2822 2823
static void mlx5e_netdev_set_tcs(struct net_device *netdev)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
2824 2825
	int nch = priv->channels.params.num_channels;
	int ntc = priv->channels.params.num_tc;
2826 2827 2828 2829 2830 2831 2832 2833 2834
	int tc;

	netdev_reset_tc(netdev);

	if (ntc == 1)
		return;

	netdev_set_num_tc(netdev, ntc);

2835 2836 2837
	/* Map netdev TCs to offset 0
	 * We have our own UP to TXQ mapping for QoS
	 */
2838
	for (tc = 0; tc < ntc; tc++)
2839
		netdev_set_tc_queue(netdev, tc, nch, 0);
2840 2841
}

2842
static void mlx5e_build_tc2txq_maps(struct mlx5e_priv *priv)
2843
{
2844
	int max_nch = priv->profile->max_nch(priv->mdev);
2845 2846
	int i, tc;

2847
	for (i = 0; i < max_nch; i++)
2848
		for (tc = 0; tc < priv->profile->max_tc; tc++)
2849 2850 2851 2852 2853 2854 2855 2856
			priv->channel_tc2txq[i][tc] = i + tc * max_nch;
}

static void mlx5e_build_tx2sq_maps(struct mlx5e_priv *priv)
{
	struct mlx5e_channel *c;
	struct mlx5e_txqsq *sq;
	int i, tc;
2857 2858 2859 2860 2861 2862 2863 2864 2865 2866

	for (i = 0; i < priv->channels.num; i++) {
		c = priv->channels.c[i];
		for (tc = 0; tc < c->num_tc; tc++) {
			sq = &c->sq[tc];
			priv->txq2sq[sq->txq_ix] = sq;
		}
	}
}

2867
void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
2868
{
2869 2870 2871 2872
	int num_txqs = priv->channels.num * priv->channels.params.num_tc;
	struct net_device *netdev = priv->netdev;

	mlx5e_netdev_set_tcs(netdev);
2873 2874
	netif_set_real_num_tx_queues(netdev, num_txqs);
	netif_set_real_num_rx_queues(netdev, priv->channels.num);
2875

2876
	mlx5e_build_tx2sq_maps(priv);
2877 2878
	mlx5e_activate_channels(&priv->channels);
	netif_tx_start_all_queues(priv->netdev);
2879

2880
	if (MLX5_ESWITCH_MANAGER(priv->mdev))
2881 2882
		mlx5e_add_sqs_fwd_rules(priv);

2883
	mlx5e_wait_channels_min_rx_wqes(&priv->channels);
2884
	mlx5e_redirect_rqts_to_channels(priv, &priv->channels);
2885 2886
}

2887
void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv)
2888
{
2889 2890
	mlx5e_redirect_rqts_to_drop(priv);

2891
	if (MLX5_ESWITCH_MANAGER(priv->mdev))
2892 2893
		mlx5e_remove_sqs_fwd_rules(priv);

2894 2895 2896 2897 2898 2899 2900 2901
	/* FIXME: This is a W/A only for tx timeout watch dog false alarm when
	 * polling for inactive tx queues.
	 */
	netif_tx_stop_all_queues(priv->netdev);
	netif_tx_disable(priv->netdev);
	mlx5e_deactivate_channels(&priv->channels);
}

2902
void mlx5e_switch_priv_channels(struct mlx5e_priv *priv,
2903 2904
				struct mlx5e_channels *new_chs,
				mlx5e_fp_hw_modify hw_modify)
2905 2906 2907
{
	struct net_device *netdev = priv->netdev;
	int new_num_txqs;
2908
	int carrier_ok;
2909 2910
	new_num_txqs = new_chs->num * new_chs->params.num_tc;

2911
	carrier_ok = netif_carrier_ok(netdev);
2912 2913 2914 2915 2916 2917 2918 2919 2920 2921
	netif_carrier_off(netdev);

	if (new_num_txqs < netdev->real_num_tx_queues)
		netif_set_real_num_tx_queues(netdev, new_num_txqs);

	mlx5e_deactivate_priv_channels(priv);
	mlx5e_close_channels(&priv->channels);

	priv->channels = *new_chs;

2922 2923 2924 2925
	/* New channels are ready to roll, modify HW settings if needed */
	if (hw_modify)
		hw_modify(priv);

2926 2927 2928
	mlx5e_refresh_tirs(priv, false);
	mlx5e_activate_priv_channels(priv);

2929 2930 2931
	/* return carrier back if needed */
	if (carrier_ok)
		netif_carrier_on(netdev);
2932 2933
}

2934
void mlx5e_timestamp_init(struct mlx5e_priv *priv)
2935 2936 2937 2938 2939
{
	priv->tstamp.tx_type   = HWTSTAMP_TX_OFF;
	priv->tstamp.rx_filter = HWTSTAMP_FILTER_NONE;
}

2940 2941 2942 2943 2944 2945 2946
int mlx5e_open_locked(struct net_device *netdev)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	int err;

	set_bit(MLX5E_STATE_OPENED, &priv->state);

2947
	err = mlx5e_open_channels(priv, &priv->channels);
2948
	if (err)
2949
		goto err_clear_state_opened_flag;
2950

2951
	mlx5e_refresh_tirs(priv, false);
2952
	mlx5e_activate_priv_channels(priv);
2953 2954
	if (priv->profile->update_carrier)
		priv->profile->update_carrier(priv);
2955

2956 2957
	if (priv->profile->update_stats)
		queue_delayed_work(priv->wq, &priv->update_stats_work, 0);
2958

2959
	return 0;
2960 2961 2962 2963

err_clear_state_opened_flag:
	clear_bit(MLX5E_STATE_OPENED, &priv->state);
	return err;
2964 2965
}

2966
int mlx5e_open(struct net_device *netdev)
2967 2968 2969 2970 2971 2972
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	int err;

	mutex_lock(&priv->state_lock);
	err = mlx5e_open_locked(netdev);
2973 2974
	if (!err)
		mlx5_set_port_admin_status(priv->mdev, MLX5_PORT_UP);
2975 2976
	mutex_unlock(&priv->state_lock);

2977 2978 2979
	if (mlx5e_vxlan_allowed(priv->mdev))
		udp_tunnel_get_rx_info(netdev);

2980 2981 2982 2983 2984 2985 2986
	return err;
}

int mlx5e_close_locked(struct net_device *netdev)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);

2987 2988 2989 2990 2991 2992
	/* May already be CLOSED in case a previous configuration operation
	 * (e.g RX/TX queue size change) that involves close&open failed.
	 */
	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
		return 0;

2993 2994 2995
	clear_bit(MLX5E_STATE_OPENED, &priv->state);

	netif_carrier_off(priv->netdev);
2996 2997
	mlx5e_deactivate_priv_channels(priv);
	mlx5e_close_channels(&priv->channels);
2998 2999 3000 3001

	return 0;
}

3002
int mlx5e_close(struct net_device *netdev)
3003 3004 3005 3006
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	int err;

3007 3008 3009
	if (!netif_device_present(netdev))
		return -ENODEV;

3010
	mutex_lock(&priv->state_lock);
3011
	mlx5_set_port_admin_status(priv->mdev, MLX5_PORT_DOWN);
3012 3013 3014 3015 3016 3017
	err = mlx5e_close_locked(netdev);
	mutex_unlock(&priv->state_lock);

	return err;
}

3018
static int mlx5e_alloc_drop_rq(struct mlx5_core_dev *mdev,
3019 3020
			       struct mlx5e_rq *rq,
			       struct mlx5e_rq_param *param)
3021 3022 3023 3024 3025 3026 3027
{
	void *rqc = param->rqc;
	void *rqc_wq = MLX5_ADDR_OF(rqc, rqc, wq);
	int err;

	param->wq.db_numa_node = param->wq.buf_numa_node;

3028 3029
	err = mlx5_wq_cyc_create(mdev, &param->wq, rqc_wq, &rq->wqe.wq,
				 &rq->wq_ctrl);
3030 3031 3032
	if (err)
		return err;

3033 3034 3035
	/* Mark as unused given "Drop-RQ" packets never reach XDP */
	xdp_rxq_info_unused(&rq->xdp_rxq);

3036
	rq->mdev = mdev;
3037 3038 3039 3040

	return 0;
}

3041
static int mlx5e_alloc_drop_cq(struct mlx5_core_dev *mdev,
3042 3043
			       struct mlx5e_cq *cq,
			       struct mlx5e_cq_param *param)
3044
{
3045 3046 3047
	param->wq.buf_numa_node = dev_to_node(&mdev->pdev->dev);
	param->wq.db_numa_node  = dev_to_node(&mdev->pdev->dev);

3048
	return mlx5e_alloc_cq_common(mdev, param, cq);
3049 3050
}

3051
static int mlx5e_open_drop_rq(struct mlx5e_priv *priv,
3052
			      struct mlx5e_rq *drop_rq)
3053
{
3054
	struct mlx5_core_dev *mdev = priv->mdev;
3055 3056 3057
	struct mlx5e_cq_param cq_param = {};
	struct mlx5e_rq_param rq_param = {};
	struct mlx5e_cq *cq = &drop_rq->cq;
3058 3059
	int err;

3060
	mlx5e_build_drop_rq_param(priv, &rq_param);
3061

3062
	err = mlx5e_alloc_drop_cq(mdev, cq, &cq_param);
3063 3064 3065
	if (err)
		return err;

3066
	err = mlx5e_create_cq(cq, &cq_param);
3067
	if (err)
3068
		goto err_free_cq;
3069

3070
	err = mlx5e_alloc_drop_rq(mdev, drop_rq, &rq_param);
3071
	if (err)
3072
		goto err_destroy_cq;
3073

3074
	err = mlx5e_create_rq(drop_rq, &rq_param);
3075
	if (err)
3076
		goto err_free_rq;
3077

3078 3079 3080 3081
	err = mlx5e_modify_rq_state(drop_rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY);
	if (err)
		mlx5_core_warn(priv->mdev, "modify_rq_state failed, rx_if_down_packets won't be counted %d\n", err);

3082 3083
	return 0;

3084
err_free_rq:
3085
	mlx5e_free_rq(drop_rq);
3086 3087

err_destroy_cq:
3088
	mlx5e_destroy_cq(cq);
3089

3090
err_free_cq:
3091
	mlx5e_free_cq(cq);
3092

3093 3094 3095
	return err;
}

3096
static void mlx5e_close_drop_rq(struct mlx5e_rq *drop_rq)
3097
{
3098 3099 3100 3101
	mlx5e_destroy_rq(drop_rq);
	mlx5e_free_rq(drop_rq);
	mlx5e_destroy_cq(&drop_rq->cq);
	mlx5e_free_cq(&drop_rq->cq);
3102 3103
}

3104 3105
int mlx5e_create_tis(struct mlx5_core_dev *mdev, int tc,
		     u32 underlay_qpn, u32 *tisn)
3106
{
3107
	u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {0};
3108 3109
	void *tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);

3110
	MLX5_SET(tisc, tisc, prio, tc << 1);
3111
	MLX5_SET(tisc, tisc, underlay_qpn, underlay_qpn);
3112
	MLX5_SET(tisc, tisc, transport_domain, mdev->mlx5e_res.td.tdn);
3113 3114 3115 3116

	if (mlx5_lag_is_lacp_owner(mdev))
		MLX5_SET(tisc, tisc, strict_lag_tx_port_affinity, 1);

3117
	return mlx5_core_create_tis(mdev, in, sizeof(in), tisn);
3118 3119
}

3120
void mlx5e_destroy_tis(struct mlx5_core_dev *mdev, u32 tisn)
3121
{
3122
	mlx5_core_destroy_tis(mdev, tisn);
3123 3124
}

3125
int mlx5e_create_tises(struct mlx5e_priv *priv)
3126 3127 3128 3129
{
	int err;
	int tc;

3130
	for (tc = 0; tc < priv->profile->max_tc; tc++) {
3131
		err = mlx5e_create_tis(priv->mdev, tc, 0, &priv->tisn[tc]);
3132 3133 3134 3135 3136 3137 3138 3139
		if (err)
			goto err_close_tises;
	}

	return 0;

err_close_tises:
	for (tc--; tc >= 0; tc--)
3140
		mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]);
3141 3142 3143 3144

	return err;
}

3145
void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv)
3146 3147 3148
{
	int tc;

3149
	for (tc = 0; tc < priv->profile->max_tc; tc++)
3150
		mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]);
3151 3152
}

3153 3154 3155
static void mlx5e_build_indir_tir_ctx(struct mlx5e_priv *priv,
				      enum mlx5e_traffic_types tt,
				      u32 *tirc)
3156
{
3157
	MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.td.tdn);
3158

3159
	mlx5e_build_tir_ctx_lro(&priv->channels.params, tirc);
3160

A
Achiad Shochat 已提交
3161
	MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
3162
	MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqt.rqtn);
3163
	mlx5e_build_indir_tir_ctx_hash(&priv->channels.params, tt, tirc, false);
3164 3165
}

3166
static void mlx5e_build_direct_tir_ctx(struct mlx5e_priv *priv, u32 rqtn, u32 *tirc)
3167
{
3168
	MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.td.tdn);
T
Tariq Toukan 已提交
3169

3170
	mlx5e_build_tir_ctx_lro(&priv->channels.params, tirc);
T
Tariq Toukan 已提交
3171 3172 3173 3174 3175 3176

	MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
	MLX5_SET(tirc, tirc, indirect_table, rqtn);
	MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_INVERTED_XOR8);
}

3177
int mlx5e_create_indirect_tirs(struct mlx5e_priv *priv)
T
Tariq Toukan 已提交
3178
{
3179
	struct mlx5e_tir *tir;
3180 3181
	void *tirc;
	int inlen;
3182
	int i = 0;
3183
	int err;
T
Tariq Toukan 已提交
3184 3185
	u32 *in;
	int tt;
3186 3187

	inlen = MLX5_ST_SZ_BYTES(create_tir_in);
3188
	in = kvzalloc(inlen, GFP_KERNEL);
3189 3190 3191
	if (!in)
		return -ENOMEM;

T
Tariq Toukan 已提交
3192 3193
	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
		memset(in, 0, inlen);
3194
		tir = &priv->indir_tir[tt];
T
Tariq Toukan 已提交
3195
		tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
3196
		mlx5e_build_indir_tir_ctx(priv, tt, tirc);
3197
		err = mlx5e_create_tir(priv->mdev, tir, in, inlen);
3198 3199 3200 3201
		if (err) {
			mlx5_core_warn(priv->mdev, "create indirect tirs failed, %d\n", err);
			goto err_destroy_inner_tirs;
		}
3202 3203
	}

3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219
	if (!mlx5e_tunnel_inner_ft_supported(priv->mdev))
		goto out;

	for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++) {
		memset(in, 0, inlen);
		tir = &priv->inner_indir_tir[i];
		tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
		mlx5e_build_inner_indir_tir_ctx(priv, i, tirc);
		err = mlx5e_create_tir(priv->mdev, tir, in, inlen);
		if (err) {
			mlx5_core_warn(priv->mdev, "create inner indirect tirs failed, %d\n", err);
			goto err_destroy_inner_tirs;
		}
	}

out:
3220 3221 3222 3223
	kvfree(in);

	return 0;

3224 3225 3226 3227
err_destroy_inner_tirs:
	for (i--; i >= 0; i--)
		mlx5e_destroy_tir(priv->mdev, &priv->inner_indir_tir[i]);

3228 3229 3230 3231 3232 3233 3234 3235
	for (tt--; tt >= 0; tt--)
		mlx5e_destroy_tir(priv->mdev, &priv->indir_tir[tt]);

	kvfree(in);

	return err;
}

3236
int mlx5e_create_direct_tirs(struct mlx5e_priv *priv)
3237 3238 3239 3240 3241 3242 3243 3244 3245 3246
{
	int nch = priv->profile->max_nch(priv->mdev);
	struct mlx5e_tir *tir;
	void *tirc;
	int inlen;
	int err;
	u32 *in;
	int ix;

	inlen = MLX5_ST_SZ_BYTES(create_tir_in);
3247
	in = kvzalloc(inlen, GFP_KERNEL);
3248 3249 3250
	if (!in)
		return -ENOMEM;

T
Tariq Toukan 已提交
3251 3252
	for (ix = 0; ix < nch; ix++) {
		memset(in, 0, inlen);
3253
		tir = &priv->direct_tir[ix];
T
Tariq Toukan 已提交
3254
		tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
3255
		mlx5e_build_direct_tir_ctx(priv, priv->direct_tir[ix].rqt.rqtn, tirc);
3256
		err = mlx5e_create_tir(priv->mdev, tir, in, inlen);
T
Tariq Toukan 已提交
3257 3258 3259 3260 3261 3262
		if (err)
			goto err_destroy_ch_tirs;
	}

	kvfree(in);

3263 3264
	return 0;

T
Tariq Toukan 已提交
3265
err_destroy_ch_tirs:
3266
	mlx5_core_warn(priv->mdev, "create direct tirs failed, %d\n", err);
T
Tariq Toukan 已提交
3267
	for (ix--; ix >= 0; ix--)
3268
		mlx5e_destroy_tir(priv->mdev, &priv->direct_tir[ix]);
T
Tariq Toukan 已提交
3269 3270

	kvfree(in);
3271 3272 3273 3274

	return err;
}

3275
void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv)
3276 3277 3278
{
	int i;

T
Tariq Toukan 已提交
3279
	for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++)
3280
		mlx5e_destroy_tir(priv->mdev, &priv->indir_tir[i]);
3281 3282 3283 3284 3285 3286

	if (!mlx5e_tunnel_inner_ft_supported(priv->mdev))
		return;

	for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++)
		mlx5e_destroy_tir(priv->mdev, &priv->inner_indir_tir[i]);
3287 3288
}

3289
void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv)
3290 3291 3292 3293 3294 3295 3296 3297
{
	int nch = priv->profile->max_nch(priv->mdev);
	int i;

	for (i = 0; i < nch; i++)
		mlx5e_destroy_tir(priv->mdev, &priv->direct_tir[i]);
}

3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311
static int mlx5e_modify_channels_scatter_fcs(struct mlx5e_channels *chs, bool enable)
{
	int err = 0;
	int i;

	for (i = 0; i < chs->num; i++) {
		err = mlx5e_modify_rq_scatter_fcs(&chs->c[i]->rq, enable);
		if (err)
			return err;
	}

	return 0;
}

3312
static int mlx5e_modify_channels_vsd(struct mlx5e_channels *chs, bool vsd)
3313 3314 3315 3316
{
	int err = 0;
	int i;

3317 3318
	for (i = 0; i < chs->num; i++) {
		err = mlx5e_modify_rq_vsd(&chs->c[i]->rq, vsd);
3319 3320 3321 3322 3323 3324 3325
		if (err)
			return err;
	}

	return 0;
}

3326 3327
static int mlx5e_setup_tc_mqprio(struct net_device *netdev,
				 struct tc_mqprio_qopt *mqprio)
3328 3329
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
S
Saeed Mahameed 已提交
3330
	struct mlx5e_channels new_channels = {};
3331
	u8 tc = mqprio->num_tc;
3332 3333
	int err = 0;

3334 3335
	mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;

3336 3337 3338 3339 3340
	if (tc && tc != MLX5E_MAX_NUM_TC)
		return -EINVAL;

	mutex_lock(&priv->state_lock);

S
Saeed Mahameed 已提交
3341 3342
	new_channels.params = priv->channels.params;
	new_channels.params.num_tc = tc ? tc : 1;
3343

S
Saeed Mahameed 已提交
3344
	if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
S
Saeed Mahameed 已提交
3345 3346 3347
		priv->channels.params = new_channels.params;
		goto out;
	}
3348

S
Saeed Mahameed 已提交
3349 3350 3351
	err = mlx5e_open_channels(priv, &new_channels);
	if (err)
		goto out;
3352

3353 3354
	priv->max_opened_tc = max_t(u8, priv->max_opened_tc,
				    new_channels.params.num_tc);
3355
	mlx5e_switch_priv_channels(priv, &new_channels, NULL);
S
Saeed Mahameed 已提交
3356
out:
3357 3358 3359 3360
	mutex_unlock(&priv->state_lock);
	return err;
}

3361
#ifdef CONFIG_MLX5_ESWITCH
3362
static int mlx5e_setup_tc_cls_flower(struct mlx5e_priv *priv,
3363 3364
				     struct tc_cls_flower_offload *cls_flower,
				     int flags)
3365
{
3366 3367
	switch (cls_flower->command) {
	case TC_CLSFLOWER_REPLACE:
3368
		return mlx5e_configure_flower(priv, cls_flower, flags);
3369
	case TC_CLSFLOWER_DESTROY:
3370
		return mlx5e_delete_flower(priv, cls_flower, flags);
3371
	case TC_CLSFLOWER_STATS:
3372
		return mlx5e_stats_flower(priv, cls_flower, flags);
3373
	default:
3374
		return -EOPNOTSUPP;
3375 3376
	}
}
3377

3378 3379
static int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
				   void *cb_priv)
3380 3381 3382
{
	struct mlx5e_priv *priv = cb_priv;

3383
	if (!tc_cls_can_offload_and_chain0(priv->netdev, type_data))
3384 3385
		return -EOPNOTSUPP;

3386 3387
	switch (type) {
	case TC_SETUP_CLSFLOWER:
3388
		return mlx5e_setup_tc_cls_flower(priv, type_data, MLX5E_TC_INGRESS);
3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404
	default:
		return -EOPNOTSUPP;
	}
}

static int mlx5e_setup_tc_block(struct net_device *dev,
				struct tc_block_offload *f)
{
	struct mlx5e_priv *priv = netdev_priv(dev);

	if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
		return -EOPNOTSUPP;

	switch (f->command) {
	case TC_BLOCK_BIND:
		return tcf_block_cb_register(f->block, mlx5e_setup_tc_block_cb,
3405
					     priv, priv, f->extack);
3406 3407 3408 3409 3410 3411 3412 3413
	case TC_BLOCK_UNBIND:
		tcf_block_cb_unregister(f->block, mlx5e_setup_tc_block_cb,
					priv);
		return 0;
	default:
		return -EOPNOTSUPP;
	}
}
3414
#endif
3415

3416 3417
static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
			  void *type_data)
3418
{
3419
	switch (type) {
3420
#ifdef CONFIG_MLX5_ESWITCH
3421 3422
	case TC_SETUP_BLOCK:
		return mlx5e_setup_tc_block(dev, type_data);
3423
#endif
3424
	case TC_SETUP_QDISC_MQPRIO:
3425
		return mlx5e_setup_tc_mqprio(dev, type_data);
3426 3427 3428
	default:
		return -EOPNOTSUPP;
	}
3429 3430
}

3431
static void
3432 3433 3434
mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
3435
	struct mlx5e_sw_stats *sstats = &priv->stats.sw;
3436
	struct mlx5e_vport_stats *vstats = &priv->stats.vport;
3437
	struct mlx5e_pport_stats *pstats = &priv->stats.pport;
3438

3439 3440 3441
	/* update HW stats in background for next time */
	queue_delayed_work(priv->wq, &priv->update_stats_work, 0);

3442 3443 3444 3445 3446 3447
	if (mlx5e_is_uplink_rep(priv)) {
		stats->rx_packets = PPORT_802_3_GET(pstats, a_frames_received_ok);
		stats->rx_bytes   = PPORT_802_3_GET(pstats, a_octets_received_ok);
		stats->tx_packets = PPORT_802_3_GET(pstats, a_frames_transmitted_ok);
		stats->tx_bytes   = PPORT_802_3_GET(pstats, a_octets_transmitted_ok);
	} else {
3448
		mlx5e_grp_sw_update_stats(priv);
3449 3450 3451 3452 3453 3454
		stats->rx_packets = sstats->rx_packets;
		stats->rx_bytes   = sstats->rx_bytes;
		stats->tx_packets = sstats->tx_packets;
		stats->tx_bytes   = sstats->tx_bytes;
		stats->tx_dropped = sstats->tx_queue_dropped;
	}
3455 3456 3457 3458

	stats->rx_dropped = priv->stats.qcnt.rx_out_of_buffer;

	stats->rx_length_errors =
3459 3460 3461
		PPORT_802_3_GET(pstats, a_in_range_length_errors) +
		PPORT_802_3_GET(pstats, a_out_of_range_length_field) +
		PPORT_802_3_GET(pstats, a_frame_too_long_errors);
3462
	stats->rx_crc_errors =
3463 3464 3465
		PPORT_802_3_GET(pstats, a_frame_check_sequence_errors);
	stats->rx_frame_errors = PPORT_802_3_GET(pstats, a_alignment_errors);
	stats->tx_aborted_errors = PPORT_2863_GET(pstats, if_out_discards);
3466 3467 3468 3469 3470 3471 3472
	stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors +
			   stats->rx_frame_errors;
	stats->tx_errors = stats->tx_aborted_errors + stats->tx_carrier_errors;

	/* vport multicast also counts packets that are dropped due to steering
	 * or rx out of buffer
	 */
3473 3474
	stats->multicast =
		VPORT_COUNTER_GET(vstats, received_eth_multicast.packets);
3475 3476 3477 3478 3479 3480
}

static void mlx5e_set_rx_mode(struct net_device *dev)
{
	struct mlx5e_priv *priv = netdev_priv(dev);

3481
	queue_work(priv->wq, &priv->set_rx_mode_work);
3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495
}

static int mlx5e_set_mac(struct net_device *netdev, void *addr)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	struct sockaddr *saddr = addr;

	if (!is_valid_ether_addr(saddr->sa_data))
		return -EADDRNOTAVAIL;

	netif_addr_lock_bh(netdev);
	ether_addr_copy(netdev->dev_addr, saddr->sa_data);
	netif_addr_unlock_bh(netdev);

3496
	queue_work(priv->wq, &priv->set_rx_mode_work);
3497 3498 3499 3500

	return 0;
}

3501
#define MLX5E_SET_FEATURE(features, feature, enable)	\
3502 3503
	do {						\
		if (enable)				\
3504
			*features |= feature;		\
3505
		else					\
3506
			*features &= ~feature;		\
3507 3508 3509 3510 3511
	} while (0)

typedef int (*mlx5e_feature_handler)(struct net_device *netdev, bool enable);

static int set_feature_lro(struct net_device *netdev, bool enable)
3512 3513
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
3514
	struct mlx5_core_dev *mdev = priv->mdev;
3515
	struct mlx5e_channels new_channels = {};
3516
	struct mlx5e_params *old_params;
3517 3518
	int err = 0;
	bool reset;
3519 3520 3521

	mutex_lock(&priv->state_lock);

3522
	old_params = &priv->channels.params;
3523 3524 3525 3526 3527 3528
	if (enable && !MLX5E_GET_PFLAG(old_params, MLX5E_PFLAG_RX_STRIDING_RQ)) {
		netdev_warn(netdev, "can't set LRO with legacy RQ\n");
		err = -EINVAL;
		goto out;
	}

3529
	reset = test_bit(MLX5E_STATE_OPENED, &priv->state);
3530

3531
	new_channels.params = *old_params;
3532 3533
	new_channels.params.lro_en = enable;

3534
	if (old_params->rq_wq_type != MLX5_WQ_TYPE_CYCLIC) {
3535 3536 3537 3538 3539
		if (mlx5e_rx_mpwqe_is_linear_skb(mdev, old_params) ==
		    mlx5e_rx_mpwqe_is_linear_skb(mdev, &new_channels.params))
			reset = false;
	}

3540
	if (!reset) {
3541
		*old_params = new_channels.params;
3542 3543
		err = mlx5e_modify_tirs_lro(priv);
		goto out;
3544
	}
3545

3546 3547 3548
	err = mlx5e_open_channels(priv, &new_channels);
	if (err)
		goto out;
3549

3550 3551
	mlx5e_switch_priv_channels(priv, &new_channels, mlx5e_modify_tirs_lro);
out:
3552
	mutex_unlock(&priv->state_lock);
3553 3554 3555
	return err;
}

3556
static int set_feature_cvlan_filter(struct net_device *netdev, bool enable)
3557 3558 3559 3560
{
	struct mlx5e_priv *priv = netdev_priv(netdev);

	if (enable)
3561
		mlx5e_enable_cvlan_filter(priv);
3562
	else
3563
		mlx5e_disable_cvlan_filter(priv);
3564 3565 3566 3567 3568 3569 3570

	return 0;
}

static int set_feature_tc_num_filters(struct net_device *netdev, bool enable)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
3571

3572
	if (!enable && mlx5e_tc_num_filters(priv)) {
3573 3574 3575 3576 3577
		netdev_err(netdev,
			   "Active offloaded tc filters, can't turn hw_tc_offload off\n");
		return -EINVAL;
	}

3578 3579 3580
	return 0;
}

3581 3582 3583 3584 3585 3586 3587 3588
static int set_feature_rx_all(struct net_device *netdev, bool enable)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	struct mlx5_core_dev *mdev = priv->mdev;

	return mlx5_set_port_fcs(mdev, !enable);
}

3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605
static int set_feature_rx_fcs(struct net_device *netdev, bool enable)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	int err;

	mutex_lock(&priv->state_lock);

	priv->channels.params.scatter_fcs_en = enable;
	err = mlx5e_modify_channels_scatter_fcs(&priv->channels, enable);
	if (err)
		priv->channels.params.scatter_fcs_en = !enable;

	mutex_unlock(&priv->state_lock);

	return err;
}

3606 3607 3608
static int set_feature_rx_vlan(struct net_device *netdev, bool enable)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
3609
	int err = 0;
3610 3611 3612

	mutex_lock(&priv->state_lock);

3613
	priv->channels.params.vlan_strip_disable = !enable;
3614 3615 3616 3617
	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
		goto unlock;

	err = mlx5e_modify_channels_vsd(&priv->channels, !enable);
3618
	if (err)
3619
		priv->channels.params.vlan_strip_disable = enable;
3620

3621
unlock:
3622 3623 3624 3625 3626
	mutex_unlock(&priv->state_lock);

	return err;
}

3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641
#ifdef CONFIG_RFS_ACCEL
static int set_feature_arfs(struct net_device *netdev, bool enable)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	int err;

	if (enable)
		err = mlx5e_arfs_enable(priv);
	else
		err = mlx5e_arfs_disable(priv);

	return err;
}
#endif

3642
static int mlx5e_handle_feature(struct net_device *netdev,
3643
				netdev_features_t *features,
3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656
				netdev_features_t wanted_features,
				netdev_features_t feature,
				mlx5e_feature_handler feature_handler)
{
	netdev_features_t changes = wanted_features ^ netdev->features;
	bool enable = !!(wanted_features & feature);
	int err;

	if (!(changes & feature))
		return 0;

	err = feature_handler(netdev, enable);
	if (err) {
3657 3658
		netdev_err(netdev, "%s feature %pNF failed, err %d\n",
			   enable ? "Enable" : "Disable", &feature, err);
3659 3660 3661
		return err;
	}

3662
	MLX5E_SET_FEATURE(features, feature, enable);
3663 3664 3665 3666 3667 3668
	return 0;
}

static int mlx5e_set_features(struct net_device *netdev,
			      netdev_features_t features)
{
3669
	netdev_features_t oper_features = netdev->features;
3670 3671 3672 3673
	int err = 0;

#define MLX5E_HANDLE_FEATURE(feature, handler) \
	mlx5e_handle_feature(netdev, &oper_features, features, feature, handler)
3674

3675 3676
	err |= MLX5E_HANDLE_FEATURE(NETIF_F_LRO, set_feature_lro);
	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_FILTER,
3677
				    set_feature_cvlan_filter);
3678 3679 3680 3681
	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_TC, set_feature_tc_num_filters);
	err |= MLX5E_HANDLE_FEATURE(NETIF_F_RXALL, set_feature_rx_all);
	err |= MLX5E_HANDLE_FEATURE(NETIF_F_RXFCS, set_feature_rx_fcs);
	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_RX, set_feature_rx_vlan);
3682
#ifdef CONFIG_RFS_ACCEL
3683
	err |= MLX5E_HANDLE_FEATURE(NETIF_F_NTUPLE, set_feature_arfs);
3684
#endif
3685

3686 3687 3688 3689 3690 3691
	if (err) {
		netdev->features = oper_features;
		return -EINVAL;
	}

	return 0;
3692 3693
}

3694 3695 3696 3697
static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
					    netdev_features_t features)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
3698
	struct mlx5e_params *params;
3699 3700

	mutex_lock(&priv->state_lock);
3701
	params = &priv->channels.params;
3702 3703 3704 3705 3706
	if (!bitmap_empty(priv->fs.vlan.active_svlans, VLAN_N_VID)) {
		/* HW strips the outer C-tag header, this is a problem
		 * for S-tag traffic.
		 */
		features &= ~NETIF_F_HW_VLAN_CTAG_RX;
3707
		if (!params->vlan_strip_disable)
3708 3709
			netdev_warn(netdev, "Dropping C-tag vlan stripping offload due to S-tag vlan\n");
	}
3710 3711 3712 3713 3714 3715
	if (!MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_STRIDING_RQ)) {
		features &= ~NETIF_F_LRO;
		if (params->lro_en)
			netdev_warn(netdev, "Disabling LRO, not supported in legacy RQ\n");
	}

3716 3717 3718 3719 3720
	mutex_unlock(&priv->state_lock);

	return features;
}

3721 3722
int mlx5e_change_mtu(struct net_device *netdev, int new_mtu,
		     change_hw_mtu_cb set_mtu_cb)
3723 3724
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
3725
	struct mlx5e_channels new_channels = {};
3726
	struct mlx5e_params *params;
3727
	int err = 0;
3728
	bool reset;
3729 3730

	mutex_lock(&priv->state_lock);
3731

3732
	params = &priv->channels.params;
3733

3734
	reset = !params->lro_en;
3735
	reset = reset && test_bit(MLX5E_STATE_OPENED, &priv->state);
3736

3737 3738 3739
	new_channels.params = *params;
	new_channels.params.sw_mtu = new_mtu;

3740 3741 3742 3743 3744 3745 3746 3747
	if (params->xdp_prog &&
	    !mlx5e_rx_is_linear_skb(priv->mdev, &new_channels.params)) {
		netdev_err(netdev, "MTU(%d) > %d is not allowed while XDP enabled\n",
			   new_mtu, MLX5E_XDP_MAX_MTU);
		err = -EINVAL;
		goto out;
	}

3748
	if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
3749 3750 3751 3752 3753 3754
		u8 ppw_old = mlx5e_mpwqe_log_pkts_per_wqe(params);
		u8 ppw_new = mlx5e_mpwqe_log_pkts_per_wqe(&new_channels.params);

		reset = reset && (ppw_old != ppw_new);
	}

3755
	if (!reset) {
3756
		params->sw_mtu = new_mtu;
3757
		set_mtu_cb(priv);
3758
		netdev->mtu = params->sw_mtu;
3759 3760
		goto out;
	}
3761

3762
	err = mlx5e_open_channels(priv, &new_channels);
3763
	if (err)
3764 3765
		goto out;

3766
	mlx5e_switch_priv_channels(priv, &new_channels, set_mtu_cb);
3767
	netdev->mtu = new_channels.params.sw_mtu;
3768

3769 3770
out:
	mutex_unlock(&priv->state_lock);
3771 3772 3773
	return err;
}

3774 3775 3776 3777 3778
static int mlx5e_change_nic_mtu(struct net_device *netdev, int new_mtu)
{
	return mlx5e_change_mtu(netdev, new_mtu, mlx5e_set_dev_port_mtu);
}

3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852
int mlx5e_hwstamp_set(struct mlx5e_priv *priv, struct ifreq *ifr)
{
	struct hwtstamp_config config;
	int err;

	if (!MLX5_CAP_GEN(priv->mdev, device_frequency_khz))
		return -EOPNOTSUPP;

	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
		return -EFAULT;

	/* TX HW timestamp */
	switch (config.tx_type) {
	case HWTSTAMP_TX_OFF:
	case HWTSTAMP_TX_ON:
		break;
	default:
		return -ERANGE;
	}

	mutex_lock(&priv->state_lock);
	/* RX HW timestamp */
	switch (config.rx_filter) {
	case HWTSTAMP_FILTER_NONE:
		/* Reset CQE compression to Admin default */
		mlx5e_modify_rx_cqe_compression_locked(priv, priv->channels.params.rx_cqe_compress_def);
		break;
	case HWTSTAMP_FILTER_ALL:
	case HWTSTAMP_FILTER_SOME:
	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V2_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
	case HWTSTAMP_FILTER_NTP_ALL:
		/* Disable CQE compression */
		netdev_warn(priv->netdev, "Disabling cqe compression");
		err = mlx5e_modify_rx_cqe_compression_locked(priv, false);
		if (err) {
			netdev_err(priv->netdev, "Failed disabling cqe compression err=%d\n", err);
			mutex_unlock(&priv->state_lock);
			return err;
		}
		config.rx_filter = HWTSTAMP_FILTER_ALL;
		break;
	default:
		mutex_unlock(&priv->state_lock);
		return -ERANGE;
	}

	memcpy(&priv->tstamp, &config, sizeof(config));
	mutex_unlock(&priv->state_lock);

	return copy_to_user(ifr->ifr_data, &config,
			    sizeof(config)) ? -EFAULT : 0;
}

int mlx5e_hwstamp_get(struct mlx5e_priv *priv, struct ifreq *ifr)
{
	struct hwtstamp_config *cfg = &priv->tstamp;

	if (!MLX5_CAP_GEN(priv->mdev, device_frequency_khz))
		return -EOPNOTSUPP;

	return copy_to_user(ifr->ifr_data, cfg, sizeof(*cfg)) ? -EFAULT : 0;
}

3853 3854
static int mlx5e_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
3855 3856
	struct mlx5e_priv *priv = netdev_priv(dev);

3857 3858
	switch (cmd) {
	case SIOCSHWTSTAMP:
3859
		return mlx5e_hwstamp_set(priv, ifr);
3860
	case SIOCGHWTSTAMP:
3861
		return mlx5e_hwstamp_get(priv, ifr);
3862 3863 3864 3865 3866
	default:
		return -EOPNOTSUPP;
	}
}

3867
#ifdef CONFIG_MLX5_ESWITCH
3868 3869 3870 3871 3872 3873 3874 3875
static int mlx5e_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev = priv->mdev;

	return mlx5_eswitch_set_vport_mac(mdev->priv.eswitch, vf + 1, mac);
}

3876 3877
static int mlx5e_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos,
			     __be16 vlan_proto)
3878 3879 3880 3881
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev = priv->mdev;

3882 3883 3884
	if (vlan_proto != htons(ETH_P_8021Q))
		return -EPROTONOSUPPORT;

3885 3886 3887 3888
	return mlx5_eswitch_set_vport_vlan(mdev->priv.eswitch, vf + 1,
					   vlan, qos);
}

3889 3890 3891 3892 3893 3894 3895 3896
static int mlx5e_set_vf_spoofchk(struct net_device *dev, int vf, bool setting)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev = priv->mdev;

	return mlx5_eswitch_set_vport_spoofchk(mdev->priv.eswitch, vf + 1, setting);
}

3897 3898 3899 3900 3901 3902 3903
static int mlx5e_set_vf_trust(struct net_device *dev, int vf, bool setting)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev = priv->mdev;

	return mlx5_eswitch_set_vport_trust(mdev->priv.eswitch, vf + 1, setting);
}
3904 3905 3906 3907 3908 3909 3910 3911

static int mlx5e_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate,
			     int max_tx_rate)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev = priv->mdev;

	return mlx5_eswitch_set_vport_rate(mdev->priv.eswitch, vf + 1,
3912
					   max_tx_rate, min_tx_rate);
3913 3914
}

3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969
static int mlx5_vport_link2ifla(u8 esw_link)
{
	switch (esw_link) {
	case MLX5_ESW_VPORT_ADMIN_STATE_DOWN:
		return IFLA_VF_LINK_STATE_DISABLE;
	case MLX5_ESW_VPORT_ADMIN_STATE_UP:
		return IFLA_VF_LINK_STATE_ENABLE;
	}
	return IFLA_VF_LINK_STATE_AUTO;
}

static int mlx5_ifla_link2vport(u8 ifla_link)
{
	switch (ifla_link) {
	case IFLA_VF_LINK_STATE_DISABLE:
		return MLX5_ESW_VPORT_ADMIN_STATE_DOWN;
	case IFLA_VF_LINK_STATE_ENABLE:
		return MLX5_ESW_VPORT_ADMIN_STATE_UP;
	}
	return MLX5_ESW_VPORT_ADMIN_STATE_AUTO;
}

static int mlx5e_set_vf_link_state(struct net_device *dev, int vf,
				   int link_state)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev = priv->mdev;

	return mlx5_eswitch_set_vport_state(mdev->priv.eswitch, vf + 1,
					    mlx5_ifla_link2vport(link_state));
}

static int mlx5e_get_vf_config(struct net_device *dev,
			       int vf, struct ifla_vf_info *ivi)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev = priv->mdev;
	int err;

	err = mlx5_eswitch_get_vport_config(mdev->priv.eswitch, vf + 1, ivi);
	if (err)
		return err;
	ivi->linkstate = mlx5_vport_link2ifla(ivi->linkstate);
	return 0;
}

static int mlx5e_get_vf_stats(struct net_device *dev,
			      int vf, struct ifla_vf_stats *vf_stats)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev = priv->mdev;

	return mlx5_eswitch_get_vport_stats(mdev->priv.eswitch, vf + 1,
					    vf_stats);
}
3970
#endif
3971

3972 3973
static void mlx5e_add_vxlan_port(struct net_device *netdev,
				 struct udp_tunnel_info *ti)
3974 3975 3976
{
	struct mlx5e_priv *priv = netdev_priv(netdev);

3977 3978 3979
	if (ti->type != UDP_TUNNEL_TYPE_VXLAN)
		return;

3980 3981 3982
	if (!mlx5e_vxlan_allowed(priv->mdev))
		return;

3983
	mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 1);
3984 3985
}

3986 3987
static void mlx5e_del_vxlan_port(struct net_device *netdev,
				 struct udp_tunnel_info *ti)
3988 3989 3990
{
	struct mlx5e_priv *priv = netdev_priv(netdev);

3991 3992 3993
	if (ti->type != UDP_TUNNEL_TYPE_VXLAN)
		return;

3994 3995 3996
	if (!mlx5e_vxlan_allowed(priv->mdev))
		return;

3997
	mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 0);
3998 3999
}

4000 4001 4002
static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
						     struct sk_buff *skb,
						     netdev_features_t features)
4003
{
4004
	unsigned int offset = 0;
4005
	struct udphdr *udph;
4006 4007
	u8 proto;
	u16 port;
4008 4009 4010 4011 4012 4013

	switch (vlan_get_protocol(skb)) {
	case htons(ETH_P_IP):
		proto = ip_hdr(skb)->protocol;
		break;
	case htons(ETH_P_IPV6):
4014
		proto = ipv6_find_hdr(skb, &offset, -1, NULL, NULL);
4015 4016 4017 4018 4019
		break;
	default:
		goto out;
	}

4020 4021 4022 4023
	switch (proto) {
	case IPPROTO_GRE:
		return features;
	case IPPROTO_UDP:
4024 4025 4026
		udph = udp_hdr(skb);
		port = be16_to_cpu(udph->dest);

4027 4028 4029 4030
		/* Verify if UDP port is being offloaded by HW */
		if (mlx5e_vxlan_lookup_port(priv, port))
			return features;
	}
4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045

out:
	/* Disable CSUM and GSO if the udp dport is not offloaded by HW */
	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
}

static netdev_features_t mlx5e_features_check(struct sk_buff *skb,
					      struct net_device *netdev,
					      netdev_features_t features)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);

	features = vlan_features_check(skb, features);
	features = vxlan_features_check(skb, features);

4046 4047 4048 4049 4050
#ifdef CONFIG_MLX5_EN_IPSEC
	if (mlx5e_ipsec_feature_check(skb, netdev, features))
		return features;
#endif

4051 4052 4053
	/* Validate if the tunneled packet is being offloaded by HW */
	if (skb->encapsulation &&
	    (features & NETIF_F_CSUM_MASK || features & NETIF_F_GSO_MASK))
4054
		return mlx5e_tunnel_features_check(priv, skb, features);
4055 4056 4057 4058

	return features;
}

4059 4060 4061
static bool mlx5e_tx_timeout_eq_recover(struct net_device *dev,
					struct mlx5e_txqsq *sq)
{
S
Saeed Mahameed 已提交
4062
	struct mlx5_eq *eq = sq->cq.mcq.eq;
4063 4064 4065
	u32 eqe_count;

	netdev_err(dev, "EQ 0x%x: Cons = 0x%x, irqn = 0x%x\n",
S
Saeed Mahameed 已提交
4066
		   eq->eqn, eq->cons_index, eq->irqn);
4067 4068 4069 4070 4071 4072

	eqe_count = mlx5_eq_poll_irq_disabled(eq);
	if (!eqe_count)
		return false;

	netdev_err(dev, "Recover %d eqes on EQ 0x%x\n", eqe_count, eq->eqn);
4073
	sq->channel->stats->eq_rearm++;
4074 4075 4076
	return true;
}

4077
static void mlx5e_tx_timeout_work(struct work_struct *work)
4078
{
4079 4080 4081
	struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
					       tx_timeout_work);
	struct net_device *dev = priv->netdev;
4082
	bool reopen_channels = false;
4083
	int i, err;
4084

4085 4086 4087 4088 4089
	rtnl_lock();
	mutex_lock(&priv->state_lock);

	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
		goto unlock;
4090

4091
	for (i = 0; i < priv->channels.num * priv->channels.params.num_tc; i++) {
4092
		struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, i);
4093
		struct mlx5e_txqsq *sq = priv->txq2sq[i];
4094

4095
		if (!netif_xmit_stopped(dev_queue))
4096
			continue;
4097 4098 4099

		netdev_err(dev,
			   "TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x, usecs since last trans: %u\n",
4100 4101
			   i, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc,
			   jiffies_to_usecs(jiffies - dev_queue->trans_start));
4102

4103 4104 4105 4106 4107 4108 4109
		/* If we recover a lost interrupt, most likely TX timeout will
		 * be resolved, skip reopening channels
		 */
		if (!mlx5e_tx_timeout_eq_recover(dev, sq)) {
			clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
			reopen_channels = true;
		}
4110 4111
	}

4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132
	if (!reopen_channels)
		goto unlock;

	mlx5e_close_locked(dev);
	err = mlx5e_open_locked(dev);
	if (err)
		netdev_err(priv->netdev,
			   "mlx5e_open_locked failed recovering from a tx_timeout, err(%d).\n",
			   err);

unlock:
	mutex_unlock(&priv->state_lock);
	rtnl_unlock();
}

static void mlx5e_tx_timeout(struct net_device *dev)
{
	struct mlx5e_priv *priv = netdev_priv(dev);

	netdev_err(dev, "TX timeout detected\n");
	queue_work(priv->wq, &priv->tx_timeout_work);
4133 4134
}

4135
static int mlx5e_xdp_allowed(struct mlx5e_priv *priv, struct bpf_prog *prog)
4136 4137
{
	struct net_device *netdev = priv->netdev;
4138
	struct mlx5e_channels new_channels = {};
4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149

	if (priv->channels.params.lro_en) {
		netdev_warn(netdev, "can't set XDP while LRO is on, disable LRO first\n");
		return -EINVAL;
	}

	if (MLX5_IPSEC_DEV(priv->mdev)) {
		netdev_warn(netdev, "can't set XDP with IPSec offload\n");
		return -EINVAL;
	}

4150 4151 4152 4153 4154 4155 4156 4157 4158
	new_channels.params = priv->channels.params;
	new_channels.params.xdp_prog = prog;

	if (!mlx5e_rx_is_linear_skb(priv->mdev, &new_channels.params)) {
		netdev_warn(netdev, "XDP is not allowed with MTU(%d) > %d\n",
			    new_channels.params.sw_mtu, MLX5E_XDP_MAX_MTU);
		return -EINVAL;
	}

4159 4160 4161
	return 0;
}

4162 4163 4164 4165 4166
static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	struct bpf_prog *old_prog;
	bool reset, was_opened;
4167
	int err;
4168 4169 4170 4171
	int i;

	mutex_lock(&priv->state_lock);

4172
	if (prog) {
4173
		err = mlx5e_xdp_allowed(priv, prog);
4174 4175
		if (err)
			goto unlock;
4176 4177
	}

4178 4179
	was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
	/* no need for full reset when exchanging programs */
4180
	reset = (!priv->channels.params.xdp_prog || !prog);
4181 4182 4183

	if (was_opened && reset)
		mlx5e_close_locked(netdev);
4184 4185 4186 4187
	if (was_opened && !reset) {
		/* num_channels is invariant here, so we can take the
		 * batched reference right upfront.
		 */
4188
		prog = bpf_prog_add(prog, priv->channels.num);
4189 4190 4191 4192 4193
		if (IS_ERR(prog)) {
			err = PTR_ERR(prog);
			goto unlock;
		}
	}
4194

4195 4196 4197
	/* exchange programs, extra prog reference we got from caller
	 * as long as we don't fail from this point onwards.
	 */
4198
	old_prog = xchg(&priv->channels.params.xdp_prog, prog);
4199 4200 4201 4202
	if (old_prog)
		bpf_prog_put(old_prog);

	if (reset) /* change RQ type according to priv->xdp_prog */
4203
		mlx5e_set_rq_type(priv->mdev, &priv->channels.params);
4204 4205 4206 4207 4208 4209 4210 4211 4212 4213

	if (was_opened && reset)
		mlx5e_open_locked(netdev);

	if (!test_bit(MLX5E_STATE_OPENED, &priv->state) || reset)
		goto unlock;

	/* exchanging programs w/o reset, we update ref counts on behalf
	 * of the channels RQs here.
	 */
4214 4215
	for (i = 0; i < priv->channels.num; i++) {
		struct mlx5e_channel *c = priv->channels.c[i];
4216

4217
		clear_bit(MLX5E_RQ_STATE_ENABLED, &c->rq.state);
4218 4219 4220 4221 4222
		napi_synchronize(&c->napi);
		/* prevent mlx5e_poll_rx_cq from accessing rq->xdp_prog */

		old_prog = xchg(&c->rq.xdp_prog, prog);

4223
		set_bit(MLX5E_RQ_STATE_ENABLED, &c->rq.state);
4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235
		/* napi_schedule in case we have missed anything */
		napi_schedule(&c->napi);

		if (old_prog)
			bpf_prog_put(old_prog);
	}

unlock:
	mutex_unlock(&priv->state_lock);
	return err;
}

4236
static u32 mlx5e_xdp_query(struct net_device *dev)
4237 4238
{
	struct mlx5e_priv *priv = netdev_priv(dev);
4239 4240
	const struct bpf_prog *xdp_prog;
	u32 prog_id = 0;
4241

4242 4243 4244 4245 4246 4247 4248
	mutex_lock(&priv->state_lock);
	xdp_prog = priv->channels.params.xdp_prog;
	if (xdp_prog)
		prog_id = xdp_prog->aux->id;
	mutex_unlock(&priv->state_lock);

	return prog_id;
4249 4250
}

4251
static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
4252 4253 4254 4255 4256
{
	switch (xdp->command) {
	case XDP_SETUP_PROG:
		return mlx5e_xdp_set(dev, xdp->prog);
	case XDP_QUERY_PROG:
4257
		xdp->prog_id = mlx5e_xdp_query(dev);
4258 4259 4260 4261 4262 4263
		return 0;
	default:
		return -EINVAL;
	}
}

4264 4265 4266 4267 4268 4269 4270
#ifdef CONFIG_NET_POLL_CONTROLLER
/* Fake "interrupt" called by netpoll (eg netconsole) to send skbs without
 * reenabling interrupts.
 */
static void mlx5e_netpoll(struct net_device *dev)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
4271 4272
	struct mlx5e_channels *chs = &priv->channels;

4273 4274
	int i;

4275 4276
	for (i = 0; i < chs->num; i++)
		napi_schedule(&chs->c[i]->napi);
4277 4278 4279
}
#endif

4280
static const struct net_device_ops mlx5e_netdev_ops = {
4281 4282 4283
	.ndo_open                = mlx5e_open,
	.ndo_stop                = mlx5e_close,
	.ndo_start_xmit          = mlx5e_xmit,
4284
	.ndo_setup_tc            = mlx5e_setup_tc,
4285
	.ndo_select_queue        = mlx5e_select_queue,
4286 4287 4288
	.ndo_get_stats64         = mlx5e_get_stats,
	.ndo_set_rx_mode         = mlx5e_set_rx_mode,
	.ndo_set_mac_address     = mlx5e_set_mac,
4289 4290
	.ndo_vlan_rx_add_vid     = mlx5e_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid    = mlx5e_vlan_rx_kill_vid,
4291
	.ndo_set_features        = mlx5e_set_features,
4292
	.ndo_fix_features        = mlx5e_fix_features,
4293
	.ndo_change_mtu          = mlx5e_change_nic_mtu,
4294
	.ndo_do_ioctl            = mlx5e_ioctl,
4295
	.ndo_set_tx_maxrate      = mlx5e_set_tx_maxrate,
4296 4297 4298
	.ndo_udp_tunnel_add      = mlx5e_add_vxlan_port,
	.ndo_udp_tunnel_del      = mlx5e_del_vxlan_port,
	.ndo_features_check      = mlx5e_features_check,
4299 4300 4301
#ifdef CONFIG_RFS_ACCEL
	.ndo_rx_flow_steer	 = mlx5e_rx_flow_steer,
#endif
4302
	.ndo_tx_timeout          = mlx5e_tx_timeout,
4303
	.ndo_bpf		 = mlx5e_xdp,
4304
	.ndo_xdp_xmit            = mlx5e_xdp_xmit,
4305 4306 4307
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller     = mlx5e_netpoll,
#endif
4308
#ifdef CONFIG_MLX5_ESWITCH
4309
	/* SRIOV E-Switch NDOs */
4310 4311
	.ndo_set_vf_mac          = mlx5e_set_vf_mac,
	.ndo_set_vf_vlan         = mlx5e_set_vf_vlan,
4312
	.ndo_set_vf_spoofchk     = mlx5e_set_vf_spoofchk,
4313
	.ndo_set_vf_trust        = mlx5e_set_vf_trust,
4314
	.ndo_set_vf_rate         = mlx5e_set_vf_rate,
4315 4316 4317
	.ndo_get_vf_config       = mlx5e_get_vf_config,
	.ndo_set_vf_link_state   = mlx5e_set_vf_link_state,
	.ndo_get_vf_stats        = mlx5e_get_vf_stats,
4318 4319
	.ndo_has_offload_stats	 = mlx5e_has_offload_stats,
	.ndo_get_offload_stats	 = mlx5e_get_offload_stats,
4320
#endif
4321 4322 4323 4324 4325
};

static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
{
	if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
4326
		return -EOPNOTSUPP;
4327 4328 4329 4330 4331
	if (!MLX5_CAP_GEN(mdev, eth_net_offloads) ||
	    !MLX5_CAP_GEN(mdev, nic_flow_table) ||
	    !MLX5_CAP_ETH(mdev, csum_cap) ||
	    !MLX5_CAP_ETH(mdev, max_lso_cap) ||
	    !MLX5_CAP_ETH(mdev, vlan_cap) ||
4332 4333 4334 4335
	    !MLX5_CAP_ETH(mdev, rss_ind_tbl_cap) ||
	    MLX5_CAP_FLOWTABLE(mdev,
			       flow_table_properties_nic_receive.max_ft_level)
			       < 3) {
4336 4337
		mlx5_core_warn(mdev,
			       "Not creating net device, some required device capabilities are missing\n");
4338
		return -EOPNOTSUPP;
4339
	}
4340 4341
	if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable))
		mlx5_core_warn(mdev, "Self loop back prevention is not supported\n");
4342
	if (!MLX5_CAP_GEN(mdev, cq_moderation))
4343
		mlx5_core_warn(mdev, "CQ moderation is not supported\n");
4344

4345 4346 4347
	return 0;
}

4348
void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len,
4349 4350 4351 4352 4353 4354 4355 4356
				   int num_channels)
{
	int i;

	for (i = 0; i < len; i++)
		indirection_rqt[i] = i % num_channels;
}

4357
static bool slow_pci_heuristic(struct mlx5_core_dev *mdev)
4358
{
4359 4360
	u32 link_speed = 0;
	u32 pci_bw = 0;
4361

4362
	mlx5e_port_max_linkspeed(mdev, &link_speed);
4363
	pci_bw = pcie_bandwidth_available(mdev->pdev, NULL, NULL, NULL);
4364 4365 4366 4367 4368 4369 4370
	mlx5_core_dbg_once(mdev, "Max link speed = %d, PCI BW = %d\n",
			   link_speed, pci_bw);

#define MLX5E_SLOW_PCI_RATIO (2)

	return link_speed && pci_bw &&
		link_speed > MLX5E_SLOW_PCI_RATIO * pci_bw;
4371 4372
}

4373
static struct net_dim_cq_moder mlx5e_get_def_tx_moderation(u8 cq_period_mode)
4374
{
4375 4376 4377 4378 4379 4380 4381 4382 4383 4384
	struct net_dim_cq_moder moder;

	moder.cq_period_mode = cq_period_mode;
	moder.pkts = MLX5E_PARAMS_DEFAULT_TX_CQ_MODERATION_PKTS;
	moder.usec = MLX5E_PARAMS_DEFAULT_TX_CQ_MODERATION_USEC;
	if (cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE)
		moder.usec = MLX5E_PARAMS_DEFAULT_TX_CQ_MODERATION_USEC_FROM_CQE;

	return moder;
}
4385

4386 4387 4388
static struct net_dim_cq_moder mlx5e_get_def_rx_moderation(u8 cq_period_mode)
{
	struct net_dim_cq_moder moder;
4389

4390 4391 4392
	moder.cq_period_mode = cq_period_mode;
	moder.pkts = MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_PKTS;
	moder.usec = MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_USEC;
4393
	if (cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE)
4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414
		moder.usec = MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_USEC_FROM_CQE;

	return moder;
}

static u8 mlx5_to_net_dim_cq_period_mode(u8 cq_period_mode)
{
	return cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE ?
		NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE :
		NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE;
}

void mlx5e_set_tx_cq_mode_params(struct mlx5e_params *params, u8 cq_period_mode)
{
	if (params->tx_dim_enabled) {
		u8 dim_period_mode = mlx5_to_net_dim_cq_period_mode(cq_period_mode);

		params->tx_cq_moderation = net_dim_get_def_tx_moderation(dim_period_mode);
	} else {
		params->tx_cq_moderation = mlx5e_get_def_tx_moderation(cq_period_mode);
	}
4415 4416 4417 4418 4419 4420

	MLX5E_SET_PFLAG(params, MLX5E_PFLAG_TX_CQE_BASED_MODER,
			params->tx_cq_moderation.cq_period_mode ==
				MLX5_CQ_PERIOD_MODE_START_FROM_CQE);
}

T
Tariq Toukan 已提交
4421 4422
void mlx5e_set_rx_cq_mode_params(struct mlx5e_params *params, u8 cq_period_mode)
{
4423
	if (params->rx_dim_enabled) {
4424 4425 4426 4427 4428
		u8 dim_period_mode = mlx5_to_net_dim_cq_period_mode(cq_period_mode);

		params->rx_cq_moderation = net_dim_get_def_rx_moderation(dim_period_mode);
	} else {
		params->rx_cq_moderation = mlx5e_get_def_rx_moderation(cq_period_mode);
4429
	}
4430

4431
	MLX5E_SET_PFLAG(params, MLX5E_PFLAG_RX_CQE_BASED_MODER,
4432 4433
			params->rx_cq_moderation.cq_period_mode ==
				MLX5_CQ_PERIOD_MODE_START_FROM_CQE);
T
Tariq Toukan 已提交
4434 4435
}

4436
static u32 mlx5e_choose_lro_timeout(struct mlx5_core_dev *mdev, u32 wanted_timeout)
4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447
{
	int i;

	/* The supported periods are organized in ascending order */
	for (i = 0; i < MLX5E_LRO_TIMEOUT_ARR_SIZE - 1; i++)
		if (MLX5_CAP_ETH(mdev, lro_timer_supported_periods[i]) >= wanted_timeout)
			break;

	return MLX5_CAP_ETH(mdev, lro_timer_supported_periods[i]);
}

4448 4449
void mlx5e_build_nic_params(struct mlx5_core_dev *mdev,
			    struct mlx5e_params *params,
4450
			    u16 max_channels, u16 mtu)
4451
{
4452
	u8 rx_cq_period_mode;
4453

4454 4455
	params->sw_mtu = mtu;
	params->hard_mtu = MLX5E_ETH_HARD_MTU;
4456 4457
	params->num_channels = max_channels;
	params->num_tc       = 1;
4458

4459 4460
	/* SQ */
	params->log_sq_size = is_kdump_kernel() ?
4461 4462
		MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE :
		MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
4463

4464
	/* set CQE compression */
4465
	params->rx_cqe_compress_def = false;
4466
	if (MLX5_CAP_GEN(mdev, cqe_compression) &&
4467
	    MLX5_CAP_GEN(mdev, vport_group_manager))
4468
		params->rx_cqe_compress_def = slow_pci_heuristic(mdev);
4469

4470 4471 4472
	MLX5E_SET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS, params->rx_cqe_compress_def);

	/* RQ */
4473 4474 4475 4476 4477 4478 4479 4480 4481 4482
	/* Prefer Striding RQ, unless any of the following holds:
	 * - Striding RQ configuration is not possible/supported.
	 * - Slow PCI heuristic.
	 * - Legacy RQ would use linear SKB while Striding RQ would use non-linear.
	 */
	if (!slow_pci_heuristic(mdev) &&
	    mlx5e_striding_rq_possible(mdev, params) &&
	    (mlx5e_rx_mpwqe_is_linear_skb(mdev, params) ||
	     !mlx5e_rx_is_linear_skb(mdev, params)))
		MLX5E_SET_PFLAG(params, MLX5E_PFLAG_RX_STRIDING_RQ, true);
4483 4484
	mlx5e_set_rq_type(mdev, params);
	mlx5e_init_rq_type_params(mdev, params);
4485

4486
	/* HW LRO */
4487

4488
	/* TODO: && MLX5_CAP_ETH(mdev, lro_cap) */
4489
	if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ)
4490 4491
		if (!mlx5e_rx_mpwqe_is_linear_skb(mdev, params))
			params->lro_en = !slow_pci_heuristic(mdev);
4492
	params->lro_timeout = mlx5e_choose_lro_timeout(mdev, MLX5E_DEFAULT_LRO_TIMEOUT);
4493

4494
	/* CQ moderation params */
4495
	rx_cq_period_mode = MLX5_CAP_GEN(mdev, cq_period_start_from_cqe) ?
4496 4497
			MLX5_CQ_PERIOD_MODE_START_FROM_CQE :
			MLX5_CQ_PERIOD_MODE_START_FROM_EQE;
4498
	params->rx_dim_enabled = MLX5_CAP_GEN(mdev, cq_moderation);
4499
	params->tx_dim_enabled = MLX5_CAP_GEN(mdev, cq_moderation);
4500 4501
	mlx5e_set_rx_cq_mode_params(params, rx_cq_period_mode);
	mlx5e_set_tx_cq_mode_params(params, MLX5_CQ_PERIOD_MODE_START_FROM_EQE);
T
Tariq Toukan 已提交
4502

4503
	/* TX inline */
4504
	params->tx_min_inline_mode = mlx5e_params_calculate_tx_min_inline(mdev);
4505

4506 4507 4508
	/* RSS */
	params->rss_hfunc = ETH_RSS_HASH_XOR;
	netdev_rss_key_fill(params->toeplitz_hash_key, sizeof(params->toeplitz_hash_key));
4509
	mlx5e_build_default_indir_rqt(params->indirection_rqt,
4510 4511
				      MLX5E_INDIR_RQT_SIZE, max_channels);
}
4512

4513 4514 4515 4516 4517 4518
static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev,
					struct net_device *netdev,
					const struct mlx5e_profile *profile,
					void *ppriv)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
4519

4520 4521 4522 4523
	priv->mdev        = mdev;
	priv->netdev      = netdev;
	priv->profile     = profile;
	priv->ppriv       = ppriv;
4524
	priv->msglevel    = MLX5E_MSG_LEVEL;
4525
	priv->max_opened_tc = 1;
4526

4527 4528
	mlx5e_build_nic_params(mdev, &priv->channels.params,
			       profile->max_nch(mdev), netdev->mtu);
T
Tariq Toukan 已提交
4529

4530 4531 4532 4533
	mutex_init(&priv->state_lock);

	INIT_WORK(&priv->update_carrier_work, mlx5e_update_carrier_work);
	INIT_WORK(&priv->set_rx_mode_work, mlx5e_set_rx_mode_work);
4534
	INIT_WORK(&priv->tx_timeout_work, mlx5e_tx_timeout_work);
4535
	INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work);
4536 4537

	mlx5e_timestamp_init(priv);
4538 4539 4540 4541 4542 4543
}

static void mlx5e_set_netdev_dev_addr(struct net_device *netdev)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);

4544
	mlx5_query_nic_vport_mac_address(priv->mdev, 0, netdev->dev_addr);
4545 4546 4547 4548 4549
	if (is_zero_ether_addr(netdev->dev_addr) &&
	    !MLX5_CAP_GEN(priv->mdev, vport_group_manager)) {
		eth_hw_addr_random(netdev);
		mlx5_core_info(priv->mdev, "Assigned random MAC address %pM\n", netdev->dev_addr);
	}
4550 4551
}

4552
#if IS_ENABLED(CONFIG_MLX5_ESWITCH)
4553 4554 4555
static const struct switchdev_ops mlx5e_switchdev_ops = {
	.switchdev_port_attr_get	= mlx5e_attr_get,
};
4556
#endif
4557

4558
static void mlx5e_build_nic_netdev(struct net_device *netdev)
4559 4560 4561
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	struct mlx5_core_dev *mdev = priv->mdev;
4562 4563
	bool fcs_supported;
	bool fcs_enabled;
4564 4565 4566

	SET_NETDEV_DEV(netdev, &mdev->pdev->dev);

4567 4568
	netdev->netdev_ops = &mlx5e_netdev_ops;

4569
#ifdef CONFIG_MLX5_CORE_EN_DCB
4570 4571
	if (MLX5_CAP_GEN(mdev, vport_group_manager) && MLX5_CAP_GEN(mdev, qos))
		netdev->dcbnl_ops = &mlx5e_dcbnl_ops;
4572
#endif
4573

4574 4575 4576 4577
	netdev->watchdog_timeo    = 15 * HZ;

	netdev->ethtool_ops	  = &mlx5e_ethtool_ops;

S
Saeed Mahameed 已提交
4578
	netdev->vlan_features    |= NETIF_F_SG;
4579 4580 4581 4582 4583 4584 4585 4586
	netdev->vlan_features    |= NETIF_F_IP_CSUM;
	netdev->vlan_features    |= NETIF_F_IPV6_CSUM;
	netdev->vlan_features    |= NETIF_F_GRO;
	netdev->vlan_features    |= NETIF_F_TSO;
	netdev->vlan_features    |= NETIF_F_TSO6;
	netdev->vlan_features    |= NETIF_F_RXCSUM;
	netdev->vlan_features    |= NETIF_F_RXHASH;

4587 4588 4589
	netdev->hw_enc_features  |= NETIF_F_HW_VLAN_CTAG_TX;
	netdev->hw_enc_features  |= NETIF_F_HW_VLAN_CTAG_RX;

4590 4591
	if (!!MLX5_CAP_ETH(mdev, lro_cap) &&
	    mlx5e_check_fragmented_striding_rq_cap(mdev))
4592 4593 4594
		netdev->vlan_features    |= NETIF_F_LRO;

	netdev->hw_features       = netdev->vlan_features;
4595
	netdev->hw_features      |= NETIF_F_HW_VLAN_CTAG_TX;
4596 4597
	netdev->hw_features      |= NETIF_F_HW_VLAN_CTAG_RX;
	netdev->hw_features      |= NETIF_F_HW_VLAN_CTAG_FILTER;
4598
	netdev->hw_features      |= NETIF_F_HW_VLAN_STAG_TX;
4599

4600
	if (mlx5e_vxlan_allowed(mdev) || MLX5_CAP_ETH(mdev, tunnel_stateless_gre)) {
4601
		netdev->hw_enc_features |= NETIF_F_IP_CSUM;
4602
		netdev->hw_enc_features |= NETIF_F_IPV6_CSUM;
4603 4604
		netdev->hw_enc_features |= NETIF_F_TSO;
		netdev->hw_enc_features |= NETIF_F_TSO6;
4605 4606 4607 4608 4609 4610 4611 4612
		netdev->hw_enc_features |= NETIF_F_GSO_PARTIAL;
	}

	if (mlx5e_vxlan_allowed(mdev)) {
		netdev->hw_features     |= NETIF_F_GSO_UDP_TUNNEL |
					   NETIF_F_GSO_UDP_TUNNEL_CSUM;
		netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL |
					   NETIF_F_GSO_UDP_TUNNEL_CSUM;
4613
		netdev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
4614 4615
	}

4616 4617 4618 4619 4620 4621 4622 4623 4624
	if (MLX5_CAP_ETH(mdev, tunnel_stateless_gre)) {
		netdev->hw_features     |= NETIF_F_GSO_GRE |
					   NETIF_F_GSO_GRE_CSUM;
		netdev->hw_enc_features |= NETIF_F_GSO_GRE |
					   NETIF_F_GSO_GRE_CSUM;
		netdev->gso_partial_features |= NETIF_F_GSO_GRE |
						NETIF_F_GSO_GRE_CSUM;
	}

4625 4626 4627 4628 4629
	netdev->hw_features	                 |= NETIF_F_GSO_PARTIAL;
	netdev->gso_partial_features             |= NETIF_F_GSO_UDP_L4;
	netdev->hw_features                      |= NETIF_F_GSO_UDP_L4;
	netdev->features                         |= NETIF_F_GSO_UDP_L4;

4630 4631 4632 4633 4634
	mlx5_query_port_fcs(mdev, &fcs_supported, &fcs_enabled);

	if (fcs_supported)
		netdev->hw_features |= NETIF_F_RXALL;

4635 4636 4637
	if (MLX5_CAP_ETH(mdev, scatter_fcs))
		netdev->hw_features |= NETIF_F_RXFCS;

4638
	netdev->features          = netdev->hw_features;
4639
	if (!priv->channels.params.lro_en)
4640 4641
		netdev->features  &= ~NETIF_F_LRO;

4642 4643 4644
	if (fcs_enabled)
		netdev->features  &= ~NETIF_F_RXALL;

4645 4646 4647
	if (!priv->channels.params.scatter_fcs_en)
		netdev->features  &= ~NETIF_F_RXFCS;

4648 4649 4650 4651
#define FT_CAP(f) MLX5_CAP_FLOWTABLE(mdev, flow_table_properties_nic_receive.f)
	if (FT_CAP(flow_modify_en) &&
	    FT_CAP(modify_root) &&
	    FT_CAP(identified_miss_table_mode) &&
4652 4653 4654 4655 4656 4657
	    FT_CAP(flow_table_modify)) {
		netdev->hw_features      |= NETIF_F_HW_TC;
#ifdef CONFIG_RFS_ACCEL
		netdev->hw_features	 |= NETIF_F_NTUPLE;
#endif
	}
4658

4659
	netdev->features         |= NETIF_F_HIGHDMA;
4660
	netdev->features         |= NETIF_F_HW_VLAN_STAG_FILTER;
4661 4662 4663 4664

	netdev->priv_flags       |= IFF_UNICAST_FLT;

	mlx5e_set_netdev_dev_addr(netdev);
4665

4666
#if IS_ENABLED(CONFIG_MLX5_ESWITCH)
4667
	if (MLX5_ESWITCH_MANAGER(mdev))
4668 4669
		netdev->switchdev_ops = &mlx5e_switchdev_ops;
#endif
4670 4671

	mlx5e_ipsec_build_netdev(priv);
4672
	mlx5e_tls_build_netdev(priv);
4673 4674
}

4675
static void mlx5e_create_q_counters(struct mlx5e_priv *priv)
4676 4677 4678 4679 4680 4681 4682 4683 4684
{
	struct mlx5_core_dev *mdev = priv->mdev;
	int err;

	err = mlx5_core_alloc_q_counter(mdev, &priv->q_counter);
	if (err) {
		mlx5_core_warn(mdev, "alloc queue counter failed, %d\n", err);
		priv->q_counter = 0;
	}
4685 4686 4687 4688 4689 4690

	err = mlx5_core_alloc_q_counter(mdev, &priv->drop_rq_q_counter);
	if (err) {
		mlx5_core_warn(mdev, "alloc drop RQ counter failed, %d\n", err);
		priv->drop_rq_q_counter = 0;
	}
4691 4692
}

4693
static void mlx5e_destroy_q_counters(struct mlx5e_priv *priv)
4694
{
4695 4696
	if (priv->q_counter)
		mlx5_core_dealloc_q_counter(priv->mdev, priv->q_counter);
4697

4698 4699
	if (priv->drop_rq_q_counter)
		mlx5_core_dealloc_q_counter(priv->mdev, priv->drop_rq_q_counter);
4700 4701
}

4702 4703
static void mlx5e_nic_init(struct mlx5_core_dev *mdev,
			   struct net_device *netdev,
4704 4705
			   const struct mlx5e_profile *profile,
			   void *ppriv)
4706 4707
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
4708
	int err;
4709

4710
	mlx5e_build_nic_netdev_priv(mdev, netdev, profile, ppriv);
4711 4712 4713
	err = mlx5e_ipsec_init(priv);
	if (err)
		mlx5_core_err(mdev, "IPSec initialization failed, %d\n", err);
4714 4715 4716
	err = mlx5e_tls_init(priv);
	if (err)
		mlx5_core_err(mdev, "TLS initialization failed, %d\n", err);
4717
	mlx5e_build_nic_netdev(netdev);
4718
	mlx5e_build_tc2txq_maps(priv);
4719 4720 4721 4722 4723
	mlx5e_vxlan_init(priv);
}

static void mlx5e_nic_cleanup(struct mlx5e_priv *priv)
{
4724
	mlx5e_tls_cleanup(priv);
4725
	mlx5e_ipsec_cleanup(priv);
4726 4727 4728 4729 4730 4731 4732 4733
	mlx5e_vxlan_cleanup(priv);
}

static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
{
	struct mlx5_core_dev *mdev = priv->mdev;
	int err;

4734 4735
	err = mlx5e_create_indirect_rqt(priv);
	if (err)
4736 4737 4738
		return err;

	err = mlx5e_create_direct_rqts(priv);
4739
	if (err)
4740 4741 4742
		goto err_destroy_indirect_rqts;

	err = mlx5e_create_indirect_tirs(priv);
4743
	if (err)
4744 4745 4746
		goto err_destroy_direct_rqts;

	err = mlx5e_create_direct_tirs(priv);
4747
	if (err)
4748 4749 4750 4751 4752 4753 4754 4755
		goto err_destroy_indirect_tirs;

	err = mlx5e_create_flow_steering(priv);
	if (err) {
		mlx5_core_warn(mdev, "create flow steering failed, %d\n", err);
		goto err_destroy_direct_tirs;
	}

4756
	err = mlx5e_tc_nic_init(priv);
4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768
	if (err)
		goto err_destroy_flow_steering;

	return 0;

err_destroy_flow_steering:
	mlx5e_destroy_flow_steering(priv);
err_destroy_direct_tirs:
	mlx5e_destroy_direct_tirs(priv);
err_destroy_indirect_tirs:
	mlx5e_destroy_indirect_tirs(priv);
err_destroy_direct_rqts:
4769
	mlx5e_destroy_direct_rqts(priv);
4770 4771 4772 4773 4774 4775 4776
err_destroy_indirect_rqts:
	mlx5e_destroy_rqt(priv, &priv->indir_rqt);
	return err;
}

static void mlx5e_cleanup_nic_rx(struct mlx5e_priv *priv)
{
4777
	mlx5e_tc_nic_cleanup(priv);
4778 4779 4780
	mlx5e_destroy_flow_steering(priv);
	mlx5e_destroy_direct_tirs(priv);
	mlx5e_destroy_indirect_tirs(priv);
4781
	mlx5e_destroy_direct_rqts(priv);
4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795
	mlx5e_destroy_rqt(priv, &priv->indir_rqt);
}

static int mlx5e_init_nic_tx(struct mlx5e_priv *priv)
{
	int err;

	err = mlx5e_create_tises(priv);
	if (err) {
		mlx5_core_warn(priv->mdev, "create tises failed, %d\n", err);
		return err;
	}

#ifdef CONFIG_MLX5_CORE_EN_DCB
4796
	mlx5e_dcbnl_initialize(priv);
4797 4798 4799 4800 4801 4802 4803 4804
#endif
	return 0;
}

static void mlx5e_nic_enable(struct mlx5e_priv *priv)
{
	struct net_device *netdev = priv->netdev;
	struct mlx5_core_dev *mdev = priv->mdev;
4805 4806 4807 4808
	u16 max_mtu;

	mlx5e_init_l2_addr(priv);

4809 4810 4811 4812
	/* Marking the link as currently not needed by the Driver */
	if (!netif_running(netdev))
		mlx5_set_port_admin_status(mdev, MLX5_PORT_DOWN);

4813 4814 4815
	/* MTU range: 68 - hw-specific max */
	netdev->min_mtu = ETH_MIN_MTU;
	mlx5_query_port_max_mtu(priv->mdev, &max_mtu, 1);
4816
	netdev->max_mtu = MLX5E_HW2SW_MTU(&priv->channels.params, max_mtu);
4817
	mlx5e_set_dev_port_mtu(priv);
4818

4819 4820
	mlx5_lag_add(mdev, netdev);

4821
	mlx5e_enable_async_events(priv);
4822

4823
	if (MLX5_ESWITCH_MANAGER(priv->mdev))
4824
		mlx5e_register_vport_reps(priv);
4825

4826 4827
	if (netdev->reg_state != NETREG_REGISTERED)
		return;
4828 4829 4830
#ifdef CONFIG_MLX5_CORE_EN_DCB
	mlx5e_dcbnl_init_app(priv);
#endif
4831 4832

	queue_work(priv->wq, &priv->set_rx_mode_work);
4833 4834 4835 4836 4837 4838

	rtnl_lock();
	if (netif_running(netdev))
		mlx5e_open(netdev);
	netif_device_attach(netdev);
	rtnl_unlock();
4839 4840 4841 4842
}

static void mlx5e_nic_disable(struct mlx5e_priv *priv)
{
4843 4844
	struct mlx5_core_dev *mdev = priv->mdev;

4845 4846 4847 4848 4849
#ifdef CONFIG_MLX5_CORE_EN_DCB
	if (priv->netdev->reg_state == NETREG_REGISTERED)
		mlx5e_dcbnl_delete_app(priv);
#endif

4850 4851 4852 4853 4854 4855
	rtnl_lock();
	if (netif_running(priv->netdev))
		mlx5e_close(priv->netdev);
	netif_device_detach(priv->netdev);
	rtnl_unlock();

4856
	queue_work(priv->wq, &priv->set_rx_mode_work);
4857

4858
	if (MLX5_ESWITCH_MANAGER(priv->mdev))
4859 4860
		mlx5e_unregister_vport_reps(priv);

4861
	mlx5e_disable_async_events(priv);
4862
	mlx5_lag_remove(mdev);
4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873
}

static const struct mlx5e_profile mlx5e_nic_profile = {
	.init		   = mlx5e_nic_init,
	.cleanup	   = mlx5e_nic_cleanup,
	.init_rx	   = mlx5e_init_nic_rx,
	.cleanup_rx	   = mlx5e_cleanup_nic_rx,
	.init_tx	   = mlx5e_init_nic_tx,
	.cleanup_tx	   = mlx5e_cleanup_nic_tx,
	.enable		   = mlx5e_nic_enable,
	.disable	   = mlx5e_nic_disable,
4874
	.update_stats	   = mlx5e_update_ndo_stats,
4875
	.max_nch	   = mlx5e_get_max_num_channels,
4876
	.update_carrier	   = mlx5e_update_carrier,
4877 4878
	.rx_handlers.handle_rx_cqe       = mlx5e_handle_rx_cqe,
	.rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
4879 4880 4881
	.max_tc		   = MLX5E_MAX_NUM_TC,
};

4882 4883
/* mlx5e generic netdev management API (move to en_common.c) */

4884 4885 4886
struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev,
				       const struct mlx5e_profile *profile,
				       void *ppriv)
4887
{
4888
	int nch = profile->max_nch(mdev);
4889 4890 4891
	struct net_device *netdev;
	struct mlx5e_priv *priv;

4892
	netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv),
4893
				    nch * profile->max_tc,
4894
				    nch);
4895 4896 4897 4898 4899
	if (!netdev) {
		mlx5_core_err(mdev, "alloc_etherdev_mqs() failed\n");
		return NULL;
	}

4900 4901 4902 4903
#ifdef CONFIG_RFS_ACCEL
	netdev->rx_cpu_rmap = mdev->rmap;
#endif

4904
	profile->init(mdev, netdev, profile, ppriv);
4905 4906 4907 4908 4909

	netif_carrier_off(netdev);

	priv = netdev_priv(netdev);

4910 4911
	priv->wq = create_singlethread_workqueue("mlx5e");
	if (!priv->wq)
4912 4913 4914 4915 4916
		goto err_cleanup_nic;

	return netdev;

err_cleanup_nic:
4917 4918
	if (profile->cleanup)
		profile->cleanup(priv);
4919 4920 4921 4922 4923
	free_netdev(netdev);

	return NULL;
}

4924
int mlx5e_attach_netdev(struct mlx5e_priv *priv)
4925
{
4926
	struct mlx5_core_dev *mdev = priv->mdev;
4927 4928 4929 4930 4931
	const struct mlx5e_profile *profile;
	int err;

	profile = priv->profile;
	clear_bit(MLX5E_STATE_DESTROYING, &priv->state);
4932

4933 4934
	err = profile->init_tx(priv);
	if (err)
T
Tariq Toukan 已提交
4935
		goto out;
4936

4937 4938 4939
	mlx5e_create_q_counters(priv);

	err = mlx5e_open_drop_rq(priv, &priv->drop_rq);
4940 4941
	if (err) {
		mlx5_core_err(mdev, "open drop rq failed, %d\n", err);
4942
		goto err_destroy_q_counters;
4943 4944
	}

4945 4946
	err = profile->init_rx(priv);
	if (err)
4947 4948
		goto err_close_drop_rq;

4949 4950
	if (profile->enable)
		profile->enable(priv);
4951

4952
	return 0;
4953 4954

err_close_drop_rq:
4955
	mlx5e_close_drop_rq(&priv->drop_rq);
4956

4957 4958
err_destroy_q_counters:
	mlx5e_destroy_q_counters(priv);
4959
	profile->cleanup_tx(priv);
4960

4961 4962
out:
	return err;
4963 4964
}

4965
void mlx5e_detach_netdev(struct mlx5e_priv *priv)
4966 4967 4968 4969 4970
{
	const struct mlx5e_profile *profile = priv->profile;

	set_bit(MLX5E_STATE_DESTROYING, &priv->state);

4971 4972 4973 4974
	if (profile->disable)
		profile->disable(priv);
	flush_workqueue(priv->wq);

4975
	profile->cleanup_rx(priv);
4976
	mlx5e_close_drop_rq(&priv->drop_rq);
4977
	mlx5e_destroy_q_counters(priv);
4978 4979 4980 4981
	profile->cleanup_tx(priv);
	cancel_delayed_work_sync(&priv->update_stats_work);
}

4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992
void mlx5e_destroy_netdev(struct mlx5e_priv *priv)
{
	const struct mlx5e_profile *profile = priv->profile;
	struct net_device *netdev = priv->netdev;

	destroy_workqueue(priv->wq);
	if (profile->cleanup)
		profile->cleanup(priv);
	free_netdev(netdev);
}

4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008
/* mlx5e_attach and mlx5e_detach scope should be only creating/destroying
 * hardware contexts and to connect it to the current netdev.
 */
static int mlx5e_attach(struct mlx5_core_dev *mdev, void *vpriv)
{
	struct mlx5e_priv *priv = vpriv;
	struct net_device *netdev = priv->netdev;
	int err;

	if (netif_device_present(netdev))
		return 0;

	err = mlx5e_create_mdev_resources(mdev);
	if (err)
		return err;

5009
	err = mlx5e_attach_netdev(priv);
5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025
	if (err) {
		mlx5e_destroy_mdev_resources(mdev);
		return err;
	}

	return 0;
}

static void mlx5e_detach(struct mlx5_core_dev *mdev, void *vpriv)
{
	struct mlx5e_priv *priv = vpriv;
	struct net_device *netdev = priv->netdev;

	if (!netif_device_present(netdev))
		return;

5026
	mlx5e_detach_netdev(priv);
5027 5028 5029
	mlx5e_destroy_mdev_resources(mdev);
}

5030 5031
static void *mlx5e_add(struct mlx5_core_dev *mdev)
{
5032 5033
	struct net_device *netdev;
	void *rpriv = NULL;
5034 5035
	void *priv;
	int err;
5036

5037 5038
	err = mlx5e_check_required_hca_cap(mdev);
	if (err)
5039 5040
		return NULL;

5041
#ifdef CONFIG_MLX5_ESWITCH
5042
	if (MLX5_ESWITCH_MANAGER(mdev)) {
5043
		rpriv = mlx5e_alloc_nic_rep_priv(mdev);
5044
		if (!rpriv) {
5045
			mlx5_core_warn(mdev, "Failed to alloc NIC rep priv data\n");
5046 5047 5048
			return NULL;
		}
	}
5049
#endif
5050

5051
	netdev = mlx5e_create_netdev(mdev, &mlx5e_nic_profile, rpriv);
5052 5053
	if (!netdev) {
		mlx5_core_err(mdev, "mlx5e_create_netdev failed\n");
5054
		goto err_free_rpriv;
5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068
	}

	priv = netdev_priv(netdev);

	err = mlx5e_attach(mdev, priv);
	if (err) {
		mlx5_core_err(mdev, "mlx5e_attach failed, %d\n", err);
		goto err_destroy_netdev;
	}

	err = register_netdev(netdev);
	if (err) {
		mlx5_core_err(mdev, "register_netdev failed, %d\n", err);
		goto err_detach;
5069
	}
5070

5071 5072 5073
#ifdef CONFIG_MLX5_CORE_EN_DCB
	mlx5e_dcbnl_init_app(priv);
#endif
5074 5075 5076 5077 5078
	return priv;

err_detach:
	mlx5e_detach(mdev, priv);
err_destroy_netdev:
5079
	mlx5e_destroy_netdev(priv);
5080
err_free_rpriv:
5081
	kfree(rpriv);
5082
	return NULL;
5083 5084 5085 5086 5087
}

static void mlx5e_remove(struct mlx5_core_dev *mdev, void *vpriv)
{
	struct mlx5e_priv *priv = vpriv;
5088
	void *ppriv = priv->ppriv;
5089

5090 5091 5092
#ifdef CONFIG_MLX5_CORE_EN_DCB
	mlx5e_dcbnl_delete_app(priv);
#endif
5093
	unregister_netdev(priv->netdev);
5094
	mlx5e_detach(mdev, vpriv);
5095
	mlx5e_destroy_netdev(priv);
5096
	kfree(ppriv);
5097 5098
}

5099 5100 5101 5102 5103 5104 5105 5106
static void *mlx5e_get_netdev(void *vpriv)
{
	struct mlx5e_priv *priv = vpriv;

	return priv->netdev;
}

static struct mlx5_interface mlx5e_interface = {
5107 5108
	.add       = mlx5e_add,
	.remove    = mlx5e_remove,
5109 5110
	.attach    = mlx5e_attach,
	.detach    = mlx5e_detach,
5111 5112 5113 5114 5115 5116 5117
	.event     = mlx5e_async_event,
	.protocol  = MLX5_INTERFACE_PROTOCOL_ETH,
	.get_dev   = mlx5e_get_netdev,
};

void mlx5e_init(void)
{
5118
	mlx5e_ipsec_build_inverse_table();
5119
	mlx5e_build_ptys2ethtool_map();
5120 5121 5122 5123 5124 5125 5126
	mlx5_register_interface(&mlx5e_interface);
}

void mlx5e_cleanup(void)
{
	mlx5_unregister_interface(&mlx5e_interface);
}