Linux Audio

Check our new training course

Loading...
v4.17
   1/* QLogic qed NIC Driver
   2 * Copyright (c) 2015-2017  QLogic Corporation
   3 *
   4 * This software is available to you under a choice of one of two
   5 * licenses.  You may choose to be licensed under the terms of the GNU
   6 * General Public License (GPL) Version 2, available from the file
   7 * COPYING in the main directory of this source tree, or the
   8 * OpenIB.org BSD license below:
   9 *
  10 *     Redistribution and use in source and binary forms, with or
  11 *     without modification, are permitted provided that the following
  12 *     conditions are met:
  13 *
  14 *      - Redistributions of source code must retain the above
  15 *        copyright notice, this list of conditions and the following
  16 *        disclaimer.
  17 *
  18 *      - Redistributions in binary form must reproduce the above
  19 *        copyright notice, this list of conditions and the following
  20 *        disclaimer in the documentation and /or other materials
  21 *        provided with the distribution.
  22 *
  23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30 * SOFTWARE.
  31 */
  32
  33#include <linux/types.h>
  34#include <linux/crc8.h>
  35#include <linux/delay.h>
  36#include <linux/kernel.h>
  37#include <linux/slab.h>
  38#include <linux/string.h>
  39#include "qed_hsi.h"
  40#include "qed_hw.h"
  41#include "qed_init_ops.h"
  42#include "qed_reg_addr.h"
  43
  44#define CDU_VALIDATION_DEFAULT_CFG	61
  45
  46static u16 con_region_offsets[3][NUM_OF_CONNECTION_TYPES_E4] = {
  47	{400, 336, 352, 304, 304, 384, 416, 352},	/* region 3 offsets */
  48	{528, 496, 416, 448, 448, 512, 544, 480},	/* region 4 offsets */
  49	{608, 544, 496, 512, 576, 592, 624, 560}	/* region 5 offsets */
  50};
  51
  52static u16 task_region_offsets[1][NUM_OF_CONNECTION_TYPES_E4] = {
  53	{240, 240, 112, 0, 0, 0, 0, 96}	/* region 1 offsets */
 
 
  54};
  55
  56/* General constants */
 
  57#define QM_PQ_MEM_4KB(pq_size)	(pq_size ? DIV_ROUND_UP((pq_size + 1) *	\
  58							QM_PQ_ELEMENT_SIZE, \
  59							0x1000) : 0)
  60#define QM_PQ_SIZE_256B(pq_size)	(pq_size ? DIV_ROUND_UP(pq_size, \
  61								0x100) - 1 : 0)
  62#define QM_INVALID_PQ_ID		0xffff
  63
  64/* Feature enable */
  65#define QM_BYPASS_EN	1
  66#define QM_BYTE_CRD_EN	1
  67
  68/* Other PQ constants */
  69#define QM_OTHER_PQS_PER_PF	4
  70
  71/* WFQ constants */
  72
  73/* Upper bound in MB, 10 * burst size of 1ms in 50Gbps */
  74#define QM_WFQ_UPPER_BOUND	62500000
  75
  76/* Bit  of VOQ in WFQ VP PQ map */
  77#define QM_WFQ_VP_PQ_VOQ_SHIFT	0
  78
  79/* Bit  of PF in WFQ VP PQ map */
  80#define QM_WFQ_VP_PQ_PF_E4_SHIFT	5
  81
  82/* 0x9000 = 4*9*1024 */
  83#define QM_WFQ_INC_VAL(weight)	((weight) * 0x9000)
  84
  85/* Max WFQ increment value is 0.7 * upper bound */
  86#define QM_WFQ_MAX_INC_VAL	((QM_WFQ_UPPER_BOUND * 7) / 10)
  87
  88/* RL constants */
  89
  90/* Period in us */
  91#define QM_RL_PERIOD	5
  92
  93/* Period in 25MHz cycles */
  94#define QM_RL_PERIOD_CLK_25M	(25 * QM_RL_PERIOD)
  95
  96/* RL increment value - rate is specified in mbps */
  97#define QM_RL_INC_VAL(rate) ({ \
  98	typeof(rate) __rate = (rate); \
  99	max_t(u32, \
 100	      (u32)(((__rate ? __rate : 1000000) * QM_RL_PERIOD * 101) / \
 101		    (8 * 100)), \
 102	      1); })
 103
 104/* PF RL Upper bound is set to 10 * burst size of 1ms in 50Gbps */
 105#define QM_PF_RL_UPPER_BOUND	62500000
 106
 107/* Max PF RL increment value is 0.7 * upper bound */
 108#define QM_PF_RL_MAX_INC_VAL	((QM_PF_RL_UPPER_BOUND * 7) / 10)
 109
 110/* Vport RL Upper bound, link speed is in Mpbs */
 111#define QM_VP_RL_UPPER_BOUND(speed)	((u32)max_t(u32, \
 112						    QM_RL_INC_VAL(speed), \
 113						    9700 + 1000))
 114
 115/* Max Vport RL increment value is the Vport RL upper bound */
 116#define QM_VP_RL_MAX_INC_VAL(speed)	QM_VP_RL_UPPER_BOUND(speed)
 117
 118/* Vport RL credit threshold in case of QM bypass */
 119#define QM_VP_RL_BYPASS_THRESH_SPEED	(QM_VP_RL_UPPER_BOUND(10000) - 1)
 120
 121/* AFullOprtnstcCrdMask constants */
 122#define QM_OPPOR_LINE_VOQ_DEF	1
 123#define QM_OPPOR_FW_STOP_DEF	0
 124#define QM_OPPOR_PQ_EMPTY_DEF	1
 125
 126/* Command Queue constants */
 127
 128/* Pure LB CmdQ lines (+spare) */
 129#define PBF_CMDQ_PURE_LB_LINES	150
 130
 131#define PBF_CMDQ_LINES_E5_RSVD_RATIO	8
 132
 133#define PBF_CMDQ_LINES_RT_OFFSET(ext_voq) \
 134	(PBF_REG_YCMD_QS_NUM_LINES_VOQ0_RT_OFFSET + \
 135	 (ext_voq) * (PBF_REG_YCMD_QS_NUM_LINES_VOQ1_RT_OFFSET - \
 136		PBF_REG_YCMD_QS_NUM_LINES_VOQ0_RT_OFFSET))
 137
 138#define PBF_BTB_GUARANTEED_RT_OFFSET(ext_voq) \
 139	(PBF_REG_BTB_GUARANTEED_VOQ0_RT_OFFSET + \
 140	 (ext_voq) * (PBF_REG_BTB_GUARANTEED_VOQ1_RT_OFFSET - \
 141		PBF_REG_BTB_GUARANTEED_VOQ0_RT_OFFSET))
 142
 143#define QM_VOQ_LINE_CRD(pbf_cmd_lines) \
 144	((((pbf_cmd_lines) - 4) * 2) | QM_LINE_CRD_REG_SIGN_BIT)
 145
 146/* BTB: blocks constants (block size = 256B) */
 147
 148/* 256B blocks in 9700B packet */
 149#define BTB_JUMBO_PKT_BLOCKS	38
 150
 151/* Headroom per-port */
 152#define BTB_HEADROOM_BLOCKS	BTB_JUMBO_PKT_BLOCKS
 153#define BTB_PURE_LB_FACTOR	10
 154
 155/* Factored (hence really 0.7) */
 156#define BTB_PURE_LB_RATIO	7
 157
 158/* QM stop command constants */
 159#define QM_STOP_PQ_MASK_WIDTH		32
 160#define QM_STOP_CMD_ADDR		2
 161#define QM_STOP_CMD_STRUCT_SIZE		2
 162#define QM_STOP_CMD_PAUSE_MASK_OFFSET	0
 163#define QM_STOP_CMD_PAUSE_MASK_SHIFT	0
 164#define QM_STOP_CMD_PAUSE_MASK_MASK	-1
 165#define QM_STOP_CMD_GROUP_ID_OFFSET	1
 166#define QM_STOP_CMD_GROUP_ID_SHIFT	16
 167#define QM_STOP_CMD_GROUP_ID_MASK	15
 168#define QM_STOP_CMD_PQ_TYPE_OFFSET	1
 169#define QM_STOP_CMD_PQ_TYPE_SHIFT	24
 170#define QM_STOP_CMD_PQ_TYPE_MASK	1
 171#define QM_STOP_CMD_MAX_POLL_COUNT	100
 172#define QM_STOP_CMD_POLL_PERIOD_US	500
 173
 174/* QM command macros */
 175#define QM_CMD_STRUCT_SIZE(cmd)	cmd ## _STRUCT_SIZE
 176#define QM_CMD_SET_FIELD(var, cmd, field, value) \
 177	SET_FIELD(var[cmd ## _ ## field ## _OFFSET], \
 178		  cmd ## _ ## field, \
 179		  value)
 180
 181#define QM_INIT_TX_PQ_MAP(p_hwfn, map, chip, pq_id, rl_valid, vp_pq_id, rl_id, \
 182			  ext_voq, wrr) \
 183	do { \
 184		typeof(map) __map; \
 185		memset(&__map, 0, sizeof(__map)); \
 186		SET_FIELD(__map.reg, QM_RF_PQ_MAP_ ## chip ## _PQ_VALID, 1); \
 187		SET_FIELD(__map.reg, QM_RF_PQ_MAP_ ## chip ## _RL_VALID, \
 188			  rl_valid); \
 189		SET_FIELD(__map.reg, QM_RF_PQ_MAP_ ## chip ## _VP_PQ_ID, \
 190			  vp_pq_id); \
 191		SET_FIELD(__map.reg, QM_RF_PQ_MAP_ ## chip ## _RL_ID, rl_id); \
 192		SET_FIELD(__map.reg, QM_RF_PQ_MAP_ ## chip ## _VOQ, ext_voq); \
 193		SET_FIELD(__map.reg, \
 194			  QM_RF_PQ_MAP_ ## chip ## _WRR_WEIGHT_GROUP, wrr); \
 195		STORE_RT_REG(p_hwfn, QM_REG_TXPQMAP_RT_OFFSET + (pq_id), \
 196			     *((u32 *)&__map)); \
 197		(map) = __map; \
 198	} while (0)
 199
 200#define WRITE_PQ_INFO_TO_RAM	1
 201#define PQ_INFO_ELEMENT(vp, pf, tc, port, rl_valid, rl) \
 202	(((vp) << 0) | ((pf) << 12) | ((tc) << 16) | ((port) << 20) | \
 203	((rl_valid) << 22) | ((rl) << 24))
 204#define PQ_INFO_RAM_GRC_ADDRESS(pq_id) \
 205	(XSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM + 21776 + (pq_id) * 4)
 206
 207/******************** INTERNAL IMPLEMENTATION *********************/
 208
 209/* Returns the external VOQ number */
 210static u8 qed_get_ext_voq(struct qed_hwfn *p_hwfn,
 211			  u8 port_id, u8 tc, u8 max_phys_tcs_per_port)
 212{
 213	if (tc == PURE_LB_TC)
 214		return NUM_OF_PHYS_TCS * MAX_NUM_PORTS_BB + port_id;
 215	else
 216		return port_id * max_phys_tcs_per_port + tc;
 217}
 218
 219/* Prepare PF RL enable/disable runtime init values */
 220static void qed_enable_pf_rl(struct qed_hwfn *p_hwfn, bool pf_rl_en)
 
 221{
 222	STORE_RT_REG(p_hwfn, QM_REG_RLPFENABLE_RT_OFFSET, pf_rl_en ? 1 : 0);
 223	if (pf_rl_en) {
 224		u8 num_ext_voqs = MAX_NUM_VOQS_E4;
 225		u64 voq_bit_mask = ((u64)1 << num_ext_voqs) - 1;
 226
 227		/* Enable RLs for all VOQs */
 228		STORE_RT_REG(p_hwfn,
 229			     QM_REG_RLPFVOQENABLE_RT_OFFSET,
 230			     (u32)voq_bit_mask);
 231		if (num_ext_voqs >= 32)
 232			STORE_RT_REG(p_hwfn, QM_REG_RLPFVOQENABLE_MSB_RT_OFFSET,
 233				     (u32)(voq_bit_mask >> 32));
 234
 235		/* Write RL period */
 236		STORE_RT_REG(p_hwfn,
 237			     QM_REG_RLPFPERIOD_RT_OFFSET, QM_RL_PERIOD_CLK_25M);
 
 238		STORE_RT_REG(p_hwfn,
 239			     QM_REG_RLPFPERIODTIMER_RT_OFFSET,
 240			     QM_RL_PERIOD_CLK_25M);
 241
 242		/* Set credit threshold for QM bypass flow */
 243		if (QM_BYPASS_EN)
 244			STORE_RT_REG(p_hwfn,
 245				     QM_REG_AFULLQMBYPTHRPFRL_RT_OFFSET,
 246				     QM_PF_RL_UPPER_BOUND);
 247	}
 248}
 249
 250/* Prepare PF WFQ enable/disable runtime init values */
 251static void qed_enable_pf_wfq(struct qed_hwfn *p_hwfn, bool pf_wfq_en)
 
 252{
 253	STORE_RT_REG(p_hwfn, QM_REG_WFQPFENABLE_RT_OFFSET, pf_wfq_en ? 1 : 0);
 254
 255	/* Set credit threshold for QM bypass flow */
 256	if (pf_wfq_en && QM_BYPASS_EN)
 257		STORE_RT_REG(p_hwfn,
 258			     QM_REG_AFULLQMBYPTHRPFWFQ_RT_OFFSET,
 259			     QM_WFQ_UPPER_BOUND);
 260}
 261
 262/* Prepare VPORT RL enable/disable runtime init values */
 263static void qed_enable_vport_rl(struct qed_hwfn *p_hwfn, bool vport_rl_en)
 
 264{
 265	STORE_RT_REG(p_hwfn, QM_REG_RLGLBLENABLE_RT_OFFSET,
 266		     vport_rl_en ? 1 : 0);
 267	if (vport_rl_en) {
 268		/* Write RL period (use timer 0 only) */
 269		STORE_RT_REG(p_hwfn,
 270			     QM_REG_RLGLBLPERIOD_0_RT_OFFSET,
 271			     QM_RL_PERIOD_CLK_25M);
 272		STORE_RT_REG(p_hwfn,
 273			     QM_REG_RLGLBLPERIODTIMER_0_RT_OFFSET,
 274			     QM_RL_PERIOD_CLK_25M);
 275
 276		/* Set credit threshold for QM bypass flow */
 277		if (QM_BYPASS_EN)
 278			STORE_RT_REG(p_hwfn,
 279				     QM_REG_AFULLQMBYPTHRGLBLRL_RT_OFFSET,
 280				     QM_VP_RL_BYPASS_THRESH_SPEED);
 281	}
 282}
 283
 284/* Prepare VPORT WFQ enable/disable runtime init values */
 285static void qed_enable_vport_wfq(struct qed_hwfn *p_hwfn, bool vport_wfq_en)
 
 286{
 287	STORE_RT_REG(p_hwfn, QM_REG_WFQVPENABLE_RT_OFFSET,
 288		     vport_wfq_en ? 1 : 0);
 289
 290	/* Set credit threshold for QM bypass flow */
 291	if (vport_wfq_en && QM_BYPASS_EN)
 292		STORE_RT_REG(p_hwfn,
 293			     QM_REG_AFULLQMBYPTHRVPWFQ_RT_OFFSET,
 294			     QM_WFQ_UPPER_BOUND);
 295}
 296
 297/* Prepare runtime init values to allocate PBF command queue lines for
 298 * the specified VOQ.
 299 */
 300static void qed_cmdq_lines_voq_rt_init(struct qed_hwfn *p_hwfn,
 301				       u8 ext_voq, u16 cmdq_lines)
 
 302{
 303	u32 qm_line_crd = QM_VOQ_LINE_CRD(cmdq_lines);
 
 
 
 
 
 304
 305	OVERWRITE_RT_REG(p_hwfn, PBF_CMDQ_LINES_RT_OFFSET(ext_voq),
 
 
 
 306			 (u32)cmdq_lines);
 307	STORE_RT_REG(p_hwfn, QM_REG_VOQCRDLINE_RT_OFFSET + ext_voq,
 308		     qm_line_crd);
 309	STORE_RT_REG(p_hwfn, QM_REG_VOQINITCRDLINE_RT_OFFSET + ext_voq,
 310		     qm_line_crd);
 311}
 312
 313/* Prepare runtime init values to allocate PBF command queue lines. */
 314static void qed_cmdq_lines_rt_init(
 315	struct qed_hwfn *p_hwfn,
 316	u8 max_ports_per_engine,
 317	u8 max_phys_tcs_per_port,
 318	struct init_qm_port_params port_params[MAX_NUM_PORTS])
 319{
 320	u8 tc, ext_voq, port_id, num_tcs_in_port;
 321	u8 num_ext_voqs = MAX_NUM_VOQS_E4;
 322
 323	/* Clear PBF lines of all VOQs */
 324	for (ext_voq = 0; ext_voq < num_ext_voqs; ext_voq++)
 325		STORE_RT_REG(p_hwfn, PBF_CMDQ_LINES_RT_OFFSET(ext_voq), 0);
 326
 
 
 
 327	for (port_id = 0; port_id < max_ports_per_engine; port_id++) {
 328		u16 phys_lines, phys_lines_per_tc;
 329
 330		if (!port_params[port_id].active)
 331			continue;
 332
 333		/* Find number of command queue lines to divide between the
 334		 * active physical TCs. In E5, 1/8 of the lines are reserved.
 335		 * the lines for pure LB TC are subtracted.
 336		 */
 337		phys_lines = port_params[port_id].num_pbf_cmd_lines;
 338		phys_lines -= PBF_CMDQ_PURE_LB_LINES;
 339
 340		/* Find #lines per active physical TC */
 341		num_tcs_in_port = 0;
 342		for (tc = 0; tc < max_phys_tcs_per_port; tc++)
 343			if (((port_params[port_id].active_phys_tcs >>
 344			      tc) & 0x1) == 1)
 345				num_tcs_in_port++;
 346		phys_lines_per_tc = phys_lines / num_tcs_in_port;
 347
 348		/* Init registers per active TC */
 349		for (tc = 0; tc < max_phys_tcs_per_port; tc++) {
 350			ext_voq = qed_get_ext_voq(p_hwfn,
 351						  port_id,
 352						  tc, max_phys_tcs_per_port);
 353			if (((port_params[port_id].active_phys_tcs >>
 354			      tc) & 0x1) == 1)
 355				qed_cmdq_lines_voq_rt_init(p_hwfn,
 356							   ext_voq,
 357							   phys_lines_per_tc);
 
 
 
 
 358		}
 359
 360		/* Init registers for pure LB TC */
 361		ext_voq = qed_get_ext_voq(p_hwfn,
 362					  port_id,
 363					  PURE_LB_TC, max_phys_tcs_per_port);
 364		qed_cmdq_lines_voq_rt_init(p_hwfn,
 365					   ext_voq, PBF_CMDQ_PURE_LB_LINES);
 366	}
 367}
 368
 369static void qed_btb_blocks_rt_init(
 370	struct qed_hwfn *p_hwfn,
 371	u8 max_ports_per_engine,
 372	u8 max_phys_tcs_per_port,
 373	struct init_qm_port_params port_params[MAX_NUM_PORTS])
 374{
 375	u32 usable_blocks, pure_lb_blocks, phys_blocks;
 376	u8 tc, ext_voq, port_id, num_tcs_in_port;
 377
 378	for (port_id = 0; port_id < max_ports_per_engine; port_id++) {
 
 
 
 379		if (!port_params[port_id].active)
 380			continue;
 381
 382		/* Subtract headroom blocks */
 
 
 383		usable_blocks = port_params[port_id].num_btb_blocks -
 384				BTB_HEADROOM_BLOCKS;
 385
 386		/* Find blocks per physical TC. Use factor to avoid floating
 387		 * arithmethic.
 388		 */
 389		num_tcs_in_port = 0;
 390		for (tc = 0; tc < NUM_OF_PHYS_TCS; tc++)
 391			if (((port_params[port_id].active_phys_tcs >>
 392			      tc) & 0x1) == 1)
 393				num_tcs_in_port++;
 394
 395		pure_lb_blocks = (usable_blocks * BTB_PURE_LB_FACTOR) /
 396				 (num_tcs_in_port * BTB_PURE_LB_FACTOR +
 397				  BTB_PURE_LB_RATIO);
 398		pure_lb_blocks = max_t(u32, BTB_JUMBO_PKT_BLOCKS,
 399				       pure_lb_blocks / BTB_PURE_LB_FACTOR);
 400		phys_blocks = (usable_blocks - pure_lb_blocks) /
 401			      num_tcs_in_port;
 402
 403		/* Init physical TCs */
 404		for (tc = 0; tc < NUM_OF_PHYS_TCS; tc++) {
 405			if (((port_params[port_id].active_phys_tcs >>
 406			      tc) & 0x1) == 1) {
 407				ext_voq =
 408					qed_get_ext_voq(p_hwfn,
 409							port_id,
 410							tc,
 411							max_phys_tcs_per_port);
 412				STORE_RT_REG(p_hwfn,
 413					     PBF_BTB_GUARANTEED_RT_OFFSET
 414					     (ext_voq), phys_blocks);
 415			}
 416		}
 417
 418		/* Init pure LB TC */
 419		ext_voq = qed_get_ext_voq(p_hwfn,
 420					  port_id,
 421					  PURE_LB_TC, max_phys_tcs_per_port);
 422		STORE_RT_REG(p_hwfn, PBF_BTB_GUARANTEED_RT_OFFSET(ext_voq),
 423			     pure_lb_blocks);
 424	}
 425}
 426
 427/* Prepare Tx PQ mapping runtime init values for the specified PF */
 428static void qed_tx_pq_map_rt_init(struct qed_hwfn *p_hwfn,
 429				  struct qed_ptt *p_ptt,
 430				  struct qed_qm_pf_rt_init_params *p_params,
 431				  u32 base_mem_addr_4kb)
 
 432{
 433	u32 tx_pq_vf_mask[MAX_QM_TX_QUEUES / QM_PF_QUEUE_GROUP_SIZE] = { 0 };
 434	struct init_qm_vport_params *vport_params = p_params->vport_params;
 435	u32 num_tx_pq_vf_masks = MAX_QM_TX_QUEUES / QM_PF_QUEUE_GROUP_SIZE;
 436	u16 num_pqs, first_pq_group, last_pq_group, i, j, pq_id, pq_group;
 437	struct init_qm_pq_params *pq_params = p_params->pq_params;
 438	u32 pq_mem_4kb, vport_pq_mem_4kb, mem_addr_4kb;
 439
 440	num_pqs = p_params->num_pf_pqs + p_params->num_vf_pqs;
 441
 442	first_pq_group = p_params->start_pq / QM_PF_QUEUE_GROUP_SIZE;
 443	last_pq_group = (p_params->start_pq + num_pqs - 1) /
 444			QM_PF_QUEUE_GROUP_SIZE;
 445
 446	pq_mem_4kb = QM_PQ_MEM_4KB(p_params->num_pf_cids);
 447	vport_pq_mem_4kb = QM_PQ_MEM_4KB(p_params->num_vf_cids);
 448	mem_addr_4kb = base_mem_addr_4kb;
 449
 450	/* Set mapping from PQ group to PF */
 
 
 
 
 
 
 
 
 451	for (pq_group = first_pq_group; pq_group <= last_pq_group; pq_group++)
 452		STORE_RT_REG(p_hwfn, QM_REG_PQTX2PF_0_RT_OFFSET + pq_group,
 453			     (u32)(p_params->pf_id));
 454
 455	/* Set PQ sizes */
 456	STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_0_RT_OFFSET,
 457		     QM_PQ_SIZE_256B(p_params->num_pf_cids));
 458	STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_1_RT_OFFSET,
 459		     QM_PQ_SIZE_256B(p_params->num_vf_cids));
 460
 461	/* Go over all Tx PQs */
 462	for (i = 0, pq_id = p_params->start_pq; i < num_pqs; i++, pq_id++) {
 463		u8 ext_voq, vport_id_in_pf, tc_id = pq_params[i].tc_id;
 464		u32 max_qm_global_rls = MAX_QM_GLOBAL_RLS;
 465		struct qm_rf_pq_map_e4 tx_pq_map;
 466		bool is_vf_pq, rl_valid;
 467		u16 *p_first_tx_pq_id;
 468
 469		ext_voq = qed_get_ext_voq(p_hwfn,
 470					  pq_params[i].port_id,
 471					  tc_id,
 472					  p_params->max_phys_tcs_per_port);
 473		is_vf_pq = (i >= p_params->num_pf_pqs);
 474		rl_valid = pq_params[i].rl_valid > 0;
 475
 476		/* Update first Tx PQ of VPORT/TC */
 477		vport_id_in_pf = pq_params[i].vport_id - p_params->start_vport;
 478		p_first_tx_pq_id =
 479		    &vport_params[vport_id_in_pf].first_tx_pq_id[tc_id];
 480		if (*p_first_tx_pq_id == QM_INVALID_PQ_ID) {
 481			u32 map_val =
 482				(ext_voq << QM_WFQ_VP_PQ_VOQ_SHIFT) |
 483				(p_params->pf_id << QM_WFQ_VP_PQ_PF_E4_SHIFT);
 484
 485			/* Create new VP PQ */
 486			*p_first_tx_pq_id = pq_id;
 487
 488			/* Map VP PQ to VOQ and PF */
 489			STORE_RT_REG(p_hwfn,
 490				     QM_REG_WFQVPMAP_RT_OFFSET +
 491				     *p_first_tx_pq_id,
 492				     map_val);
 493		}
 494
 495		/* Check RL ID */
 496		if (rl_valid && pq_params[i].vport_id >= max_qm_global_rls) {
 497			DP_NOTICE(p_hwfn,
 498				  "Invalid VPORT ID for rate limiter configuration\n");
 499			rl_valid = false;
 500		}
 501
 502		/* Prepare PQ map entry */
 503		QM_INIT_TX_PQ_MAP(p_hwfn,
 504				  tx_pq_map,
 505				  E4,
 506				  pq_id,
 507				  rl_valid ? 1 : 0,
 508				  *p_first_tx_pq_id,
 509				  rl_valid ? pq_params[i].vport_id : 0,
 510				  ext_voq, pq_params[i].wrr_group);
 511
 512		/* Set PQ base address */
 
 
 
 513		STORE_RT_REG(p_hwfn,
 514			     QM_REG_BASEADDRTXPQ_RT_OFFSET + pq_id,
 515			     mem_addr_4kb);
 516
 517		/* Clear PQ pointer table entry (64 bit) */
 518		if (p_params->is_pf_loading)
 519			for (j = 0; j < 2; j++)
 520				STORE_RT_REG(p_hwfn,
 521					     QM_REG_PTRTBLTX_RT_OFFSET +
 522					     (pq_id * 2) + j, 0);
 523
 524		/* Write PQ info to RAM */
 525		if (WRITE_PQ_INFO_TO_RAM != 0) {
 526			u32 pq_info = 0;
 527
 528			pq_info = PQ_INFO_ELEMENT(*p_first_tx_pq_id,
 529						  p_params->pf_id,
 530						  tc_id,
 531						  pq_params[i].port_id,
 532						  rl_valid ? 1 : 0,
 533						  rl_valid ?
 534						  pq_params[i].vport_id : 0);
 535			qed_wr(p_hwfn, p_ptt, PQ_INFO_RAM_GRC_ADDRESS(pq_id),
 536			       pq_info);
 537		}
 538
 539		/* If VF PQ, add indication to PQ VF mask */
 540		if (is_vf_pq) {
 541			tx_pq_vf_mask[pq_id /
 542				      QM_PF_QUEUE_GROUP_SIZE] |=
 543			    BIT((pq_id % QM_PF_QUEUE_GROUP_SIZE));
 
 
 544			mem_addr_4kb += vport_pq_mem_4kb;
 545		} else {
 546			mem_addr_4kb += pq_mem_4kb;
 547		}
 548	}
 549
 550	/* Store Tx PQ VF mask to size select register */
 551	for (i = 0; i < num_tx_pq_vf_masks; i++)
 552		if (tx_pq_vf_mask[i])
 553			STORE_RT_REG(p_hwfn,
 554				     QM_REG_MAXPQSIZETXSEL_0_RT_OFFSET + i,
 555				     tx_pq_vf_mask[i]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 556}
 557
 558/* Prepare Other PQ mapping runtime init values for the specified PF */
 559static void qed_other_pq_map_rt_init(struct qed_hwfn *p_hwfn,
 
 560				     u8 pf_id,
 561				     bool is_pf_loading,
 562				     u32 num_pf_cids,
 563				     u32 num_tids, u32 base_mem_addr_4kb)
 
 564{
 565	u32 pq_size, pq_mem_4kb, mem_addr_4kb;
 566	u16 i, j, pq_id, pq_group;
 567
 568	/* A single other PQ group is used in each PF, where PQ group i is used
 569	 * in PF i.
 570	 */
 571	pq_group = pf_id;
 572	pq_size = num_pf_cids + num_tids;
 573	pq_mem_4kb = QM_PQ_MEM_4KB(pq_size);
 574	mem_addr_4kb = base_mem_addr_4kb;
 575
 576	/* Map PQ group to PF */
 577	STORE_RT_REG(p_hwfn, QM_REG_PQOTHER2PF_0_RT_OFFSET + pq_group,
 578		     (u32)(pf_id));
 579
 580	/* Set PQ sizes */
 581	STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_2_RT_OFFSET,
 582		     QM_PQ_SIZE_256B(pq_size));
 583
 584	for (i = 0, pq_id = pf_id * QM_PF_QUEUE_GROUP_SIZE;
 585	     i < QM_OTHER_PQS_PER_PF; i++, pq_id++) {
 586		/* Set PQ base address */
 587		STORE_RT_REG(p_hwfn,
 588			     QM_REG_BASEADDROTHERPQ_RT_OFFSET + pq_id,
 589			     mem_addr_4kb);
 590
 591		/* Clear PQ pointer table entry */
 592		if (is_pf_loading)
 593			for (j = 0; j < 2; j++)
 594				STORE_RT_REG(p_hwfn,
 595					     QM_REG_PTRTBLOTHER_RT_OFFSET +
 596					     (pq_id * 2) + j, 0);
 597
 598		mem_addr_4kb += pq_mem_4kb;
 599	}
 600}
 601
 602/* Prepare PF WFQ runtime init values for the specified PF.
 603 * Return -1 on error.
 604 */
 605static int qed_pf_wfq_rt_init(struct qed_hwfn *p_hwfn,
 606
 607			      struct qed_qm_pf_rt_init_params *p_params)
 608{
 609	u16 num_tx_pqs = p_params->num_pf_pqs + p_params->num_vf_pqs;
 610	struct init_qm_pq_params *pq_params = p_params->pq_params;
 611	u32 inc_val, crd_reg_offset;
 612	u8 ext_voq;
 613	u16 i;
 614
 
 
 
 
 
 
 615	inc_val = QM_WFQ_INC_VAL(p_params->pf_wfq);
 616	if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) {
 617		DP_NOTICE(p_hwfn, "Invalid PF WFQ weight configuration\n");
 618		return -1;
 619	}
 
 
 
 
 
 620
 621	for (i = 0; i < num_tx_pqs; i++) {
 622		ext_voq = qed_get_ext_voq(p_hwfn,
 623					  pq_params[i].port_id,
 624					  pq_params[i].tc_id,
 625					  p_params->max_phys_tcs_per_port);
 626		crd_reg_offset =
 627			(p_params->pf_id < MAX_NUM_PFS_BB ?
 628			 QM_REG_WFQPFCRD_RT_OFFSET :
 629			 QM_REG_WFQPFCRD_MSB_RT_OFFSET) +
 630			ext_voq * MAX_NUM_PFS_BB +
 631			(p_params->pf_id % MAX_NUM_PFS_BB);
 632		OVERWRITE_RT_REG(p_hwfn,
 633				 crd_reg_offset, (u32)QM_WFQ_CRD_REG_SIGN_BIT);
 
 
 634	}
 635
 636	STORE_RT_REG(p_hwfn,
 637		     QM_REG_WFQPFUPPERBOUND_RT_OFFSET + p_params->pf_id,
 638		     QM_WFQ_UPPER_BOUND | (u32)QM_WFQ_CRD_REG_SIGN_BIT);
 639	STORE_RT_REG(p_hwfn, QM_REG_WFQPFWEIGHT_RT_OFFSET + p_params->pf_id,
 640		     inc_val);
 641
 642	return 0;
 643}
 644
 645/* Prepare PF RL runtime init values for the specified PF.
 646 * Return -1 on error.
 647 */
 648static int qed_pf_rl_rt_init(struct qed_hwfn *p_hwfn, u8 pf_id, u32 pf_rl)
 
 
 649{
 650	u32 inc_val = QM_RL_INC_VAL(pf_rl);
 651
 652	if (inc_val > QM_PF_RL_MAX_INC_VAL) {
 653		DP_NOTICE(p_hwfn, "Invalid PF rate limit configuration\n");
 654		return -1;
 655	}
 656
 657	STORE_RT_REG(p_hwfn,
 658		     QM_REG_RLPFCRD_RT_OFFSET + pf_id,
 659		     (u32)QM_RL_CRD_REG_SIGN_BIT);
 660	STORE_RT_REG(p_hwfn,
 661		     QM_REG_RLPFUPPERBOUND_RT_OFFSET + pf_id,
 662		     QM_PF_RL_UPPER_BOUND | (u32)QM_RL_CRD_REG_SIGN_BIT);
 663	STORE_RT_REG(p_hwfn, QM_REG_RLPFINCVAL_RT_OFFSET + pf_id, inc_val);
 664
 665	return 0;
 666}
 667
 668/* Prepare VPORT WFQ runtime init values for the specified VPORTs.
 669 * Return -1 on error.
 670 */
 671static int qed_vp_wfq_rt_init(struct qed_hwfn *p_hwfn,
 672			      u8 num_vports,
 673			      struct init_qm_vport_params *vport_params)
 674{
 675	u16 vport_pq_id;
 676	u32 inc_val;
 677	u8 tc, i;
 678
 679	/* Go over all PF VPORTs */
 680	for (i = 0; i < num_vports; i++) {
 
 681		if (!vport_params[i].vport_wfq)
 682			continue;
 683
 684		inc_val = QM_WFQ_INC_VAL(vport_params[i].vport_wfq);
 685		if (inc_val > QM_WFQ_MAX_INC_VAL) {
 686			DP_NOTICE(p_hwfn,
 687				  "Invalid VPORT WFQ weight configuration\n");
 688			return -1;
 689		}
 690
 691		/* Each VPORT can have several VPORT PQ IDs for various TCs */
 
 
 692		for (tc = 0; tc < NUM_OF_TCS; tc++) {
 693			vport_pq_id = vport_params[i].first_tx_pq_id[tc];
 
 694			if (vport_pq_id != QM_INVALID_PQ_ID) {
 695				STORE_RT_REG(p_hwfn,
 696					     QM_REG_WFQVPCRD_RT_OFFSET +
 697					     vport_pq_id,
 698					     (u32)QM_WFQ_CRD_REG_SIGN_BIT);
 699				STORE_RT_REG(p_hwfn,
 700					     QM_REG_WFQVPWEIGHT_RT_OFFSET +
 701					     vport_pq_id, inc_val);
 702			}
 703		}
 704	}
 705
 706	return 0;
 707}
 708
 709/* Prepare VPORT RL runtime init values for the specified VPORTs.
 710 * Return -1 on error.
 711 */
 712static int qed_vport_rl_rt_init(struct qed_hwfn *p_hwfn,
 713				u8 start_vport,
 714				u8 num_vports,
 715				u32 link_speed,
 716				struct init_qm_vport_params *vport_params)
 717{
 718	u8 i, vport_id;
 719	u32 inc_val;
 720
 721	if (start_vport + num_vports >= MAX_QM_GLOBAL_RLS) {
 722		DP_NOTICE(p_hwfn,
 723			  "Invalid VPORT ID for rate limiter configuration\n");
 724		return -1;
 725	}
 726
 727	/* Go over all PF VPORTs */
 728	for (i = 0, vport_id = start_vport; i < num_vports; i++, vport_id++) {
 729		inc_val = QM_RL_INC_VAL(vport_params[i].vport_rl ?
 730			  vport_params[i].vport_rl :
 731			  link_speed);
 732		if (inc_val > QM_VP_RL_MAX_INC_VAL(link_speed)) {
 733			DP_NOTICE(p_hwfn,
 734				  "Invalid VPORT rate-limit configuration\n");
 735			return -1;
 736		}
 737
 738		STORE_RT_REG(p_hwfn, QM_REG_RLGLBLCRD_RT_OFFSET + vport_id,
 739			     (u32)QM_RL_CRD_REG_SIGN_BIT);
 
 740		STORE_RT_REG(p_hwfn,
 741			     QM_REG_RLGLBLUPPERBOUND_RT_OFFSET + vport_id,
 742			     QM_VP_RL_UPPER_BOUND(link_speed) |
 743			     (u32)QM_RL_CRD_REG_SIGN_BIT);
 744		STORE_RT_REG(p_hwfn, QM_REG_RLGLBLINCVAL_RT_OFFSET + vport_id,
 745			     inc_val);
 746	}
 747
 748	return 0;
 749}
 750
 751static bool qed_poll_on_qm_cmd_ready(struct qed_hwfn *p_hwfn,
 752				     struct qed_ptt *p_ptt)
 753{
 754	u32 reg_val, i;
 755
 756	for (i = 0, reg_val = 0; i < QM_STOP_CMD_MAX_POLL_COUNT && !reg_val;
 757	     i++) {
 758		udelay(QM_STOP_CMD_POLL_PERIOD_US);
 759		reg_val = qed_rd(p_hwfn, p_ptt, QM_REG_SDMCMDREADY);
 760	}
 761
 762	/* Check if timeout while waiting for SDM command ready */
 763	if (i == QM_STOP_CMD_MAX_POLL_COUNT) {
 764		DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
 765			   "Timeout when waiting for QM SDM command ready signal\n");
 766		return false;
 767	}
 768
 769	return true;
 770}
 771
 772static bool qed_send_qm_cmd(struct qed_hwfn *p_hwfn,
 773			    struct qed_ptt *p_ptt,
 774			    u32 cmd_addr, u32 cmd_data_lsb, u32 cmd_data_msb)
 
 
 775{
 776	if (!qed_poll_on_qm_cmd_ready(p_hwfn, p_ptt))
 777		return false;
 778
 779	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDADDR, cmd_addr);
 780	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDDATALSB, cmd_data_lsb);
 781	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDDATAMSB, cmd_data_msb);
 782	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDGO, 1);
 783	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDGO, 0);
 784
 785	return qed_poll_on_qm_cmd_ready(p_hwfn, p_ptt);
 786}
 787
 788/******************** INTERFACE IMPLEMENTATION *********************/
 789
 790u32 qed_qm_pf_mem_size(u32 num_pf_cids,
 791		       u32 num_vf_cids,
 792		       u32 num_tids, u16 num_pf_pqs, u16 num_vf_pqs)
 
 
 793{
 794	return QM_PQ_MEM_4KB(num_pf_cids) * num_pf_pqs +
 795	       QM_PQ_MEM_4KB(num_vf_cids) * num_vf_pqs +
 796	       QM_PQ_MEM_4KB(num_pf_cids + num_tids) * QM_OTHER_PQS_PER_PF;
 797}
 798
 799int qed_qm_common_rt_init(struct qed_hwfn *p_hwfn,
 800			  struct qed_qm_common_rt_init_params *p_params)
 
 801{
 802	/* Init AFullOprtnstcCrdMask */
 803	u32 mask = (QM_OPPOR_LINE_VOQ_DEF <<
 804		    QM_RF_OPPORTUNISTIC_MASK_LINEVOQ_SHIFT) |
 805		   (QM_BYTE_CRD_EN << QM_RF_OPPORTUNISTIC_MASK_BYTEVOQ_SHIFT) |
 806		   (p_params->pf_wfq_en <<
 807		    QM_RF_OPPORTUNISTIC_MASK_PFWFQ_SHIFT) |
 808		   (p_params->vport_wfq_en <<
 809		    QM_RF_OPPORTUNISTIC_MASK_VPWFQ_SHIFT) |
 810		   (p_params->pf_rl_en <<
 811		    QM_RF_OPPORTUNISTIC_MASK_PFRL_SHIFT) |
 812		   (p_params->vport_rl_en <<
 813		    QM_RF_OPPORTUNISTIC_MASK_VPQCNRL_SHIFT) |
 814		   (QM_OPPOR_FW_STOP_DEF <<
 815		    QM_RF_OPPORTUNISTIC_MASK_FWPAUSE_SHIFT) |
 816		   (QM_OPPOR_PQ_EMPTY_DEF <<
 817		    QM_RF_OPPORTUNISTIC_MASK_QUEUEEMPTY_SHIFT);
 818
 819	STORE_RT_REG(p_hwfn, QM_REG_AFULLOPRTNSTCCRDMASK_RT_OFFSET, mask);
 820
 821	/* Enable/disable PF RL */
 822	qed_enable_pf_rl(p_hwfn, p_params->pf_rl_en);
 823
 824	/* Enable/disable PF WFQ */
 825	qed_enable_pf_wfq(p_hwfn, p_params->pf_wfq_en);
 826
 827	/* Enable/disable VPORT RL */
 828	qed_enable_vport_rl(p_hwfn, p_params->vport_rl_en);
 829
 830	/* Enable/disable VPORT WFQ */
 831	qed_enable_vport_wfq(p_hwfn, p_params->vport_wfq_en);
 832
 833	/* Init PBF CMDQ line credit */
 834	qed_cmdq_lines_rt_init(p_hwfn,
 835			       p_params->max_ports_per_engine,
 836			       p_params->max_phys_tcs_per_port,
 837			       p_params->port_params);
 838
 839	/* Init BTB blocks in PBF */
 840	qed_btb_blocks_rt_init(p_hwfn,
 841			       p_params->max_ports_per_engine,
 842			       p_params->max_phys_tcs_per_port,
 843			       p_params->port_params);
 844
 845	return 0;
 846}
 847
 848int qed_qm_pf_rt_init(struct qed_hwfn *p_hwfn,
 849		      struct qed_ptt *p_ptt,
 850		      struct qed_qm_pf_rt_init_params *p_params)
 851{
 852	struct init_qm_vport_params *vport_params = p_params->vport_params;
 853	u32 other_mem_size_4kb = QM_PQ_MEM_4KB(p_params->num_pf_cids +
 854					       p_params->num_tids) *
 855				 QM_OTHER_PQS_PER_PF;
 856	u8 tc, i;
 857
 858	/* Clear first Tx PQ ID array for each VPORT */
 859	for (i = 0; i < p_params->num_vports; i++)
 860		for (tc = 0; tc < NUM_OF_TCS; tc++)
 861			vport_params[i].first_tx_pq_id[tc] = QM_INVALID_PQ_ID;
 862
 863	/* Map Other PQs (if any) */
 864	qed_other_pq_map_rt_init(p_hwfn,
 865				 p_params->pf_id,
 866				 p_params->is_pf_loading, p_params->num_pf_cids,
 867				 p_params->num_tids, 0);
 868
 869	/* Map Tx PQs */
 870	qed_tx_pq_map_rt_init(p_hwfn, p_ptt, p_params, other_mem_size_4kb);
 871
 872	/* Init PF WFQ */
 873	if (p_params->pf_wfq)
 874		if (qed_pf_wfq_rt_init(p_hwfn, p_params))
 875			return -1;
 876
 877	/* Init PF RL */
 878	if (qed_pf_rl_rt_init(p_hwfn, p_params->pf_id, p_params->pf_rl))
 879		return -1;
 880
 881	/* Set VPORT WFQ */
 882	if (qed_vp_wfq_rt_init(p_hwfn, p_params->num_vports, vport_params))
 883		return -1;
 884
 885	/* Set VPORT RL */
 886	if (qed_vport_rl_rt_init(p_hwfn, p_params->start_vport,
 887				 p_params->num_vports, p_params->link_speed,
 888				 vport_params))
 889		return -1;
 890
 891	return 0;
 892}
 893
 894int qed_init_pf_wfq(struct qed_hwfn *p_hwfn,
 895		    struct qed_ptt *p_ptt, u8 pf_id, u16 pf_wfq)
 896{
 897	u32 inc_val = QM_WFQ_INC_VAL(pf_wfq);
 898
 899	if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) {
 900		DP_NOTICE(p_hwfn, "Invalid PF WFQ weight configuration\n");
 901		return -1;
 902	}
 903
 904	qed_wr(p_hwfn, p_ptt, QM_REG_WFQPFWEIGHT + pf_id * 4, inc_val);
 905
 906	return 0;
 907}
 908
 909int qed_init_pf_rl(struct qed_hwfn *p_hwfn,
 910		   struct qed_ptt *p_ptt, u8 pf_id, u32 pf_rl)
 
 
 911{
 912	u32 inc_val = QM_RL_INC_VAL(pf_rl);
 913
 914	if (inc_val > QM_PF_RL_MAX_INC_VAL) {
 915		DP_NOTICE(p_hwfn, "Invalid PF rate limit configuration\n");
 916		return -1;
 917	}
 918
 919	qed_wr(p_hwfn,
 920	       p_ptt, QM_REG_RLPFCRD + pf_id * 4, (u32)QM_RL_CRD_REG_SIGN_BIT);
 
 921	qed_wr(p_hwfn, p_ptt, QM_REG_RLPFINCVAL + pf_id * 4, inc_val);
 922
 923	return 0;
 924}
 925
 926int qed_init_vport_wfq(struct qed_hwfn *p_hwfn,
 927		       struct qed_ptt *p_ptt,
 928		       u16 first_tx_pq_id[NUM_OF_TCS], u16 vport_wfq)
 929{
 930	u16 vport_pq_id;
 931	u32 inc_val;
 932	u8 tc;
 933
 934	inc_val = QM_WFQ_INC_VAL(vport_wfq);
 935	if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) {
 936		DP_NOTICE(p_hwfn, "Invalid VPORT WFQ weight configuration\n");
 937		return -1;
 938	}
 939
 940	for (tc = 0; tc < NUM_OF_TCS; tc++) {
 941		vport_pq_id = first_tx_pq_id[tc];
 942		if (vport_pq_id != QM_INVALID_PQ_ID)
 943			qed_wr(p_hwfn,
 944			       p_ptt,
 945			       QM_REG_WFQVPWEIGHT + vport_pq_id * 4, inc_val);
 946	}
 947
 948	return 0;
 949}
 950
 951int qed_init_vport_rl(struct qed_hwfn *p_hwfn,
 952		      struct qed_ptt *p_ptt,
 953		      u8 vport_id, u32 vport_rl, u32 link_speed)
 
 954{
 955	u32 inc_val, max_qm_global_rls = MAX_QM_GLOBAL_RLS;
 956
 957	if (vport_id >= max_qm_global_rls) {
 958		DP_NOTICE(p_hwfn,
 959			  "Invalid VPORT ID for rate limiter configuration\n");
 960		return -1;
 961	}
 962
 963	inc_val = QM_RL_INC_VAL(vport_rl ? vport_rl : link_speed);
 964	if (inc_val > QM_VP_RL_MAX_INC_VAL(link_speed)) {
 965		DP_NOTICE(p_hwfn, "Invalid VPORT rate-limit configuration\n");
 966		return -1;
 967	}
 968
 969	qed_wr(p_hwfn,
 970	       p_ptt,
 971	       QM_REG_RLGLBLCRD + vport_id * 4, (u32)QM_RL_CRD_REG_SIGN_BIT);
 972	qed_wr(p_hwfn, p_ptt, QM_REG_RLGLBLINCVAL + vport_id * 4, inc_val);
 973
 974	return 0;
 975}
 976
 977bool qed_send_qm_stop_cmd(struct qed_hwfn *p_hwfn,
 978			  struct qed_ptt *p_ptt,
 979			  bool is_release_cmd,
 980			  bool is_tx_pq, u16 start_pq, u16 num_pqs)
 
 
 981{
 982	u32 cmd_arr[QM_CMD_STRUCT_SIZE(QM_STOP_CMD)] = { 0 };
 983	u32 pq_mask = 0, last_pq, pq_id;
 984
 985	last_pq = start_pq + num_pqs - 1;
 986
 987	/* Set command's PQ type */
 988	QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD, PQ_TYPE, is_tx_pq ? 0 : 1);
 989
 990	/* Go over requested PQs */
 991	for (pq_id = start_pq; pq_id <= last_pq; pq_id++) {
 992		/* Set PQ bit in mask (stop command only) */
 993		if (!is_release_cmd)
 994			pq_mask |= BIT((pq_id % QM_STOP_PQ_MASK_WIDTH));
 995
 996		/* If last PQ or end of PQ mask, write command */
 997		if ((pq_id == last_pq) ||
 998		    (pq_id % QM_STOP_PQ_MASK_WIDTH ==
 999		     (QM_STOP_PQ_MASK_WIDTH - 1))) {
1000			QM_CMD_SET_FIELD(cmd_arr,
1001					 QM_STOP_CMD, PAUSE_MASK, pq_mask);
1002			QM_CMD_SET_FIELD(cmd_arr,
1003					 QM_STOP_CMD,
1004					 GROUP_ID,
1005					 pq_id / QM_STOP_PQ_MASK_WIDTH);
1006			if (!qed_send_qm_cmd(p_hwfn, p_ptt, QM_STOP_CMD_ADDR,
1007					     cmd_arr[0], cmd_arr[1]))
1008				return false;
1009			pq_mask = 0;
1010		}
1011	}
1012
1013	return true;
1014}
1015
1016
1017#define SET_TUNNEL_TYPE_ENABLE_BIT(var, offset, enable) \
1018	do { \
1019		typeof(var) *__p_var = &(var); \
1020		typeof(offset) __offset = offset; \
1021		*__p_var = (*__p_var & ~BIT(__offset)) | \
1022			   ((enable) ? BIT(__offset) : 0); \
1023	} while (0)
1024#define PRS_ETH_TUNN_OUTPUT_FORMAT        -188897008
1025#define PRS_ETH_OUTPUT_FORMAT             -46832
1026
1027void qed_set_vxlan_dest_port(struct qed_hwfn *p_hwfn,
1028			     struct qed_ptt *p_ptt, u16 dest_port)
1029{
1030	/* Update PRS register */
1031	qed_wr(p_hwfn, p_ptt, PRS_REG_VXLAN_PORT, dest_port);
1032
1033	/* Update NIG register */
1034	qed_wr(p_hwfn, p_ptt, NIG_REG_VXLAN_CTRL, dest_port);
1035
1036	/* Update PBF register */
1037	qed_wr(p_hwfn, p_ptt, PBF_REG_VXLAN_PORT, dest_port);
1038}
1039
1040void qed_set_vxlan_enable(struct qed_hwfn *p_hwfn,
1041			  struct qed_ptt *p_ptt, bool vxlan_enable)
1042{
1043	u32 reg_val;
1044	u8 shift;
1045
1046	/* Update PRS register */
1047	reg_val = qed_rd(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN);
1048	shift = PRS_REG_ENCAPSULATION_TYPE_EN_VXLAN_ENABLE_SHIFT;
1049	SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, vxlan_enable);
1050	qed_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val);
1051	if (reg_val) {
1052		reg_val =
1053		    qed_rd(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0_BB_K2);
1054
1055		/* Update output  only if tunnel blocks not included. */
1056		if (reg_val == (u32)PRS_ETH_OUTPUT_FORMAT)
1057			qed_wr(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0_BB_K2,
1058			       (u32)PRS_ETH_TUNN_OUTPUT_FORMAT);
1059	}
1060
1061	/* Update NIG register */
1062	reg_val = qed_rd(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE);
1063	shift = NIG_REG_ENC_TYPE_ENABLE_VXLAN_ENABLE_SHIFT;
1064	SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, vxlan_enable);
1065	qed_wr(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE, reg_val);
1066
1067	/* Update DORQ register */
1068	qed_wr(p_hwfn,
1069	       p_ptt, DORQ_REG_L2_EDPM_TUNNEL_VXLAN_EN, vxlan_enable ? 1 : 0);
1070}
1071
1072void qed_set_gre_enable(struct qed_hwfn *p_hwfn,
1073			struct qed_ptt *p_ptt,
1074			bool eth_gre_enable, bool ip_gre_enable)
1075{
1076	u32 reg_val;
1077	u8 shift;
1078
1079	/* Update PRS register */
1080	reg_val = qed_rd(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN);
1081	shift = PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GRE_ENABLE_SHIFT;
1082	SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, eth_gre_enable);
1083	shift = PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GRE_ENABLE_SHIFT;
1084	SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, ip_gre_enable);
1085	qed_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val);
1086	if (reg_val) {
1087		reg_val =
1088		    qed_rd(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0_BB_K2);
1089
1090		/* Update output  only if tunnel blocks not included. */
1091		if (reg_val == (u32)PRS_ETH_OUTPUT_FORMAT)
1092			qed_wr(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0_BB_K2,
1093			       (u32)PRS_ETH_TUNN_OUTPUT_FORMAT);
1094	}
1095
1096	/* Update NIG register */
1097	reg_val = qed_rd(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE);
1098	shift = NIG_REG_ENC_TYPE_ENABLE_ETH_OVER_GRE_ENABLE_SHIFT;
1099	SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, eth_gre_enable);
1100	shift = NIG_REG_ENC_TYPE_ENABLE_IP_OVER_GRE_ENABLE_SHIFT;
1101	SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, ip_gre_enable);
1102	qed_wr(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE, reg_val);
1103
1104	/* Update DORQ registers */
1105	qed_wr(p_hwfn,
1106	       p_ptt,
1107	       DORQ_REG_L2_EDPM_TUNNEL_GRE_ETH_EN, eth_gre_enable ? 1 : 0);
1108	qed_wr(p_hwfn,
1109	       p_ptt, DORQ_REG_L2_EDPM_TUNNEL_GRE_IP_EN, ip_gre_enable ? 1 : 0);
1110}
1111
1112void qed_set_geneve_dest_port(struct qed_hwfn *p_hwfn,
1113			      struct qed_ptt *p_ptt, u16 dest_port)
1114{
1115	/* Update PRS register */
1116	qed_wr(p_hwfn, p_ptt, PRS_REG_NGE_PORT, dest_port);
1117
1118	/* Update NIG register */
1119	qed_wr(p_hwfn, p_ptt, NIG_REG_NGE_PORT, dest_port);
1120
1121	/* Update PBF register */
1122	qed_wr(p_hwfn, p_ptt, PBF_REG_NGE_PORT, dest_port);
1123}
1124
1125void qed_set_geneve_enable(struct qed_hwfn *p_hwfn,
1126			   struct qed_ptt *p_ptt,
1127			   bool eth_geneve_enable, bool ip_geneve_enable)
1128{
1129	u32 reg_val;
1130	u8 shift;
1131
1132	/* Update PRS register */
1133	reg_val = qed_rd(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN);
1134	shift = PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GENEVE_ENABLE_SHIFT;
1135	SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, eth_geneve_enable);
1136	shift = PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GENEVE_ENABLE_SHIFT;
1137	SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, ip_geneve_enable);
1138	qed_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val);
1139	if (reg_val) {
1140		reg_val =
1141		    qed_rd(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0_BB_K2);
1142
1143		/* Update output  only if tunnel blocks not included. */
1144		if (reg_val == (u32)PRS_ETH_OUTPUT_FORMAT)
1145			qed_wr(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0_BB_K2,
1146			       (u32)PRS_ETH_TUNN_OUTPUT_FORMAT);
1147	}
1148
1149	/* Update NIG register */
1150	qed_wr(p_hwfn, p_ptt, NIG_REG_NGE_ETH_ENABLE,
1151	       eth_geneve_enable ? 1 : 0);
1152	qed_wr(p_hwfn, p_ptt, NIG_REG_NGE_IP_ENABLE, ip_geneve_enable ? 1 : 0);
1153
1154	/* EDPM with geneve tunnel not supported in BB */
1155	if (QED_IS_BB_B0(p_hwfn->cdev))
1156		return;
1157
1158	/* Update DORQ registers */
1159	qed_wr(p_hwfn,
1160	       p_ptt,
1161	       DORQ_REG_L2_EDPM_TUNNEL_NGE_ETH_EN_K2_E5,
1162	       eth_geneve_enable ? 1 : 0);
1163	qed_wr(p_hwfn,
1164	       p_ptt,
1165	       DORQ_REG_L2_EDPM_TUNNEL_NGE_IP_EN_K2_E5,
1166	       ip_geneve_enable ? 1 : 0);
1167}
1168
1169#define PRS_ETH_VXLAN_NO_L2_ENABLE_OFFSET   4
1170#define PRS_ETH_VXLAN_NO_L2_OUTPUT_FORMAT      -927094512
1171
1172void qed_set_vxlan_no_l2_enable(struct qed_hwfn *p_hwfn,
1173				struct qed_ptt *p_ptt, bool enable)
1174{
1175	u32 reg_val, cfg_mask;
1176
1177	/* read PRS config register */
1178	reg_val = qed_rd(p_hwfn, p_ptt, PRS_REG_MSG_INFO);
1179
1180	/* set VXLAN_NO_L2_ENABLE mask */
1181	cfg_mask = BIT(PRS_ETH_VXLAN_NO_L2_ENABLE_OFFSET);
1182
1183	if (enable) {
1184		/* set VXLAN_NO_L2_ENABLE flag */
1185		reg_val |= cfg_mask;
1186
1187		/* update PRS FIC  register */
1188		qed_wr(p_hwfn,
1189		       p_ptt,
1190		       PRS_REG_OUTPUT_FORMAT_4_0_BB_K2,
1191		       (u32)PRS_ETH_VXLAN_NO_L2_OUTPUT_FORMAT);
1192	} else {
1193		/* clear VXLAN_NO_L2_ENABLE flag */
1194		reg_val &= ~cfg_mask;
1195	}
1196
1197	/* write PRS config register */
1198	qed_wr(p_hwfn, p_ptt, PRS_REG_MSG_INFO, reg_val);
1199}
1200
1201#define T_ETH_PACKET_ACTION_GFT_EVENTID  23
1202#define PARSER_ETH_CONN_GFT_ACTION_CM_HDR  272
1203#define T_ETH_PACKET_MATCH_RFS_EVENTID 25
1204#define PARSER_ETH_CONN_CM_HDR 0
1205#define CAM_LINE_SIZE sizeof(u32)
1206#define RAM_LINE_SIZE sizeof(u64)
1207#define REG_SIZE sizeof(u32)
1208
1209void qed_gft_disable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, u16 pf_id)
1210{
1211	/* Disable gft search for PF */
1212	qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_GFT, 0);
1213
1214	/* Clean ram & cam for next gft session */
1215
1216	/* Zero camline */
1217	qed_wr(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE * pf_id, 0);
1218
1219	/* Zero ramline */
1220	qed_wr(p_hwfn,
1221	       p_ptt, PRS_REG_GFT_PROFILE_MASK_RAM + RAM_LINE_SIZE * pf_id, 0);
1222	qed_wr(p_hwfn,
1223	       p_ptt,
1224	       PRS_REG_GFT_PROFILE_MASK_RAM + RAM_LINE_SIZE * pf_id + REG_SIZE,
1225	       0);
1226}
1227
1228void qed_set_gft_event_id_cm_hdr(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
1229{
1230	u32 rfs_cm_hdr_event_id;
1231
1232	/* Set RFS event ID to be awakened i Tstorm By Prs */
1233	rfs_cm_hdr_event_id = qed_rd(p_hwfn, p_ptt, PRS_REG_CM_HDR_GFT);
1234	rfs_cm_hdr_event_id |= T_ETH_PACKET_ACTION_GFT_EVENTID <<
1235			       PRS_REG_CM_HDR_GFT_EVENT_ID_SHIFT;
1236	rfs_cm_hdr_event_id |= PARSER_ETH_CONN_GFT_ACTION_CM_HDR <<
1237			       PRS_REG_CM_HDR_GFT_CM_HDR_SHIFT;
1238	qed_wr(p_hwfn, p_ptt, PRS_REG_CM_HDR_GFT, rfs_cm_hdr_event_id);
1239}
1240
1241void qed_gft_config(struct qed_hwfn *p_hwfn,
1242		    struct qed_ptt *p_ptt,
1243		    u16 pf_id,
1244		    bool tcp,
1245		    bool udp,
1246		    bool ipv4, bool ipv6, enum gft_profile_type profile_type)
1247{
1248	u32 reg_val, cam_line, ram_line_lo, ram_line_hi;
1249
1250	if (!ipv6 && !ipv4)
1251		DP_NOTICE(p_hwfn,
1252			  "gft_config: must accept at least on of - ipv4 or ipv6'\n");
1253	if (!tcp && !udp)
1254		DP_NOTICE(p_hwfn,
1255			  "gft_config: must accept at least on of - udp or tcp\n");
1256	if (profile_type >= MAX_GFT_PROFILE_TYPE)
1257		DP_NOTICE(p_hwfn, "gft_config: unsupported gft_profile_type\n");
1258
1259	/* Set RFS event ID to be awakened i Tstorm By Prs */
1260	reg_val = T_ETH_PACKET_MATCH_RFS_EVENTID <<
1261		  PRS_REG_CM_HDR_GFT_EVENT_ID_SHIFT;
1262	reg_val |= PARSER_ETH_CONN_CM_HDR << PRS_REG_CM_HDR_GFT_CM_HDR_SHIFT;
1263	qed_wr(p_hwfn, p_ptt, PRS_REG_CM_HDR_GFT, reg_val);
1264
1265	/* Do not load context only cid in PRS on match. */
1266	qed_wr(p_hwfn, p_ptt, PRS_REG_LOAD_L2_FILTER, 0);
1267
1268	/* Do not use tenant ID exist bit for gft search */
1269	qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_TENANT_ID, 0);
1270
1271	/* Set Cam */
1272	cam_line = 0;
1273	SET_FIELD(cam_line, GFT_CAM_LINE_MAPPED_VALID, 1);
1274
1275	/* Filters are per PF!! */
1276	SET_FIELD(cam_line,
1277		  GFT_CAM_LINE_MAPPED_PF_ID_MASK,
1278		  GFT_CAM_LINE_MAPPED_PF_ID_MASK_MASK);
1279	SET_FIELD(cam_line, GFT_CAM_LINE_MAPPED_PF_ID, pf_id);
1280
1281	if (!(tcp && udp)) {
1282		SET_FIELD(cam_line,
1283			  GFT_CAM_LINE_MAPPED_UPPER_PROTOCOL_TYPE_MASK,
1284			  GFT_CAM_LINE_MAPPED_UPPER_PROTOCOL_TYPE_MASK_MASK);
1285		if (tcp)
1286			SET_FIELD(cam_line,
1287				  GFT_CAM_LINE_MAPPED_UPPER_PROTOCOL_TYPE,
1288				  GFT_PROFILE_TCP_PROTOCOL);
1289		else
1290			SET_FIELD(cam_line,
1291				  GFT_CAM_LINE_MAPPED_UPPER_PROTOCOL_TYPE,
1292				  GFT_PROFILE_UDP_PROTOCOL);
1293	}
1294
1295	if (!(ipv4 && ipv6)) {
1296		SET_FIELD(cam_line, GFT_CAM_LINE_MAPPED_IP_VERSION_MASK, 1);
1297		if (ipv4)
1298			SET_FIELD(cam_line,
1299				  GFT_CAM_LINE_MAPPED_IP_VERSION,
1300				  GFT_PROFILE_IPV4);
1301		else
1302			SET_FIELD(cam_line,
1303				  GFT_CAM_LINE_MAPPED_IP_VERSION,
1304				  GFT_PROFILE_IPV6);
1305	}
1306
1307	/* Write characteristics to cam */
1308	qed_wr(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE * pf_id,
1309	       cam_line);
1310	cam_line =
1311	    qed_rd(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE * pf_id);
1312
1313	/* Write line to RAM - compare to filter 4 tuple */
1314	ram_line_lo = 0;
1315	ram_line_hi = 0;
1316
1317	/* Tunnel type */
1318	SET_FIELD(ram_line_lo, GFT_RAM_LINE_TUNNEL_DST_PORT, 1);
1319	SET_FIELD(ram_line_lo, GFT_RAM_LINE_TUNNEL_OVER_IP_PROTOCOL, 1);
1320
1321	if (profile_type == GFT_PROFILE_TYPE_4_TUPLE) {
1322		SET_FIELD(ram_line_hi, GFT_RAM_LINE_DST_IP, 1);
1323		SET_FIELD(ram_line_hi, GFT_RAM_LINE_SRC_IP, 1);
1324		SET_FIELD(ram_line_hi, GFT_RAM_LINE_OVER_IP_PROTOCOL, 1);
1325		SET_FIELD(ram_line_lo, GFT_RAM_LINE_ETHERTYPE, 1);
1326		SET_FIELD(ram_line_lo, GFT_RAM_LINE_SRC_PORT, 1);
1327		SET_FIELD(ram_line_lo, GFT_RAM_LINE_DST_PORT, 1);
1328	} else if (profile_type == GFT_PROFILE_TYPE_L4_DST_PORT) {
1329		SET_FIELD(ram_line_hi, GFT_RAM_LINE_OVER_IP_PROTOCOL, 1);
1330		SET_FIELD(ram_line_lo, GFT_RAM_LINE_ETHERTYPE, 1);
1331		SET_FIELD(ram_line_lo, GFT_RAM_LINE_DST_PORT, 1);
1332	} else if (profile_type == GFT_PROFILE_TYPE_IP_DST_ADDR) {
1333		SET_FIELD(ram_line_hi, GFT_RAM_LINE_DST_IP, 1);
1334		SET_FIELD(ram_line_lo, GFT_RAM_LINE_ETHERTYPE, 1);
1335	} else if (profile_type == GFT_PROFILE_TYPE_IP_SRC_ADDR) {
1336		SET_FIELD(ram_line_hi, GFT_RAM_LINE_SRC_IP, 1);
1337		SET_FIELD(ram_line_lo, GFT_RAM_LINE_ETHERTYPE, 1);
1338	} else if (profile_type == GFT_PROFILE_TYPE_TUNNEL_TYPE) {
1339		SET_FIELD(ram_line_lo, GFT_RAM_LINE_TUNNEL_ETHERTYPE, 1);
1340	}
1341
1342	qed_wr(p_hwfn,
1343	       p_ptt,
1344	       PRS_REG_GFT_PROFILE_MASK_RAM + RAM_LINE_SIZE * pf_id,
1345	       ram_line_lo);
1346	qed_wr(p_hwfn,
1347	       p_ptt,
1348	       PRS_REG_GFT_PROFILE_MASK_RAM + RAM_LINE_SIZE * pf_id + REG_SIZE,
1349	       ram_line_hi);
1350
1351	/* Set default profile so that no filter match will happen */
1352	qed_wr(p_hwfn,
1353	       p_ptt,
1354	       PRS_REG_GFT_PROFILE_MASK_RAM + RAM_LINE_SIZE *
1355	       PRS_GFT_CAM_LINES_NO_MATCH, 0xffffffff);
1356	qed_wr(p_hwfn,
1357	       p_ptt,
1358	       PRS_REG_GFT_PROFILE_MASK_RAM + RAM_LINE_SIZE *
1359	       PRS_GFT_CAM_LINES_NO_MATCH + REG_SIZE, 0x3ff);
1360
1361	/* Enable gft search */
1362	qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_GFT, 1);
1363}
1364
1365DECLARE_CRC8_TABLE(cdu_crc8_table);
1366
1367/* Calculate and return CDU validation byte per connection type/region/cid */
1368static u8 qed_calc_cdu_validation_byte(u8 conn_type, u8 region, u32 cid)
1369{
1370	const u8 validation_cfg = CDU_VALIDATION_DEFAULT_CFG;
1371	u8 crc, validation_byte = 0;
1372	static u8 crc8_table_valid; /* automatically initialized to 0 */
1373	u32 validation_string = 0;
1374	u32 data_to_crc;
1375
1376	if (!crc8_table_valid) {
1377		crc8_populate_msb(cdu_crc8_table, 0x07);
1378		crc8_table_valid = 1;
1379	}
1380
1381	/* The CRC is calculated on the String-to-compress:
1382	 * [31:8]  = {CID[31:20],CID[11:0]}
1383	 * [7:4]   = Region
1384	 * [3:0]   = Type
1385	 */
1386	if ((validation_cfg >> CDU_CONTEXT_VALIDATION_CFG_USE_CID) & 1)
1387		validation_string |= (cid & 0xFFF00000) | ((cid & 0xFFF) << 8);
1388
1389	if ((validation_cfg >> CDU_CONTEXT_VALIDATION_CFG_USE_REGION) & 1)
1390		validation_string |= ((region & 0xF) << 4);
1391
1392	if ((validation_cfg >> CDU_CONTEXT_VALIDATION_CFG_USE_TYPE) & 1)
1393		validation_string |= (conn_type & 0xF);
1394
1395	/* Convert to big-endian and calculate CRC8 */
1396	data_to_crc = be32_to_cpu(validation_string);
1397
1398	crc = crc8(cdu_crc8_table,
1399		   (u8 *)&data_to_crc, sizeof(data_to_crc), CRC8_INIT_VALUE);
1400
1401	/* The validation byte [7:0] is composed:
1402	 * for type A validation
1403	 * [7]          = active configuration bit
1404	 * [6:0]        = crc[6:0]
1405	 *
1406	 * for type B validation
1407	 * [7]          = active configuration bit
1408	 * [6:3]        = connection_type[3:0]
1409	 * [2:0]        = crc[2:0]
1410	 */
1411	validation_byte |=
1412	    ((validation_cfg >>
1413	      CDU_CONTEXT_VALIDATION_CFG_USE_ACTIVE) & 1) << 7;
1414
1415	if ((validation_cfg >>
1416	     CDU_CONTEXT_VALIDATION_CFG_VALIDATION_TYPE_SHIFT) & 1)
1417		validation_byte |= ((conn_type & 0xF) << 3) | (crc & 0x7);
1418	else
1419		validation_byte |= crc & 0x7F;
1420
1421	return validation_byte;
1422}
1423
1424/* Calcualte and set validation bytes for session context */
1425void qed_calc_session_ctx_validation(void *p_ctx_mem,
1426				     u16 ctx_size, u8 ctx_type, u32 cid)
1427{
1428	u8 *x_val_ptr, *t_val_ptr, *u_val_ptr, *p_ctx;
1429
1430	p_ctx = (u8 * const)p_ctx_mem;
1431	x_val_ptr = &p_ctx[con_region_offsets[0][ctx_type]];
1432	t_val_ptr = &p_ctx[con_region_offsets[1][ctx_type]];
1433	u_val_ptr = &p_ctx[con_region_offsets[2][ctx_type]];
1434
1435	memset(p_ctx, 0, ctx_size);
1436
1437	*x_val_ptr = qed_calc_cdu_validation_byte(ctx_type, 3, cid);
1438	*t_val_ptr = qed_calc_cdu_validation_byte(ctx_type, 4, cid);
1439	*u_val_ptr = qed_calc_cdu_validation_byte(ctx_type, 5, cid);
1440}
1441
1442/* Calcualte and set validation bytes for task context */
1443void qed_calc_task_ctx_validation(void *p_ctx_mem,
1444				  u16 ctx_size, u8 ctx_type, u32 tid)
1445{
1446	u8 *p_ctx, *region1_val_ptr;
1447
1448	p_ctx = (u8 * const)p_ctx_mem;
1449	region1_val_ptr = &p_ctx[task_region_offsets[0][ctx_type]];
1450
1451	memset(p_ctx, 0, ctx_size);
1452
1453	*region1_val_ptr = qed_calc_cdu_validation_byte(ctx_type, 1, tid);
1454}
1455
1456/* Memset session context to 0 while preserving validation bytes */
1457void qed_memset_session_ctx(void *p_ctx_mem, u32 ctx_size, u8 ctx_type)
1458{
1459	u8 *x_val_ptr, *t_val_ptr, *u_val_ptr, *p_ctx;
1460	u8 x_val, t_val, u_val;
1461
1462	p_ctx = (u8 * const)p_ctx_mem;
1463	x_val_ptr = &p_ctx[con_region_offsets[0][ctx_type]];
1464	t_val_ptr = &p_ctx[con_region_offsets[1][ctx_type]];
1465	u_val_ptr = &p_ctx[con_region_offsets[2][ctx_type]];
1466
1467	x_val = *x_val_ptr;
1468	t_val = *t_val_ptr;
1469	u_val = *u_val_ptr;
1470
1471	memset(p_ctx, 0, ctx_size);
1472
1473	*x_val_ptr = x_val;
1474	*t_val_ptr = t_val;
1475	*u_val_ptr = u_val;
1476}
1477
1478/* Memset task context to 0 while preserving validation bytes */
1479void qed_memset_task_ctx(void *p_ctx_mem, u32 ctx_size, u8 ctx_type)
1480{
1481	u8 *p_ctx, *region1_val_ptr;
1482	u8 region1_val;
1483
1484	p_ctx = (u8 * const)p_ctx_mem;
1485	region1_val_ptr = &p_ctx[task_region_offsets[0][ctx_type]];
1486
1487	region1_val = *region1_val_ptr;
1488
1489	memset(p_ctx, 0, ctx_size);
1490
1491	*region1_val_ptr = region1_val;
1492}
1493
1494/* Enable and configure context validation */
1495void qed_enable_context_validation(struct qed_hwfn *p_hwfn,
1496				   struct qed_ptt *p_ptt)
1497{
1498	u32 ctx_validation;
1499
1500	/* Enable validation for connection region 3: CCFC_CTX_VALID0[31:24] */
1501	ctx_validation = CDU_VALIDATION_DEFAULT_CFG << 24;
1502	qed_wr(p_hwfn, p_ptt, CDU_REG_CCFC_CTX_VALID0, ctx_validation);
1503
1504	/* Enable validation for connection region 5: CCFC_CTX_VALID1[15:8] */
1505	ctx_validation = CDU_VALIDATION_DEFAULT_CFG << 8;
1506	qed_wr(p_hwfn, p_ptt, CDU_REG_CCFC_CTX_VALID1, ctx_validation);
1507
1508	/* Enable validation for connection region 1: TCFC_CTX_VALID0[15:8] */
1509	ctx_validation = CDU_VALIDATION_DEFAULT_CFG << 8;
1510	qed_wr(p_hwfn, p_ptt, CDU_REG_TCFC_CTX_VALID0, ctx_validation);
1511}
v4.6
  1/* QLogic qed NIC Driver
  2 * Copyright (c) 2015 QLogic Corporation
  3 *
  4 * This software is available under the terms of the GNU General Public License
  5 * (GPL) Version 2, available from the file COPYING in the main directory of
  6 * this source tree.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  7 */
  8
  9#include <linux/types.h>
 
 10#include <linux/delay.h>
 11#include <linux/kernel.h>
 12#include <linux/slab.h>
 13#include <linux/string.h>
 14#include "qed_hsi.h"
 15#include "qed_hw.h"
 16#include "qed_init_ops.h"
 17#include "qed_reg_addr.h"
 18
 19enum cminterface {
 20	MCM_SEC,
 21	MCM_PRI,
 22	UCM_SEC,
 23	UCM_PRI,
 24	TCM_SEC,
 25	TCM_PRI,
 26	YCM_SEC,
 27	YCM_PRI,
 28	XCM_SEC,
 29	XCM_PRI,
 30	NUM_OF_CM_INTERFACES
 31};
 32
 33/* general constants */
 34#define QM_PQ_ELEMENT_SIZE                      4 /* in bytes */
 35#define QM_PQ_MEM_4KB(pq_size)	(pq_size ? DIV_ROUND_UP((pq_size + 1) *	\
 36							QM_PQ_ELEMENT_SIZE, \
 37							0x1000) : 0)
 38#define QM_PQ_SIZE_256B(pq_size)	(pq_size ? DIV_ROUND_UP(pq_size, \
 39								0x100) - 1 : 0)
 40#define QM_INVALID_PQ_ID                        0xffff
 41/* feature enable */
 42#define QM_BYPASS_EN                            1
 43#define QM_BYTE_CRD_EN                          1
 44/* other PQ constants */
 45#define QM_OTHER_PQS_PER_PF                     4
 
 
 
 46/* WFQ constants */
 47#define QM_WFQ_UPPER_BOUND		6250000
 48#define QM_WFQ_VP_PQ_VOQ_SHIFT          0
 49#define QM_WFQ_VP_PQ_PF_SHIFT           5
 50#define QM_WFQ_INC_VAL(weight)          ((weight) * 0x9000)
 51#define QM_WFQ_MAX_INC_VAL                      4375000
 52#define QM_WFQ_INIT_CRD(inc_val)        (2 * (inc_val))
 
 
 
 
 
 
 
 
 
 
 53/* RL constants */
 54#define QM_RL_UPPER_BOUND                       6250000
 55#define QM_RL_PERIOD                            5               /* in us */
 56#define QM_RL_PERIOD_CLK_25M            (25 * QM_RL_PERIOD)
 57#define QM_RL_INC_VAL(rate)		max_t(u32,	\
 58					      (((rate ? rate : 1000000)	\
 59						* QM_RL_PERIOD) / 8), 1)
 60#define QM_RL_MAX_INC_VAL                       4375000
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 61/* AFullOprtnstcCrdMask constants */
 62#define QM_OPPOR_LINE_VOQ_DEF           1
 63#define QM_OPPOR_FW_STOP_DEF            0
 64#define QM_OPPOR_PQ_EMPTY_DEF           1
 65#define EAGLE_WORKAROUND_TC                     7
 66/* Command Queue constants */
 67#define PBF_CMDQ_PURE_LB_LINES                          150
 68#define PBF_CMDQ_EAGLE_WORKAROUND_LINES         8
 69#define PBF_CMDQ_LINES_RT_OFFSET(voq)           (		 \
 70		PBF_REG_YCMD_QS_NUM_LINES_VOQ0_RT_OFFSET + voq * \
 71		(PBF_REG_YCMD_QS_NUM_LINES_VOQ1_RT_OFFSET -	 \
 72		 PBF_REG_YCMD_QS_NUM_LINES_VOQ0_RT_OFFSET))
 73#define PBF_BTB_GUARANTEED_RT_OFFSET(voq)       (	      \
 74		PBF_REG_BTB_GUARANTEED_VOQ0_RT_OFFSET + voq * \
 75		(PBF_REG_BTB_GUARANTEED_VOQ1_RT_OFFSET -      \
 76		 PBF_REG_BTB_GUARANTEED_VOQ0_RT_OFFSET))
 77#define QM_VOQ_LINE_CRD(pbf_cmd_lines)          ((((pbf_cmd_lines) - \
 78						   4) *		     \
 79						  2) | QM_LINE_CRD_REG_SIGN_BIT)
 
 
 
 
 
 
 80/* BTB: blocks constants (block size = 256B) */
 81#define BTB_JUMBO_PKT_BLOCKS            38
 82#define BTB_HEADROOM_BLOCKS                     BTB_JUMBO_PKT_BLOCKS
 83#define BTB_EAGLE_WORKAROUND_BLOCKS     4
 84#define BTB_PURE_LB_FACTOR                      10
 85#define BTB_PURE_LB_RATIO                       7
 
 
 
 
 
 
 86/* QM stop command constants */
 87#define QM_STOP_PQ_MASK_WIDTH                   32
 88#define QM_STOP_CMD_ADDR                                0x2
 89#define QM_STOP_CMD_STRUCT_SIZE                 2
 90#define QM_STOP_CMD_PAUSE_MASK_OFFSET   0
 91#define QM_STOP_CMD_PAUSE_MASK_SHIFT    0
 92#define QM_STOP_CMD_PAUSE_MASK_MASK             -1
 93#define QM_STOP_CMD_GROUP_ID_OFFSET             1
 94#define QM_STOP_CMD_GROUP_ID_SHIFT              16
 95#define QM_STOP_CMD_GROUP_ID_MASK               15
 96#define QM_STOP_CMD_PQ_TYPE_OFFSET              1
 97#define QM_STOP_CMD_PQ_TYPE_SHIFT               24
 98#define QM_STOP_CMD_PQ_TYPE_MASK                1
 99#define QM_STOP_CMD_MAX_POLL_COUNT              100
100#define QM_STOP_CMD_POLL_PERIOD_US              500
 
101/* QM command macros */
102#define QM_CMD_STRUCT_SIZE(cmd)			cmd ## \
103	_STRUCT_SIZE
104#define QM_CMD_SET_FIELD(var, cmd, field,				  \
105			 value)        SET_FIELD(var[cmd ## _ ## field ## \
106						     _OFFSET],		  \
107						 cmd ## _ ## field,	  \
108						 value)
109/* QM: VOQ macros */
110#define PHYS_VOQ(port, tc, max_phy_tcs_pr_port)	((port) *	\
111						 (max_phy_tcs_pr_port) \
112						 + (tc))
113#define LB_VOQ(port)				( \
114		MAX_PHYS_VOQS + (port))
115#define VOQ(port, tc, max_phy_tcs_pr_port)	\
116	((tc) <		\
117	 LB_TC ? PHYS_VOQ(port,		\
118			  tc,			 \
119			  max_phy_tcs_pr_port) \
120		: LB_VOQ(port))
 
 
 
 
 
 
 
 
 
 
 
 
 
121/******************** INTERNAL IMPLEMENTATION *********************/
 
 
 
 
 
 
 
 
 
 
 
122/* Prepare PF RL enable/disable runtime init values */
123static void qed_enable_pf_rl(struct qed_hwfn *p_hwfn,
124			     bool pf_rl_en)
125{
126	STORE_RT_REG(p_hwfn, QM_REG_RLPFENABLE_RT_OFFSET, pf_rl_en ? 1 : 0);
127	if (pf_rl_en) {
128		/* enable RLs for all VOQs */
129		STORE_RT_REG(p_hwfn, QM_REG_RLPFVOQENABLE_RT_OFFSET,
130			     (1 << MAX_NUM_VOQS) - 1);
131		/* write RL period */
 
 
 
 
 
 
 
 
132		STORE_RT_REG(p_hwfn,
133			     QM_REG_RLPFPERIOD_RT_OFFSET,
134			     QM_RL_PERIOD_CLK_25M);
135		STORE_RT_REG(p_hwfn,
136			     QM_REG_RLPFPERIODTIMER_RT_OFFSET,
137			     QM_RL_PERIOD_CLK_25M);
138		/* set credit threshold for QM bypass flow */
 
139		if (QM_BYPASS_EN)
140			STORE_RT_REG(p_hwfn,
141				     QM_REG_AFULLQMBYPTHRPFRL_RT_OFFSET,
142				     QM_RL_UPPER_BOUND);
143	}
144}
145
146/* Prepare PF WFQ enable/disable runtime init values */
147static void qed_enable_pf_wfq(struct qed_hwfn *p_hwfn,
148			      bool pf_wfq_en)
149{
150	STORE_RT_REG(p_hwfn, QM_REG_WFQPFENABLE_RT_OFFSET, pf_wfq_en ? 1 : 0);
151	/* set credit threshold for QM bypass flow */
 
152	if (pf_wfq_en && QM_BYPASS_EN)
153		STORE_RT_REG(p_hwfn,
154			     QM_REG_AFULLQMBYPTHRPFWFQ_RT_OFFSET,
155			     QM_WFQ_UPPER_BOUND);
156}
157
158/* Prepare VPORT RL enable/disable runtime init values */
159static void qed_enable_vport_rl(struct qed_hwfn *p_hwfn,
160				bool vport_rl_en)
161{
162	STORE_RT_REG(p_hwfn, QM_REG_RLGLBLENABLE_RT_OFFSET,
163		     vport_rl_en ? 1 : 0);
164	if (vport_rl_en) {
165		/* write RL period (use timer 0 only) */
166		STORE_RT_REG(p_hwfn,
167			     QM_REG_RLGLBLPERIOD_0_RT_OFFSET,
168			     QM_RL_PERIOD_CLK_25M);
169		STORE_RT_REG(p_hwfn,
170			     QM_REG_RLGLBLPERIODTIMER_0_RT_OFFSET,
171			     QM_RL_PERIOD_CLK_25M);
172		/* set credit threshold for QM bypass flow */
 
173		if (QM_BYPASS_EN)
174			STORE_RT_REG(p_hwfn,
175				     QM_REG_AFULLQMBYPTHRGLBLRL_RT_OFFSET,
176				     QM_RL_UPPER_BOUND);
177	}
178}
179
180/* Prepare VPORT WFQ enable/disable runtime init values */
181static void qed_enable_vport_wfq(struct qed_hwfn *p_hwfn,
182				 bool vport_wfq_en)
183{
184	STORE_RT_REG(p_hwfn, QM_REG_WFQVPENABLE_RT_OFFSET,
185		     vport_wfq_en ? 1 : 0);
186	/* set credit threshold for QM bypass flow */
 
187	if (vport_wfq_en && QM_BYPASS_EN)
188		STORE_RT_REG(p_hwfn,
189			     QM_REG_AFULLQMBYPTHRVPWFQ_RT_OFFSET,
190			     QM_WFQ_UPPER_BOUND);
191}
192
193/* Prepare runtime init values to allocate PBF command queue lines for
194 * the specified VOQ
195 */
196static void qed_cmdq_lines_voq_rt_init(struct qed_hwfn *p_hwfn,
197				       u8 voq,
198				       u16 cmdq_lines)
199{
200	u32 qm_line_crd;
201
202	/* In A0 - Limit the size of pbf queue so that only 511 commands with
203	 * the minimum size of 4 (FCoE minimum size)
204	 */
205	bool is_bb_a0 = QED_IS_BB_A0(p_hwfn->cdev);
206
207	if (is_bb_a0)
208		cmdq_lines = min_t(u32, cmdq_lines, 1022);
209	qm_line_crd = QM_VOQ_LINE_CRD(cmdq_lines);
210	OVERWRITE_RT_REG(p_hwfn, PBF_CMDQ_LINES_RT_OFFSET(voq),
211			 (u32)cmdq_lines);
212	STORE_RT_REG(p_hwfn, QM_REG_VOQCRDLINE_RT_OFFSET + voq, qm_line_crd);
213	STORE_RT_REG(p_hwfn, QM_REG_VOQINITCRDLINE_RT_OFFSET + voq,
 
214		     qm_line_crd);
215}
216
217/* Prepare runtime init values to allocate PBF command queue lines. */
218static void qed_cmdq_lines_rt_init(
219	struct qed_hwfn *p_hwfn,
220	u8 max_ports_per_engine,
221	u8 max_phys_tcs_per_port,
222	struct init_qm_port_params port_params[MAX_NUM_PORTS])
223{
224	u8 tc, voq, port_id;
 
 
 
 
 
225
226	/* clear PBF lines for all VOQs */
227	for (voq = 0; voq < MAX_NUM_VOQS; voq++)
228		STORE_RT_REG(p_hwfn, PBF_CMDQ_LINES_RT_OFFSET(voq), 0);
229	for (port_id = 0; port_id < max_ports_per_engine; port_id++) {
230		if (port_params[port_id].active) {
231			u16 phys_lines, phys_lines_per_tc;
232			u8 phys_tcs = port_params[port_id].num_active_phys_tcs;
233
234			/* find #lines to divide between the active
235			 * physical TCs.
236			 */
237			phys_lines = port_params[port_id].num_pbf_cmd_lines -
238				     PBF_CMDQ_PURE_LB_LINES;
239			/* find #lines per active physical TC */
240			phys_lines_per_tc = phys_lines / phys_tcs;
241			/* init registers per active TC */
242			for (tc = 0; tc < phys_tcs; tc++) {
243				voq = PHYS_VOQ(port_id, tc,
244					       max_phys_tcs_per_port);
245				qed_cmdq_lines_voq_rt_init(p_hwfn, voq,
 
 
 
 
 
 
 
 
 
 
 
 
 
246							   phys_lines_per_tc);
247			}
248			/* init registers for pure LB TC */
249			qed_cmdq_lines_voq_rt_init(p_hwfn, LB_VOQ(port_id),
250						   PBF_CMDQ_PURE_LB_LINES);
251		}
 
 
 
 
 
 
 
252	}
253}
254
255static void qed_btb_blocks_rt_init(
256	struct qed_hwfn *p_hwfn,
257	u8 max_ports_per_engine,
258	u8 max_phys_tcs_per_port,
259	struct init_qm_port_params port_params[MAX_NUM_PORTS])
260{
261	u32 usable_blocks, pure_lb_blocks, phys_blocks;
262	u8 tc, voq, port_id;
263
264	for (port_id = 0; port_id < max_ports_per_engine; port_id++) {
265		u32 temp;
266		u8 phys_tcs;
267
268		if (!port_params[port_id].active)
269			continue;
270
271		phys_tcs = port_params[port_id].num_active_phys_tcs;
272
273		/* subtract headroom blocks */
274		usable_blocks = port_params[port_id].num_btb_blocks -
275				BTB_HEADROOM_BLOCKS;
276
277		/* find blocks per physical TC. use factor to avoid
278		 * floating arithmethic.
279		 */
 
 
 
 
 
 
280		pure_lb_blocks = (usable_blocks * BTB_PURE_LB_FACTOR) /
281				 (phys_tcs * BTB_PURE_LB_FACTOR +
282				  BTB_PURE_LB_RATIO);
283		pure_lb_blocks = max_t(u32, BTB_JUMBO_PKT_BLOCKS,
284				       pure_lb_blocks / BTB_PURE_LB_FACTOR);
285		phys_blocks = (usable_blocks - pure_lb_blocks) / phys_tcs;
 
286
287		/* init physical TCs */
288		for (tc = 0; tc < phys_tcs; tc++) {
289			voq = PHYS_VOQ(port_id, tc, max_phys_tcs_per_port);
290			STORE_RT_REG(p_hwfn, PBF_BTB_GUARANTEED_RT_OFFSET(voq),
291				     phys_blocks);
 
 
 
 
 
 
 
 
292		}
293
294		/* init pure LB TC */
295		temp = LB_VOQ(port_id);
296		STORE_RT_REG(p_hwfn, PBF_BTB_GUARANTEED_RT_OFFSET(temp),
 
 
297			     pure_lb_blocks);
298	}
299}
300
301/* Prepare Tx PQ mapping runtime init values for the specified PF */
302static void qed_tx_pq_map_rt_init(
303	struct qed_hwfn *p_hwfn,
304	struct qed_ptt *p_ptt,
305	struct qed_qm_pf_rt_init_params *p_params,
306	u32 base_mem_addr_4kb)
307{
 
308	struct init_qm_vport_params *vport_params = p_params->vport_params;
309	u16 num_pqs = p_params->num_pf_pqs + p_params->num_vf_pqs;
310	u16 first_pq_group = p_params->start_pq / QM_PF_QUEUE_GROUP_SIZE;
311	u16 last_pq_group = (p_params->start_pq + num_pqs - 1) /
312			    QM_PF_QUEUE_GROUP_SIZE;
313	bool is_bb_a0 = QED_IS_BB_A0(p_hwfn->cdev);
314	u16 i, pq_id, pq_group;
 
 
 
 
 
 
 
 
315
316	/* a bit per Tx PQ indicating if the PQ is associated with a VF */
317	u32 tx_pq_vf_mask[MAX_QM_TX_QUEUES / QM_PF_QUEUE_GROUP_SIZE] = { 0 };
318	u32 tx_pq_vf_mask_width = is_bb_a0 ? 32 : QM_PF_QUEUE_GROUP_SIZE;
319	u32 num_tx_pq_vf_masks = MAX_QM_TX_QUEUES / tx_pq_vf_mask_width;
320	u32 pq_mem_4kb = QM_PQ_MEM_4KB(p_params->num_pf_cids);
321	u32 vport_pq_mem_4kb = QM_PQ_MEM_4KB(p_params->num_vf_cids);
322	u32 mem_addr_4kb = base_mem_addr_4kb;
323
324	/* set mapping from PQ group to PF */
325	for (pq_group = first_pq_group; pq_group <= last_pq_group; pq_group++)
326		STORE_RT_REG(p_hwfn, QM_REG_PQTX2PF_0_RT_OFFSET + pq_group,
327			     (u32)(p_params->pf_id));
328	/* set PQ sizes */
 
329	STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_0_RT_OFFSET,
330		     QM_PQ_SIZE_256B(p_params->num_pf_cids));
331	STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_1_RT_OFFSET,
332		     QM_PQ_SIZE_256B(p_params->num_vf_cids));
333
334	/* go over all Tx PQs */
335	for (i = 0, pq_id = p_params->start_pq; i < num_pqs; i++, pq_id++) {
336		u8 voq = VOQ(p_params->port_id, p_params->pq_params[i].tc_id,
337			     p_params->max_phys_tcs_per_port);
338		bool is_vf_pq = (i >= p_params->num_pf_pqs);
339		struct qm_rf_pq_map tx_pq_map;
340
341		/* update first Tx PQ of VPORT/TC */
342		u8 vport_id_in_pf = p_params->pq_params[i].vport_id -
343				    p_params->start_vport;
344		u16 *pq_ids = &vport_params[vport_id_in_pf].first_tx_pq_id[0];
345		u16 first_tx_pq_id = pq_ids[p_params->pq_params[i].tc_id];
346
347		if (first_tx_pq_id == QM_INVALID_PQ_ID) {
348			/* create new VP PQ */
349			pq_ids[p_params->pq_params[i].tc_id] = pq_id;
350			first_tx_pq_id = pq_id;
351			/* map VP PQ to VOQ and PF */
 
 
 
 
 
 
 
 
 
 
352			STORE_RT_REG(p_hwfn,
353				     QM_REG_WFQVPMAP_RT_OFFSET +
354				     first_tx_pq_id,
355				     (voq << QM_WFQ_VP_PQ_VOQ_SHIFT) |
356				     (p_params->pf_id <<
357				      QM_WFQ_VP_PQ_PF_SHIFT));
 
 
 
 
 
358		}
359		/* fill PQ map entry */
360		memset(&tx_pq_map, 0, sizeof(tx_pq_map));
361		SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_PQ_VALID, 1);
362		SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_RL_VALID,
363			  is_vf_pq ? 1 : 0);
364		SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_VP_PQ_ID, first_tx_pq_id);
365		SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_RL_ID,
366			  is_vf_pq ? p_params->pq_params[i].vport_id : 0);
367		SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_VOQ, voq);
368		SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_WRR_WEIGHT_GROUP,
369			  p_params->pq_params[i].wrr_group);
370		/* write PQ map entry to CAM */
371		STORE_RT_REG(p_hwfn, QM_REG_TXPQMAP_RT_OFFSET + pq_id,
372			     *((u32 *)&tx_pq_map));
373		/* set base address */
374		STORE_RT_REG(p_hwfn,
375			     QM_REG_BASEADDRTXPQ_RT_OFFSET + pq_id,
376			     mem_addr_4kb);
377		/* check if VF PQ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
378		if (is_vf_pq) {
379			/* if PQ is associated with a VF, add indication
380			 * to PQ VF mask
381			 */
382			tx_pq_vf_mask[pq_id / tx_pq_vf_mask_width] |=
383				(1 << (pq_id % tx_pq_vf_mask_width));
384			mem_addr_4kb += vport_pq_mem_4kb;
385		} else {
386			mem_addr_4kb += pq_mem_4kb;
387		}
388	}
389
390	/* store Tx PQ VF mask to size select register */
391	for (i = 0; i < num_tx_pq_vf_masks; i++) {
392		if (tx_pq_vf_mask[i]) {
393			if (is_bb_a0) {
394				u32 curr_mask = 0, addr;
395
396				addr = QM_REG_MAXPQSIZETXSEL_0 + (i * 4);
397				if (!p_params->is_first_pf)
398					curr_mask = qed_rd(p_hwfn, p_ptt,
399							   addr);
400
401				addr = QM_REG_MAXPQSIZETXSEL_0_RT_OFFSET + i;
402
403				STORE_RT_REG(p_hwfn, addr,
404					     curr_mask | tx_pq_vf_mask[i]);
405			} else {
406				u32 addr;
407
408				addr = QM_REG_MAXPQSIZETXSEL_0_RT_OFFSET + i;
409				STORE_RT_REG(p_hwfn, addr,
410					     tx_pq_vf_mask[i]);
411			}
412		}
413	}
414}
415
416/* Prepare Other PQ mapping runtime init values for the specified PF */
417static void qed_other_pq_map_rt_init(struct qed_hwfn *p_hwfn,
418				     u8 port_id,
419				     u8 pf_id,
 
420				     u32 num_pf_cids,
421				     u32 num_tids,
422				     u32 base_mem_addr_4kb)
423{
424	u16 i, pq_id;
 
425
426	/* a single other PQ group is used in each PF,
427	 * where PQ group i is used in PF i.
428	 */
429	u16 pq_group = pf_id;
430	u32 pq_size = num_pf_cids + num_tids;
431	u32 pq_mem_4kb = QM_PQ_MEM_4KB(pq_size);
432	u32 mem_addr_4kb = base_mem_addr_4kb;
433
434	/* map PQ group to PF */
435	STORE_RT_REG(p_hwfn, QM_REG_PQOTHER2PF_0_RT_OFFSET + pq_group,
436		     (u32)(pf_id));
437	/* set PQ sizes */
 
438	STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_2_RT_OFFSET,
439		     QM_PQ_SIZE_256B(pq_size));
440	/* set base address */
441	for (i = 0, pq_id = pf_id * QM_PF_QUEUE_GROUP_SIZE;
442	     i < QM_OTHER_PQS_PER_PF; i++, pq_id++) {
 
443		STORE_RT_REG(p_hwfn,
444			     QM_REG_BASEADDROTHERPQ_RT_OFFSET + pq_id,
445			     mem_addr_4kb);
 
 
 
 
 
 
 
 
446		mem_addr_4kb += pq_mem_4kb;
447	}
448}
449
450/* Prepare PF WFQ runtime init values for the specified PF.
451 * Return -1 on error.
452 */
453static int qed_pf_wfq_rt_init(struct qed_hwfn *p_hwfn,
 
454			      struct qed_qm_pf_rt_init_params *p_params)
455{
456	u16 num_tx_pqs = p_params->num_pf_pqs + p_params->num_vf_pqs;
457	u32 crd_reg_offset;
458	u32 inc_val;
 
459	u16 i;
460
461	if (p_params->pf_id < MAX_NUM_PFS_BB)
462		crd_reg_offset = QM_REG_WFQPFCRD_RT_OFFSET;
463	else
464		crd_reg_offset = QM_REG_WFQPFCRD_MSB_RT_OFFSET +
465				 (p_params->pf_id % MAX_NUM_PFS_BB);
466
467	inc_val = QM_WFQ_INC_VAL(p_params->pf_wfq);
468	if (inc_val > QM_WFQ_MAX_INC_VAL) {
469		DP_NOTICE(p_hwfn, "Invalid PF WFQ weight configuration");
470		return -1;
471	}
472	STORE_RT_REG(p_hwfn, QM_REG_WFQPFWEIGHT_RT_OFFSET + p_params->pf_id,
473		     inc_val);
474	STORE_RT_REG(p_hwfn,
475		     QM_REG_WFQPFUPPERBOUND_RT_OFFSET + p_params->pf_id,
476		     QM_WFQ_UPPER_BOUND | QM_WFQ_CRD_REG_SIGN_BIT);
477
478	for (i = 0; i < num_tx_pqs; i++) {
479		u8 voq = VOQ(p_params->port_id, p_params->pq_params[i].tc_id,
480			     p_params->max_phys_tcs_per_port);
481
 
 
 
 
 
 
 
482		OVERWRITE_RT_REG(p_hwfn,
483				 crd_reg_offset + voq * MAX_NUM_PFS_BB,
484				 QM_WFQ_INIT_CRD(inc_val) |
485				 QM_WFQ_CRD_REG_SIGN_BIT);
486	}
487
 
 
 
 
 
 
488	return 0;
489}
490
491/* Prepare PF RL runtime init values for the specified PF.
492 * Return -1 on error.
493 */
494static int qed_pf_rl_rt_init(struct qed_hwfn *p_hwfn,
495			     u8 pf_id,
496			     u32 pf_rl)
497{
498	u32 inc_val = QM_RL_INC_VAL(pf_rl);
499
500	if (inc_val > QM_RL_MAX_INC_VAL) {
501		DP_NOTICE(p_hwfn, "Invalid PF rate limit configuration");
502		return -1;
503	}
504	STORE_RT_REG(p_hwfn, QM_REG_RLPFCRD_RT_OFFSET + pf_id,
505		     QM_RL_CRD_REG_SIGN_BIT);
506	STORE_RT_REG(p_hwfn, QM_REG_RLPFUPPERBOUND_RT_OFFSET + pf_id,
507		     QM_RL_UPPER_BOUND | QM_RL_CRD_REG_SIGN_BIT);
 
 
 
508	STORE_RT_REG(p_hwfn, QM_REG_RLPFINCVAL_RT_OFFSET + pf_id, inc_val);
 
509	return 0;
510}
511
512/* Prepare VPORT WFQ runtime init values for the specified VPORTs.
513 * Return -1 on error.
514 */
515static int qed_vp_wfq_rt_init(struct qed_hwfn *p_hwfn,
516			      u8 num_vports,
517			      struct init_qm_vport_params *vport_params)
518{
 
519	u32 inc_val;
520	u8 tc, i;
521
522	/* go over all PF VPORTs */
523	for (i = 0; i < num_vports; i++) {
524
525		if (!vport_params[i].vport_wfq)
526			continue;
527
528		inc_val = QM_WFQ_INC_VAL(vport_params[i].vport_wfq);
529		if (inc_val > QM_WFQ_MAX_INC_VAL) {
530			DP_NOTICE(p_hwfn,
531				  "Invalid VPORT WFQ weight configuration");
532			return -1;
533		}
534
535		/* each VPORT can have several VPORT PQ IDs for
536		 * different TCs
537		 */
538		for (tc = 0; tc < NUM_OF_TCS; tc++) {
539			u16 vport_pq_id = vport_params[i].first_tx_pq_id[tc];
540
541			if (vport_pq_id != QM_INVALID_PQ_ID) {
542				STORE_RT_REG(p_hwfn,
543					     QM_REG_WFQVPCRD_RT_OFFSET +
544					     vport_pq_id,
545					     QM_WFQ_CRD_REG_SIGN_BIT);
546				STORE_RT_REG(p_hwfn,
547					     QM_REG_WFQVPWEIGHT_RT_OFFSET +
548					     vport_pq_id, inc_val);
549			}
550		}
551	}
552
553	return 0;
554}
555
 
 
 
556static int qed_vport_rl_rt_init(struct qed_hwfn *p_hwfn,
557				u8 start_vport,
558				u8 num_vports,
 
559				struct init_qm_vport_params *vport_params)
560{
561	u8 i, vport_id;
 
 
 
 
 
 
 
562
563	/* go over all PF VPORTs */
564	for (i = 0, vport_id = start_vport; i < num_vports; i++, vport_id++) {
565		u32 inc_val = QM_RL_INC_VAL(vport_params[i].vport_rl);
566
567		if (inc_val > QM_RL_MAX_INC_VAL) {
 
568			DP_NOTICE(p_hwfn,
569				  "Invalid VPORT rate-limit configuration");
570			return -1;
571		}
572
573		STORE_RT_REG(p_hwfn,
574			     QM_REG_RLGLBLCRD_RT_OFFSET + vport_id,
575			     QM_RL_CRD_REG_SIGN_BIT);
576		STORE_RT_REG(p_hwfn,
577			     QM_REG_RLGLBLUPPERBOUND_RT_OFFSET + vport_id,
578			     QM_RL_UPPER_BOUND | QM_RL_CRD_REG_SIGN_BIT);
579		STORE_RT_REG(p_hwfn,
580			     QM_REG_RLGLBLINCVAL_RT_OFFSET + vport_id,
581			     inc_val);
582	}
583
584	return 0;
585}
586
587static bool qed_poll_on_qm_cmd_ready(struct qed_hwfn *p_hwfn,
588				     struct qed_ptt *p_ptt)
589{
590	u32 reg_val, i;
591
592	for (i = 0, reg_val = 0; i < QM_STOP_CMD_MAX_POLL_COUNT && reg_val == 0;
593	     i++) {
594		udelay(QM_STOP_CMD_POLL_PERIOD_US);
595		reg_val = qed_rd(p_hwfn, p_ptt, QM_REG_SDMCMDREADY);
596	}
597
598	/* check if timeout while waiting for SDM command ready */
599	if (i == QM_STOP_CMD_MAX_POLL_COUNT) {
600		DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
601			   "Timeout when waiting for QM SDM command ready signal\n");
602		return false;
603	}
604
605	return true;
606}
607
608static bool qed_send_qm_cmd(struct qed_hwfn *p_hwfn,
609			    struct qed_ptt *p_ptt,
610			    u32 cmd_addr,
611			    u32 cmd_data_lsb,
612			    u32 cmd_data_msb)
613{
614	if (!qed_poll_on_qm_cmd_ready(p_hwfn, p_ptt))
615		return false;
616
617	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDADDR, cmd_addr);
618	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDDATALSB, cmd_data_lsb);
619	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDDATAMSB, cmd_data_msb);
620	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDGO, 1);
621	qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDGO, 0);
622
623	return qed_poll_on_qm_cmd_ready(p_hwfn, p_ptt);
624}
625
626/******************** INTERFACE IMPLEMENTATION *********************/
627u32 qed_qm_pf_mem_size(u8 pf_id,
628		       u32 num_pf_cids,
629		       u32 num_vf_cids,
630		       u32 num_tids,
631		       u16 num_pf_pqs,
632		       u16 num_vf_pqs)
633{
634	return QM_PQ_MEM_4KB(num_pf_cids) * num_pf_pqs +
635	       QM_PQ_MEM_4KB(num_vf_cids) * num_vf_pqs +
636	       QM_PQ_MEM_4KB(num_pf_cids + num_tids) * QM_OTHER_PQS_PER_PF;
637}
638
639int qed_qm_common_rt_init(
640	struct qed_hwfn *p_hwfn,
641	struct qed_qm_common_rt_init_params *p_params)
642{
643	/* init AFullOprtnstcCrdMask */
644	u32 mask = (QM_OPPOR_LINE_VOQ_DEF <<
645		    QM_RF_OPPORTUNISTIC_MASK_LINEVOQ_SHIFT) |
646		   (QM_BYTE_CRD_EN << QM_RF_OPPORTUNISTIC_MASK_BYTEVOQ_SHIFT) |
647		   (p_params->pf_wfq_en <<
648		    QM_RF_OPPORTUNISTIC_MASK_PFWFQ_SHIFT) |
649		   (p_params->vport_wfq_en <<
650		    QM_RF_OPPORTUNISTIC_MASK_VPWFQ_SHIFT) |
651		   (p_params->pf_rl_en <<
652		    QM_RF_OPPORTUNISTIC_MASK_PFRL_SHIFT) |
653		   (p_params->vport_rl_en <<
654		    QM_RF_OPPORTUNISTIC_MASK_VPQCNRL_SHIFT) |
655		   (QM_OPPOR_FW_STOP_DEF <<
656		    QM_RF_OPPORTUNISTIC_MASK_FWPAUSE_SHIFT) |
657		   (QM_OPPOR_PQ_EMPTY_DEF <<
658		    QM_RF_OPPORTUNISTIC_MASK_QUEUEEMPTY_SHIFT);
659
660	STORE_RT_REG(p_hwfn, QM_REG_AFULLOPRTNSTCCRDMASK_RT_OFFSET, mask);
 
 
661	qed_enable_pf_rl(p_hwfn, p_params->pf_rl_en);
 
 
662	qed_enable_pf_wfq(p_hwfn, p_params->pf_wfq_en);
 
 
663	qed_enable_vport_rl(p_hwfn, p_params->vport_rl_en);
 
 
664	qed_enable_vport_wfq(p_hwfn, p_params->vport_wfq_en);
 
 
665	qed_cmdq_lines_rt_init(p_hwfn,
666			       p_params->max_ports_per_engine,
667			       p_params->max_phys_tcs_per_port,
668			       p_params->port_params);
 
 
669	qed_btb_blocks_rt_init(p_hwfn,
670			       p_params->max_ports_per_engine,
671			       p_params->max_phys_tcs_per_port,
672			       p_params->port_params);
 
673	return 0;
674}
675
676int qed_qm_pf_rt_init(struct qed_hwfn *p_hwfn,
677		      struct qed_ptt *p_ptt,
678		      struct qed_qm_pf_rt_init_params *p_params)
679{
680	struct init_qm_vport_params *vport_params = p_params->vport_params;
681	u32 other_mem_size_4kb = QM_PQ_MEM_4KB(p_params->num_pf_cids +
682					       p_params->num_tids) *
683				 QM_OTHER_PQS_PER_PF;
684	u8 tc, i;
685
686	/* clear first Tx PQ ID array for each VPORT */
687	for (i = 0; i < p_params->num_vports; i++)
688		for (tc = 0; tc < NUM_OF_TCS; tc++)
689			vport_params[i].first_tx_pq_id[tc] = QM_INVALID_PQ_ID;
690
691	/* map Other PQs (if any) */
692	qed_other_pq_map_rt_init(p_hwfn, p_params->port_id, p_params->pf_id,
693				 p_params->num_pf_cids, p_params->num_tids, 0);
 
 
694
695	/* map Tx PQs */
696	qed_tx_pq_map_rt_init(p_hwfn, p_ptt, p_params, other_mem_size_4kb);
697
 
698	if (p_params->pf_wfq)
699		if (qed_pf_wfq_rt_init(p_hwfn, p_params))
700			return -1;
701
 
702	if (qed_pf_rl_rt_init(p_hwfn, p_params->pf_id, p_params->pf_rl))
703		return -1;
704
 
705	if (qed_vp_wfq_rt_init(p_hwfn, p_params->num_vports, vport_params))
706		return -1;
707
 
708	if (qed_vport_rl_rt_init(p_hwfn, p_params->start_vport,
709				 p_params->num_vports, vport_params))
 
 
 
 
 
 
 
 
 
 
 
 
 
710		return -1;
 
 
 
711
712	return 0;
713}
714
715int qed_init_pf_rl(struct qed_hwfn *p_hwfn,
716		   struct qed_ptt *p_ptt,
717		   u8 pf_id,
718		   u32 pf_rl)
719{
720	u32 inc_val = QM_RL_INC_VAL(pf_rl);
721
722	if (inc_val > QM_RL_MAX_INC_VAL) {
723		DP_NOTICE(p_hwfn, "Invalid PF rate limit configuration");
724		return -1;
725	}
726
727	qed_wr(p_hwfn, p_ptt,
728	       QM_REG_RLPFCRD + pf_id * 4,
729	       QM_RL_CRD_REG_SIGN_BIT);
730	qed_wr(p_hwfn, p_ptt, QM_REG_RLPFINCVAL + pf_id * 4, inc_val);
731
732	return 0;
733}
734
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
735int qed_init_vport_rl(struct qed_hwfn *p_hwfn,
736		      struct qed_ptt *p_ptt,
737		      u8 vport_id,
738		      u32 vport_rl)
739{
740	u32 inc_val = QM_RL_INC_VAL(vport_rl);
 
 
 
 
 
 
741
742	if (inc_val > QM_RL_MAX_INC_VAL) {
743		DP_NOTICE(p_hwfn, "Invalid VPORT rate-limit configuration");
 
744		return -1;
745	}
746
747	qed_wr(p_hwfn, p_ptt,
748	       QM_REG_RLGLBLCRD + vport_id * 4,
749	       QM_RL_CRD_REG_SIGN_BIT);
750	qed_wr(p_hwfn, p_ptt, QM_REG_RLGLBLINCVAL + vport_id * 4, inc_val);
751
752	return 0;
753}
754
755bool qed_send_qm_stop_cmd(struct qed_hwfn *p_hwfn,
756			  struct qed_ptt *p_ptt,
757			  bool is_release_cmd,
758			  bool is_tx_pq,
759			  u16 start_pq,
760			  u16 num_pqs)
761{
762	u32 cmd_arr[QM_CMD_STRUCT_SIZE(QM_STOP_CMD)] = { 0 };
763	u32 pq_mask = 0, last_pq = start_pq + num_pqs - 1, pq_id;
 
 
764
765	/* set command's PQ type */
766	QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD, PQ_TYPE, is_tx_pq ? 0 : 1);
767
 
768	for (pq_id = start_pq; pq_id <= last_pq; pq_id++) {
769		/* set PQ bit in mask (stop command only) */
770		if (!is_release_cmd)
771			pq_mask |= (1 << (pq_id % QM_STOP_PQ_MASK_WIDTH));
772
773		/* if last PQ or end of PQ mask, write command */
774		if ((pq_id == last_pq) ||
775		    (pq_id % QM_STOP_PQ_MASK_WIDTH ==
776		     (QM_STOP_PQ_MASK_WIDTH - 1))) {
777			QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD,
778					 PAUSE_MASK, pq_mask);
779			QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD,
 
780					 GROUP_ID,
781					 pq_id / QM_STOP_PQ_MASK_WIDTH);
782			if (!qed_send_qm_cmd(p_hwfn, p_ptt, QM_STOP_CMD_ADDR,
783					     cmd_arr[0], cmd_arr[1]))
784				return false;
785			pq_mask = 0;
786		}
787	}
788
789	return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
790}