en_main.c 111.2 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 "eswitch.h"
39
#include "en.h"
40
#include "en_tc.h"
41
#include "en_rep.h"
42
#include "vxlan.h"
43 44

struct mlx5e_rq_param {
45 46
	u32			rqc[MLX5_ST_SZ_DW(rqc)];
	struct mlx5_wq_param	wq;
47 48 49 50 51 52 53 54 55 56 57
};

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 已提交
58
	u8                         cq_period_mode;
59 60 61 62 63
};

struct mlx5e_channel_param {
	struct mlx5e_rq_param      rq;
	struct mlx5e_sq_param      sq;
64
	struct mlx5e_sq_param      xdp_sq;
T
Tariq Toukan 已提交
65
	struct mlx5e_sq_param      icosq;
66 67
	struct mlx5e_cq_param      rx_cq;
	struct mlx5e_cq_param      tx_cq;
T
Tariq Toukan 已提交
68
	struct mlx5e_cq_param      icosq_cq;
69 70
};

71 72 73 74 75 76 77
static bool mlx5e_check_fragmented_striding_rq_cap(struct mlx5_core_dev *mdev)
{
	return MLX5_CAP_GEN(mdev, striding_rq) &&
		MLX5_CAP_GEN(mdev, umr_ptr_rlky) &&
		MLX5_CAP_ETH(mdev, reg_umr_sq);
}

78 79
void mlx5e_set_rq_type_params(struct mlx5_core_dev *mdev,
			      struct mlx5e_params *params, u8 rq_type)
80
{
81 82 83
	params->rq_wq_type = rq_type;
	params->lro_wqe_sz = MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
	switch (params->rq_wq_type) {
84
	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
85
		params->log_rq_size = is_kdump_kernel() ?
86 87
			MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE_MPW :
			MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE_MPW;
88 89 90 91 92 93
		params->mpwqe_log_stride_sz =
			MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS) ?
			MLX5_MPWRQ_CQE_CMPRS_LOG_STRIDE_SZ(mdev) :
			MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev);
		params->mpwqe_log_num_strides = MLX5_MPWRQ_LOG_WQE_SZ -
			params->mpwqe_log_stride_sz;
94 95
		break;
	default: /* MLX5_WQ_TYPE_LINKED_LIST */
96
		params->log_rq_size = is_kdump_kernel() ?
97 98
			MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE :
			MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE;
99 100 101
		params->rq_headroom = params->xdp_prog ?
			XDP_PACKET_HEADROOM : MLX5_RX_HEADROOM;
		params->rq_headroom += NET_IP_ALIGN;
102 103

		/* Extra room needed for build_skb */
104
		params->lro_wqe_sz -= params->rq_headroom +
105
			SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
106 107
	}

108 109 110 111 112
	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,
		       BIT(params->log_rq_size),
		       BIT(params->mpwqe_log_stride_sz),
		       MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS));
113 114
}

115
static void mlx5e_set_rq_params(struct mlx5_core_dev *mdev, struct mlx5e_params *params)
116
{
117 118
	u8 rq_type = mlx5e_check_fragmented_striding_rq_cap(mdev) &&
		    !params->xdp_prog ?
119 120
		    MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ :
		    MLX5_WQ_TYPE_LINKED_LIST;
121
	mlx5e_set_rq_type_params(mdev, params, rq_type);
122 123
}

124 125 126 127 128 129
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,
130 131
					    MLX5_QUERY_VPORT_STATE_IN_OP_MOD_VNIC_VPORT,
					    0);
132

133 134
	if (port_state == VPORT_STATE_UP) {
		netdev_info(priv->netdev, "Link up\n");
135
		netif_carrier_on(priv->netdev);
136 137
	} else {
		netdev_info(priv->netdev, "Link down\n");
138
		netif_carrier_off(priv->netdev);
139
	}
140 141 142 143 144 145 146 147 148
}

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))
149 150
		if (priv->profile->update_carrier)
			priv->profile->update_carrier(priv);
151 152 153
	mutex_unlock(&priv->state_lock);
}

154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
static void mlx5e_tx_timeout_work(struct work_struct *work)
{
	struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
					       tx_timeout_work);
	int err;

	rtnl_lock();
	mutex_lock(&priv->state_lock);
	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
		goto unlock;
	mlx5e_close_locked(priv->netdev);
	err = mlx5e_open_locked(priv->netdev);
	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();
}

174
static void mlx5e_update_sw_counters(struct mlx5e_priv *priv)
175
{
176
	struct mlx5e_sw_stats temp, *s = &temp;
177 178
	struct mlx5e_rq_stats *rq_stats;
	struct mlx5e_sq_stats *sq_stats;
179
	u64 tx_offload_none = 0;
180 181
	int i, j;

182
	memset(s, 0, sizeof(*s));
183 184 185 186
	for (i = 0; i < priv->channels.num; i++) {
		struct mlx5e_channel *c = priv->channels.c[i];

		rq_stats = &c->rq.stats;
187

188 189
		s->rx_packets	+= rq_stats->packets;
		s->rx_bytes	+= rq_stats->bytes;
190 191
		s->rx_lro_packets += rq_stats->lro_packets;
		s->rx_lro_bytes	+= rq_stats->lro_bytes;
192
		s->rx_csum_none	+= rq_stats->csum_none;
193 194
		s->rx_csum_complete += rq_stats->csum_complete;
		s->rx_csum_unnecessary_inner += rq_stats->csum_unnecessary_inner;
195
		s->rx_xdp_drop += rq_stats->xdp_drop;
196 197
		s->rx_xdp_tx += rq_stats->xdp_tx;
		s->rx_xdp_tx_full += rq_stats->xdp_tx_full;
198
		s->rx_wqe_err   += rq_stats->wqe_err;
199
		s->rx_mpwqe_filler += rq_stats->mpwqe_filler;
200
		s->rx_buff_alloc_err += rq_stats->buff_alloc_err;
T
Tariq Toukan 已提交
201 202
		s->rx_cqe_compress_blks += rq_stats->cqe_compress_blks;
		s->rx_cqe_compress_pkts += rq_stats->cqe_compress_pkts;
203
		s->rx_page_reuse  += rq_stats->page_reuse;
204 205 206 207
		s->rx_cache_reuse += rq_stats->cache_reuse;
		s->rx_cache_full  += rq_stats->cache_full;
		s->rx_cache_empty += rq_stats->cache_empty;
		s->rx_cache_busy  += rq_stats->cache_busy;
208

209
		for (j = 0; j < priv->channels.params.num_tc; j++) {
210
			sq_stats = &c->sq[j].stats;
211

212 213
			s->tx_packets		+= sq_stats->packets;
			s->tx_bytes		+= sq_stats->bytes;
214 215 216 217
			s->tx_tso_packets	+= sq_stats->tso_packets;
			s->tx_tso_bytes		+= sq_stats->tso_bytes;
			s->tx_tso_inner_packets	+= sq_stats->tso_inner_packets;
			s->tx_tso_inner_bytes	+= sq_stats->tso_inner_bytes;
218 219 220
			s->tx_queue_stopped	+= sq_stats->stopped;
			s->tx_queue_wake	+= sq_stats->wake;
			s->tx_queue_dropped	+= sq_stats->dropped;
221
			s->tx_xmit_more		+= sq_stats->xmit_more;
222 223
			s->tx_csum_partial_inner += sq_stats->csum_partial_inner;
			tx_offload_none		+= sq_stats->csum_none;
224 225 226
		}
	}

227
	/* Update calculated offload counters */
228 229
	s->tx_csum_partial = s->tx_packets - tx_offload_none - s->tx_csum_partial_inner;
	s->rx_csum_unnecessary = s->rx_packets - s->rx_csum_none - s->rx_csum_complete;
230

231
	s->link_down_events_phy = MLX5_GET(ppcnt_reg,
232 233
				priv->stats.pport.phy_counters,
				counter_set.phys_layer_cntrs.link_down_events);
234
	memcpy(&priv->stats.sw, s, sizeof(*s));
235 236 237 238 239 240
}

static void mlx5e_update_vport_counters(struct mlx5e_priv *priv)
{
	int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out);
	u32 *out = (u32 *)priv->stats.vport.query_vport_out;
241
	u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {0};
242 243
	struct mlx5_core_dev *mdev = priv->mdev;

244 245 246 247 248
	MLX5_SET(query_vport_counter_in, in, opcode,
		 MLX5_CMD_OP_QUERY_VPORT_COUNTER);
	MLX5_SET(query_vport_counter_in, in, op_mod, 0);
	MLX5_SET(query_vport_counter_in, in, other_vport, 0);

249 250 251
	mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen);
}

252
static void mlx5e_update_pport_counters(struct mlx5e_priv *priv, bool full)
253 254 255
{
	struct mlx5e_pport_stats *pstats = &priv->stats.pport;
	struct mlx5_core_dev *mdev = priv->mdev;
256
	u32 in[MLX5_ST_SZ_DW(ppcnt_reg)] = {0};
257
	int sz = MLX5_ST_SZ_BYTES(ppcnt_reg);
258
	int prio;
259
	void *out;
260

261
	MLX5_SET(ppcnt_reg, in, local_port, 1);
262

263 264 265
	out = pstats->IEEE_802_3_counters;
	MLX5_SET(ppcnt_reg, in, grp, MLX5_IEEE_802_3_COUNTERS_GROUP);
	mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0);
266

267 268 269
	if (!full)
		return;

270 271 272 273 274 275 276
	out = pstats->RFC_2863_counters;
	MLX5_SET(ppcnt_reg, in, grp, MLX5_RFC_2863_COUNTERS_GROUP);
	mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0);

	out = pstats->RFC_2819_counters;
	MLX5_SET(ppcnt_reg, in, grp, MLX5_RFC_2819_COUNTERS_GROUP);
	mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0);
277

278 279 280 281
	out = pstats->phy_counters;
	MLX5_SET(ppcnt_reg, in, grp, MLX5_PHYSICAL_LAYER_COUNTERS_GROUP);
	mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0);

282 283 284 285 286 287
	if (MLX5_CAP_PCAM_FEATURE(mdev, ppcnt_statistical_group)) {
		out = pstats->phy_statistical_counters;
		MLX5_SET(ppcnt_reg, in, grp, MLX5_PHYSICAL_LAYER_STATISTICAL_GROUP);
		mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0);
	}

288 289 290 291 292 293 294
	MLX5_SET(ppcnt_reg, in, grp, MLX5_PER_PRIORITY_COUNTERS_GROUP);
	for (prio = 0; prio < NUM_PPORT_PRIO; prio++) {
		out = pstats->per_prio_counters[prio];
		MLX5_SET(ppcnt_reg, in, prio_tc, prio);
		mlx5_core_access_reg(mdev, in, sz, out, sz,
				     MLX5_REG_PPCNT, 0, 0);
	}
295 296 297 298 299
}

static void mlx5e_update_q_counter(struct mlx5e_priv *priv)
{
	struct mlx5e_qcounter_stats *qcnt = &priv->stats.qcnt;
300 301
	u32 out[MLX5_ST_SZ_DW(query_q_counter_out)];
	int err;
302 303 304 305

	if (!priv->q_counter)
		return;

306 307 308 309 310
	err = mlx5_core_query_q_counter(priv->mdev, priv->q_counter, 0, out, sizeof(out));
	if (err)
		return;

	qcnt->rx_out_of_buffer = MLX5_GET(query_q_counter_out, out, out_of_buffer);
311 312
}

313 314 315 316
static void mlx5e_update_pcie_counters(struct mlx5e_priv *priv)
{
	struct mlx5e_pcie_stats *pcie_stats = &priv->stats.pcie;
	struct mlx5_core_dev *mdev = priv->mdev;
317
	u32 in[MLX5_ST_SZ_DW(mpcnt_reg)] = {0};
318 319 320 321 322 323 324 325 326 327 328
	int sz = MLX5_ST_SZ_BYTES(mpcnt_reg);
	void *out;

	if (!MLX5_CAP_MCAM_FEATURE(mdev, pcie_performance_group))
		return;

	out = pcie_stats->pcie_perf_counters;
	MLX5_SET(mpcnt_reg, in, grp, MLX5_PCIE_PERFORMANCE_COUNTERS_GROUP);
	mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_MPCNT, 0, 0);
}

329
void mlx5e_update_stats(struct mlx5e_priv *priv, bool full)
330
{
331 332 333
	if (full)
		mlx5e_update_pcie_counters(priv);
	mlx5e_update_pport_counters(priv, full);
S
Saeed Mahameed 已提交
334 335
	mlx5e_update_vport_counters(priv);
	mlx5e_update_q_counter(priv);
336
	mlx5e_update_sw_counters(priv);
337 338
}

339 340 341 342 343
static void mlx5e_update_ndo_stats(struct mlx5e_priv *priv)
{
	mlx5e_update_stats(priv, false);
}

344
void mlx5e_update_stats_work(struct work_struct *work)
345 346 347 348 349 350
{
	struct delayed_work *dwork = to_delayed_work(work);
	struct mlx5e_priv *priv = container_of(dwork, struct mlx5e_priv,
					       update_stats_work);
	mutex_lock(&priv->state_lock);
	if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
351
		priv->profile->update_stats(priv);
352 353
		queue_delayed_work(priv->wq, dwork,
				   msecs_to_jiffies(MLX5E_UPDATE_STATS_INTERVAL));
354 355 356 357
	}
	mutex_unlock(&priv->state_lock);
}

358 359
static void mlx5e_async_event(struct mlx5_core_dev *mdev, void *vpriv,
			      enum mlx5_dev_event event, unsigned long param)
360
{
361
	struct mlx5e_priv *priv = vpriv;
362 363
	struct ptp_clock_event ptp_event;
	struct mlx5_eqe *eqe = NULL;
364

365
	if (!test_bit(MLX5E_STATE_ASYNC_EVENTS_ENABLED, &priv->state))
366 367
		return;

368 369 370
	switch (event) {
	case MLX5_DEV_EVENT_PORT_UP:
	case MLX5_DEV_EVENT_PORT_DOWN:
371
		queue_work(priv->wq, &priv->update_carrier_work);
372
		break;
373 374 375 376 377 378 379 380 381
	case MLX5_DEV_EVENT_PPS:
		eqe = (struct mlx5_eqe *)param;
		ptp_event.type = PTP_CLOCK_EXTTS;
		ptp_event.index = eqe->data.pps.pin;
		ptp_event.timestamp =
			timecounter_cyc2time(&priv->tstamp.clock,
					     be64_to_cpu(eqe->data.pps.time_stamp));
		mlx5e_pps_event_handler(vpriv, &ptp_event);
		break;
382 383 384 385 386 387 388
	default:
		break;
	}
}

static void mlx5e_enable_async_events(struct mlx5e_priv *priv)
{
389
	set_bit(MLX5E_STATE_ASYNC_EVENTS_ENABLED, &priv->state);
390 391 392 393
}

static void mlx5e_disable_async_events(struct mlx5e_priv *priv)
{
394
	clear_bit(MLX5E_STATE_ASYNC_EVENTS_ENABLED, &priv->state);
395
	synchronize_irq(mlx5_get_msix_vec(priv->mdev, MLX5_EQ_VEC_ASYNC));
396 397
}

398 399 400 401 402 403 404 405 406 407
static inline int mlx5e_get_wqe_mtt_sz(void)
{
	/* UMR copies MTTs in units of MLX5_UMR_MTT_ALIGNMENT bytes.
	 * To avoid copying garbage after the mtt array, we allocate
	 * a little more.
	 */
	return ALIGN(MLX5_MPWRQ_PAGES_PER_WQE * sizeof(__be64),
		     MLX5_UMR_MTT_ALIGNMENT);
}

S
Saeed Mahameed 已提交
408 409 410 411
static inline void mlx5e_build_umr_wqe(struct mlx5e_rq *rq,
				       struct mlx5e_icosq *sq,
				       struct mlx5e_umr_wqe *wqe,
				       u16 ix)
412 413 414 415
{
	struct mlx5_wqe_ctrl_seg      *cseg = &wqe->ctrl;
	struct mlx5_wqe_umr_ctrl_seg *ucseg = &wqe->uctrl;
	struct mlx5_wqe_data_seg      *dseg = &wqe->data;
416
	struct mlx5e_mpw_info *wi = &rq->mpwqe.info[ix];
417 418 419 420 421 422 423 424 425
	u8 ds_cnt = DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS);
	u32 umr_wqe_mtt_offset = mlx5e_get_wqe_mtt_offset(rq, ix);

	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;

	ucseg->flags = MLX5_UMR_TRANSLATION_OFFSET_EN;
426
	ucseg->xlt_octowords =
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
		cpu_to_be16(MLX5_MTT_OCTW(MLX5_MPWRQ_PAGES_PER_WQE));
	ucseg->bsf_octowords =
		cpu_to_be16(MLX5_MTT_OCTW(umr_wqe_mtt_offset));
	ucseg->mkey_mask     = cpu_to_be64(MLX5_MKEY_MASK_FREE);

	dseg->lkey = sq->mkey_be;
	dseg->addr = cpu_to_be64(wi->umr.mtt_addr);
}

static int mlx5e_rq_alloc_mpwqe_info(struct mlx5e_rq *rq,
				     struct mlx5e_channel *c)
{
	int wq_sz = mlx5_wq_ll_get_size(&rq->wq);
	int mtt_sz = mlx5e_get_wqe_mtt_sz();
	int mtt_alloc = mtt_sz + MLX5_UMR_ALIGN - 1;
	int i;

444 445 446
	rq->mpwqe.info = kzalloc_node(wq_sz * sizeof(*rq->mpwqe.info),
				      GFP_KERNEL, cpu_to_node(c->cpu));
	if (!rq->mpwqe.info)
447 448 449
		goto err_out;

	/* We allocate more than mtt_sz as we will align the pointer */
450
	rq->mpwqe.mtt_no_align = kzalloc_node(mtt_alloc * wq_sz, GFP_KERNEL,
451
					cpu_to_node(c->cpu));
452
	if (unlikely(!rq->mpwqe.mtt_no_align))
453 454 455
		goto err_free_wqe_info;

	for (i = 0; i < wq_sz; i++) {
456
		struct mlx5e_mpw_info *wi = &rq->mpwqe.info[i];
457

458
		wi->umr.mtt = PTR_ALIGN(rq->mpwqe.mtt_no_align + i * mtt_alloc,
459 460 461 462 463 464 465 466 467 468 469 470 471
					MLX5_UMR_ALIGN);
		wi->umr.mtt_addr = dma_map_single(c->pdev, wi->umr.mtt, mtt_sz,
						  PCI_DMA_TODEVICE);
		if (unlikely(dma_mapping_error(c->pdev, wi->umr.mtt_addr)))
			goto err_unmap_mtts;

		mlx5e_build_umr_wqe(rq, &c->icosq, &wi->umr.wqe, i);
	}

	return 0;

err_unmap_mtts:
	while (--i >= 0) {
472
		struct mlx5e_mpw_info *wi = &rq->mpwqe.info[i];
473 474 475 476

		dma_unmap_single(c->pdev, wi->umr.mtt_addr, mtt_sz,
				 PCI_DMA_TODEVICE);
	}
477
	kfree(rq->mpwqe.mtt_no_align);
478
err_free_wqe_info:
479
	kfree(rq->mpwqe.info);
480 481 482 483 484 485 486 487 488 489 490 491

err_out:
	return -ENOMEM;
}

static void mlx5e_rq_free_mpwqe_info(struct mlx5e_rq *rq)
{
	int wq_sz = mlx5_wq_ll_get_size(&rq->wq);
	int mtt_sz = mlx5e_get_wqe_mtt_sz();
	int i;

	for (i = 0; i < wq_sz; i++) {
492
		struct mlx5e_mpw_info *wi = &rq->mpwqe.info[i];
493 494 495 496

		dma_unmap_single(rq->pdev, wi->umr.mtt_addr, mtt_sz,
				 PCI_DMA_TODEVICE);
	}
497 498
	kfree(rq->mpwqe.mtt_no_align);
	kfree(rq->mpwqe.info);
499 500
}

501
static int mlx5e_create_umr_mkey(struct mlx5_core_dev *mdev,
T
Tariq Toukan 已提交
502 503
				 u64 npages, u8 page_shift,
				 struct mlx5_core_mkey *umr_mkey)
504 505 506 507 508 509
{
	int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
	void *mkc;
	u32 *in;
	int err;

T
Tariq Toukan 已提交
510 511 512
	if (!MLX5E_VALID_NUM_MTTS(npages))
		return -EINVAL;

513
	in = kvzalloc(inlen, GFP_KERNEL);
514 515 516 517 518 519 520 521 522 523 524 525 526
	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);
	MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_MTT);

	MLX5_SET(mkc, mkc, qpn, 0xffffff);
	MLX5_SET(mkc, mkc, pd, mdev->mlx5e_res.pdn);
T
Tariq Toukan 已提交
527
	MLX5_SET64(mkc, mkc, len, npages << page_shift);
528 529
	MLX5_SET(mkc, mkc, translations_octword_size,
		 MLX5_MTT_OCTW(npages));
T
Tariq Toukan 已提交
530
	MLX5_SET(mkc, mkc, log_page_size, page_shift);
531

T
Tariq Toukan 已提交
532
	err = mlx5_core_create_mkey(mdev, umr_mkey, in, inlen);
533 534 535 536 537

	kvfree(in);
	return err;
}

538
static int mlx5e_create_rq_umr_mkey(struct mlx5_core_dev *mdev, struct mlx5e_rq *rq)
T
Tariq Toukan 已提交
539
{
540
	u64 num_mtts = MLX5E_REQUIRED_MTTS(mlx5_wq_ll_get_size(&rq->wq));
T
Tariq Toukan 已提交
541

542
	return mlx5e_create_umr_mkey(mdev, num_mtts, PAGE_SHIFT, &rq->umr_mkey);
T
Tariq Toukan 已提交
543 544
}

545
static int mlx5e_alloc_rq(struct mlx5e_channel *c,
546 547
			  struct mlx5e_params *params,
			  struct mlx5e_rq_param *rqp,
548
			  struct mlx5e_rq *rq)
549
{
550
	struct mlx5_core_dev *mdev = c->mdev;
551
	void *rqc = rqp->rqc;
552
	void *rqc_wq = MLX5_ADDR_OF(rqc, rqc, wq);
553
	u32 byte_count;
554
	int npages;
555 556 557 558
	int wq_sz;
	int err;
	int i;

559
	rqp->wq.db_numa_node = cpu_to_node(c->cpu);
560

561
	err = mlx5_wq_ll_create(mdev, &rqp->wq, rqc_wq, &rq->wq,
562 563 564 565 566 567 568 569
				&rq->wq_ctrl);
	if (err)
		return err;

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

	wq_sz = mlx5_wq_ll_get_size(&rq->wq);

570
	rq->wq_type = params->rq_wq_type;
571 572
	rq->pdev    = c->pdev;
	rq->netdev  = c->netdev;
573
	rq->tstamp  = c->tstamp;
574 575
	rq->channel = c;
	rq->ix      = c->ix;
576
	rq->mdev    = mdev;
577

578
	rq->xdp_prog = params->xdp_prog ? bpf_prog_inc(params->xdp_prog) : NULL;
579 580 581 582 583
	if (IS_ERR(rq->xdp_prog)) {
		err = PTR_ERR(rq->xdp_prog);
		rq->xdp_prog = NULL;
		goto err_rq_wq_destroy;
	}
584

585 586
	rq->buff.map_dir = rq->xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;
	rq->rx_headroom = params->rq_headroom;
587

588
	switch (rq->wq_type) {
589
	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
590

591
		rq->alloc_wqe = mlx5e_alloc_rx_mpwqe;
592
		rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe;
593

594 595 596 597 598 599 600
		rq->handle_rx_cqe = c->priv->profile->rx_handlers.handle_rx_cqe_mpwqe;
		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;
		}

601 602
		rq->mpwqe_stride_sz = BIT(params->mpwqe_log_stride_sz);
		rq->mpwqe_num_strides = BIT(params->mpwqe_log_num_strides);
603 604 605

		rq->buff.wqe_sz = rq->mpwqe_stride_sz * rq->mpwqe_num_strides;
		byte_count = rq->buff.wqe_sz;
T
Tariq Toukan 已提交
606

607
		err = mlx5e_create_rq_umr_mkey(mdev, rq);
608 609
		if (err)
			goto err_rq_wq_destroy;
T
Tariq Toukan 已提交
610 611 612 613 614
		rq->mkey_be = cpu_to_be32(rq->umr_mkey.key);

		err = mlx5e_rq_alloc_mpwqe_info(rq, c);
		if (err)
			goto err_destroy_umr_mkey;
615 616
		break;
	default: /* MLX5_WQ_TYPE_LINKED_LIST */
617 618 619 620
		rq->wqe.frag_info =
			kzalloc_node(wq_sz * sizeof(*rq->wqe.frag_info),
				     GFP_KERNEL, cpu_to_node(c->cpu));
		if (!rq->wqe.frag_info) {
621 622 623 624
			err = -ENOMEM;
			goto err_rq_wq_destroy;
		}
		rq->alloc_wqe = mlx5e_alloc_rx_wqe;
625
		rq->dealloc_wqe = mlx5e_dealloc_rx_wqe;
626

627 628
		rq->handle_rx_cqe = c->priv->profile->rx_handlers.handle_rx_cqe;
		if (!rq->handle_rx_cqe) {
629
			kfree(rq->wqe.frag_info);
630 631 632 633 634
			err = -EINVAL;
			netdev_err(c->netdev, "RX handler of RQ is not set, err %d\n", err);
			goto err_rq_wq_destroy;
		}

635 636
		rq->buff.wqe_sz = params->lro_en  ?
				params->lro_wqe_sz :
637
				MLX5E_SW2HW_MTU(c->priv, c->netdev->mtu);
638
		rq->wqe.page_reuse = !params->xdp_prog && !params->lro_en;
639 640 641
		byte_count = rq->buff.wqe_sz;

		/* calc the required page order */
642 643
		rq->wqe.frag_sz = MLX5_SKB_FRAG_SZ(rq->rx_headroom + byte_count);
		npages = DIV_ROUND_UP(rq->wqe.frag_sz, PAGE_SIZE);
644 645
		rq->buff.page_order = order_base_2(npages);

646
		byte_count |= MLX5_HW_START_PADDING;
647
		rq->mkey_be = c->mkey_be;
648
	}
649 650 651 652

	for (i = 0; i < wq_sz; i++) {
		struct mlx5e_rx_wqe *wqe = mlx5_wq_ll_get_wqe(&rq->wq, i);

653
		wqe->data.byte_count = cpu_to_be32(byte_count);
654
		wqe->data.lkey = rq->mkey_be;
655 656
	}

657
	INIT_WORK(&rq->am.work, mlx5e_rx_am_work);
658
	rq->am.mode = params->rx_cq_period_mode;
659 660 661
	rq->page_cache.head = 0;
	rq->page_cache.tail = 0;

662 663
	return 0;

T
Tariq Toukan 已提交
664 665 666
err_destroy_umr_mkey:
	mlx5_core_destroy_mkey(mdev, &rq->umr_mkey);

667
err_rq_wq_destroy:
668 669
	if (rq->xdp_prog)
		bpf_prog_put(rq->xdp_prog);
670 671 672 673 674
	mlx5_wq_destroy(&rq->wq_ctrl);

	return err;
}

675
static void mlx5e_free_rq(struct mlx5e_rq *rq)
676
{
677 678
	int i;

679 680 681
	if (rq->xdp_prog)
		bpf_prog_put(rq->xdp_prog);

682 683
	switch (rq->wq_type) {
	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
684
		mlx5e_rq_free_mpwqe_info(rq);
685
		mlx5_core_destroy_mkey(rq->mdev, &rq->umr_mkey);
686 687
		break;
	default: /* MLX5_WQ_TYPE_LINKED_LIST */
688
		kfree(rq->wqe.frag_info);
689 690
	}

691 692 693 694 695 696
	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);
	}
697 698 699
	mlx5_wq_destroy(&rq->wq_ctrl);
}

700 701
static int mlx5e_create_rq(struct mlx5e_rq *rq,
			   struct mlx5e_rq_param *param)
702
{
703
	struct mlx5_core_dev *mdev = rq->mdev;
704 705 706 707 708 709 710 711 712

	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;
713
	in = kvzalloc(inlen, GFP_KERNEL);
714 715 716 717 718 719 720 721
	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));

722
	MLX5_SET(rqc,  rqc, cqn,		rq->cq.mcq.cqn);
723 724
	MLX5_SET(rqc,  rqc, state,		MLX5_RQC_STATE_RST);
	MLX5_SET(wq,   wq,  log_wq_pg_sz,	rq->wq_ctrl.buf.page_shift -
725
						MLX5_ADAPTER_PAGE_SHIFT);
726 727 728 729 730
	MLX5_SET64(wq, wq,  dbr_addr,		rq->wq_ctrl.db.dma);

	mlx5_fill_page_array(&rq->wq_ctrl.buf,
			     (__be64 *)MLX5_ADDR_OF(wq, wq, pas));

731
	err = mlx5_core_create_rq(mdev, in, inlen, &rq->rqn);
732 733 734 735 736 737

	kvfree(in);

	return err;
}

738 739
static int mlx5e_modify_rq_state(struct mlx5e_rq *rq, int curr_state,
				 int next_state)
740 741
{
	struct mlx5e_channel *c = rq->channel;
742
	struct mlx5_core_dev *mdev = c->mdev;
743 744 745 746 747 748 749

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

	inlen = MLX5_ST_SZ_BYTES(modify_rq_in);
750
	in = kvzalloc(inlen, GFP_KERNEL);
751 752 753 754 755 756 757 758
	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);

759
	err = mlx5_core_modify_rq(mdev, rq->rqn, in, inlen);
760 761 762 763 764 765

	kvfree(in);

	return err;
}

766 767 768 769 770 771 772 773 774 775 776 777
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);
778
	in = kvzalloc(inlen, GFP_KERNEL);
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796
	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;
}

797 798 799
static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd)
{
	struct mlx5e_channel *c = rq->channel;
800
	struct mlx5_core_dev *mdev = c->mdev;
801 802 803 804 805 806
	void *in;
	void *rqc;
	int inlen;
	int err;

	inlen = MLX5_ST_SZ_BYTES(modify_rq_in);
807
	in = kvzalloc(inlen, GFP_KERNEL);
808 809 810 811 812 813
	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);
814 815
	MLX5_SET64(modify_rq_in, in, modify_bitmask,
		   MLX5_MODIFY_RQ_IN_MODIFY_BITMASK_VSD);
816 817 818 819 820 821 822 823 824 825
	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;
}

826
static void mlx5e_destroy_rq(struct mlx5e_rq *rq)
827
{
828
	mlx5_core_destroy_rq(rq->mdev, rq->rqn);
829 830 831 832
}

static int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq)
{
833
	unsigned long exp_time = jiffies + msecs_to_jiffies(20000);
834
	struct mlx5e_channel *c = rq->channel;
835

836
	struct mlx5_wq_ll *wq = &rq->wq;
837
	u16 min_wqes = mlx5_min_rx_wqes(rq->wq_type, mlx5_wq_ll_get_size(wq));
838

839
	while (time_before(jiffies, exp_time)) {
840
		if (wq->cur_sz >= min_wqes)
841 842 843 844 845
			return 0;

		msleep(20);
	}

846
	netdev_warn(c->netdev, "Failed to get min RX wqes on RQN[0x%x] wq cur_sz(%d) min_rx_wqes(%d)\n",
847
		    rq->rqn, wq->cur_sz, min_wqes);
848 849 850
	return -ETIMEDOUT;
}

851 852 853 854 855 856 857
static void mlx5e_free_rx_descs(struct mlx5e_rq *rq)
{
	struct mlx5_wq_ll *wq = &rq->wq;
	struct mlx5e_rx_wqe *wqe;
	__be16 wqe_ix_be;
	u16 wqe_ix;

858 859
	/* UMR WQE (if in progress) is always at wq->head */
	if (test_bit(MLX5E_RQ_STATE_UMR_WQE_IN_PROGRESS, &rq->state))
860
		mlx5e_free_rx_mpwqe(rq, &rq->mpwqe.info[wq->head]);
861

862 863 864 865 866 867 868 869
	while (!mlx5_wq_ll_is_empty(wq)) {
		wqe_ix_be = *wq->tail_next;
		wqe_ix    = be16_to_cpu(wqe_ix_be);
		wqe       = mlx5_wq_ll_get_wqe(&rq->wq, wqe_ix);
		rq->dealloc_wqe(rq, wqe_ix);
		mlx5_wq_ll_pop(&rq->wq, wqe_ix_be,
			       &wqe->next.next_wqe_index);
	}
870 871 872 873 874 875 876 877 878 879

	if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST && rq->wqe.page_reuse) {
		/* Clean outstanding pages on handled WQEs that decided to do page-reuse,
		 * but yet to be re-posted.
		 */
		int wq_sz = mlx5_wq_ll_get_size(&rq->wq);

		for (wqe_ix = 0; wqe_ix < wq_sz; wqe_ix++)
			rq->dealloc_wqe(rq, wqe_ix);
	}
880 881
}

882
static int mlx5e_open_rq(struct mlx5e_channel *c,
883
			 struct mlx5e_params *params,
884 885 886 887 888
			 struct mlx5e_rq_param *param,
			 struct mlx5e_rq *rq)
{
	int err;

889
	err = mlx5e_alloc_rq(c, params, param, rq);
890 891 892
	if (err)
		return err;

893
	err = mlx5e_create_rq(rq, param);
894
	if (err)
895
		goto err_free_rq;
896

897
	err = mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY);
898
	if (err)
899
		goto err_destroy_rq;
900

901
	if (params->rx_am_enabled)
902 903
		set_bit(MLX5E_RQ_STATE_AM, &c->rq.state);

904 905 906 907
	return 0;

err_destroy_rq:
	mlx5e_destroy_rq(rq);
908 909
err_free_rq:
	mlx5e_free_rq(rq);
910 911 912 913

	return err;
}

914 915 916 917 918 919 920 921 922 923 924 925 926 927
static void mlx5e_activate_rq(struct mlx5e_rq *rq)
{
	struct mlx5e_icosq *sq = &rq->channel->icosq;
	u16 pi = sq->pc & sq->wq.sz_m1;
	struct mlx5e_tx_wqe *nopwqe;

	set_bit(MLX5E_RQ_STATE_ENABLED, &rq->state);
	sq->db.ico_wqe[pi].opcode     = MLX5_OPCODE_NOP;
	sq->db.ico_wqe[pi].num_wqebbs = 1;
	nopwqe = mlx5e_post_nop(&sq->wq, sq->sqn, &sq->pc);
	mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, &nopwqe->ctrl);
}

static void mlx5e_deactivate_rq(struct mlx5e_rq *rq)
928
{
929
	clear_bit(MLX5E_RQ_STATE_ENABLED, &rq->state);
930
	napi_synchronize(&rq->channel->napi); /* prevent mlx5e_post_rx_wqes */
931
}
932

933 934 935
static void mlx5e_close_rq(struct mlx5e_rq *rq)
{
	cancel_work_sync(&rq->am.work);
936
	mlx5e_destroy_rq(rq);
937 938
	mlx5e_free_rx_descs(rq);
	mlx5e_free_rq(rq);
939 940
}

S
Saeed Mahameed 已提交
941
static void mlx5e_free_xdpsq_db(struct mlx5e_xdpsq *sq)
942
{
S
Saeed Mahameed 已提交
943
	kfree(sq->db.di);
944 945
}

S
Saeed Mahameed 已提交
946
static int mlx5e_alloc_xdpsq_db(struct mlx5e_xdpsq *sq, int numa)
947 948 949
{
	int wq_sz = mlx5_wq_cyc_get_size(&sq->wq);

S
Saeed Mahameed 已提交
950
	sq->db.di = kzalloc_node(sizeof(*sq->db.di) * wq_sz,
951
				     GFP_KERNEL, numa);
S
Saeed Mahameed 已提交
952 953
	if (!sq->db.di) {
		mlx5e_free_xdpsq_db(sq);
954 955 956 957 958 959
		return -ENOMEM;
	}

	return 0;
}

S
Saeed Mahameed 已提交
960
static int mlx5e_alloc_xdpsq(struct mlx5e_channel *c,
961
			     struct mlx5e_params *params,
S
Saeed Mahameed 已提交
962 963 964 965
			     struct mlx5e_sq_param *param,
			     struct mlx5e_xdpsq *sq)
{
	void *sqc_wq               = MLX5_ADDR_OF(sqc, param->sqc, wq);
966
	struct mlx5_core_dev *mdev = c->mdev;
S
Saeed Mahameed 已提交
967 968 969 970 971 972
	int err;

	sq->pdev      = c->pdev;
	sq->mkey_be   = c->mkey_be;
	sq->channel   = c;
	sq->uar_map   = mdev->mlx5e_res.bfreg.map;
973
	sq->min_inline_mode = params->tx_min_inline_mode;
S
Saeed Mahameed 已提交
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999

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

	err = mlx5e_alloc_xdpsq_db(sq, cpu_to_node(c->cpu));
	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)
1000
{
1001
	kfree(sq->db.ico_wqe);
1002 1003
}

S
Saeed Mahameed 已提交
1004
static int mlx5e_alloc_icosq_db(struct mlx5e_icosq *sq, int numa)
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
{
	u8 wq_sz = mlx5_wq_cyc_get_size(&sq->wq);

	sq->db.ico_wqe = kzalloc_node(sizeof(*sq->db.ico_wqe) * wq_sz,
				      GFP_KERNEL, numa);
	if (!sq->db.ico_wqe)
		return -ENOMEM;

	return 0;
}

S
Saeed Mahameed 已提交
1016 1017 1018
static int mlx5e_alloc_icosq(struct mlx5e_channel *c,
			     struct mlx5e_sq_param *param,
			     struct mlx5e_icosq *sq)
1019
{
S
Saeed Mahameed 已提交
1020
	void *sqc_wq               = MLX5_ADDR_OF(sqc, param->sqc, wq);
1021
	struct mlx5_core_dev *mdev = c->mdev;
S
Saeed Mahameed 已提交
1022
	int err;
1023

S
Saeed Mahameed 已提交
1024 1025 1026 1027
	sq->pdev      = c->pdev;
	sq->mkey_be   = c->mkey_be;
	sq->channel   = c;
	sq->uar_map   = mdev->mlx5e_res.bfreg.map;
1028

S
Saeed Mahameed 已提交
1029 1030 1031 1032 1033
	param->wq.db_numa_node = cpu_to_node(c->cpu);
	err = mlx5_wq_cyc_create(mdev, &param->wq, sqc_wq, &sq->wq, &sq->wq_ctrl);
	if (err)
		return err;
	sq->wq.db = &sq->wq.db[MLX5_SND_DBR];
1034

S
Saeed Mahameed 已提交
1035 1036 1037 1038 1039
	err = mlx5e_alloc_icosq_db(sq, cpu_to_node(c->cpu));
	if (err)
		goto err_sq_wq_destroy;

	sq->edge = (sq->wq.sz_m1 + 1) - MLX5E_ICOSQ_MAX_WQEBBS;
1040 1041

	return 0;
S
Saeed Mahameed 已提交
1042 1043 1044 1045 1046

err_sq_wq_destroy:
	mlx5_wq_destroy(&sq->wq_ctrl);

	return err;
1047 1048
}

S
Saeed Mahameed 已提交
1049
static void mlx5e_free_icosq(struct mlx5e_icosq *sq)
1050
{
S
Saeed Mahameed 已提交
1051 1052
	mlx5e_free_icosq_db(sq);
	mlx5_wq_destroy(&sq->wq_ctrl);
1053 1054
}

S
Saeed Mahameed 已提交
1055
static void mlx5e_free_txqsq_db(struct mlx5e_txqsq *sq)
1056
{
S
Saeed Mahameed 已提交
1057 1058
	kfree(sq->db.wqe_info);
	kfree(sq->db.dma_fifo);
1059 1060
}

S
Saeed Mahameed 已提交
1061
static int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa)
1062
{
S
Saeed Mahameed 已提交
1063 1064 1065 1066 1067 1068 1069
	int wq_sz = mlx5_wq_cyc_get_size(&sq->wq);
	int df_sz = wq_sz * MLX5_SEND_WQEBB_NUM_DS;

	sq->db.dma_fifo = kzalloc_node(df_sz * sizeof(*sq->db.dma_fifo),
					   GFP_KERNEL, numa);
	sq->db.wqe_info = kzalloc_node(wq_sz * sizeof(*sq->db.wqe_info),
					   GFP_KERNEL, numa);
S
Saeed Mahameed 已提交
1070
	if (!sq->db.dma_fifo || !sq->db.wqe_info) {
S
Saeed Mahameed 已提交
1071 1072
		mlx5e_free_txqsq_db(sq);
		return -ENOMEM;
1073
	}
S
Saeed Mahameed 已提交
1074 1075 1076 1077

	sq->dma_fifo_mask = df_sz - 1;

	return 0;
1078 1079
}

S
Saeed Mahameed 已提交
1080
static int mlx5e_alloc_txqsq(struct mlx5e_channel *c,
1081
			     int txq_ix,
1082
			     struct mlx5e_params *params,
S
Saeed Mahameed 已提交
1083 1084
			     struct mlx5e_sq_param *param,
			     struct mlx5e_txqsq *sq)
1085
{
S
Saeed Mahameed 已提交
1086
	void *sqc_wq               = MLX5_ADDR_OF(sqc, param->sqc, wq);
1087
	struct mlx5_core_dev *mdev = c->mdev;
1088 1089
	int err;

1090
	sq->pdev      = c->pdev;
1091
	sq->tstamp    = c->tstamp;
1092 1093
	sq->mkey_be   = c->mkey_be;
	sq->channel   = c;
1094
	sq->txq_ix    = txq_ix;
1095
	sq->uar_map   = mdev->mlx5e_res.bfreg.map;
1096 1097
	sq->max_inline      = params->tx_max_inline;
	sq->min_inline_mode = params->tx_min_inline_mode;
1098

1099
	param->wq.db_numa_node = cpu_to_node(c->cpu);
S
Saeed Mahameed 已提交
1100
	err = mlx5_wq_cyc_create(mdev, &param->wq, sqc_wq, &sq->wq, &sq->wq_ctrl);
1101
	if (err)
1102
		return err;
S
Saeed Mahameed 已提交
1103
	sq->wq.db    = &sq->wq.db[MLX5_SND_DBR];
1104

S
Saeed Mahameed 已提交
1105
	err = mlx5e_alloc_txqsq_db(sq, cpu_to_node(c->cpu));
D
Dan Carpenter 已提交
1106
	if (err)
1107 1108
		goto err_sq_wq_destroy;

S
Saeed Mahameed 已提交
1109
	sq->edge = (sq->wq.sz_m1 + 1) - MLX5_SEND_WQE_MAX_WQEBBS;
1110 1111 1112 1113 1114 1115 1116 1117 1118

	return 0;

err_sq_wq_destroy:
	mlx5_wq_destroy(&sq->wq_ctrl);

	return err;
}

S
Saeed Mahameed 已提交
1119
static void mlx5e_free_txqsq(struct mlx5e_txqsq *sq)
1120
{
S
Saeed Mahameed 已提交
1121
	mlx5e_free_txqsq_db(sq);
1122 1123 1124
	mlx5_wq_destroy(&sq->wq_ctrl);
}

1125 1126 1127 1128 1129 1130 1131 1132
struct mlx5e_create_sq_param {
	struct mlx5_wq_ctrl        *wq_ctrl;
	u32                         cqn;
	u32                         tisn;
	u8                          tis_lst_sz;
	u8                          min_inline_mode;
};

1133
static int mlx5e_create_sq(struct mlx5_core_dev *mdev,
1134 1135 1136
			   struct mlx5e_sq_param *param,
			   struct mlx5e_create_sq_param *csp,
			   u32 *sqn)
1137 1138 1139 1140 1141 1142 1143 1144
{
	void *in;
	void *sqc;
	void *wq;
	int inlen;
	int err;

	inlen = MLX5_ST_SZ_BYTES(create_sq_in) +
1145
		sizeof(u64) * csp->wq_ctrl->buf.npages;
1146
	in = kvzalloc(inlen, GFP_KERNEL);
1147 1148 1149 1150 1151 1152 1153
	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));
1154 1155 1156
	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);
1157 1158

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

1161
	MLX5_SET(sqc,  sqc, state, MLX5_SQC_STATE_RST);
1162 1163

	MLX5_SET(wq,   wq, wq_type,       MLX5_WQ_TYPE_CYCLIC);
1164
	MLX5_SET(wq,   wq, uar_page,      mdev->mlx5e_res.bfreg.index);
1165
	MLX5_SET(wq,   wq, log_wq_pg_sz,  csp->wq_ctrl->buf.page_shift -
1166
					  MLX5_ADAPTER_PAGE_SHIFT);
1167
	MLX5_SET64(wq, wq, dbr_addr,      csp->wq_ctrl->db.dma);
1168

1169
	mlx5_fill_page_array(&csp->wq_ctrl->buf, (__be64 *)MLX5_ADDR_OF(wq, wq, pas));
1170

1171
	err = mlx5_core_create_sq(mdev, in, inlen, sqn);
1172 1173 1174 1175 1176 1177

	kvfree(in);

	return err;
}

1178 1179 1180 1181 1182 1183 1184
struct mlx5e_modify_sq_param {
	int curr_state;
	int next_state;
	bool rl_update;
	int rl_index;
};

1185
static int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn,
1186
			   struct mlx5e_modify_sq_param *p)
1187 1188 1189 1190 1191 1192 1193
{
	void *in;
	void *sqc;
	int inlen;
	int err;

	inlen = MLX5_ST_SZ_BYTES(modify_sq_in);
1194
	in = kvzalloc(inlen, GFP_KERNEL);
1195 1196 1197 1198 1199
	if (!in)
		return -ENOMEM;

	sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx);

1200 1201 1202
	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) {
1203
		MLX5_SET64(modify_sq_in, in, modify_bitmask, 1);
1204
		MLX5_SET(sqc,  sqc, packet_pacing_rate_limit_index, p->rl_index);
1205
	}
1206

1207
	err = mlx5_core_modify_sq(mdev, sqn, in, inlen);
1208 1209 1210 1211 1212 1213

	kvfree(in);

	return err;
}

1214
static void mlx5e_destroy_sq(struct mlx5_core_dev *mdev, u32 sqn)
1215
{
1216
	mlx5_core_destroy_sq(mdev, sqn);
1217 1218
}

1219
static int mlx5e_create_sq_rdy(struct mlx5_core_dev *mdev,
S
Saeed Mahameed 已提交
1220 1221 1222
			       struct mlx5e_sq_param *param,
			       struct mlx5e_create_sq_param *csp,
			       u32 *sqn)
1223
{
1224
	struct mlx5e_modify_sq_param msp = {0};
S
Saeed Mahameed 已提交
1225 1226
	int err;

1227
	err = mlx5e_create_sq(mdev, param, csp, sqn);
S
Saeed Mahameed 已提交
1228 1229 1230 1231 1232
	if (err)
		return err;

	msp.curr_state = MLX5_SQC_STATE_RST;
	msp.next_state = MLX5_SQC_STATE_RDY;
1233
	err = mlx5e_modify_sq(mdev, *sqn, &msp);
S
Saeed Mahameed 已提交
1234
	if (err)
1235
		mlx5e_destroy_sq(mdev, *sqn);
S
Saeed Mahameed 已提交
1236 1237 1238 1239

	return err;
}

1240 1241 1242
static int mlx5e_set_sq_maxrate(struct net_device *dev,
				struct mlx5e_txqsq *sq, u32 rate);

S
Saeed Mahameed 已提交
1243
static int mlx5e_open_txqsq(struct mlx5e_channel *c,
1244
			    u32 tisn,
1245
			    int txq_ix,
1246
			    struct mlx5e_params *params,
S
Saeed Mahameed 已提交
1247 1248 1249 1250
			    struct mlx5e_sq_param *param,
			    struct mlx5e_txqsq *sq)
{
	struct mlx5e_create_sq_param csp = {};
1251
	u32 tx_rate;
1252 1253
	int err;

1254
	err = mlx5e_alloc_txqsq(c, txq_ix, params, param, sq);
1255 1256 1257
	if (err)
		return err;

1258
	csp.tisn            = tisn;
S
Saeed Mahameed 已提交
1259
	csp.tis_lst_sz      = 1;
1260 1261 1262
	csp.cqn             = sq->cq.mcq.cqn;
	csp.wq_ctrl         = &sq->wq_ctrl;
	csp.min_inline_mode = sq->min_inline_mode;
1263
	err = mlx5e_create_sq_rdy(c->mdev, param, &csp, &sq->sqn);
1264
	if (err)
S
Saeed Mahameed 已提交
1265
		goto err_free_txqsq;
1266

1267
	tx_rate = c->priv->tx_rates[sq->txq_ix];
1268
	if (tx_rate)
1269
		mlx5e_set_sq_maxrate(c->netdev, sq, tx_rate);
1270

1271 1272
	return 0;

S
Saeed Mahameed 已提交
1273
err_free_txqsq:
1274
	clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
S
Saeed Mahameed 已提交
1275
	mlx5e_free_txqsq(sq);
1276 1277 1278 1279

	return err;
}

1280 1281
static void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq)
{
1282
	sq->txq = netdev_get_tx_queue(sq->channel->netdev, sq->txq_ix);
1283 1284 1285 1286 1287
	set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
	netdev_tx_reset_queue(sq->txq);
	netif_tx_start_queue(sq->txq);
}

1288 1289 1290 1291 1292 1293 1294
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);
}

1295
static void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq)
1296
{
1297 1298
	struct mlx5e_channel *c = sq->channel;

1299
	clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
1300
	/* prevent netif_tx_wake_queue */
1301
	napi_synchronize(&c->napi);
1302

S
Saeed Mahameed 已提交
1303
	netif_tx_disable_queue(sq->txq);
1304

S
Saeed Mahameed 已提交
1305 1306 1307
	/* last doorbell out, godspeed .. */
	if (mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, 1)) {
		struct mlx5e_tx_wqe *nop;
1308

S
Saeed Mahameed 已提交
1309
		sq->db.wqe_info[(sq->pc & sq->wq.sz_m1)].skb = NULL;
S
Saeed Mahameed 已提交
1310 1311
		nop = mlx5e_post_nop(&sq->wq, sq->sqn, &sq->pc);
		mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, &nop->ctrl);
1312
	}
1313 1314 1315 1316 1317
}

static void mlx5e_close_txqsq(struct mlx5e_txqsq *sq)
{
	struct mlx5e_channel *c = sq->channel;
1318
	struct mlx5_core_dev *mdev = c->mdev;
1319

1320
	mlx5e_destroy_sq(mdev, sq->sqn);
1321 1322
	if (sq->rate_limit)
		mlx5_rl_remove_rate(mdev, sq->rate_limit);
S
Saeed Mahameed 已提交
1323 1324 1325 1326 1327
	mlx5e_free_txqsq_descs(sq);
	mlx5e_free_txqsq(sq);
}

static int mlx5e_open_icosq(struct mlx5e_channel *c,
1328
			    struct mlx5e_params *params,
S
Saeed Mahameed 已提交
1329 1330 1331 1332 1333 1334
			    struct mlx5e_sq_param *param,
			    struct mlx5e_icosq *sq)
{
	struct mlx5e_create_sq_param csp = {};
	int err;

1335
	err = mlx5e_alloc_icosq(c, param, sq);
S
Saeed Mahameed 已提交
1336 1337 1338 1339 1340
	if (err)
		return err;

	csp.cqn             = sq->cq.mcq.cqn;
	csp.wq_ctrl         = &sq->wq_ctrl;
1341
	csp.min_inline_mode = params->tx_min_inline_mode;
S
Saeed Mahameed 已提交
1342
	set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
1343
	err = mlx5e_create_sq_rdy(c->mdev, param, &csp, &sq->sqn);
S
Saeed Mahameed 已提交
1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362
	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);

1363
	mlx5e_destroy_sq(c->mdev, sq->sqn);
S
Saeed Mahameed 已提交
1364 1365 1366 1367
	mlx5e_free_icosq(sq);
}

static int mlx5e_open_xdpsq(struct mlx5e_channel *c,
1368
			    struct mlx5e_params *params,
S
Saeed Mahameed 已提交
1369 1370 1371 1372 1373 1374 1375 1376 1377
			    struct mlx5e_sq_param *param,
			    struct mlx5e_xdpsq *sq)
{
	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;

1378
	err = mlx5e_alloc_xdpsq(c, params, param, sq);
S
Saeed Mahameed 已提交
1379 1380 1381 1382
	if (err)
		return err;

	csp.tis_lst_sz      = 1;
1383
	csp.tisn            = c->priv->tisn[0]; /* tc = 0 */
S
Saeed Mahameed 已提交
1384 1385 1386 1387
	csp.cqn             = sq->cq.mcq.cqn;
	csp.wq_ctrl         = &sq->wq_ctrl;
	csp.min_inline_mode = sq->min_inline_mode;
	set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
1388
	err = mlx5e_create_sq_rdy(c->mdev, param, &csp, &sq->sqn);
S
Saeed Mahameed 已提交
1389 1390 1391 1392 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
	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);

1427
	mlx5e_destroy_sq(c->mdev, sq->sqn);
S
Saeed Mahameed 已提交
1428 1429
	mlx5e_free_xdpsq_descs(sq);
	mlx5e_free_xdpsq(sq);
1430 1431
}

1432 1433 1434
static int mlx5e_alloc_cq_common(struct mlx5_core_dev *mdev,
				 struct mlx5e_cq_param *param,
				 struct mlx5e_cq *cq)
1435 1436 1437
{
	struct mlx5_core_cq *mcq = &cq->mcq;
	int eqn_not_used;
1438
	unsigned int irqn;
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
	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;
	}

1465
	cq->mdev = mdev;
1466 1467 1468 1469

	return 0;
}

1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
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;

	param->wq.buf_numa_node = cpu_to_node(c->cpu);
	param->wq.db_numa_node  = cpu_to_node(c->cpu);
	param->eq_ix   = c->ix;

	err = mlx5e_alloc_cq_common(mdev, param, cq);

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

	return err;
}

1489
static void mlx5e_free_cq(struct mlx5e_cq *cq)
1490
{
1491
	mlx5_cqwq_destroy(&cq->wq_ctrl);
1492 1493
}

1494
static int mlx5e_create_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
1495
{
1496
	struct mlx5_core_dev *mdev = cq->mdev;
1497 1498 1499 1500 1501
	struct mlx5_core_cq *mcq = &cq->mcq;

	void *in;
	void *cqc;
	int inlen;
1502
	unsigned int irqn_not_used;
1503 1504 1505 1506
	int eqn;
	int err;

	inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
1507
		sizeof(u64) * cq->wq_ctrl.frag_buf.npages;
1508
	in = kvzalloc(inlen, GFP_KERNEL);
1509 1510 1511 1512 1513 1514 1515
	if (!in)
		return -ENOMEM;

	cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context);

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

1516 1517
	mlx5_fill_page_frag_array(&cq->wq_ctrl.frag_buf,
				  (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas));
1518 1519 1520

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

T
Tariq Toukan 已提交
1521
	MLX5_SET(cqc,   cqc, cq_period_mode, param->cq_period_mode);
1522
	MLX5_SET(cqc,   cqc, c_eqn,         eqn);
E
Eli Cohen 已提交
1523
	MLX5_SET(cqc,   cqc, uar_page,      mdev->priv.uar->index);
1524
	MLX5_SET(cqc,   cqc, log_page_size, cq->wq_ctrl.frag_buf.page_shift -
1525
					    MLX5_ADAPTER_PAGE_SHIFT);
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539
	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;
}

1540
static void mlx5e_destroy_cq(struct mlx5e_cq *cq)
1541
{
1542
	mlx5_core_destroy_cq(cq->mdev, &cq->mcq);
1543 1544 1545
}

static int mlx5e_open_cq(struct mlx5e_channel *c,
1546
			 struct mlx5e_cq_moder moder,
1547
			 struct mlx5e_cq_param *param,
1548
			 struct mlx5e_cq *cq)
1549
{
1550
	struct mlx5_core_dev *mdev = c->mdev;
1551 1552
	int err;

1553
	err = mlx5e_alloc_cq(c, param, cq);
1554 1555 1556
	if (err)
		return err;

1557
	err = mlx5e_create_cq(cq, param);
1558
	if (err)
1559
		goto err_free_cq;
1560

1561
	if (MLX5_CAP_GEN(mdev, cq_moderation))
1562
		mlx5_core_modify_cq_moderation(mdev, &cq->mcq, moder.usec, moder.pkts);
1563 1564
	return 0;

1565 1566
err_free_cq:
	mlx5e_free_cq(cq);
1567 1568 1569 1570 1571 1572 1573

	return err;
}

static void mlx5e_close_cq(struct mlx5e_cq *cq)
{
	mlx5e_destroy_cq(cq);
1574
	mlx5e_free_cq(cq);
1575 1576 1577 1578 1579 1580 1581 1582
}

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

static int mlx5e_open_tx_cqs(struct mlx5e_channel *c,
1583
			     struct mlx5e_params *params,
1584 1585 1586 1587 1588 1589
			     struct mlx5e_channel_param *cparam)
{
	int err;
	int tc;

	for (tc = 0; tc < c->num_tc; tc++) {
1590 1591
		err = mlx5e_open_cq(c, params->tx_cq_moderation,
				    &cparam->tx_cq, &c->sq[tc].cq);
1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613
		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,
1614
			  struct mlx5e_params *params,
1615 1616 1617 1618 1619
			  struct mlx5e_channel_param *cparam)
{
	int err;
	int tc;

1620 1621
	for (tc = 0; tc < params->num_tc; tc++) {
		int txq_ix = c->ix + tc * params->num_channels;
1622

1623 1624
		err = mlx5e_open_txqsq(c, c->priv->tisn[tc], txq_ix,
				       params, &cparam->sq, &c->sq[tc]);
1625 1626 1627 1628 1629 1630 1631 1632
		if (err)
			goto err_close_sqs;
	}

	return 0;

err_close_sqs:
	for (tc--; tc >= 0; tc--)
S
Saeed Mahameed 已提交
1633
		mlx5e_close_txqsq(&c->sq[tc]);
1634 1635 1636 1637 1638 1639 1640 1641 1642

	return err;
}

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

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

1646
static int mlx5e_set_sq_maxrate(struct net_device *dev,
S
Saeed Mahameed 已提交
1647
				struct mlx5e_txqsq *sq, u32 rate)
1648 1649 1650
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev = priv->mdev;
1651
	struct mlx5e_modify_sq_param msp = {0};
1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673
	u16 rl_index = 0;
	int err;

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

	if (sq->rate_limit)
		/* remove current rl index to free space to next ones */
		mlx5_rl_remove_rate(mdev, sq->rate_limit);

	sq->rate_limit = 0;

	if (rate) {
		err = mlx5_rl_add_rate(mdev, rate, &rl_index);
		if (err) {
			netdev_err(dev, "Failed configuring rate %u: %d\n",
				   rate, err);
			return err;
		}
	}

1674 1675 1676 1677
	msp.curr_state = MLX5_SQC_STATE_RDY;
	msp.next_state = MLX5_SQC_STATE_RDY;
	msp.rl_index   = rl_index;
	msp.rl_update  = true;
1678
	err = mlx5e_modify_sq(mdev, sq->sqn, &msp);
1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695
	if (err) {
		netdev_err(dev, "Failed configuring rate %u: %d\n",
			   rate, err);
		/* remove the rate from the table */
		if (rate)
			mlx5_rl_remove_rate(mdev, rate);
		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;
1696
	struct mlx5e_txqsq *sq = priv->txq2sq[index];
1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722
	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;
}

1723
static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
1724
			      struct mlx5e_params *params,
1725 1726 1727
			      struct mlx5e_channel_param *cparam,
			      struct mlx5e_channel **cp)
{
1728
	struct mlx5e_cq_moder icocq_moder = {0, 0};
1729 1730 1731 1732 1733 1734 1735 1736 1737 1738
	struct net_device *netdev = priv->netdev;
	int cpu = mlx5e_get_cpu(priv, ix);
	struct mlx5e_channel *c;
	int err;

	c = kzalloc_node(sizeof(*c), GFP_KERNEL, cpu_to_node(cpu));
	if (!c)
		return -ENOMEM;

	c->priv     = priv;
1739 1740
	c->mdev     = priv->mdev;
	c->tstamp   = &priv->tstamp;
1741 1742 1743 1744
	c->ix       = ix;
	c->cpu      = cpu;
	c->pdev     = &priv->mdev->pdev->dev;
	c->netdev   = priv->netdev;
1745
	c->mkey_be  = cpu_to_be32(priv->mdev->mlx5e_res.mkey.key);
1746 1747
	c->num_tc   = params->num_tc;
	c->xdp      = !!params->xdp_prog;
1748

1749 1750
	netif_napi_add(netdev, &c->napi, mlx5e_napi_poll, 64);

1751
	err = mlx5e_open_cq(c, icocq_moder, &cparam->icosq_cq, &c->icosq.cq);
1752 1753 1754
	if (err)
		goto err_napi_del;

1755
	err = mlx5e_open_tx_cqs(c, params, cparam);
T
Tariq Toukan 已提交
1756 1757 1758
	if (err)
		goto err_close_icosq_cq;

1759
	err = mlx5e_open_cq(c, params->rx_cq_moderation, &cparam->rx_cq, &c->rq.cq);
1760 1761 1762
	if (err)
		goto err_close_tx_cqs;

1763
	/* XDP SQ CQ params are same as normal TXQ sq CQ params */
1764 1765
	err = c->xdp ? mlx5e_open_cq(c, params->tx_cq_moderation,
				     &cparam->tx_cq, &c->rq.xdpsq.cq) : 0;
1766 1767 1768
	if (err)
		goto err_close_rx_cq;

1769 1770
	napi_enable(&c->napi);

1771
	err = mlx5e_open_icosq(c, params, &cparam->icosq, &c->icosq);
1772 1773 1774
	if (err)
		goto err_disable_napi;

1775
	err = mlx5e_open_sqs(c, params, cparam);
T
Tariq Toukan 已提交
1776 1777 1778
	if (err)
		goto err_close_icosq;

1779
	err = c->xdp ? mlx5e_open_xdpsq(c, params, &cparam->xdp_sq, &c->rq.xdpsq) : 0;
1780 1781
	if (err)
		goto err_close_sqs;
1782

1783
	err = mlx5e_open_rq(c, params, &cparam->rq, &c->rq);
1784
	if (err)
1785
		goto err_close_xdp_sq;
1786 1787 1788 1789

	*cp = c;

	return 0;
1790
err_close_xdp_sq:
1791
	if (c->xdp)
S
Saeed Mahameed 已提交
1792
		mlx5e_close_xdpsq(&c->rq.xdpsq);
1793 1794 1795 1796

err_close_sqs:
	mlx5e_close_sqs(c);

T
Tariq Toukan 已提交
1797
err_close_icosq:
S
Saeed Mahameed 已提交
1798
	mlx5e_close_icosq(&c->icosq);
T
Tariq Toukan 已提交
1799

1800 1801
err_disable_napi:
	napi_disable(&c->napi);
1802
	if (c->xdp)
1803
		mlx5e_close_cq(&c->rq.xdpsq.cq);
1804 1805

err_close_rx_cq:
1806 1807 1808 1809 1810
	mlx5e_close_cq(&c->rq.cq);

err_close_tx_cqs:
	mlx5e_close_tx_cqs(c);

T
Tariq Toukan 已提交
1811 1812 1813
err_close_icosq_cq:
	mlx5e_close_cq(&c->icosq.cq);

1814 1815 1816 1817 1818 1819 1820
err_napi_del:
	netif_napi_del(&c->napi);
	kfree(c);

	return err;
}

1821 1822 1823 1824 1825 1826 1827
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);
1828
	netif_set_xps_queue(c->netdev, get_cpu_mask(c->cpu), c->ix);
1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839
}

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]);
}

1840 1841 1842
static void mlx5e_close_channel(struct mlx5e_channel *c)
{
	mlx5e_close_rq(&c->rq);
1843
	if (c->xdp)
S
Saeed Mahameed 已提交
1844
		mlx5e_close_xdpsq(&c->rq.xdpsq);
1845
	mlx5e_close_sqs(c);
S
Saeed Mahameed 已提交
1846
	mlx5e_close_icosq(&c->icosq);
1847
	napi_disable(&c->napi);
1848
	if (c->xdp)
1849
		mlx5e_close_cq(&c->rq.xdpsq.cq);
1850 1851
	mlx5e_close_cq(&c->rq.cq);
	mlx5e_close_tx_cqs(c);
T
Tariq Toukan 已提交
1852
	mlx5e_close_cq(&c->icosq.cq);
1853
	netif_napi_del(&c->napi);
E
Eric Dumazet 已提交
1854

1855 1856 1857 1858
	kfree(c);
}

static void mlx5e_build_rq_param(struct mlx5e_priv *priv,
1859
				 struct mlx5e_params *params,
1860 1861 1862 1863 1864
				 struct mlx5e_rq_param *param)
{
	void *rqc = param->rqc;
	void *wq = MLX5_ADDR_OF(rqc, rqc, wq);

1865
	switch (params->rq_wq_type) {
1866
	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
1867 1868
		MLX5_SET(wq, wq, log_wqe_num_of_strides, params->mpwqe_log_num_strides - 9);
		MLX5_SET(wq, wq, log_wqe_stride_size, params->mpwqe_log_stride_sz - 6);
1869 1870 1871 1872 1873 1874
		MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ);
		break;
	default: /* MLX5_WQ_TYPE_LINKED_LIST */
		MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_LINKED_LIST);
	}

1875 1876
	MLX5_SET(wq, wq, end_padding_mode, MLX5_WQ_END_PAD_MODE_ALIGN);
	MLX5_SET(wq, wq, log_wq_stride,    ilog2(sizeof(struct mlx5e_rx_wqe)));
1877
	MLX5_SET(wq, wq, log_wq_sz,        params->log_rq_size);
1878
	MLX5_SET(wq, wq, pd,               priv->mdev->mlx5e_res.pdn);
1879
	MLX5_SET(rqc, rqc, counter_set_id, priv->q_counter);
1880
	MLX5_SET(rqc, rqc, vsd,            params->vlan_strip_disable);
1881
	MLX5_SET(rqc, rqc, scatter_fcs,    params->scatter_fcs_en);
1882

1883
	param->wq.buf_numa_node = dev_to_node(&priv->mdev->pdev->dev);
1884 1885 1886
	param->wq.linear = 1;
}

1887 1888 1889 1890 1891 1892 1893 1894 1895
static void mlx5e_build_drop_rq_param(struct mlx5e_rq_param *param)
{
	void *rqc = param->rqc;
	void *wq = MLX5_ADDR_OF(rqc, rqc, wq);

	MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_LINKED_LIST);
	MLX5_SET(wq, wq, log_wq_stride,    ilog2(sizeof(struct mlx5e_rx_wqe)));
}

T
Tariq Toukan 已提交
1896 1897
static void mlx5e_build_sq_param_common(struct mlx5e_priv *priv,
					struct mlx5e_sq_param *param)
1898 1899 1900 1901 1902
{
	void *sqc = param->sqc;
	void *wq = MLX5_ADDR_OF(sqc, sqc, wq);

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

1905
	param->wq.buf_numa_node = dev_to_node(&priv->mdev->pdev->dev);
T
Tariq Toukan 已提交
1906 1907 1908
}

static void mlx5e_build_sq_param(struct mlx5e_priv *priv,
1909
				 struct mlx5e_params *params,
T
Tariq Toukan 已提交
1910 1911 1912 1913 1914 1915
				 struct mlx5e_sq_param *param)
{
	void *sqc = param->sqc;
	void *wq = MLX5_ADDR_OF(sqc, sqc, wq);

	mlx5e_build_sq_param_common(priv, param);
1916
	MLX5_SET(wq, wq, log_wq_sz, params->log_sq_size);
1917 1918 1919 1920 1921 1922 1923
}

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

E
Eli Cohen 已提交
1924
	MLX5_SET(cqc, cqc, uar_page, priv->mdev->priv.uar->index);
1925 1926 1927
}

static void mlx5e_build_rx_cq_param(struct mlx5e_priv *priv,
1928
				    struct mlx5e_params *params,
1929 1930 1931
				    struct mlx5e_cq_param *param)
{
	void *cqc = param->cqc;
1932
	u8 log_cq_size;
1933

1934
	switch (params->rq_wq_type) {
1935
	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
1936
		log_cq_size = params->log_rq_size + params->mpwqe_log_num_strides;
1937 1938
		break;
	default: /* MLX5_WQ_TYPE_LINKED_LIST */
1939
		log_cq_size = params->log_rq_size;
1940 1941 1942
	}

	MLX5_SET(cqc, cqc, log_cq_size, log_cq_size);
1943
	if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
T
Tariq Toukan 已提交
1944 1945 1946
		MLX5_SET(cqc, cqc, mini_cqe_res_format, MLX5_CQE_FORMAT_CSUM);
		MLX5_SET(cqc, cqc, cqe_comp_en, 1);
	}
1947 1948 1949 1950 1951

	mlx5e_build_common_cq_param(priv, param);
}

static void mlx5e_build_tx_cq_param(struct mlx5e_priv *priv,
1952
				    struct mlx5e_params *params,
1953 1954 1955 1956
				    struct mlx5e_cq_param *param)
{
	void *cqc = param->cqc;

1957
	MLX5_SET(cqc, cqc, log_cq_size, params->log_sq_size);
1958 1959

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

	param->cq_period_mode = MLX5_CQ_PERIOD_MODE_START_FROM_EQE;
1962 1963
}

T
Tariq Toukan 已提交
1964
static void mlx5e_build_ico_cq_param(struct mlx5e_priv *priv,
1965 1966
				     u8 log_wq_size,
				     struct mlx5e_cq_param *param)
T
Tariq Toukan 已提交
1967 1968 1969 1970 1971 1972
{
	void *cqc = param->cqc;

	MLX5_SET(cqc, cqc, log_cq_size, log_wq_size);

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

	param->cq_period_mode = MLX5_CQ_PERIOD_MODE_START_FROM_EQE;
T
Tariq Toukan 已提交
1975 1976 1977
}

static void mlx5e_build_icosq_param(struct mlx5e_priv *priv,
1978 1979
				    u8 log_wq_size,
				    struct mlx5e_sq_param *param)
T
Tariq Toukan 已提交
1980 1981 1982 1983 1984 1985 1986
{
	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);
1987
	MLX5_SET(sqc, sqc, reg_umr, MLX5_CAP_ETH(priv->mdev, reg_umr_sq));
T
Tariq Toukan 已提交
1988 1989
}

1990
static void mlx5e_build_xdpsq_param(struct mlx5e_priv *priv,
1991
				    struct mlx5e_params *params,
1992 1993 1994 1995 1996 1997
				    struct mlx5e_sq_param *param)
{
	void *sqc = param->sqc;
	void *wq = MLX5_ADDR_OF(sqc, sqc, wq);

	mlx5e_build_sq_param_common(priv, param);
1998
	MLX5_SET(wq, wq, log_wq_sz, params->log_sq_size);
1999 2000
}

2001 2002 2003
static void mlx5e_build_channel_param(struct mlx5e_priv *priv,
				      struct mlx5e_params *params,
				      struct mlx5e_channel_param *cparam)
2004
{
2005
	u8 icosq_log_wq_sz = MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE;
T
Tariq Toukan 已提交
2006

2007 2008 2009 2010 2011 2012 2013
	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);
2014 2015
}

2016 2017
int mlx5e_open_channels(struct mlx5e_priv *priv,
			struct mlx5e_channels *chs)
2018
{
2019
	struct mlx5e_channel_param *cparam;
2020
	int err = -ENOMEM;
2021 2022
	int i;

2023
	chs->num = chs->params.num_channels;
2024

2025
	chs->c = kcalloc(chs->num, sizeof(struct mlx5e_channel *), GFP_KERNEL);
2026
	cparam = kzalloc(sizeof(struct mlx5e_channel_param), GFP_KERNEL);
2027 2028
	if (!chs->c || !cparam)
		goto err_free;
2029

2030
	mlx5e_build_channel_param(priv, &chs->params, cparam);
2031
	for (i = 0; i < chs->num; i++) {
2032
		err = mlx5e_open_channel(priv, i, &chs->params, cparam, &chs->c[i]);
2033 2034 2035 2036
		if (err)
			goto err_close_channels;
	}

2037
	kfree(cparam);
2038 2039 2040 2041
	return 0;

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

2044
err_free:
2045
	kfree(chs->c);
2046
	kfree(cparam);
2047
	chs->num = 0;
2048 2049 2050
	return err;
}

2051
static void mlx5e_activate_channels(struct mlx5e_channels *chs)
2052 2053 2054
{
	int i;

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
	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;

	for (i = 0; i < chs->num; i++) {
		err = mlx5e_wait_for_min_rx_wqes(&chs->c[i]->rq);
		if (err)
			break;
	}

	return err;
}

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

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

2081
void mlx5e_close_channels(struct mlx5e_channels *chs)
2082 2083
{
	int i;
2084

2085 2086
	for (i = 0; i < chs->num; i++)
		mlx5e_close_channel(chs->c[i]);
2087

2088 2089
	kfree(chs->c);
	chs->num = 0;
2090 2091
}

2092 2093
static int
mlx5e_create_rqt(struct mlx5e_priv *priv, int sz, struct mlx5e_rqt *rqt)
2094 2095 2096 2097 2098
{
	struct mlx5_core_dev *mdev = priv->mdev;
	void *rqtc;
	int inlen;
	int err;
T
Tariq Toukan 已提交
2099
	u32 *in;
2100
	int i;
2101 2102

	inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * sz;
2103
	in = kvzalloc(inlen, GFP_KERNEL);
2104 2105 2106 2107 2108 2109 2110 2111
	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);

2112 2113
	for (i = 0; i < sz; i++)
		MLX5_SET(rqtc, rqtc, rq_num[i], priv->drop_rq.rqn);
2114

2115 2116 2117
	err = mlx5_core_create_rqt(mdev, in, inlen, &rqt->rqtn);
	if (!err)
		rqt->enabled = true;
2118 2119

	kvfree(in);
T
Tariq Toukan 已提交
2120 2121 2122
	return err;
}

2123
void mlx5e_destroy_rqt(struct mlx5e_priv *priv, struct mlx5e_rqt *rqt)
T
Tariq Toukan 已提交
2124
{
2125 2126
	rqt->enabled = false;
	mlx5_core_destroy_rqt(priv->mdev, rqt->rqtn);
T
Tariq Toukan 已提交
2127 2128
}

2129
int mlx5e_create_indirect_rqt(struct mlx5e_priv *priv)
2130 2131
{
	struct mlx5e_rqt *rqt = &priv->indir_rqt;
2132
	int err;
2133

2134 2135 2136 2137
	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;
2138 2139
}

2140
int mlx5e_create_direct_rqts(struct mlx5e_priv *priv)
T
Tariq Toukan 已提交
2141
{
2142
	struct mlx5e_rqt *rqt;
T
Tariq Toukan 已提交
2143 2144 2145
	int err;
	int ix;

2146
	for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) {
2147
		rqt = &priv->direct_tir[ix].rqt;
2148
		err = mlx5e_create_rqt(priv, 1 /*size */, rqt);
T
Tariq Toukan 已提交
2149 2150 2151 2152 2153 2154 2155
		if (err)
			goto err_destroy_rqts;
	}

	return 0;

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

2160 2161 2162
	return err;
}

2163 2164 2165 2166 2167 2168 2169 2170
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);
}

2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202
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;
}

static int mlx5e_bits_invert(unsigned long a, int size)
{
	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));

2203
			ix = priv->channels.params.indirection_rqt[ix];
2204 2205 2206 2207 2208 2209 2210 2211 2212 2213
			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)
2214 2215 2216 2217
{
	struct mlx5_core_dev *mdev = priv->mdev;
	void *rqtc;
	int inlen;
T
Tariq Toukan 已提交
2218
	u32 *in;
2219 2220 2221
	int err;

	inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + sizeof(u32) * sz;
2222
	in = kvzalloc(inlen, GFP_KERNEL);
2223 2224 2225 2226 2227 2228 2229
	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);
2230
	mlx5e_fill_rqt_rqns(priv, sz, rrp, rqtc);
T
Tariq Toukan 已提交
2231
	err = mlx5_core_modify_rqt(mdev, rqtn, in, inlen);
2232 2233 2234 2235 2236

	kvfree(in);
	return err;
}

2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250
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)
2251
{
T
Tariq Toukan 已提交
2252 2253 2254
	u32 rqtn;
	int ix;

2255
	if (priv->indir_rqt.enabled) {
2256
		/* RSS RQ table */
2257
		rqtn = priv->indir_rqt.rqtn;
2258
		mlx5e_redirect_rqt(priv, rqtn, MLX5E_INDIR_RQT_SIZE, rrp);
2259 2260
	}

2261 2262 2263
	for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) {
		struct mlx5e_redirect_rqt_param direct_rrp = {
			.is_rss = false,
2264 2265 2266
			{
				.rqn    = mlx5e_get_direct_rqn(priv, ix, rrp)
			},
2267 2268 2269
		};

		/* Direct RQ Tables */
2270 2271
		if (!priv->direct_tir[ix].rqt.enabled)
			continue;
2272

2273
		rqtn = priv->direct_tir[ix].rqt.rqtn;
2274
		mlx5e_redirect_rqt(priv, rqtn, 1, direct_rrp);
T
Tariq Toukan 已提交
2275
	}
2276 2277
}

2278 2279 2280 2281 2282
static void mlx5e_redirect_rqts_to_channels(struct mlx5e_priv *priv,
					    struct mlx5e_channels *chs)
{
	struct mlx5e_redirect_rqt_param rrp = {
		.is_rss        = true,
2283 2284 2285 2286 2287 2288
		{
			.rss = {
				.channels  = chs,
				.hfunc     = chs->params.rss_hfunc,
			}
		},
2289 2290 2291 2292 2293 2294 2295 2296 2297
	};

	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,
2298 2299 2300
		{
			.rqn = priv->drop_rq.rqn,
		},
2301 2302 2303 2304 2305
	};

	mlx5e_redirect_rqts(priv, drop_rrp);
}

2306
static void mlx5e_build_tir_ctx_lro(struct mlx5e_params *params, void *tirc)
2307
{
2308
	if (!params->lro_en)
2309 2310 2311 2312 2313 2314 2315 2316
		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,
2317 2318
		 (params->lro_wqe_sz - ROUGH_MAX_L2_L3_HDR_SZ) >> 8);
	MLX5_SET(tirc, tirc, lro_timeout_period_usecs, params->lro_timeout);
2319 2320
}

2321 2322 2323
void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_params *params,
				    enum mlx5e_traffic_types tt,
				    void *tirc)
2324
{
2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338
	void *hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);

#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)

2339 2340
	MLX5_SET(tirc, tirc, rx_hash_fn, mlx5e_rx_hash_fn(params->rss_hfunc));
	if (params->rss_hfunc == ETH_RSS_HASH_TOP) {
2341 2342 2343 2344 2345 2346
		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);
2347
		memcpy(rss_key, params->toeplitz_hash_key, len);
2348
	}
2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430

	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__);
	}
2431 2432
}

T
Tariq Toukan 已提交
2433
static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
2434 2435 2436 2437 2438 2439 2440
{
	struct mlx5_core_dev *mdev = priv->mdev;

	void *in;
	void *tirc;
	int inlen;
	int err;
T
Tariq Toukan 已提交
2441
	int tt;
T
Tariq Toukan 已提交
2442
	int ix;
2443 2444

	inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
2445
	in = kvzalloc(inlen, GFP_KERNEL);
2446 2447 2448 2449 2450 2451
	if (!in)
		return -ENOMEM;

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

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

T
Tariq Toukan 已提交
2454
	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
2455
		err = mlx5_core_modify_tir(mdev, priv->indir_tir[tt].tirn, in,
T
Tariq Toukan 已提交
2456
					   inlen);
T
Tariq Toukan 已提交
2457
		if (err)
T
Tariq Toukan 已提交
2458
			goto free_in;
T
Tariq Toukan 已提交
2459
	}
2460

2461
	for (ix = 0; ix < priv->profile->max_nch(priv->mdev); ix++) {
T
Tariq Toukan 已提交
2462 2463 2464 2465 2466 2467 2468
		err = mlx5_core_modify_tir(mdev, priv->direct_tir[ix].tirn,
					   in, inlen);
		if (err)
			goto free_in;
	}

free_in:
2469 2470 2471 2472 2473
	kvfree(in);

	return err;
}

2474
static int mlx5e_set_mtu(struct mlx5e_priv *priv, u16 mtu)
2475 2476
{
	struct mlx5_core_dev *mdev = priv->mdev;
2477
	u16 hw_mtu = MLX5E_SW2HW_MTU(priv, mtu);
2478 2479
	int err;

2480
	err = mlx5_set_port_mtu(mdev, hw_mtu, 1);
2481 2482 2483
	if (err)
		return err;

2484 2485 2486 2487
	/* Update vport context MTU */
	mlx5_modify_nic_vport_mtu(mdev, hw_mtu);
	return 0;
}
2488

2489 2490 2491 2492 2493
static void mlx5e_query_mtu(struct mlx5e_priv *priv, u16 *mtu)
{
	struct mlx5_core_dev *mdev = priv->mdev;
	u16 hw_mtu = 0;
	int err;
2494

2495 2496 2497 2498
	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);

2499
	*mtu = MLX5E_HW2SW_MTU(priv, hw_mtu);
2500 2501
}

2502
static int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv)
2503
{
2504
	struct net_device *netdev = priv->netdev;
2505 2506 2507 2508 2509 2510
	u16 mtu;
	int err;

	err = mlx5e_set_mtu(priv, netdev->mtu);
	if (err)
		return err;
2511

2512 2513 2514 2515
	mlx5e_query_mtu(priv, &mtu);
	if (mtu != netdev->mtu)
		netdev_warn(netdev, "%s: VPort MTU %d is different than netdev mtu %d\n",
			    __func__, mtu, netdev->mtu);
2516

2517
	netdev->mtu = mtu;
2518 2519 2520
	return 0;
}

2521 2522 2523
static void mlx5e_netdev_set_tcs(struct net_device *netdev)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
2524 2525
	int nch = priv->channels.params.num_channels;
	int ntc = priv->channels.params.num_tc;
2526 2527 2528 2529 2530 2531 2532 2533 2534
	int tc;

	netdev_reset_tc(netdev);

	if (ntc == 1)
		return;

	netdev_set_num_tc(netdev, ntc);

2535 2536 2537
	/* Map netdev TCs to offset 0
	 * We have our own UP to TXQ mapping for QoS
	 */
2538
	for (tc = 0; tc < ntc; tc++)
2539
		netdev_set_tc_queue(netdev, tc, nch, 0);
2540 2541
}

2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560
static void mlx5e_build_channels_tx_maps(struct mlx5e_priv *priv)
{
	struct mlx5e_channel *c;
	struct mlx5e_txqsq *sq;
	int i, tc;

	for (i = 0; i < priv->channels.num; i++)
		for (tc = 0; tc < priv->profile->max_tc; tc++)
			priv->channel_tc2txq[i][tc] = i + tc * priv->channels.num;

	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;
		}
	}
}

2561 2562 2563 2564 2565 2566
static bool mlx5e_is_eswitch_vport_mngr(struct mlx5_core_dev *mdev)
{
	return (MLX5_CAP_GEN(mdev, vport_group_manager) &&
		MLX5_CAP_GEN(mdev, port_type) == MLX5_CAP_PORT_TYPE_ETH);
}

2567
void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
2568
{
2569 2570 2571 2572
	int num_txqs = priv->channels.num * priv->channels.params.num_tc;
	struct net_device *netdev = priv->netdev;

	mlx5e_netdev_set_tcs(netdev);
2573 2574
	netif_set_real_num_tx_queues(netdev, num_txqs);
	netif_set_real_num_rx_queues(netdev, priv->channels.num);
2575

2576 2577 2578
	mlx5e_build_channels_tx_maps(priv);
	mlx5e_activate_channels(&priv->channels);
	netif_tx_start_all_queues(priv->netdev);
2579

2580
	if (mlx5e_is_eswitch_vport_mngr(priv->mdev))
2581 2582
		mlx5e_add_sqs_fwd_rules(priv);

2583
	mlx5e_wait_channels_min_rx_wqes(&priv->channels);
2584
	mlx5e_redirect_rqts_to_channels(priv, &priv->channels);
2585 2586
}

2587
void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv)
2588
{
2589 2590
	mlx5e_redirect_rqts_to_drop(priv);

2591
	if (mlx5e_is_eswitch_vport_mngr(priv->mdev))
2592 2593
		mlx5e_remove_sqs_fwd_rules(priv);

2594 2595 2596 2597 2598 2599 2600 2601
	/* 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);
}

2602
void mlx5e_switch_priv_channels(struct mlx5e_priv *priv,
2603 2604
				struct mlx5e_channels *new_chs,
				mlx5e_fp_hw_modify hw_modify)
2605 2606 2607
{
	struct net_device *netdev = priv->netdev;
	int new_num_txqs;
2608
	int carrier_ok;
2609 2610
	new_num_txqs = new_chs->num * new_chs->params.num_tc;

2611
	carrier_ok = netif_carrier_ok(netdev);
2612 2613 2614 2615 2616 2617 2618 2619 2620 2621
	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;

2622 2623 2624 2625
	/* New channels are ready to roll, modify HW settings if needed */
	if (hw_modify)
		hw_modify(priv);

2626 2627 2628
	mlx5e_refresh_tirs(priv, false);
	mlx5e_activate_priv_channels(priv);

2629 2630 2631
	/* return carrier back if needed */
	if (carrier_ok)
		netif_carrier_on(netdev);
2632 2633
}

2634 2635 2636 2637 2638 2639 2640
int mlx5e_open_locked(struct net_device *netdev)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	int err;

	set_bit(MLX5E_STATE_OPENED, &priv->state);

2641
	err = mlx5e_open_channels(priv, &priv->channels);
2642
	if (err)
2643
		goto err_clear_state_opened_flag;
2644

2645
	mlx5e_refresh_tirs(priv, false);
2646
	mlx5e_activate_priv_channels(priv);
2647 2648
	if (priv->profile->update_carrier)
		priv->profile->update_carrier(priv);
2649
	mlx5e_timestamp_init(priv);
2650

2651 2652
	if (priv->profile->update_stats)
		queue_delayed_work(priv->wq, &priv->update_stats_work, 0);
2653

2654
	return 0;
2655 2656 2657 2658

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

2661
int mlx5e_open(struct net_device *netdev)
2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	int err;

	mutex_lock(&priv->state_lock);
	err = mlx5e_open_locked(netdev);
	mutex_unlock(&priv->state_lock);

	return err;
}

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

2677 2678 2679 2680 2681 2682
	/* 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;

2683 2684
	clear_bit(MLX5E_STATE_OPENED, &priv->state);

2685
	mlx5e_timestamp_cleanup(priv);
2686
	netif_carrier_off(priv->netdev);
2687 2688
	mlx5e_deactivate_priv_channels(priv);
	mlx5e_close_channels(&priv->channels);
2689 2690 2691 2692

	return 0;
}

2693
int mlx5e_close(struct net_device *netdev)
2694 2695 2696 2697
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	int err;

2698 2699 2700
	if (!netif_device_present(netdev))
		return -ENODEV;

2701 2702 2703 2704 2705 2706 2707
	mutex_lock(&priv->state_lock);
	err = mlx5e_close_locked(netdev);
	mutex_unlock(&priv->state_lock);

	return err;
}

2708
static int mlx5e_alloc_drop_rq(struct mlx5_core_dev *mdev,
2709 2710
			       struct mlx5e_rq *rq,
			       struct mlx5e_rq_param *param)
2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722
{
	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;

	err = mlx5_wq_ll_create(mdev, &param->wq, rqc_wq, &rq->wq,
				&rq->wq_ctrl);
	if (err)
		return err;

2723
	rq->mdev = mdev;
2724 2725 2726 2727

	return 0;
}

2728
static int mlx5e_alloc_drop_cq(struct mlx5_core_dev *mdev,
2729 2730
			       struct mlx5e_cq *cq,
			       struct mlx5e_cq_param *param)
2731
{
2732
	return mlx5e_alloc_cq_common(mdev, param, cq);
2733 2734
}

2735 2736
static int mlx5e_open_drop_rq(struct mlx5_core_dev *mdev,
			      struct mlx5e_rq *drop_rq)
2737
{
2738 2739 2740
	struct mlx5e_cq_param cq_param = {};
	struct mlx5e_rq_param rq_param = {};
	struct mlx5e_cq *cq = &drop_rq->cq;
2741 2742
	int err;

2743
	mlx5e_build_drop_rq_param(&rq_param);
2744

2745
	err = mlx5e_alloc_drop_cq(mdev, cq, &cq_param);
2746 2747 2748
	if (err)
		return err;

2749
	err = mlx5e_create_cq(cq, &cq_param);
2750
	if (err)
2751
		goto err_free_cq;
2752

2753
	err = mlx5e_alloc_drop_rq(mdev, drop_rq, &rq_param);
2754
	if (err)
2755
		goto err_destroy_cq;
2756

2757
	err = mlx5e_create_rq(drop_rq, &rq_param);
2758
	if (err)
2759
		goto err_free_rq;
2760 2761 2762

	return 0;

2763
err_free_rq:
2764
	mlx5e_free_rq(drop_rq);
2765 2766

err_destroy_cq:
2767
	mlx5e_destroy_cq(cq);
2768

2769
err_free_cq:
2770
	mlx5e_free_cq(cq);
2771

2772 2773 2774
	return err;
}

2775
static void mlx5e_close_drop_rq(struct mlx5e_rq *drop_rq)
2776
{
2777 2778 2779 2780
	mlx5e_destroy_rq(drop_rq);
	mlx5e_free_rq(drop_rq);
	mlx5e_destroy_cq(&drop_rq->cq);
	mlx5e_free_cq(&drop_rq->cq);
2781 2782
}

2783 2784
int mlx5e_create_tis(struct mlx5_core_dev *mdev, int tc,
		     u32 underlay_qpn, u32 *tisn)
2785
{
2786
	u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {0};
2787 2788
	void *tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);

2789
	MLX5_SET(tisc, tisc, prio, tc << 1);
2790
	MLX5_SET(tisc, tisc, underlay_qpn, underlay_qpn);
2791
	MLX5_SET(tisc, tisc, transport_domain, mdev->mlx5e_res.td.tdn);
2792 2793 2794 2795

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

2796
	return mlx5_core_create_tis(mdev, in, sizeof(in), tisn);
2797 2798
}

2799
void mlx5e_destroy_tis(struct mlx5_core_dev *mdev, u32 tisn)
2800
{
2801
	mlx5_core_destroy_tis(mdev, tisn);
2802 2803
}

2804
int mlx5e_create_tises(struct mlx5e_priv *priv)
2805 2806 2807 2808
{
	int err;
	int tc;

2809
	for (tc = 0; tc < priv->profile->max_tc; tc++) {
2810
		err = mlx5e_create_tis(priv->mdev, tc, 0, &priv->tisn[tc]);
2811 2812 2813 2814 2815 2816 2817 2818
		if (err)
			goto err_close_tises;
	}

	return 0;

err_close_tises:
	for (tc--; tc >= 0; tc--)
2819
		mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]);
2820 2821 2822 2823

	return err;
}

2824
void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv)
2825 2826 2827
{
	int tc;

2828
	for (tc = 0; tc < priv->profile->max_tc; tc++)
2829
		mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]);
2830 2831
}

2832 2833 2834
static void mlx5e_build_indir_tir_ctx(struct mlx5e_priv *priv,
				      enum mlx5e_traffic_types tt,
				      u32 *tirc)
2835
{
2836
	MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.td.tdn);
2837

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

A
Achiad Shochat 已提交
2840
	MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
2841
	MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqt.rqtn);
2842
	mlx5e_build_indir_tir_ctx_hash(&priv->channels.params, tt, tirc);
2843 2844
}

2845
static void mlx5e_build_direct_tir_ctx(struct mlx5e_priv *priv, u32 rqtn, u32 *tirc)
2846
{
2847
	MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.td.tdn);
T
Tariq Toukan 已提交
2848

2849
	mlx5e_build_tir_ctx_lro(&priv->channels.params, tirc);
T
Tariq Toukan 已提交
2850 2851 2852 2853 2854 2855

	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);
}

2856
int mlx5e_create_indirect_tirs(struct mlx5e_priv *priv)
T
Tariq Toukan 已提交
2857
{
2858
	struct mlx5e_tir *tir;
2859 2860 2861
	void *tirc;
	int inlen;
	int err;
T
Tariq Toukan 已提交
2862 2863
	u32 *in;
	int tt;
2864 2865

	inlen = MLX5_ST_SZ_BYTES(create_tir_in);
2866
	in = kvzalloc(inlen, GFP_KERNEL);
2867 2868 2869
	if (!in)
		return -ENOMEM;

T
Tariq Toukan 已提交
2870 2871
	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
		memset(in, 0, inlen);
2872
		tir = &priv->indir_tir[tt];
T
Tariq Toukan 已提交
2873
		tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
2874
		mlx5e_build_indir_tir_ctx(priv, tt, tirc);
2875
		err = mlx5e_create_tir(priv->mdev, tir, in, inlen);
2876
		if (err)
2877
			goto err_destroy_tirs;
2878 2879
	}

2880 2881 2882 2883 2884
	kvfree(in);

	return 0;

err_destroy_tirs:
2885
	mlx5_core_warn(priv->mdev, "create indirect tirs failed, %d\n", err);
2886 2887 2888 2889 2890 2891 2892 2893
	for (tt--; tt >= 0; tt--)
		mlx5e_destroy_tir(priv->mdev, &priv->indir_tir[tt]);

	kvfree(in);

	return err;
}

2894
int mlx5e_create_direct_tirs(struct mlx5e_priv *priv)
2895 2896 2897 2898 2899 2900 2901 2902 2903 2904
{
	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);
2905
	in = kvzalloc(inlen, GFP_KERNEL);
2906 2907 2908
	if (!in)
		return -ENOMEM;

T
Tariq Toukan 已提交
2909 2910
	for (ix = 0; ix < nch; ix++) {
		memset(in, 0, inlen);
2911
		tir = &priv->direct_tir[ix];
T
Tariq Toukan 已提交
2912
		tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
2913
		mlx5e_build_direct_tir_ctx(priv, priv->direct_tir[ix].rqt.rqtn, tirc);
2914
		err = mlx5e_create_tir(priv->mdev, tir, in, inlen);
T
Tariq Toukan 已提交
2915 2916 2917 2918 2919 2920
		if (err)
			goto err_destroy_ch_tirs;
	}

	kvfree(in);

2921 2922
	return 0;

T
Tariq Toukan 已提交
2923
err_destroy_ch_tirs:
2924
	mlx5_core_warn(priv->mdev, "create direct tirs failed, %d\n", err);
T
Tariq Toukan 已提交
2925
	for (ix--; ix >= 0; ix--)
2926
		mlx5e_destroy_tir(priv->mdev, &priv->direct_tir[ix]);
T
Tariq Toukan 已提交
2927 2928

	kvfree(in);
2929 2930 2931 2932

	return err;
}

2933
void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv)
2934 2935 2936
{
	int i;

T
Tariq Toukan 已提交
2937
	for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++)
2938
		mlx5e_destroy_tir(priv->mdev, &priv->indir_tir[i]);
2939 2940
}

2941
void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv)
2942 2943 2944 2945 2946 2947 2948 2949
{
	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]);
}

2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963
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;
}

2964
static int mlx5e_modify_channels_vsd(struct mlx5e_channels *chs, bool vsd)
2965 2966 2967 2968
{
	int err = 0;
	int i;

2969 2970
	for (i = 0; i < chs->num; i++) {
		err = mlx5e_modify_rq_vsd(&chs->c[i]->rq, vsd);
2971 2972 2973 2974 2975 2976 2977
		if (err)
			return err;
	}

	return 0;
}

2978 2979 2980
static int mlx5e_setup_tc(struct net_device *netdev, u8 tc)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
S
Saeed Mahameed 已提交
2981
	struct mlx5e_channels new_channels = {};
2982 2983 2984 2985 2986 2987 2988
	int err = 0;

	if (tc && tc != MLX5E_MAX_NUM_TC)
		return -EINVAL;

	mutex_lock(&priv->state_lock);

S
Saeed Mahameed 已提交
2989 2990
	new_channels.params = priv->channels.params;
	new_channels.params.num_tc = tc ? tc : 1;
2991

S
Saeed Mahameed 已提交
2992
	if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
S
Saeed Mahameed 已提交
2993 2994 2995
		priv->channels.params = new_channels.params;
		goto out;
	}
2996

S
Saeed Mahameed 已提交
2997 2998 2999
	err = mlx5e_open_channels(priv, &new_channels);
	if (err)
		goto out;
3000

3001
	mlx5e_switch_priv_channels(priv, &new_channels, NULL);
S
Saeed Mahameed 已提交
3002
out:
3003 3004 3005 3006 3007
	mutex_unlock(&priv->state_lock);
	return err;
}

static int mlx5e_ndo_setup_tc(struct net_device *dev, u32 handle,
3008 3009
			      u32 chain_index, __be16 proto,
			      struct tc_to_netdev *tc)
3010
{
3011 3012 3013 3014 3015
	struct mlx5e_priv *priv = netdev_priv(dev);

	if (TC_H_MAJ(handle) != TC_H_MAJ(TC_H_INGRESS))
		goto mqprio;

3016 3017 3018
	if (chain_index)
		return -EOPNOTSUPP;

3019
	switch (tc->type) {
3020 3021 3022 3023 3024 3025
	case TC_SETUP_CLSFLOWER:
		switch (tc->cls_flower->command) {
		case TC_CLSFLOWER_REPLACE:
			return mlx5e_configure_flower(priv, proto, tc->cls_flower);
		case TC_CLSFLOWER_DESTROY:
			return mlx5e_delete_flower(priv, tc->cls_flower);
3026 3027
		case TC_CLSFLOWER_STATS:
			return mlx5e_stats_flower(priv, tc->cls_flower);
3028
		}
3029 3030 3031 3032 3033
	default:
		return -EOPNOTSUPP;
	}

mqprio:
3034
	if (tc->type != TC_SETUP_MQPRIO)
3035 3036
		return -EINVAL;

3037 3038 3039
	tc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;

	return mlx5e_setup_tc(dev, tc->mqprio->num_tc);
3040 3041
}

3042
static void
3043 3044 3045
mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
3046
	struct mlx5e_sw_stats *sstats = &priv->stats.sw;
3047
	struct mlx5e_vport_stats *vstats = &priv->stats.vport;
3048
	struct mlx5e_pport_stats *pstats = &priv->stats.pport;
3049

3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061
	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 {
		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;
	}
3062 3063 3064 3065

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

	stats->rx_length_errors =
3066 3067 3068
		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);
3069
	stats->rx_crc_errors =
3070 3071 3072
		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);
3073
	stats->tx_carrier_errors =
3074
		PPORT_802_3_GET(pstats, a_symbol_error_during_carrier);
3075 3076 3077 3078 3079 3080 3081
	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
	 */
3082 3083
	stats->multicast =
		VPORT_COUNTER_GET(vstats, received_eth_multicast.packets);
3084 3085 3086 3087 3088 3089
}

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

3090
	queue_work(priv->wq, &priv->set_rx_mode_work);
3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104
}

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);

3105
	queue_work(priv->wq, &priv->set_rx_mode_work);
3106 3107 3108 3109

	return 0;
}

3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120
#define MLX5E_SET_FEATURE(netdev, feature, enable)	\
	do {						\
		if (enable)				\
			netdev->features |= feature;	\
		else					\
			netdev->features &= ~feature;	\
	} while (0)

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

static int set_feature_lro(struct net_device *netdev, bool enable)
3121 3122
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
3123 3124 3125
	struct mlx5e_channels new_channels = {};
	int err = 0;
	bool reset;
3126 3127 3128

	mutex_lock(&priv->state_lock);

3129 3130
	reset = (priv->channels.params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST);
	reset = reset && test_bit(MLX5E_STATE_OPENED, &priv->state);
3131

3132 3133 3134 3135 3136 3137 3138
	new_channels.params = priv->channels.params;
	new_channels.params.lro_en = enable;

	if (!reset) {
		priv->channels.params = new_channels.params;
		err = mlx5e_modify_tirs_lro(priv);
		goto out;
3139
	}
3140

3141 3142 3143
	err = mlx5e_open_channels(priv, &new_channels);
	if (err)
		goto out;
3144

3145 3146
	mlx5e_switch_priv_channels(priv, &new_channels, mlx5e_modify_tirs_lro);
out:
3147
	mutex_unlock(&priv->state_lock);
3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165
	return err;
}

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

	if (enable)
		mlx5e_enable_vlan_filter(priv);
	else
		mlx5e_disable_vlan_filter(priv);

	return 0;
}

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

3167
	if (!enable && mlx5e_tc_num_filters(priv)) {
3168 3169 3170 3171 3172
		netdev_err(netdev,
			   "Active offloaded tc filters, can't turn hw_tc_offload off\n");
		return -EINVAL;
	}

3173 3174 3175
	return 0;
}

3176 3177 3178 3179 3180 3181 3182 3183
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);
}

3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200
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;
}

3201 3202 3203
static int set_feature_rx_vlan(struct net_device *netdev, bool enable)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
3204
	int err = 0;
3205 3206 3207

	mutex_lock(&priv->state_lock);

3208
	priv->channels.params.vlan_strip_disable = !enable;
3209 3210 3211 3212
	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
		goto unlock;

	err = mlx5e_modify_channels_vsd(&priv->channels, !enable);
3213
	if (err)
3214
		priv->channels.params.vlan_strip_disable = enable;
3215

3216
unlock:
3217 3218 3219 3220 3221
	mutex_unlock(&priv->state_lock);

	return err;
}

3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236
#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

3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271
static int mlx5e_handle_feature(struct net_device *netdev,
				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) {
		netdev_err(netdev, "%s feature 0x%llx failed err %d\n",
			   enable ? "Enable" : "Disable", feature, err);
		return err;
	}

	MLX5E_SET_FEATURE(netdev, feature, enable);
	return 0;
}

static int mlx5e_set_features(struct net_device *netdev,
			      netdev_features_t features)
{
	int err;

	err  = mlx5e_handle_feature(netdev, features, NETIF_F_LRO,
				    set_feature_lro);
	err |= mlx5e_handle_feature(netdev, features,
				    NETIF_F_HW_VLAN_CTAG_FILTER,
				    set_feature_vlan_filter);
	err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_TC,
				    set_feature_tc_num_filters);
3272 3273
	err |= mlx5e_handle_feature(netdev, features, NETIF_F_RXALL,
				    set_feature_rx_all);
3274 3275
	err |= mlx5e_handle_feature(netdev, features, NETIF_F_RXFCS,
				    set_feature_rx_fcs);
3276 3277
	err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_VLAN_CTAG_RX,
				    set_feature_rx_vlan);
3278 3279 3280 3281
#ifdef CONFIG_RFS_ACCEL
	err |= mlx5e_handle_feature(netdev, features, NETIF_F_NTUPLE,
				    set_feature_arfs);
#endif
3282 3283

	return err ? -EINVAL : 0;
3284 3285 3286 3287 3288
}

static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
3289 3290
	struct mlx5e_channels new_channels = {};
	int curr_mtu;
3291
	int err = 0;
3292
	bool reset;
3293 3294

	mutex_lock(&priv->state_lock);
3295

3296 3297
	reset = !priv->channels.params.lro_en &&
		(priv->channels.params.rq_wq_type !=
3298 3299
		 MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ);

3300
	reset = reset && test_bit(MLX5E_STATE_OPENED, &priv->state);
3301

3302
	curr_mtu    = netdev->mtu;
3303
	netdev->mtu = new_mtu;
3304

3305 3306 3307 3308
	if (!reset) {
		mlx5e_set_dev_port_mtu(priv);
		goto out;
	}
3309

3310 3311 3312 3313 3314 3315 3316 3317
	new_channels.params = priv->channels.params;
	err = mlx5e_open_channels(priv, &new_channels);
	if (err) {
		netdev->mtu = curr_mtu;
		goto out;
	}

	mlx5e_switch_priv_channels(priv, &new_channels, mlx5e_set_dev_port_mtu);
3318

3319 3320
out:
	mutex_unlock(&priv->state_lock);
3321 3322 3323
	return err;
}

3324 3325
static int mlx5e_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
3326 3327
	struct mlx5e_priv *priv = netdev_priv(dev);

3328 3329
	switch (cmd) {
	case SIOCSHWTSTAMP:
3330
		return mlx5e_hwstamp_set(priv, ifr);
3331
	case SIOCGHWTSTAMP:
3332
		return mlx5e_hwstamp_get(priv, ifr);
3333 3334 3335 3336 3337
	default:
		return -EOPNOTSUPP;
	}
}

3338 3339 3340 3341 3342 3343 3344 3345
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);
}

3346 3347
static int mlx5e_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos,
			     __be16 vlan_proto)
3348 3349 3350 3351
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev = priv->mdev;

3352 3353 3354
	if (vlan_proto != htons(ETH_P_8021Q))
		return -EPROTONOSUPPORT;

3355 3356 3357 3358
	return mlx5_eswitch_set_vport_vlan(mdev->priv.eswitch, vf + 1,
					   vlan, qos);
}

3359 3360 3361 3362 3363 3364 3365 3366
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);
}

3367 3368 3369 3370 3371 3372 3373
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);
}
3374 3375 3376 3377 3378 3379 3380 3381

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,
3382
					   max_tx_rate, min_tx_rate);
3383 3384
}

3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440
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);
}

3441 3442
static void mlx5e_add_vxlan_port(struct net_device *netdev,
				 struct udp_tunnel_info *ti)
3443 3444 3445
{
	struct mlx5e_priv *priv = netdev_priv(netdev);

3446 3447 3448
	if (ti->type != UDP_TUNNEL_TYPE_VXLAN)
		return;

3449 3450 3451
	if (!mlx5e_vxlan_allowed(priv->mdev))
		return;

3452
	mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 1);
3453 3454
}

3455 3456
static void mlx5e_del_vxlan_port(struct net_device *netdev,
				 struct udp_tunnel_info *ti)
3457 3458 3459
{
	struct mlx5e_priv *priv = netdev_priv(netdev);

3460 3461 3462
	if (ti->type != UDP_TUNNEL_TYPE_VXLAN)
		return;

3463 3464 3465
	if (!mlx5e_vxlan_allowed(priv->mdev))
		return;

3466
	mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 0);
3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518
}

static netdev_features_t mlx5e_vxlan_features_check(struct mlx5e_priv *priv,
						    struct sk_buff *skb,
						    netdev_features_t features)
{
	struct udphdr *udph;
	u16 proto;
	u16 port = 0;

	switch (vlan_get_protocol(skb)) {
	case htons(ETH_P_IP):
		proto = ip_hdr(skb)->protocol;
		break;
	case htons(ETH_P_IPV6):
		proto = ipv6_hdr(skb)->nexthdr;
		break;
	default:
		goto out;
	}

	if (proto == IPPROTO_UDP) {
		udph = udp_hdr(skb);
		port = be16_to_cpu(udph->dest);
	}

	/* Verify if UDP port is being offloaded by HW */
	if (port && mlx5e_vxlan_lookup_port(priv, port))
		return features;

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);

	/* Validate if the tunneled packet is being offloaded by HW */
	if (skb->encapsulation &&
	    (features & NETIF_F_CSUM_MASK || features & NETIF_F_GSO_MASK))
		return mlx5e_vxlan_features_check(priv, skb, features);

	return features;
}

3519 3520 3521 3522 3523 3524 3525 3526
static void mlx5e_tx_timeout(struct net_device *dev)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	bool sched_work = false;
	int i;

	netdev_err(dev, "TX timeout detected\n");

3527
	for (i = 0; i < priv->channels.num * priv->channels.params.num_tc; i++) {
3528
		struct mlx5e_txqsq *sq = priv->txq2sq[i];
3529

3530
		if (!netif_xmit_stopped(netdev_get_tx_queue(dev, i)))
3531 3532
			continue;
		sched_work = true;
3533
		clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
3534 3535 3536 3537 3538 3539 3540 3541
		netdev_err(dev, "TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x\n",
			   i, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc);
	}

	if (sched_work && test_bit(MLX5E_STATE_OPENED, &priv->state))
		schedule_work(&priv->tx_timeout_work);
}

3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559
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;
	int err = 0;
	bool reset, was_opened;
	int i;

	mutex_lock(&priv->state_lock);

	if ((netdev->features & NETIF_F_LRO) && prog) {
		netdev_warn(netdev, "can't set XDP while LRO is on, disable LRO first\n");
		err = -EINVAL;
		goto unlock;
	}

	was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
	/* no need for full reset when exchanging programs */
3560
	reset = (!priv->channels.params.xdp_prog || !prog);
3561 3562 3563

	if (was_opened && reset)
		mlx5e_close_locked(netdev);
3564 3565 3566 3567
	if (was_opened && !reset) {
		/* num_channels is invariant here, so we can take the
		 * batched reference right upfront.
		 */
3568
		prog = bpf_prog_add(prog, priv->channels.num);
3569 3570 3571 3572 3573
		if (IS_ERR(prog)) {
			err = PTR_ERR(prog);
			goto unlock;
		}
	}
3574

3575 3576 3577
	/* exchange programs, extra prog reference we got from caller
	 * as long as we don't fail from this point onwards.
	 */
3578
	old_prog = xchg(&priv->channels.params.xdp_prog, prog);
3579 3580 3581 3582
	if (old_prog)
		bpf_prog_put(old_prog);

	if (reset) /* change RQ type according to priv->xdp_prog */
3583
		mlx5e_set_rq_params(priv->mdev, &priv->channels.params);
3584 3585 3586 3587 3588 3589 3590 3591 3592 3593

	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.
	 */
3594 3595
	for (i = 0; i < priv->channels.num; i++) {
		struct mlx5e_channel *c = priv->channels.c[i];
3596

3597
		clear_bit(MLX5E_RQ_STATE_ENABLED, &c->rq.state);
3598 3599 3600 3601 3602
		napi_synchronize(&c->napi);
		/* prevent mlx5e_poll_rx_cq from accessing rq->xdp_prog */

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

3603
		set_bit(MLX5E_RQ_STATE_ENABLED, &c->rq.state);
3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616
		/* napi_schedule in case we have missed anything */
		set_bit(MLX5E_CHANNEL_NAPI_SCHED, &c->flags);
		napi_schedule(&c->napi);

		if (old_prog)
			bpf_prog_put(old_prog);
	}

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

3617
static u32 mlx5e_xdp_query(struct net_device *dev)
3618 3619
{
	struct mlx5e_priv *priv = netdev_priv(dev);
3620 3621
	const struct bpf_prog *xdp_prog;
	u32 prog_id = 0;
3622

3623 3624 3625 3626 3627 3628 3629
	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;
3630 3631 3632 3633 3634 3635 3636 3637
}

static int mlx5e_xdp(struct net_device *dev, struct netdev_xdp *xdp)
{
	switch (xdp->command) {
	case XDP_SETUP_PROG:
		return mlx5e_xdp_set(dev, xdp->prog);
	case XDP_QUERY_PROG:
3638 3639
		xdp->prog_id = mlx5e_xdp_query(dev);
		xdp->prog_attached = !!xdp->prog_id;
3640 3641 3642 3643 3644 3645
		return 0;
	default:
		return -EINVAL;
	}
}

3646 3647 3648 3649 3650 3651 3652
#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);
3653 3654
	struct mlx5e_channels *chs = &priv->channels;

3655 3656
	int i;

3657 3658
	for (i = 0; i < chs->num; i++)
		napi_schedule(&chs->c[i]->napi);
3659 3660 3661
}
#endif

3662
static const struct net_device_ops mlx5e_netdev_ops_basic = {
3663 3664 3665
	.ndo_open                = mlx5e_open,
	.ndo_stop                = mlx5e_close,
	.ndo_start_xmit          = mlx5e_xmit,
3666 3667
	.ndo_setup_tc            = mlx5e_ndo_setup_tc,
	.ndo_select_queue        = mlx5e_select_queue,
3668 3669 3670
	.ndo_get_stats64         = mlx5e_get_stats,
	.ndo_set_rx_mode         = mlx5e_set_rx_mode,
	.ndo_set_mac_address     = mlx5e_set_mac,
3671 3672
	.ndo_vlan_rx_add_vid     = mlx5e_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid    = mlx5e_vlan_rx_kill_vid,
3673
	.ndo_set_features        = mlx5e_set_features,
3674 3675
	.ndo_change_mtu          = mlx5e_change_mtu,
	.ndo_do_ioctl            = mlx5e_ioctl,
3676
	.ndo_set_tx_maxrate      = mlx5e_set_tx_maxrate,
3677 3678 3679
#ifdef CONFIG_RFS_ACCEL
	.ndo_rx_flow_steer	 = mlx5e_rx_flow_steer,
#endif
3680
	.ndo_tx_timeout          = mlx5e_tx_timeout,
3681
	.ndo_xdp		 = mlx5e_xdp,
3682 3683 3684
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller     = mlx5e_netpoll,
#endif
3685 3686 3687 3688 3689 3690
};

static const struct net_device_ops mlx5e_netdev_ops_sriov = {
	.ndo_open                = mlx5e_open,
	.ndo_stop                = mlx5e_close,
	.ndo_start_xmit          = mlx5e_xmit,
3691 3692
	.ndo_setup_tc            = mlx5e_ndo_setup_tc,
	.ndo_select_queue        = mlx5e_select_queue,
3693 3694 3695 3696 3697 3698 3699 3700
	.ndo_get_stats64         = mlx5e_get_stats,
	.ndo_set_rx_mode         = mlx5e_set_rx_mode,
	.ndo_set_mac_address     = mlx5e_set_mac,
	.ndo_vlan_rx_add_vid     = mlx5e_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid    = mlx5e_vlan_rx_kill_vid,
	.ndo_set_features        = mlx5e_set_features,
	.ndo_change_mtu          = mlx5e_change_mtu,
	.ndo_do_ioctl            = mlx5e_ioctl,
3701 3702
	.ndo_udp_tunnel_add	 = mlx5e_add_vxlan_port,
	.ndo_udp_tunnel_del	 = mlx5e_del_vxlan_port,
3703
	.ndo_set_tx_maxrate      = mlx5e_set_tx_maxrate,
3704
	.ndo_features_check      = mlx5e_features_check,
3705 3706 3707
#ifdef CONFIG_RFS_ACCEL
	.ndo_rx_flow_steer	 = mlx5e_rx_flow_steer,
#endif
3708 3709
	.ndo_set_vf_mac          = mlx5e_set_vf_mac,
	.ndo_set_vf_vlan         = mlx5e_set_vf_vlan,
3710
	.ndo_set_vf_spoofchk     = mlx5e_set_vf_spoofchk,
3711
	.ndo_set_vf_trust        = mlx5e_set_vf_trust,
3712
	.ndo_set_vf_rate         = mlx5e_set_vf_rate,
3713 3714 3715
	.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,
3716
	.ndo_tx_timeout          = mlx5e_tx_timeout,
3717
	.ndo_xdp		 = mlx5e_xdp,
3718 3719 3720
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller     = mlx5e_netpoll,
#endif
3721 3722
	.ndo_has_offload_stats	 = mlx5e_has_offload_stats,
	.ndo_get_offload_stats	 = mlx5e_get_offload_stats,
3723 3724 3725 3726 3727
};

static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
{
	if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
3728
		return -EOPNOTSUPP;
3729 3730 3731 3732 3733
	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) ||
3734 3735 3736 3737
	    !MLX5_CAP_ETH(mdev, rss_ind_tbl_cap) ||
	    MLX5_CAP_FLOWTABLE(mdev,
			       flow_table_properties_nic_receive.max_ft_level)
			       < 3) {
3738 3739
		mlx5_core_warn(mdev,
			       "Not creating net device, some required device capabilities are missing\n");
3740
		return -EOPNOTSUPP;
3741
	}
3742 3743
	if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable))
		mlx5_core_warn(mdev, "Self loop back prevention is not supported\n");
3744
	if (!MLX5_CAP_GEN(mdev, cq_moderation))
3745
		mlx5_core_warn(mdev, "CQ moderation is not supported\n");
3746

3747 3748 3749
	return 0;
}

3750 3751 3752 3753 3754 3755 3756 3757 3758
u16 mlx5e_get_max_inline_cap(struct mlx5_core_dev *mdev)
{
	int bf_buf_size = (1 << MLX5_CAP_GEN(mdev, log_bf_reg_size)) / 2;

	return bf_buf_size -
	       sizeof(struct mlx5e_tx_wqe) +
	       2 /*sizeof(mlx5e_tx_wqe.inline_hdr_start)*/;
}

3759 3760
void mlx5e_build_default_indir_rqt(struct mlx5_core_dev *mdev,
				   u32 *indirection_rqt, int len,
3761 3762
				   int num_channels)
{
3763 3764
	int node = mdev->priv.numa_node;
	int node_num_of_cores;
3765 3766
	int i;

3767 3768 3769 3770 3771 3772 3773 3774
	if (node == -1)
		node = first_online_node;

	node_num_of_cores = cpumask_weight(cpumask_of_node(node));

	if (node_num_of_cores)
		num_channels = min_t(int, num_channels, node_num_of_cores);

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

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
static int mlx5e_get_pci_bw(struct mlx5_core_dev *mdev, u32 *pci_bw)
{
	enum pcie_link_width width;
	enum pci_bus_speed speed;
	int err = 0;

	err = pcie_get_minimum_link(mdev->pdev, &speed, &width);
	if (err)
		return err;

	if (speed == PCI_SPEED_UNKNOWN || width == PCIE_LNK_WIDTH_UNKNOWN)
		return -EINVAL;

	switch (speed) {
	case PCIE_SPEED_2_5GT:
		*pci_bw = 2500 * width;
		break;
	case PCIE_SPEED_5_0GT:
		*pci_bw = 5000 * width;
		break;
	case PCIE_SPEED_8_0GT:
		*pci_bw = 8000 * width;
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static bool cqe_compress_heuristic(u32 link_speed, u32 pci_bw)
{
	return (link_speed && pci_bw &&
		(pci_bw < 40000) && (pci_bw < link_speed));
}

3815 3816 3817 3818 3819 3820
static bool hw_lro_heuristic(u32 link_speed, u32 pci_bw)
{
	return !(link_speed && pci_bw &&
		 (pci_bw <= 16000) && (pci_bw < link_speed));
}

T
Tariq Toukan 已提交
3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832
void mlx5e_set_rx_cq_mode_params(struct mlx5e_params *params, u8 cq_period_mode)
{
	params->rx_cq_period_mode = cq_period_mode;

	params->rx_cq_moderation.pkts =
		MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_PKTS;
	params->rx_cq_moderation.usec =
			MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_USEC;

	if (cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE)
		params->rx_cq_moderation.usec =
			MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_USEC_FROM_CQE;
3833

3834 3835 3836 3837
	if (params->rx_am_enabled)
		params->rx_cq_moderation =
			mlx5e_am_get_def_profile(params->rx_cq_period_mode);

3838 3839
	MLX5E_SET_PFLAG(params, MLX5E_PFLAG_RX_CQE_BASED_MODER,
			params->rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE);
T
Tariq Toukan 已提交
3840 3841
}

3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853
u32 mlx5e_choose_lro_timeout(struct mlx5_core_dev *mdev, u32 wanted_timeout)
{
	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]);
}

3854 3855 3856
void mlx5e_build_nic_params(struct mlx5_core_dev *mdev,
			    struct mlx5e_params *params,
			    u16 max_channels)
3857
{
3858
	u8 cq_period_mode = 0;
3859 3860
	u32 link_speed = 0;
	u32 pci_bw = 0;
3861

3862 3863
	params->num_channels = max_channels;
	params->num_tc       = 1;
3864

3865 3866 3867 3868 3869
	mlx5e_get_max_linkspeed(mdev, &link_speed);
	mlx5e_get_pci_bw(mdev, &pci_bw);
	mlx5_core_dbg(mdev, "Max link speed = %d, PCI BW = %d\n",
		      link_speed, pci_bw);

3870 3871
	/* SQ */
	params->log_sq_size = is_kdump_kernel() ?
3872 3873
		MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE :
		MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
3874

3875
	/* set CQE compression */
3876
	params->rx_cqe_compress_def = false;
3877
	if (MLX5_CAP_GEN(mdev, cqe_compression) &&
3878
	    MLX5_CAP_GEN(mdev, vport_group_manager))
3879
		params->rx_cqe_compress_def = cqe_compress_heuristic(link_speed, pci_bw);
3880

3881 3882 3883 3884
	MLX5E_SET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS, params->rx_cqe_compress_def);

	/* RQ */
	mlx5e_set_rq_params(mdev, params);
3885

3886
	/* HW LRO */
3887

3888
	/* TODO: && MLX5_CAP_ETH(mdev, lro_cap) */
3889
	if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ)
3890
		params->lro_en = hw_lro_heuristic(link_speed, pci_bw);
3891
	params->lro_timeout = mlx5e_choose_lro_timeout(mdev, MLX5E_DEFAULT_LRO_TIMEOUT);
3892

3893 3894 3895 3896 3897 3898
	/* CQ moderation params */
	cq_period_mode = MLX5_CAP_GEN(mdev, cq_period_start_from_cqe) ?
			MLX5_CQ_PERIOD_MODE_START_FROM_CQE :
			MLX5_CQ_PERIOD_MODE_START_FROM_EQE;
	params->rx_am_enabled = MLX5_CAP_GEN(mdev, cq_moderation);
	mlx5e_set_rx_cq_mode_params(params, cq_period_mode);
T
Tariq Toukan 已提交
3899

3900 3901
	params->tx_cq_moderation.usec = MLX5E_PARAMS_DEFAULT_TX_CQ_MODERATION_USEC;
	params->tx_cq_moderation.pkts = MLX5E_PARAMS_DEFAULT_TX_CQ_MODERATION_PKTS;
T
Tariq Toukan 已提交
3902

3903 3904 3905 3906
	/* TX inline */
	params->tx_max_inline = mlx5e_get_max_inline_cap(mdev);
	mlx5_query_min_inline(mdev, &params->tx_min_inline_mode);
	if (params->tx_min_inline_mode == MLX5_INLINE_MODE_NONE &&
3907
	    !MLX5_CAP_ETH(mdev, wqe_vlan_insert))
3908
		params->tx_min_inline_mode = MLX5_INLINE_MODE_L2;
3909

3910 3911 3912 3913 3914 3915
	/* RSS */
	params->rss_hfunc = ETH_RSS_HASH_XOR;
	netdev_rss_key_fill(params->toeplitz_hash_key, sizeof(params->toeplitz_hash_key));
	mlx5e_build_default_indir_rqt(mdev, params->indirection_rqt,
				      MLX5E_INDIR_RQT_SIZE, max_channels);
}
3916

3917 3918 3919 3920 3921 3922
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);
3923

3924 3925 3926 3927
	priv->mdev        = mdev;
	priv->netdev      = netdev;
	priv->profile     = profile;
	priv->ppriv       = ppriv;
3928
	priv->hard_mtu = MLX5E_ETH_HARD_MTU;
3929

3930
	mlx5e_build_nic_params(mdev, &priv->channels.params, profile->max_nch(mdev));
T
Tariq Toukan 已提交
3931

3932 3933 3934 3935
	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);
3936
	INIT_WORK(&priv->tx_timeout_work, mlx5e_tx_timeout_work);
3937 3938 3939 3940 3941 3942 3943
	INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work);
}

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

3944
	mlx5_query_nic_vport_mac_address(priv->mdev, 0, netdev->dev_addr);
3945 3946 3947 3948 3949
	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);
	}
3950 3951
}

3952 3953 3954 3955
static const struct switchdev_ops mlx5e_switchdev_ops = {
	.switchdev_port_attr_get	= mlx5e_attr_get,
};

3956
static void mlx5e_build_nic_netdev(struct net_device *netdev)
3957 3958 3959
{
	struct mlx5e_priv *priv = netdev_priv(netdev);
	struct mlx5_core_dev *mdev = priv->mdev;
3960 3961
	bool fcs_supported;
	bool fcs_enabled;
3962 3963 3964

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

3965
	if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
3966
		netdev->netdev_ops = &mlx5e_netdev_ops_sriov;
3967
#ifdef CONFIG_MLX5_CORE_EN_DCB
H
Huy Nguyen 已提交
3968 3969
		if (MLX5_CAP_GEN(mdev, qos))
			netdev->dcbnl_ops = &mlx5e_dcbnl_ops;
3970 3971
#endif
	} else {
3972
		netdev->netdev_ops = &mlx5e_netdev_ops_basic;
3973
	}
3974

3975 3976 3977 3978
	netdev->watchdog_timeo    = 15 * HZ;

	netdev->ethtool_ops	  = &mlx5e_ethtool_ops;

S
Saeed Mahameed 已提交
3979
	netdev->vlan_features    |= NETIF_F_SG;
3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991
	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;

	if (!!MLX5_CAP_ETH(mdev, lro_cap))
		netdev->vlan_features    |= NETIF_F_LRO;

	netdev->hw_features       = netdev->vlan_features;
3992
	netdev->hw_features      |= NETIF_F_HW_VLAN_CTAG_TX;
3993 3994 3995
	netdev->hw_features      |= NETIF_F_HW_VLAN_CTAG_RX;
	netdev->hw_features      |= NETIF_F_HW_VLAN_CTAG_FILTER;

3996
	if (mlx5e_vxlan_allowed(mdev)) {
3997 3998 3999
		netdev->hw_features     |= NETIF_F_GSO_UDP_TUNNEL |
					   NETIF_F_GSO_UDP_TUNNEL_CSUM |
					   NETIF_F_GSO_PARTIAL;
4000
		netdev->hw_enc_features |= NETIF_F_IP_CSUM;
4001
		netdev->hw_enc_features |= NETIF_F_IPV6_CSUM;
4002 4003 4004
		netdev->hw_enc_features |= NETIF_F_TSO;
		netdev->hw_enc_features |= NETIF_F_TSO6;
		netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL;
4005 4006 4007
		netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM |
					   NETIF_F_GSO_PARTIAL;
		netdev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
4008 4009
	}

4010 4011 4012 4013 4014
	mlx5_query_port_fcs(mdev, &fcs_supported, &fcs_enabled);

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

4015 4016 4017
	if (MLX5_CAP_ETH(mdev, scatter_fcs))
		netdev->hw_features |= NETIF_F_RXFCS;

4018
	netdev->features          = netdev->hw_features;
4019
	if (!priv->channels.params.lro_en)
4020 4021
		netdev->features  &= ~NETIF_F_LRO;

4022 4023 4024
	if (fcs_enabled)
		netdev->features  &= ~NETIF_F_RXALL;

4025 4026 4027
	if (!priv->channels.params.scatter_fcs_en)
		netdev->features  &= ~NETIF_F_RXFCS;

4028 4029 4030 4031
#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) &&
4032 4033 4034 4035 4036 4037
	    FT_CAP(flow_table_modify)) {
		netdev->hw_features      |= NETIF_F_HW_TC;
#ifdef CONFIG_RFS_ACCEL
		netdev->hw_features	 |= NETIF_F_NTUPLE;
#endif
	}
4038

4039 4040 4041 4042 4043
	netdev->features         |= NETIF_F_HIGHDMA;

	netdev->priv_flags       |= IFF_UNICAST_FLT;

	mlx5e_set_netdev_dev_addr(netdev);
4044 4045 4046 4047 4048

#ifdef CONFIG_NET_SWITCHDEV
	if (MLX5_CAP_GEN(mdev, vport_group_manager))
		netdev->switchdev_ops = &mlx5e_switchdev_ops;
#endif
4049 4050
}

4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070
static void mlx5e_create_q_counter(struct mlx5e_priv *priv)
{
	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;
	}
}

static void mlx5e_destroy_q_counter(struct mlx5e_priv *priv)
{
	if (!priv->q_counter)
		return;

	mlx5_core_dealloc_q_counter(priv->mdev, priv->q_counter);
}

4071 4072
static void mlx5e_nic_init(struct mlx5_core_dev *mdev,
			   struct net_device *netdev,
4073 4074
			   const struct mlx5e_profile *profile,
			   void *ppriv)
4075 4076 4077
{
	struct mlx5e_priv *priv = netdev_priv(netdev);

4078
	mlx5e_build_nic_netdev_priv(mdev, netdev, profile, ppriv);
4079 4080 4081 4082 4083 4084 4085
	mlx5e_build_nic_netdev(netdev);
	mlx5e_vxlan_init(priv);
}

static void mlx5e_nic_cleanup(struct mlx5e_priv *priv)
{
	mlx5e_vxlan_cleanup(priv);
4086

4087 4088
	if (priv->channels.params.xdp_prog)
		bpf_prog_put(priv->channels.params.xdp_prog);
4089 4090 4091 4092 4093 4094 4095
}

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

4096 4097
	err = mlx5e_create_indirect_rqt(priv);
	if (err)
4098 4099 4100
		return err;

	err = mlx5e_create_direct_rqts(priv);
4101
	if (err)
4102 4103 4104
		goto err_destroy_indirect_rqts;

	err = mlx5e_create_indirect_tirs(priv);
4105
	if (err)
4106 4107 4108
		goto err_destroy_direct_rqts;

	err = mlx5e_create_direct_tirs(priv);
4109
	if (err)
4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130
		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;
	}

	err = mlx5e_tc_init(priv);
	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:
4131
	mlx5e_destroy_direct_rqts(priv);
4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142
err_destroy_indirect_rqts:
	mlx5e_destroy_rqt(priv, &priv->indir_rqt);
	return err;
}

static void mlx5e_cleanup_nic_rx(struct mlx5e_priv *priv)
{
	mlx5e_tc_cleanup(priv);
	mlx5e_destroy_flow_steering(priv);
	mlx5e_destroy_direct_tirs(priv);
	mlx5e_destroy_indirect_tirs(priv);
4143
	mlx5e_destroy_direct_rqts(priv);
4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157
	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
4158
	mlx5e_dcbnl_initialize(priv);
4159 4160 4161 4162 4163 4164 4165 4166
#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;
4167 4168 4169 4170 4171 4172 4173
	u16 max_mtu;

	mlx5e_init_l2_addr(priv);

	/* MTU range: 68 - hw-specific max */
	netdev->min_mtu = ETH_MIN_MTU;
	mlx5_query_port_max_mtu(priv->mdev, &max_mtu, 1);
4174
	netdev->max_mtu = MLX5E_HW2SW_MTU(priv, max_mtu);
4175
	mlx5e_set_dev_port_mtu(priv);
4176

4177 4178
	mlx5_lag_add(mdev, netdev);

4179
	mlx5e_enable_async_events(priv);
4180

4181 4182
	if (MLX5_CAP_GEN(mdev, vport_group_manager))
		mlx5e_register_vport_reps(priv);
4183

4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194
	if (netdev->reg_state != NETREG_REGISTERED)
		return;

	/* Device already registered: sync netdev system state */
	if (mlx5e_vxlan_allowed(mdev)) {
		rtnl_lock();
		udp_tunnel_get_rx_info(netdev);
		rtnl_unlock();
	}

	queue_work(priv->wq, &priv->set_rx_mode_work);
4195 4196 4197 4198 4199 4200

	rtnl_lock();
	if (netif_running(netdev))
		mlx5e_open(netdev);
	netif_device_attach(netdev);
	rtnl_unlock();
4201 4202 4203 4204
}

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

4207 4208 4209 4210 4211 4212
	rtnl_lock();
	if (netif_running(priv->netdev))
		mlx5e_close(priv->netdev);
	netif_device_detach(priv->netdev);
	rtnl_unlock();

4213
	queue_work(priv->wq, &priv->set_rx_mode_work);
4214

4215
	if (MLX5_CAP_GEN(mdev, vport_group_manager))
4216 4217
		mlx5e_unregister_vport_reps(priv);

4218
	mlx5e_disable_async_events(priv);
4219
	mlx5_lag_remove(mdev);
4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230
}

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,
4231
	.update_stats	   = mlx5e_update_ndo_stats,
4232
	.max_nch	   = mlx5e_get_max_num_channels,
4233
	.update_carrier	   = mlx5e_update_carrier,
4234 4235
	.rx_handlers.handle_rx_cqe       = mlx5e_handle_rx_cqe,
	.rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
4236 4237 4238
	.max_tc		   = MLX5E_MAX_NUM_TC,
};

4239 4240
/* mlx5e generic netdev management API (move to en_common.c) */

4241 4242 4243
struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev,
				       const struct mlx5e_profile *profile,
				       void *ppriv)
4244
{
4245
	int nch = profile->max_nch(mdev);
4246 4247 4248
	struct net_device *netdev;
	struct mlx5e_priv *priv;

4249
	netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv),
4250
				    nch * profile->max_tc,
4251
				    nch);
4252 4253 4254 4255 4256
	if (!netdev) {
		mlx5_core_err(mdev, "alloc_etherdev_mqs() failed\n");
		return NULL;
	}

4257 4258 4259 4260
#ifdef CONFIG_RFS_ACCEL
	netdev->rx_cpu_rmap = mdev->rmap;
#endif

4261
	profile->init(mdev, netdev, profile, ppriv);
4262 4263 4264 4265 4266

	netif_carrier_off(netdev);

	priv = netdev_priv(netdev);

4267 4268
	priv->wq = create_singlethread_workqueue("mlx5e");
	if (!priv->wq)
4269 4270 4271 4272 4273
		goto err_cleanup_nic;

	return netdev;

err_cleanup_nic:
4274 4275
	if (profile->cleanup)
		profile->cleanup(priv);
4276 4277 4278 4279 4280
	free_netdev(netdev);

	return NULL;
}

4281
int mlx5e_attach_netdev(struct mlx5e_priv *priv)
4282
{
4283
	struct mlx5_core_dev *mdev = priv->mdev;
4284 4285 4286 4287 4288
	const struct mlx5e_profile *profile;
	int err;

	profile = priv->profile;
	clear_bit(MLX5E_STATE_DESTROYING, &priv->state);
4289

4290 4291
	err = profile->init_tx(priv);
	if (err)
T
Tariq Toukan 已提交
4292
		goto out;
4293

4294
	err = mlx5e_open_drop_rq(mdev, &priv->drop_rq);
4295 4296
	if (err) {
		mlx5_core_err(mdev, "open drop rq failed, %d\n", err);
4297
		goto err_cleanup_tx;
4298 4299
	}

4300 4301
	err = profile->init_rx(priv);
	if (err)
4302 4303
		goto err_close_drop_rq;

4304 4305
	mlx5e_create_q_counter(priv);

4306 4307
	if (profile->enable)
		profile->enable(priv);
4308

4309
	return 0;
4310 4311

err_close_drop_rq:
4312
	mlx5e_close_drop_rq(&priv->drop_rq);
4313

4314 4315
err_cleanup_tx:
	profile->cleanup_tx(priv);
4316

4317 4318
out:
	return err;
4319 4320
}

4321
void mlx5e_detach_netdev(struct mlx5e_priv *priv)
4322 4323 4324 4325 4326
{
	const struct mlx5e_profile *profile = priv->profile;

	set_bit(MLX5E_STATE_DESTROYING, &priv->state);

4327 4328 4329 4330
	if (profile->disable)
		profile->disable(priv);
	flush_workqueue(priv->wq);

4331 4332
	mlx5e_destroy_q_counter(priv);
	profile->cleanup_rx(priv);
4333
	mlx5e_close_drop_rq(&priv->drop_rq);
4334 4335 4336 4337
	profile->cleanup_tx(priv);
	cancel_delayed_work_sync(&priv->update_stats_work);
}

4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348
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);
}

4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364
/* 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;

4365
	err = mlx5e_attach_netdev(priv);
4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381
	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;

4382
	mlx5e_detach_netdev(priv);
4383 4384 4385
	mlx5e_destroy_mdev_resources(mdev);
}

4386 4387
static void *mlx5e_add(struct mlx5_core_dev *mdev)
{
4388
	struct mlx5_eswitch *esw = mdev->priv.eswitch;
4389
	int total_vfs = MLX5_TOTAL_VPORTS(mdev);
4390
	struct mlx5e_rep_priv *rpriv = NULL;
4391 4392 4393 4394
	void *priv;
	int vport;
	int err;
	struct net_device *netdev;
4395

4396 4397
	err = mlx5e_check_required_hca_cap(mdev);
	if (err)
4398 4399
		return NULL;

4400 4401 4402 4403 4404 4405 4406 4407 4408
	if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
		rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
		if (!rpriv) {
			mlx5_core_warn(mdev,
				       "Not creating net device, Failed to alloc rep priv data\n");
			return NULL;
		}
		rpriv->rep = &esw->offloads.vport_reps[0];
	}
4409

4410
	netdev = mlx5e_create_netdev(mdev, &mlx5e_nic_profile, rpriv);
4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427
	if (!netdev) {
		mlx5_core_err(mdev, "mlx5e_create_netdev failed\n");
		goto err_unregister_reps;
	}

	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;
4428
	}
4429 4430 4431 4432 4433 4434 4435

	return priv;

err_detach:
	mlx5e_detach(mdev, priv);

err_destroy_netdev:
4436
	mlx5e_destroy_netdev(priv);
4437 4438 4439 4440 4441

err_unregister_reps:
	for (vport = 1; vport < total_vfs; vport++)
		mlx5_eswitch_unregister_vport_rep(esw, vport);

4442
	kfree(rpriv);
4443
	return NULL;
4444 4445 4446 4447 4448
}

static void mlx5e_remove(struct mlx5_core_dev *mdev, void *vpriv)
{
	struct mlx5e_priv *priv = vpriv;
4449
	void *ppriv = priv->ppriv;
4450

4451
	unregister_netdev(priv->netdev);
4452
	mlx5e_detach(mdev, vpriv);
4453
	mlx5e_destroy_netdev(priv);
4454
	kfree(ppriv);
4455 4456
}

4457 4458 4459 4460 4461 4462 4463 4464
static void *mlx5e_get_netdev(void *vpriv)
{
	struct mlx5e_priv *priv = vpriv;

	return priv->netdev;
}

static struct mlx5_interface mlx5e_interface = {
4465 4466
	.add       = mlx5e_add,
	.remove    = mlx5e_remove,
4467 4468
	.attach    = mlx5e_attach,
	.detach    = mlx5e_detach,
4469 4470 4471 4472 4473 4474 4475
	.event     = mlx5e_async_event,
	.protocol  = MLX5_INTERFACE_PROTOCOL_ETH,
	.get_dev   = mlx5e_get_netdev,
};

void mlx5e_init(void)
{
4476
	mlx5e_build_ptys2ethtool_map();
4477 4478 4479 4480 4481 4482 4483
	mlx5_register_interface(&mlx5e_interface);
}

void mlx5e_cleanup(void)
{
	mlx5_unregister_interface(&mlx5e_interface);
}