qed_init_fw_funcs.c 29.5 KB
Newer Older
1
/* QLogic qed NIC Driver
M
Mintz, Yuval 已提交
2
 * Copyright (c) 2015-2017  QLogic Corporation
3
 *
M
Mintz, Yuval 已提交
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
 * 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.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
 */

#include <linux/types.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
#include "qed_hsi.h"
#include "qed_hw.h"
#include "qed_init_ops.h"
#include "qed_reg_addr.h"

enum cminterface {
	MCM_SEC,
	MCM_PRI,
	UCM_SEC,
	UCM_PRI,
	TCM_SEC,
	TCM_PRI,
	YCM_SEC,
	YCM_PRI,
	XCM_SEC,
	XCM_PRI,
	NUM_OF_CM_INTERFACES
};

/* general constants */
#define QM_PQ_MEM_4KB(pq_size)	(pq_size ? DIV_ROUND_UP((pq_size + 1) *	\
							QM_PQ_ELEMENT_SIZE, \
							0x1000) : 0)
#define QM_PQ_SIZE_256B(pq_size)	(pq_size ? DIV_ROUND_UP(pq_size, \
								0x100) - 1 : 0)
#define QM_INVALID_PQ_ID                        0xffff
/* feature enable */
#define QM_BYPASS_EN                            1
#define QM_BYTE_CRD_EN                          1
/* other PQ constants */
#define QM_OTHER_PQS_PER_PF                     4
/* WFQ constants */
Y
Yuval Mintz 已提交
70
#define QM_WFQ_UPPER_BOUND		62500000
71 72 73
#define QM_WFQ_VP_PQ_VOQ_SHIFT          0
#define QM_WFQ_VP_PQ_PF_SHIFT           5
#define QM_WFQ_INC_VAL(weight)          ((weight) * 0x9000)
Y
Yuval Mintz 已提交
74 75
#define QM_WFQ_MAX_INC_VAL                      43750000

76
/* RL constants */
Y
Yuval Mintz 已提交
77
#define QM_RL_UPPER_BOUND                       62500000
78 79
#define QM_RL_PERIOD                            5               /* in us */
#define QM_RL_PERIOD_CLK_25M            (25 * QM_RL_PERIOD)
Y
Yuval Mintz 已提交
80
#define QM_RL_MAX_INC_VAL                       43750000
81
#define QM_RL_INC_VAL(rate)		max_t(u32,	\
Y
Yuval Mintz 已提交
82 83 84 85
					      (u32)(((rate ? rate : \
						      1000000) *    \
						     QM_RL_PERIOD * \
						     101) / (8 * 100)), 1)
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
/* AFullOprtnstcCrdMask constants */
#define QM_OPPOR_LINE_VOQ_DEF           1
#define QM_OPPOR_FW_STOP_DEF            0
#define QM_OPPOR_PQ_EMPTY_DEF           1
/* Command Queue constants */
#define PBF_CMDQ_PURE_LB_LINES                          150
#define PBF_CMDQ_LINES_RT_OFFSET(voq)           (		 \
		PBF_REG_YCMD_QS_NUM_LINES_VOQ0_RT_OFFSET + voq * \
		(PBF_REG_YCMD_QS_NUM_LINES_VOQ1_RT_OFFSET -	 \
		 PBF_REG_YCMD_QS_NUM_LINES_VOQ0_RT_OFFSET))
#define PBF_BTB_GUARANTEED_RT_OFFSET(voq)       (	      \
		PBF_REG_BTB_GUARANTEED_VOQ0_RT_OFFSET + voq * \
		(PBF_REG_BTB_GUARANTEED_VOQ1_RT_OFFSET -      \
		 PBF_REG_BTB_GUARANTEED_VOQ0_RT_OFFSET))
#define QM_VOQ_LINE_CRD(pbf_cmd_lines)          ((((pbf_cmd_lines) - \
						   4) *		     \
						  2) | QM_LINE_CRD_REG_SIGN_BIT)
/* BTB: blocks constants (block size = 256B) */
#define BTB_JUMBO_PKT_BLOCKS            38
#define BTB_HEADROOM_BLOCKS                     BTB_JUMBO_PKT_BLOCKS
#define BTB_PURE_LB_FACTOR                      10
#define BTB_PURE_LB_RATIO                       7
/* QM stop command constants */
#define QM_STOP_PQ_MASK_WIDTH                   32
#define QM_STOP_CMD_ADDR                                0x2
#define QM_STOP_CMD_STRUCT_SIZE                 2
#define QM_STOP_CMD_PAUSE_MASK_OFFSET   0
#define QM_STOP_CMD_PAUSE_MASK_SHIFT    0
#define QM_STOP_CMD_PAUSE_MASK_MASK             -1
#define QM_STOP_CMD_GROUP_ID_OFFSET             1
#define QM_STOP_CMD_GROUP_ID_SHIFT              16
#define QM_STOP_CMD_GROUP_ID_MASK               15
#define QM_STOP_CMD_PQ_TYPE_OFFSET              1
#define QM_STOP_CMD_PQ_TYPE_SHIFT               24
#define QM_STOP_CMD_PQ_TYPE_MASK                1
#define QM_STOP_CMD_MAX_POLL_COUNT              100
#define QM_STOP_CMD_POLL_PERIOD_US              500
/* QM command macros */
#define QM_CMD_STRUCT_SIZE(cmd)			cmd ## \
	_STRUCT_SIZE
#define QM_CMD_SET_FIELD(var, cmd, field,				  \
			 value)        SET_FIELD(var[cmd ## _ ## field ## \
						     _OFFSET],		  \
						 cmd ## _ ## field,	  \
						 value)
/* QM: VOQ macros */
Y
Yuval Mintz 已提交
132 133 134
#define PHYS_VOQ(port, tc, max_phys_tcs_per_port) ((port) *	\
						   (max_phys_tcs_per_port) + \
						   (tc))
135 136 137 138 139 140 141 142 143 144
#define LB_VOQ(port)				( \
		MAX_PHYS_VOQS + (port))
#define VOQ(port, tc, max_phy_tcs_pr_port)	\
	((tc) <		\
	 LB_TC ? PHYS_VOQ(port,		\
			  tc,			 \
			  max_phy_tcs_pr_port) \
		: LB_VOQ(port))
/******************** INTERNAL IMPLEMENTATION *********************/
/* Prepare PF RL enable/disable runtime init values */
Y
Yuval Mintz 已提交
145
static void qed_enable_pf_rl(struct qed_hwfn *p_hwfn, bool pf_rl_en)
146 147 148 149 150 151 152 153
{
	STORE_RT_REG(p_hwfn, QM_REG_RLPFENABLE_RT_OFFSET, pf_rl_en ? 1 : 0);
	if (pf_rl_en) {
		/* enable RLs for all VOQs */
		STORE_RT_REG(p_hwfn, QM_REG_RLPFVOQENABLE_RT_OFFSET,
			     (1 << MAX_NUM_VOQS) - 1);
		/* write RL period */
		STORE_RT_REG(p_hwfn,
Y
Yuval Mintz 已提交
154
			     QM_REG_RLPFPERIOD_RT_OFFSET, QM_RL_PERIOD_CLK_25M);
155 156 157 158 159 160 161 162 163 164 165 166
		STORE_RT_REG(p_hwfn,
			     QM_REG_RLPFPERIODTIMER_RT_OFFSET,
			     QM_RL_PERIOD_CLK_25M);
		/* set credit threshold for QM bypass flow */
		if (QM_BYPASS_EN)
			STORE_RT_REG(p_hwfn,
				     QM_REG_AFULLQMBYPTHRPFRL_RT_OFFSET,
				     QM_RL_UPPER_BOUND);
	}
}

/* Prepare PF WFQ enable/disable runtime init values */
Y
Yuval Mintz 已提交
167
static void qed_enable_pf_wfq(struct qed_hwfn *p_hwfn, bool pf_wfq_en)
168 169 170 171 172 173 174 175 176 177
{
	STORE_RT_REG(p_hwfn, QM_REG_WFQPFENABLE_RT_OFFSET, pf_wfq_en ? 1 : 0);
	/* set credit threshold for QM bypass flow */
	if (pf_wfq_en && QM_BYPASS_EN)
		STORE_RT_REG(p_hwfn,
			     QM_REG_AFULLQMBYPTHRPFWFQ_RT_OFFSET,
			     QM_WFQ_UPPER_BOUND);
}

/* Prepare VPORT RL enable/disable runtime init values */
Y
Yuval Mintz 已提交
178
static void qed_enable_vport_rl(struct qed_hwfn *p_hwfn, bool vport_rl_en)
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
{
	STORE_RT_REG(p_hwfn, QM_REG_RLGLBLENABLE_RT_OFFSET,
		     vport_rl_en ? 1 : 0);
	if (vport_rl_en) {
		/* write RL period (use timer 0 only) */
		STORE_RT_REG(p_hwfn,
			     QM_REG_RLGLBLPERIOD_0_RT_OFFSET,
			     QM_RL_PERIOD_CLK_25M);
		STORE_RT_REG(p_hwfn,
			     QM_REG_RLGLBLPERIODTIMER_0_RT_OFFSET,
			     QM_RL_PERIOD_CLK_25M);
		/* set credit threshold for QM bypass flow */
		if (QM_BYPASS_EN)
			STORE_RT_REG(p_hwfn,
				     QM_REG_AFULLQMBYPTHRGLBLRL_RT_OFFSET,
				     QM_RL_UPPER_BOUND);
	}
}

/* Prepare VPORT WFQ enable/disable runtime init values */
Y
Yuval Mintz 已提交
199
static void qed_enable_vport_wfq(struct qed_hwfn *p_hwfn, bool vport_wfq_en)
200 201 202 203 204 205 206 207 208 209 210 211 212 213
{
	STORE_RT_REG(p_hwfn, QM_REG_WFQVPENABLE_RT_OFFSET,
		     vport_wfq_en ? 1 : 0);
	/* set credit threshold for QM bypass flow */
	if (vport_wfq_en && QM_BYPASS_EN)
		STORE_RT_REG(p_hwfn,
			     QM_REG_AFULLQMBYPTHRVPWFQ_RT_OFFSET,
			     QM_WFQ_UPPER_BOUND);
}

/* Prepare runtime init values to allocate PBF command queue lines for
 * the specified VOQ
 */
static void qed_cmdq_lines_voq_rt_init(struct qed_hwfn *p_hwfn,
Y
Yuval Mintz 已提交
214
				       u8 voq, u16 cmdq_lines)
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
{
	u32 qm_line_crd;

	qm_line_crd = QM_VOQ_LINE_CRD(cmdq_lines);
	OVERWRITE_RT_REG(p_hwfn, PBF_CMDQ_LINES_RT_OFFSET(voq),
			 (u32)cmdq_lines);
	STORE_RT_REG(p_hwfn, QM_REG_VOQCRDLINE_RT_OFFSET + voq, qm_line_crd);
	STORE_RT_REG(p_hwfn, QM_REG_VOQINITCRDLINE_RT_OFFSET + voq,
		     qm_line_crd);
}

/* Prepare runtime init values to allocate PBF command queue lines. */
static void qed_cmdq_lines_rt_init(
	struct qed_hwfn *p_hwfn,
	u8 max_ports_per_engine,
	u8 max_phys_tcs_per_port,
	struct init_qm_port_params port_params[MAX_NUM_PORTS])
{
Y
Yuval Mintz 已提交
233
	u8 tc, voq, port_id, num_tcs_in_port;
234 235 236 237 238 239 240 241

	/* clear PBF lines for all VOQs */
	for (voq = 0; voq < MAX_NUM_VOQS; voq++)
		STORE_RT_REG(p_hwfn, PBF_CMDQ_LINES_RT_OFFSET(voq), 0);
	for (port_id = 0; port_id < max_ports_per_engine; port_id++) {
		if (port_params[port_id].active) {
			u16 phys_lines, phys_lines_per_tc;

Y
Yuval Mintz 已提交
242
			/* find #lines to divide between active phys TCs */
243 244 245
			phys_lines = port_params[port_id].num_pbf_cmd_lines -
				     PBF_CMDQ_PURE_LB_LINES;
			/* find #lines per active physical TC */
Y
Yuval Mintz 已提交
246 247 248 249 250 251 252 253
			num_tcs_in_port = 0;
			for (tc = 0; tc < NUM_OF_PHYS_TCS; tc++) {
				if (((port_params[port_id].active_phys_tcs >>
				      tc) & 0x1) == 1)
					num_tcs_in_port++;
			}

			phys_lines_per_tc = phys_lines / num_tcs_in_port;
254
			/* init registers per active TC */
Y
Yuval Mintz 已提交
255 256 257 258 259
			for (tc = 0; tc < NUM_OF_PHYS_TCS; tc++) {
				if (((port_params[port_id].active_phys_tcs >>
				      tc) & 0x1) != 1)
					continue;

260 261 262 263 264
				voq = PHYS_VOQ(port_id, tc,
					       max_phys_tcs_per_port);
				qed_cmdq_lines_voq_rt_init(p_hwfn, voq,
							   phys_lines_per_tc);
			}
Y
Yuval Mintz 已提交
265

266 267 268 269 270 271 272 273 274 275 276 277 278 279
			/* init registers for pure LB TC */
			qed_cmdq_lines_voq_rt_init(p_hwfn, LB_VOQ(port_id),
						   PBF_CMDQ_PURE_LB_LINES);
		}
	}
}

static void qed_btb_blocks_rt_init(
	struct qed_hwfn *p_hwfn,
	u8 max_ports_per_engine,
	u8 max_phys_tcs_per_port,
	struct init_qm_port_params port_params[MAX_NUM_PORTS])
{
	u32 usable_blocks, pure_lb_blocks, phys_blocks;
Y
Yuval Mintz 已提交
280
	u8 tc, voq, port_id, num_tcs_in_port;
281 282 283 284 285 286 287 288 289 290 291

	for (port_id = 0; port_id < max_ports_per_engine; port_id++) {
		u32 temp;

		if (!port_params[port_id].active)
			continue;

		/* subtract headroom blocks */
		usable_blocks = port_params[port_id].num_btb_blocks -
				BTB_HEADROOM_BLOCKS;

Y
Yuval Mintz 已提交
292 293 294 295 296 297 298 299
		/* find blocks per physical TC */
		num_tcs_in_port = 0;
		for (tc = 0; tc < NUM_OF_PHYS_TCS; tc++) {
			if (((port_params[port_id].active_phys_tcs >>
			      tc) & 0x1) == 1)
				num_tcs_in_port++;
		}

300
		pure_lb_blocks = (usable_blocks * BTB_PURE_LB_FACTOR) /
Y
Yuval Mintz 已提交
301
				 (num_tcs_in_port * BTB_PURE_LB_FACTOR +
302 303 304
				  BTB_PURE_LB_RATIO);
		pure_lb_blocks = max_t(u32, BTB_JUMBO_PKT_BLOCKS,
				       pure_lb_blocks / BTB_PURE_LB_FACTOR);
Y
Yuval Mintz 已提交
305 306
		phys_blocks = (usable_blocks - pure_lb_blocks) /
			      num_tcs_in_port;
307 308

		/* init physical TCs */
Y
Yuval Mintz 已提交
309 310 311 312 313 314 315
		for (tc = 0; tc < NUM_OF_PHYS_TCS; tc++) {
			if (((port_params[port_id].active_phys_tcs >>
			      tc) & 0x1) != 1)
				continue;

			voq = PHYS_VOQ(port_id, tc,
				       max_phys_tcs_per_port);
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
			STORE_RT_REG(p_hwfn, PBF_BTB_GUARANTEED_RT_OFFSET(voq),
				     phys_blocks);
		}

		/* init pure LB TC */
		temp = LB_VOQ(port_id);
		STORE_RT_REG(p_hwfn, PBF_BTB_GUARANTEED_RT_OFFSET(temp),
			     pure_lb_blocks);
	}
}

/* Prepare Tx PQ mapping runtime init values for the specified PF */
static void qed_tx_pq_map_rt_init(
	struct qed_hwfn *p_hwfn,
	struct qed_ptt *p_ptt,
	struct qed_qm_pf_rt_init_params *p_params,
	u32 base_mem_addr_4kb)
{
	struct init_qm_vport_params *vport_params = p_params->vport_params;
	u16 num_pqs = p_params->num_pf_pqs + p_params->num_vf_pqs;
	u16 first_pq_group = p_params->start_pq / QM_PF_QUEUE_GROUP_SIZE;
	u16 last_pq_group = (p_params->start_pq + num_pqs - 1) /
			    QM_PF_QUEUE_GROUP_SIZE;
	u16 i, pq_id, pq_group;

	/* a bit per Tx PQ indicating if the PQ is associated with a VF */
	u32 tx_pq_vf_mask[MAX_QM_TX_QUEUES / QM_PF_QUEUE_GROUP_SIZE] = { 0 };
M
Mintz, Yuval 已提交
343
	u32 num_tx_pq_vf_masks = MAX_QM_TX_QUEUES / QM_PF_QUEUE_GROUP_SIZE;
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
	u32 pq_mem_4kb = QM_PQ_MEM_4KB(p_params->num_pf_cids);
	u32 vport_pq_mem_4kb = QM_PQ_MEM_4KB(p_params->num_vf_cids);
	u32 mem_addr_4kb = base_mem_addr_4kb;

	/* set mapping from PQ group to PF */
	for (pq_group = first_pq_group; pq_group <= last_pq_group; pq_group++)
		STORE_RT_REG(p_hwfn, QM_REG_PQTX2PF_0_RT_OFFSET + pq_group,
			     (u32)(p_params->pf_id));
	/* set PQ sizes */
	STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_0_RT_OFFSET,
		     QM_PQ_SIZE_256B(p_params->num_pf_cids));
	STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_1_RT_OFFSET,
		     QM_PQ_SIZE_256B(p_params->num_vf_cids));

	/* go over all Tx PQs */
	for (i = 0, pq_id = p_params->start_pq; i < num_pqs; i++, pq_id++) {
		u8 voq = VOQ(p_params->port_id, p_params->pq_params[i].tc_id,
			     p_params->max_phys_tcs_per_port);
		bool is_vf_pq = (i >= p_params->num_pf_pqs);
		struct qm_rf_pq_map tx_pq_map;

M
Mintz, Yuval 已提交
365 366 367 368
		bool rl_valid = p_params->pq_params[i].rl_valid &&
				(p_params->pq_params[i].vport_id <
				 MAX_QM_GLOBAL_RLS);

369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
		/* update first Tx PQ of VPORT/TC */
		u8 vport_id_in_pf = p_params->pq_params[i].vport_id -
				    p_params->start_vport;
		u16 *pq_ids = &vport_params[vport_id_in_pf].first_tx_pq_id[0];
		u16 first_tx_pq_id = pq_ids[p_params->pq_params[i].tc_id];

		if (first_tx_pq_id == QM_INVALID_PQ_ID) {
			/* create new VP PQ */
			pq_ids[p_params->pq_params[i].tc_id] = pq_id;
			first_tx_pq_id = pq_id;
			/* map VP PQ to VOQ and PF */
			STORE_RT_REG(p_hwfn,
				     QM_REG_WFQVPMAP_RT_OFFSET +
				     first_tx_pq_id,
				     (voq << QM_WFQ_VP_PQ_VOQ_SHIFT) |
				     (p_params->pf_id <<
				      QM_WFQ_VP_PQ_PF_SHIFT));
		}
M
Mintz, Yuval 已提交
387 388 389 390

		if (p_params->pq_params[i].rl_valid && !rl_valid)
			DP_NOTICE(p_hwfn,
				  "Invalid VPORT ID for rate limiter configuration");
391 392 393
		/* fill PQ map entry */
		memset(&tx_pq_map, 0, sizeof(tx_pq_map));
		SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_PQ_VALID, 1);
M
Mintz, Yuval 已提交
394 395
		SET_FIELD(tx_pq_map.reg,
			  QM_RF_PQ_MAP_RL_VALID, rl_valid ? 1 : 0);
396 397
		SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_VP_PQ_ID, first_tx_pq_id);
		SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_RL_ID,
M
Mintz, Yuval 已提交
398
			  rl_valid ?
Y
Yuval Mintz 已提交
399
			  p_params->pq_params[i].vport_id : 0);
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
		SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_VOQ, voq);
		SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_WRR_WEIGHT_GROUP,
			  p_params->pq_params[i].wrr_group);
		/* write PQ map entry to CAM */
		STORE_RT_REG(p_hwfn, QM_REG_TXPQMAP_RT_OFFSET + pq_id,
			     *((u32 *)&tx_pq_map));
		/* set base address */
		STORE_RT_REG(p_hwfn,
			     QM_REG_BASEADDRTXPQ_RT_OFFSET + pq_id,
			     mem_addr_4kb);
		/* check if VF PQ */
		if (is_vf_pq) {
			/* if PQ is associated with a VF, add indication
			 * to PQ VF mask
			 */
M
Mintz, Yuval 已提交
415 416 417
			tx_pq_vf_mask[pq_id /
				      QM_PF_QUEUE_GROUP_SIZE] |=
			    BIT((pq_id % QM_PF_QUEUE_GROUP_SIZE));
418 419 420 421 422 423 424 425 426
			mem_addr_4kb += vport_pq_mem_4kb;
		} else {
			mem_addr_4kb += pq_mem_4kb;
		}
	}

	/* store Tx PQ VF mask to size select register */
	for (i = 0; i < num_tx_pq_vf_masks; i++) {
		if (tx_pq_vf_mask[i]) {
Y
Yuval Mintz 已提交
427
			u32 addr;
428

Y
Yuval Mintz 已提交
429 430 431
			addr = QM_REG_MAXPQSIZETXSEL_0_RT_OFFSET + i;
			STORE_RT_REG(p_hwfn, addr,
				     tx_pq_vf_mask[i]);
432 433 434 435 436 437 438 439 440
		}
	}
}

/* Prepare Other PQ mapping runtime init values for the specified PF */
static void qed_other_pq_map_rt_init(struct qed_hwfn *p_hwfn,
				     u8 port_id,
				     u8 pf_id,
				     u32 num_pf_cids,
Y
Yuval Mintz 已提交
441
				     u32 num_tids, u32 base_mem_addr_4kb)
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
{
	u16 i, pq_id;

	/* a single other PQ group is used in each PF,
	 * where PQ group i is used in PF i.
	 */
	u16 pq_group = pf_id;
	u32 pq_size = num_pf_cids + num_tids;
	u32 pq_mem_4kb = QM_PQ_MEM_4KB(pq_size);
	u32 mem_addr_4kb = base_mem_addr_4kb;

	/* map PQ group to PF */
	STORE_RT_REG(p_hwfn, QM_REG_PQOTHER2PF_0_RT_OFFSET + pq_group,
		     (u32)(pf_id));
	/* set PQ sizes */
	STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_2_RT_OFFSET,
		     QM_PQ_SIZE_256B(pq_size));
	/* set base address */
	for (i = 0, pq_id = pf_id * QM_PF_QUEUE_GROUP_SIZE;
	     i < QM_OTHER_PQS_PER_PF; i++, pq_id++) {
		STORE_RT_REG(p_hwfn,
			     QM_REG_BASEADDROTHERPQ_RT_OFFSET + pq_id,
			     mem_addr_4kb);
		mem_addr_4kb += pq_mem_4kb;
	}
}

/* Prepare PF WFQ runtime init values for the specified PF.
 * Return -1 on error.
 */
static int qed_pf_wfq_rt_init(struct qed_hwfn *p_hwfn,
			      struct qed_qm_pf_rt_init_params *p_params)
{
	u16 num_tx_pqs = p_params->num_pf_pqs + p_params->num_vf_pqs;
	u32 crd_reg_offset;
	u32 inc_val;
	u16 i;

	if (p_params->pf_id < MAX_NUM_PFS_BB)
		crd_reg_offset = QM_REG_WFQPFCRD_RT_OFFSET;
	else
M
Mintz, Yuval 已提交
483 484
		crd_reg_offset = QM_REG_WFQPFCRD_MSB_RT_OFFSET;
	crd_reg_offset += p_params->pf_id % MAX_NUM_PFS_BB;
485 486

	inc_val = QM_WFQ_INC_VAL(p_params->pf_wfq);
Y
Yuval Mintz 已提交
487
	if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) {
488 489 490 491 492 493 494 495 496 497 498 499 500
		DP_NOTICE(p_hwfn, "Invalid PF WFQ weight configuration");
		return -1;
	}

	for (i = 0; i < num_tx_pqs; i++) {
		u8 voq = VOQ(p_params->port_id, p_params->pq_params[i].tc_id,
			     p_params->max_phys_tcs_per_port);

		OVERWRITE_RT_REG(p_hwfn,
				 crd_reg_offset + voq * MAX_NUM_PFS_BB,
				 QM_WFQ_CRD_REG_SIGN_BIT);
	}

Y
Yuval Mintz 已提交
501 502 503
	STORE_RT_REG(p_hwfn,
		     QM_REG_WFQPFUPPERBOUND_RT_OFFSET + p_params->pf_id,
		     QM_WFQ_UPPER_BOUND | QM_WFQ_CRD_REG_SIGN_BIT);
M
Mintz, Yuval 已提交
504 505
	STORE_RT_REG(p_hwfn, QM_REG_WFQPFWEIGHT_RT_OFFSET + p_params->pf_id,
		     inc_val);
506 507 508 509 510 511
	return 0;
}

/* Prepare PF RL runtime init values for the specified PF.
 * Return -1 on error.
 */
Y
Yuval Mintz 已提交
512
static int qed_pf_rl_rt_init(struct qed_hwfn *p_hwfn, u8 pf_id, u32 pf_rl)
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
{
	u32 inc_val = QM_RL_INC_VAL(pf_rl);

	if (inc_val > QM_RL_MAX_INC_VAL) {
		DP_NOTICE(p_hwfn, "Invalid PF rate limit configuration");
		return -1;
	}
	STORE_RT_REG(p_hwfn, QM_REG_RLPFCRD_RT_OFFSET + pf_id,
		     QM_RL_CRD_REG_SIGN_BIT);
	STORE_RT_REG(p_hwfn, QM_REG_RLPFUPPERBOUND_RT_OFFSET + pf_id,
		     QM_RL_UPPER_BOUND | QM_RL_CRD_REG_SIGN_BIT);
	STORE_RT_REG(p_hwfn, QM_REG_RLPFINCVAL_RT_OFFSET + pf_id, inc_val);
	return 0;
}

/* Prepare VPORT WFQ runtime init values for the specified VPORTs.
 * Return -1 on error.
 */
static int qed_vp_wfq_rt_init(struct qed_hwfn *p_hwfn,
			      u8 num_vports,
			      struct init_qm_vport_params *vport_params)
{
	u32 inc_val;
Y
Yuval Mintz 已提交
536
	u8 tc, i;
537 538

	/* go over all PF VPORTs */
Y
Yuval Mintz 已提交
539
	for (i = 0; i < num_vports; i++) {
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554

		if (!vport_params[i].vport_wfq)
			continue;

		inc_val = QM_WFQ_INC_VAL(vport_params[i].vport_wfq);
		if (inc_val > QM_WFQ_MAX_INC_VAL) {
			DP_NOTICE(p_hwfn,
				  "Invalid VPORT WFQ weight configuration");
			return -1;
		}

		/* each VPORT can have several VPORT PQ IDs for
		 * different TCs
		 */
		for (tc = 0; tc < NUM_OF_TCS; tc++) {
Y
Yuval Mintz 已提交
555
			u16 vport_pq_id = vport_params[i].first_tx_pq_id[tc];
556 557 558 559 560 561

			if (vport_pq_id != QM_INVALID_PQ_ID) {
				STORE_RT_REG(p_hwfn,
					     QM_REG_WFQVPCRD_RT_OFFSET +
					     vport_pq_id,
					     QM_WFQ_CRD_REG_SIGN_BIT);
Y
Yuval Mintz 已提交
562 563 564
				STORE_RT_REG(p_hwfn,
					     QM_REG_WFQVPWEIGHT_RT_OFFSET +
					     vport_pq_id, inc_val);
565 566 567 568 569 570 571 572 573 574 575 576 577 578
			}
		}
	}

	return 0;
}

static int qed_vport_rl_rt_init(struct qed_hwfn *p_hwfn,
				u8 start_vport,
				u8 num_vports,
				struct init_qm_vport_params *vport_params)
{
	u8 i, vport_id;

M
Mintz, Yuval 已提交
579 580 581 582 583 584
	if (start_vport + num_vports >= MAX_QM_GLOBAL_RLS) {
		DP_NOTICE(p_hwfn,
			  "Invalid VPORT ID for rate limiter configuration");
		return -1;
	}

585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
	/* go over all PF VPORTs */
	for (i = 0, vport_id = start_vport; i < num_vports; i++, vport_id++) {
		u32 inc_val = QM_RL_INC_VAL(vport_params[i].vport_rl);

		if (inc_val > QM_RL_MAX_INC_VAL) {
			DP_NOTICE(p_hwfn,
				  "Invalid VPORT rate-limit configuration");
			return -1;
		}

		STORE_RT_REG(p_hwfn,
			     QM_REG_RLGLBLCRD_RT_OFFSET + vport_id,
			     QM_RL_CRD_REG_SIGN_BIT);
		STORE_RT_REG(p_hwfn,
			     QM_REG_RLGLBLUPPERBOUND_RT_OFFSET + vport_id,
			     QM_RL_UPPER_BOUND | QM_RL_CRD_REG_SIGN_BIT);
		STORE_RT_REG(p_hwfn,
			     QM_REG_RLGLBLINCVAL_RT_OFFSET + vport_id,
			     inc_val);
	}

	return 0;
}

static bool qed_poll_on_qm_cmd_ready(struct qed_hwfn *p_hwfn,
				     struct qed_ptt *p_ptt)
{
	u32 reg_val, i;

	for (i = 0, reg_val = 0; i < QM_STOP_CMD_MAX_POLL_COUNT && reg_val == 0;
	     i++) {
		udelay(QM_STOP_CMD_POLL_PERIOD_US);
		reg_val = qed_rd(p_hwfn, p_ptt, QM_REG_SDMCMDREADY);
	}

	/* check if timeout while waiting for SDM command ready */
	if (i == QM_STOP_CMD_MAX_POLL_COUNT) {
		DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
			   "Timeout when waiting for QM SDM command ready signal\n");
		return false;
	}

	return true;
}

static bool qed_send_qm_cmd(struct qed_hwfn *p_hwfn,
			    struct qed_ptt *p_ptt,
Y
Yuval Mintz 已提交
632
			    u32 cmd_addr, u32 cmd_data_lsb, u32 cmd_data_msb)
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
{
	if (!qed_poll_on_qm_cmd_ready(p_hwfn, p_ptt))
		return false;

	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDADDR, cmd_addr);
	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDDATALSB, cmd_data_lsb);
	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDDATAMSB, cmd_data_msb);
	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDGO, 1);
	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDGO, 0);

	return qed_poll_on_qm_cmd_ready(p_hwfn, p_ptt);
}

/******************** INTERFACE IMPLEMENTATION *********************/
u32 qed_qm_pf_mem_size(u8 pf_id,
		       u32 num_pf_cids,
		       u32 num_vf_cids,
Y
Yuval Mintz 已提交
650
		       u32 num_tids, u16 num_pf_pqs, u16 num_vf_pqs)
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
{
	return QM_PQ_MEM_4KB(num_pf_cids) * num_pf_pqs +
	       QM_PQ_MEM_4KB(num_vf_cids) * num_vf_pqs +
	       QM_PQ_MEM_4KB(num_pf_cids + num_tids) * QM_OTHER_PQS_PER_PF;
}

int qed_qm_common_rt_init(
	struct qed_hwfn *p_hwfn,
	struct qed_qm_common_rt_init_params *p_params)
{
	/* init AFullOprtnstcCrdMask */
	u32 mask = (QM_OPPOR_LINE_VOQ_DEF <<
		    QM_RF_OPPORTUNISTIC_MASK_LINEVOQ_SHIFT) |
		   (QM_BYTE_CRD_EN << QM_RF_OPPORTUNISTIC_MASK_BYTEVOQ_SHIFT) |
		   (p_params->pf_wfq_en <<
		    QM_RF_OPPORTUNISTIC_MASK_PFWFQ_SHIFT) |
		   (p_params->vport_wfq_en <<
		    QM_RF_OPPORTUNISTIC_MASK_VPWFQ_SHIFT) |
		   (p_params->pf_rl_en <<
		    QM_RF_OPPORTUNISTIC_MASK_PFRL_SHIFT) |
		   (p_params->vport_rl_en <<
		    QM_RF_OPPORTUNISTIC_MASK_VPQCNRL_SHIFT) |
		   (QM_OPPOR_FW_STOP_DEF <<
		    QM_RF_OPPORTUNISTIC_MASK_FWPAUSE_SHIFT) |
		   (QM_OPPOR_PQ_EMPTY_DEF <<
		    QM_RF_OPPORTUNISTIC_MASK_QUEUEEMPTY_SHIFT);

	STORE_RT_REG(p_hwfn, QM_REG_AFULLOPRTNSTCCRDMASK_RT_OFFSET, mask);
	qed_enable_pf_rl(p_hwfn, p_params->pf_rl_en);
	qed_enable_pf_wfq(p_hwfn, p_params->pf_wfq_en);
	qed_enable_vport_rl(p_hwfn, p_params->vport_rl_en);
	qed_enable_vport_wfq(p_hwfn, p_params->vport_wfq_en);
	qed_cmdq_lines_rt_init(p_hwfn,
			       p_params->max_ports_per_engine,
			       p_params->max_phys_tcs_per_port,
			       p_params->port_params);
	qed_btb_blocks_rt_init(p_hwfn,
			       p_params->max_ports_per_engine,
			       p_params->max_phys_tcs_per_port,
			       p_params->port_params);
	return 0;
}

int qed_qm_pf_rt_init(struct qed_hwfn *p_hwfn,
		      struct qed_ptt *p_ptt,
		      struct qed_qm_pf_rt_init_params *p_params)
{
	struct init_qm_vport_params *vport_params = p_params->vport_params;
	u32 other_mem_size_4kb = QM_PQ_MEM_4KB(p_params->num_pf_cids +
					       p_params->num_tids) *
				 QM_OTHER_PQS_PER_PF;
	u8 tc, i;

	/* clear first Tx PQ ID array for each VPORT */
	for (i = 0; i < p_params->num_vports; i++)
		for (tc = 0; tc < NUM_OF_TCS; tc++)
			vport_params[i].first_tx_pq_id[tc] = QM_INVALID_PQ_ID;

	/* map Other PQs (if any) */
	qed_other_pq_map_rt_init(p_hwfn, p_params->port_id, p_params->pf_id,
				 p_params->num_pf_cids, p_params->num_tids, 0);

	/* map Tx PQs */
	qed_tx_pq_map_rt_init(p_hwfn, p_ptt, p_params, other_mem_size_4kb);

	if (p_params->pf_wfq)
		if (qed_pf_wfq_rt_init(p_hwfn, p_params))
			return -1;

	if (qed_pf_rl_rt_init(p_hwfn, p_params->pf_id, p_params->pf_rl))
		return -1;

Y
Yuval Mintz 已提交
723
	if (qed_vp_wfq_rt_init(p_hwfn, p_params->num_vports, vport_params))
724 725 726 727 728 729 730 731 732
		return -1;

	if (qed_vport_rl_rt_init(p_hwfn, p_params->start_vport,
				 p_params->num_vports, vport_params))
		return -1;

	return 0;
}

733
int qed_init_pf_wfq(struct qed_hwfn *p_hwfn,
Y
Yuval Mintz 已提交
734
		    struct qed_ptt *p_ptt, u8 pf_id, u16 pf_wfq)
735 736 737 738 739 740 741 742 743 744 745 746
{
	u32 inc_val = QM_WFQ_INC_VAL(pf_wfq);

	if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) {
		DP_NOTICE(p_hwfn, "Invalid PF WFQ weight configuration");
		return -1;
	}

	qed_wr(p_hwfn, p_ptt, QM_REG_WFQPFWEIGHT + pf_id * 4, inc_val);
	return 0;
}

747
int qed_init_pf_rl(struct qed_hwfn *p_hwfn,
Y
Yuval Mintz 已提交
748
		   struct qed_ptt *p_ptt, u8 pf_id, u32 pf_rl)
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
{
	u32 inc_val = QM_RL_INC_VAL(pf_rl);

	if (inc_val > QM_RL_MAX_INC_VAL) {
		DP_NOTICE(p_hwfn, "Invalid PF rate limit configuration");
		return -1;
	}

	qed_wr(p_hwfn, p_ptt,
	       QM_REG_RLPFCRD + pf_id * 4,
	       QM_RL_CRD_REG_SIGN_BIT);
	qed_wr(p_hwfn, p_ptt, QM_REG_RLPFINCVAL + pf_id * 4, inc_val);

	return 0;
}

765 766
int qed_init_vport_wfq(struct qed_hwfn *p_hwfn,
		       struct qed_ptt *p_ptt,
Y
Yuval Mintz 已提交
767
		       u16 first_tx_pq_id[NUM_OF_TCS], u16 vport_wfq)
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
{
	u32 inc_val = QM_WFQ_INC_VAL(vport_wfq);
	u8 tc;

	if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) {
		DP_NOTICE(p_hwfn, "Invalid VPORT WFQ weight configuration");
		return -1;
	}

	for (tc = 0; tc < NUM_OF_TCS; tc++) {
		u16 vport_pq_id = first_tx_pq_id[tc];

		if (vport_pq_id != QM_INVALID_PQ_ID)
			qed_wr(p_hwfn, p_ptt,
			       QM_REG_WFQVPWEIGHT + vport_pq_id * 4,
			       inc_val);
	}

	return 0;
}

789
int qed_init_vport_rl(struct qed_hwfn *p_hwfn,
Y
Yuval Mintz 已提交
790
		      struct qed_ptt *p_ptt, u8 vport_id, u32 vport_rl)
791 792 793
{
	u32 inc_val = QM_RL_INC_VAL(vport_rl);

M
Mintz, Yuval 已提交
794 795 796 797 798 799
	if (vport_id >= MAX_QM_GLOBAL_RLS) {
		DP_NOTICE(p_hwfn,
			  "Invalid VPORT ID for rate limiter configuration");
		return -1;
	}

800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
	if (inc_val > QM_RL_MAX_INC_VAL) {
		DP_NOTICE(p_hwfn, "Invalid VPORT rate-limit configuration");
		return -1;
	}

	qed_wr(p_hwfn, p_ptt,
	       QM_REG_RLGLBLCRD + vport_id * 4,
	       QM_RL_CRD_REG_SIGN_BIT);
	qed_wr(p_hwfn, p_ptt, QM_REG_RLGLBLINCVAL + vport_id * 4, inc_val);

	return 0;
}

bool qed_send_qm_stop_cmd(struct qed_hwfn *p_hwfn,
			  struct qed_ptt *p_ptt,
			  bool is_release_cmd,
Y
Yuval Mintz 已提交
816
			  bool is_tx_pq, u16 start_pq, u16 num_pqs)
817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
{
	u32 cmd_arr[QM_CMD_STRUCT_SIZE(QM_STOP_CMD)] = { 0 };
	u32 pq_mask = 0, last_pq = start_pq + num_pqs - 1, pq_id;

	/* set command's PQ type */
	QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD, PQ_TYPE, is_tx_pq ? 0 : 1);

	for (pq_id = start_pq; pq_id <= last_pq; pq_id++) {
		/* set PQ bit in mask (stop command only) */
		if (!is_release_cmd)
			pq_mask |= (1 << (pq_id % QM_STOP_PQ_MASK_WIDTH));

		/* if last PQ or end of PQ mask, write command */
		if ((pq_id == last_pq) ||
		    (pq_id % QM_STOP_PQ_MASK_WIDTH ==
		     (QM_STOP_PQ_MASK_WIDTH - 1))) {
			QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD,
					 PAUSE_MASK, pq_mask);
			QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD,
					 GROUP_ID,
					 pq_id / QM_STOP_PQ_MASK_WIDTH);
			if (!qed_send_qm_cmd(p_hwfn, p_ptt, QM_STOP_CMD_ADDR,
					     cmd_arr[0], cmd_arr[1]))
				return false;
			pq_mask = 0;
		}
	}

	return true;
}
847 848 849 850 851 852 853 854 855 856 857 858 859

static void
qed_set_tunnel_type_enable_bit(unsigned long *var, int bit, bool enable)
{
	if (enable)
		set_bit(bit, var);
	else
		clear_bit(bit, var);
}

#define PRS_ETH_TUNN_FIC_FORMAT	-188897008

void qed_set_vxlan_dest_port(struct qed_hwfn *p_hwfn,
Y
Yuval Mintz 已提交
860
			     struct qed_ptt *p_ptt, u16 dest_port)
861 862
{
	qed_wr(p_hwfn, p_ptt, PRS_REG_VXLAN_PORT, dest_port);
Y
Yuval Mintz 已提交
863
	qed_wr(p_hwfn, p_ptt, NIG_REG_VXLAN_CTRL, dest_port);
864 865 866 867
	qed_wr(p_hwfn, p_ptt, PBF_REG_VXLAN_PORT, dest_port);
}

void qed_set_vxlan_enable(struct qed_hwfn *p_hwfn,
Y
Yuval Mintz 已提交
868
			  struct qed_ptt *p_ptt, bool vxlan_enable)
869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924
{
	unsigned long reg_val = 0;
	u8 shift;

	reg_val = qed_rd(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN);
	shift = PRS_REG_ENCAPSULATION_TYPE_EN_VXLAN_ENABLE_SHIFT;
	qed_set_tunnel_type_enable_bit(&reg_val, shift, vxlan_enable);

	qed_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val);

	if (reg_val)
		qed_wr(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0,
		       PRS_ETH_TUNN_FIC_FORMAT);

	reg_val = qed_rd(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE);
	shift = NIG_REG_ENC_TYPE_ENABLE_VXLAN_ENABLE_SHIFT;
	qed_set_tunnel_type_enable_bit(&reg_val, shift, vxlan_enable);

	qed_wr(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE, reg_val);

	qed_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_VXLAN_EN,
	       vxlan_enable ? 1 : 0);
}

void qed_set_gre_enable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
			bool eth_gre_enable, bool ip_gre_enable)
{
	unsigned long reg_val = 0;
	u8 shift;

	reg_val = qed_rd(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN);
	shift = PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GRE_ENABLE_SHIFT;
	qed_set_tunnel_type_enable_bit(&reg_val, shift, eth_gre_enable);

	shift = PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GRE_ENABLE_SHIFT;
	qed_set_tunnel_type_enable_bit(&reg_val, shift, ip_gre_enable);
	qed_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val);
	if (reg_val)
		qed_wr(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0,
		       PRS_ETH_TUNN_FIC_FORMAT);

	reg_val = qed_rd(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE);
	shift = NIG_REG_ENC_TYPE_ENABLE_ETH_OVER_GRE_ENABLE_SHIFT;
	qed_set_tunnel_type_enable_bit(&reg_val, shift, eth_gre_enable);

	shift = NIG_REG_ENC_TYPE_ENABLE_IP_OVER_GRE_ENABLE_SHIFT;
	qed_set_tunnel_type_enable_bit(&reg_val, shift, ip_gre_enable);
	qed_wr(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE, reg_val);

	qed_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_GRE_ETH_EN,
	       eth_gre_enable ? 1 : 0);
	qed_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_GRE_IP_EN,
	       ip_gre_enable ? 1 : 0);
}

void qed_set_geneve_dest_port(struct qed_hwfn *p_hwfn,
Y
Yuval Mintz 已提交
925
			      struct qed_ptt *p_ptt, u16 dest_port)
926 927 928 929 930 931 932 933
{
	qed_wr(p_hwfn, p_ptt, PRS_REG_NGE_PORT, dest_port);
	qed_wr(p_hwfn, p_ptt, NIG_REG_NGE_PORT, dest_port);
	qed_wr(p_hwfn, p_ptt, PBF_REG_NGE_PORT, dest_port);
}

void qed_set_geneve_enable(struct qed_hwfn *p_hwfn,
			   struct qed_ptt *p_ptt,
Y
Yuval Mintz 已提交
934
			   bool eth_geneve_enable, bool ip_geneve_enable)
935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963
{
	unsigned long reg_val = 0;
	u8 shift;

	reg_val = qed_rd(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN);
	shift = PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GENEVE_ENABLE_SHIFT;
	qed_set_tunnel_type_enable_bit(&reg_val, shift, eth_geneve_enable);

	shift = PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GENEVE_ENABLE_SHIFT;
	qed_set_tunnel_type_enable_bit(&reg_val, shift, ip_geneve_enable);

	qed_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val);
	if (reg_val)
		qed_wr(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0,
		       PRS_ETH_TUNN_FIC_FORMAT);

	qed_wr(p_hwfn, p_ptt, NIG_REG_NGE_ETH_ENABLE,
	       eth_geneve_enable ? 1 : 0);
	qed_wr(p_hwfn, p_ptt, NIG_REG_NGE_IP_ENABLE, ip_geneve_enable ? 1 : 0);

	/* EDPM with geneve tunnel not supported in BB_B0 */
	if (QED_IS_BB_B0(p_hwfn->cdev))
		return;

	qed_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_NGE_ETH_EN,
	       eth_geneve_enable ? 1 : 0);
	qed_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_NGE_IP_EN,
	       ip_geneve_enable ? 1 : 0);
}