1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, v.1, (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://opensource.org/licenses/CDDL-1.0. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2014-2017 Cavium, Inc. 24 * The contents of this file are subject to the terms of the Common Development 25 * and Distribution License, v.1, (the "License"). 26 27 * You may not use this file except in compliance with the License. 28 29 * You can obtain a copy of the License at available 30 * at http://opensource.org/licenses/CDDL-1.0 31 32 * See the License for the specific language governing permissions and 33 * limitations under the License. 34 */ 35 36 #include "bcm_osal.h" 37 #include "ecore_hw.h" 38 #include "ecore_init_ops.h" 39 #include "reg_addr.h" 40 #include "ecore_rt_defs.h" 41 #include "ecore_hsi_common.h" 42 #include "ecore_hsi_init_func.h" 43 #include "ecore_hsi_eth.h" 44 #include "ecore_hsi_init_tool.h" 45 #include "ecore_iro.h" 46 #include "ecore_init_fw_funcs.h" 47 48 #define CDU_VALIDATION_DEFAULT_CFG 61 49 50 static u16 con_region_offsets[3][E4_NUM_OF_CONNECTION_TYPES] = { 51 { 400, 336, 352, 304, 304, 384, 416, 352}, /* region 3 offsets */ 52 { 528, 496, 416, 448, 448, 512, 544, 480}, /* region 4 offsets */ 53 { 608, 544, 496, 512, 576, 592, 624, 560} /* region 5 offsets */ 54 }; 55 static u16 task_region_offsets[1][E4_NUM_OF_CONNECTION_TYPES] = { 56 { 240, 240, 112, 0, 0, 0, 0, 96} /* region 1 offsets */ 57 }; 58 59 /* General constants */ 60 #define QM_PQ_MEM_4KB(pq_size) (pq_size ? DIV_ROUND_UP((pq_size + 1) * QM_PQ_ELEMENT_SIZE, 0x1000) : 0) 61 #define QM_PQ_SIZE_256B(pq_size) (pq_size ? DIV_ROUND_UP(pq_size, 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_SHIFT 5 81 82 /* 0x9000 = 4*9*1024 */ 83 #define QM_WFQ_INC_VAL(weight) ((weight) * 0x9000) 84 85 /* 0.7 * upper bound (62500000) */ 86 #define QM_WFQ_MAX_INC_VAL 43750000 87 88 /* RL constants: */ 89 90 /* Upper bound is set to 10 * burst size of 1ms in 50Gbps */ 91 #define QM_RL_UPPER_BOUND 62500000 92 93 /* Period in us */ 94 #define QM_RL_PERIOD 5 95 96 /* Period in 25MHz cycles */ 97 #define QM_RL_PERIOD_CLK_25M (25 * QM_RL_PERIOD) 98 99 /* 0.7 * upper bound (62500000) */ 100 #define QM_RL_MAX_INC_VAL 43750000 101 102 /* RL increment value - rate is specified in mbps. the factor of 1.01 was 103 * added after seeing only 99% factor reached in a 25Gbps port with DPDK RFC 104 * 2544 test. In this scenario the PF RL was reducing the line rate to 99% 105 * although the credit increment value was the correct one and FW calculated 106 * correct packet sizes. The reason for the inaccuracy of the RL is unknown at 107 * this point. 108 */ 109 #define QM_RL_INC_VAL(rate) OSAL_MAX_T(u32, (u32)(((rate ? rate : 1000000) * QM_RL_PERIOD * 101) / (8 * 100)), 1) 110 111 /* AFullOprtnstcCrdMask constants */ 112 #define QM_OPPOR_LINE_VOQ_DEF 1 113 #define QM_OPPOR_FW_STOP_DEF 0 114 #define QM_OPPOR_PQ_EMPTY_DEF 1 115 116 /* Command Queue constants: */ 117 118 /* Pure LB CmdQ lines (+spare) */ 119 #define PBF_CMDQ_PURE_LB_LINES 150 120 121 #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)) 122 123 #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)) 124 125 #define QM_VOQ_LINE_CRD(pbf_cmd_lines) ((((pbf_cmd_lines) - 4) * 2) | QM_LINE_CRD_REG_SIGN_BIT) 126 127 /* BTB: blocks constants (block size = 256B) */ 128 129 /* 256B blocks in 9700B packet */ 130 #define BTB_JUMBO_PKT_BLOCKS 38 131 132 /* Headroom per-port */ 133 #define BTB_HEADROOM_BLOCKS BTB_JUMBO_PKT_BLOCKS 134 #define BTB_PURE_LB_FACTOR 10 135 136 /* Factored (hence really 0.7) */ 137 #define BTB_PURE_LB_RATIO 7 138 139 /* QM stop command constants */ 140 #define QM_STOP_PQ_MASK_WIDTH 32 141 #define QM_STOP_CMD_ADDR 2 142 #define QM_STOP_CMD_STRUCT_SIZE 2 143 #define QM_STOP_CMD_PAUSE_MASK_OFFSET 0 144 #define QM_STOP_CMD_PAUSE_MASK_SHIFT 0 145 #define QM_STOP_CMD_PAUSE_MASK_MASK UINT_MAX 146 #define QM_STOP_CMD_GROUP_ID_OFFSET 1 147 #define QM_STOP_CMD_GROUP_ID_SHIFT 16 148 #define QM_STOP_CMD_GROUP_ID_MASK 15 149 #define QM_STOP_CMD_PQ_TYPE_OFFSET 1 150 #define QM_STOP_CMD_PQ_TYPE_SHIFT 24 151 #define QM_STOP_CMD_PQ_TYPE_MASK 1 152 #define QM_STOP_CMD_MAX_POLL_COUNT 100 153 #define QM_STOP_CMD_POLL_PERIOD_US 500 154 155 /* QM command macros */ 156 #define QM_CMD_STRUCT_SIZE(cmd) cmd##_STRUCT_SIZE 157 #define QM_CMD_SET_FIELD(var, cmd, field, value) SET_FIELD(var[cmd##_##field##_OFFSET], cmd##_##field, value) 158 159 /* QM: VOQ macros */ 160 #define PHYS_VOQ(port, tc, max_phys_tcs_per_port) ((port) * (max_phys_tcs_per_port) + (tc)) 161 #define LB_VOQ(port) (MAX_PHYS_VOQS + (port)) 162 #define VOQ(port, tc, max_phys_tcs_per_port) ((tc) < LB_TC ? PHYS_VOQ(port, tc, max_phys_tcs_per_port) : LB_VOQ(port)) 163 164 165 /******************** INTERNAL IMPLEMENTATION *********************/ 166 167 /* Prepare PF RL enable/disable runtime init values */ 168 static void ecore_enable_pf_rl(struct ecore_hwfn *p_hwfn, 169 bool pf_rl_en) 170 { 171 STORE_RT_REG(p_hwfn, QM_REG_RLPFENABLE_RT_OFFSET, pf_rl_en ? 1 : 0); 172 if (pf_rl_en) { 173 174 /* Enable RLs for all VOQs */ 175 STORE_RT_REG(p_hwfn, QM_REG_RLPFVOQENABLE_RT_OFFSET, (1 << MAX_NUM_VOQS) - 1); 176 177 /* Write RL period */ 178 STORE_RT_REG(p_hwfn, QM_REG_RLPFPERIOD_RT_OFFSET, QM_RL_PERIOD_CLK_25M); 179 STORE_RT_REG(p_hwfn, QM_REG_RLPFPERIODTIMER_RT_OFFSET, QM_RL_PERIOD_CLK_25M); 180 181 /* Set credit threshold for QM bypass flow */ 182 if (QM_BYPASS_EN) 183 STORE_RT_REG(p_hwfn, QM_REG_AFULLQMBYPTHRPFRL_RT_OFFSET, QM_RL_UPPER_BOUND); 184 } 185 } 186 187 /* Prepare PF WFQ enable/disable runtime init values */ 188 static void ecore_enable_pf_wfq(struct ecore_hwfn *p_hwfn, 189 bool pf_wfq_en) 190 { 191 STORE_RT_REG(p_hwfn, QM_REG_WFQPFENABLE_RT_OFFSET, pf_wfq_en ? 1 : 0); 192 193 /* Set credit threshold for QM bypass flow */ 194 if (pf_wfq_en && QM_BYPASS_EN) 195 STORE_RT_REG(p_hwfn, QM_REG_AFULLQMBYPTHRPFWFQ_RT_OFFSET, QM_WFQ_UPPER_BOUND); 196 } 197 198 /* Prepare VPORT RL enable/disable runtime init values */ 199 static void ecore_enable_vport_rl(struct ecore_hwfn *p_hwfn, 200 bool vport_rl_en) 201 { 202 STORE_RT_REG(p_hwfn, QM_REG_RLGLBLENABLE_RT_OFFSET, vport_rl_en ? 1 : 0); 203 if (vport_rl_en) { 204 205 /* Write RL period (use timer 0 only) */ 206 STORE_RT_REG(p_hwfn, QM_REG_RLGLBLPERIOD_0_RT_OFFSET, QM_RL_PERIOD_CLK_25M); 207 STORE_RT_REG(p_hwfn, QM_REG_RLGLBLPERIODTIMER_0_RT_OFFSET, QM_RL_PERIOD_CLK_25M); 208 209 /* Set credit threshold for QM bypass flow */ 210 if (QM_BYPASS_EN) 211 STORE_RT_REG(p_hwfn, QM_REG_AFULLQMBYPTHRGLBLRL_RT_OFFSET, QM_RL_UPPER_BOUND); 212 } 213 } 214 215 /* Prepare VPORT WFQ enable/disable runtime init values */ 216 static void ecore_enable_vport_wfq(struct ecore_hwfn *p_hwfn, 217 bool vport_wfq_en) 218 { 219 STORE_RT_REG(p_hwfn, QM_REG_WFQVPENABLE_RT_OFFSET, vport_wfq_en ? 1 : 0); 220 221 /* Set credit threshold for QM bypass flow */ 222 if (vport_wfq_en && QM_BYPASS_EN) 223 STORE_RT_REG(p_hwfn, QM_REG_AFULLQMBYPTHRVPWFQ_RT_OFFSET, QM_WFQ_UPPER_BOUND); 224 } 225 226 /* Prepare runtime init values to allocate PBF command queue lines for 227 * the specified VOQ. 228 */ 229 static void ecore_cmdq_lines_voq_rt_init(struct ecore_hwfn *p_hwfn, 230 u8 voq, 231 u16 cmdq_lines) 232 { 233 u32 qm_line_crd; 234 235 qm_line_crd = QM_VOQ_LINE_CRD(cmdq_lines); 236 237 OVERWRITE_RT_REG(p_hwfn, PBF_CMDQ_LINES_RT_OFFSET(voq), (u32)cmdq_lines); 238 STORE_RT_REG(p_hwfn, QM_REG_VOQCRDLINE_RT_OFFSET + voq, qm_line_crd); 239 STORE_RT_REG(p_hwfn, QM_REG_VOQINITCRDLINE_RT_OFFSET + voq, qm_line_crd); 240 } 241 242 /* Prepare runtime init values to allocate PBF command queue lines. */ 243 static void ecore_cmdq_lines_rt_init(struct ecore_hwfn *p_hwfn, 244 u8 max_ports_per_engine, 245 u8 max_phys_tcs_per_port, 246 struct init_qm_port_params port_params[MAX_NUM_PORTS]) 247 { 248 u8 tc, voq, port_id, num_tcs_in_port; 249 250 /* Clear PBF lines for all VOQs */ 251 for (voq = 0; voq < MAX_NUM_VOQS; voq++) 252 STORE_RT_REG(p_hwfn, PBF_CMDQ_LINES_RT_OFFSET(voq), 0); 253 254 for (port_id = 0; port_id < max_ports_per_engine; port_id++) { 255 u16 phys_lines, phys_lines_per_tc; 256 257 if (!port_params[port_id].active) 258 continue; 259 260 /* Find #lines to divide between the active physical TCs */ 261 phys_lines = port_params[port_id].num_pbf_cmd_lines - PBF_CMDQ_PURE_LB_LINES; 262 263 /* Find #lines per active physical TC */ 264 num_tcs_in_port = 0; 265 for (tc = 0; tc < NUM_OF_PHYS_TCS; tc++) 266 if (((port_params[port_id].active_phys_tcs >> tc) & 0x1) == 1) 267 num_tcs_in_port++; 268 phys_lines_per_tc = phys_lines / num_tcs_in_port; 269 270 /* Init registers per active TC */ 271 for (tc = 0; tc < NUM_OF_PHYS_TCS; tc++) { 272 if (((port_params[port_id].active_phys_tcs >> tc) & 0x1) == 1) { 273 voq = PHYS_VOQ(port_id, tc, max_phys_tcs_per_port); 274 ecore_cmdq_lines_voq_rt_init(p_hwfn, voq, phys_lines_per_tc); 275 } 276 } 277 278 /* Init registers for pure LB TC */ 279 ecore_cmdq_lines_voq_rt_init(p_hwfn, LB_VOQ(port_id), PBF_CMDQ_PURE_LB_LINES); 280 } 281 } 282 283 /* Prepare runtime init values to allocate guaranteed BTB blocks for the 284 * specified port. The guaranteed BTB space is divided between the TCs as 285 * follows (shared space Is currently not used): 286 * 1. Parameters: 287 * B - BTB blocks for this port 288 * C - Number of physical TCs for this port 289 * 2. Calculation: 290 * a. 38 blocks (9700B jumbo frame) are allocated for global per port 291 * headroom. 292 * b. B = B - 38 (remainder after global headroom allocation). 293 * c. MAX(38,B/(C+0.7)) blocks are allocated for the pure LB VOQ. 294 * d. B = B � MAX(38, B/(C+0.7)) (remainder after pure LB allocation). 295 * e. B/C blocks are allocated for each physical TC. 296 * Assumptions: 297 * - MTU is up to 9700 bytes (38 blocks) 298 * - All TCs are considered symmetrical (same rate and packet size) 299 * - No optimization for lossy TC (all are considered lossless). Shared space 300 * is not enabled and allocated for each TC. 301 */ 302 static void ecore_btb_blocks_rt_init(struct ecore_hwfn *p_hwfn, 303 u8 max_ports_per_engine, 304 u8 max_phys_tcs_per_port, 305 struct init_qm_port_params port_params[MAX_NUM_PORTS]) 306 { 307 u32 usable_blocks, pure_lb_blocks, phys_blocks; 308 u8 tc, voq, port_id, num_tcs_in_port; 309 310 for (port_id = 0; port_id < max_ports_per_engine; port_id++) { 311 if (!port_params[port_id].active) 312 continue; 313 314 /* Subtract headroom blocks */ 315 usable_blocks = port_params[port_id].num_btb_blocks - BTB_HEADROOM_BLOCKS; 316 317 /* Find blocks per physical TC. use factor to avoid floating 318 * arithmethic. 319 */ 320 num_tcs_in_port = 0; 321 for (tc = 0; tc < NUM_OF_PHYS_TCS; tc++) 322 if (((port_params[port_id].active_phys_tcs >> tc) & 0x1) == 1) 323 num_tcs_in_port++; 324 325 pure_lb_blocks = (usable_blocks * BTB_PURE_LB_FACTOR) / (num_tcs_in_port * BTB_PURE_LB_FACTOR + BTB_PURE_LB_RATIO); 326 pure_lb_blocks = OSAL_MAX_T(u32, BTB_JUMBO_PKT_BLOCKS, pure_lb_blocks / BTB_PURE_LB_FACTOR); 327 phys_blocks = (usable_blocks - pure_lb_blocks) / num_tcs_in_port; 328 329 /* Init physical TCs */ 330 for (tc = 0; tc < NUM_OF_PHYS_TCS; tc++) { 331 if (((port_params[port_id].active_phys_tcs >> tc) & 0x1) == 1) { 332 voq = PHYS_VOQ(port_id, tc, max_phys_tcs_per_port); 333 STORE_RT_REG(p_hwfn, PBF_BTB_GUARANTEED_RT_OFFSET(voq), phys_blocks); 334 } 335 } 336 337 /* Init pure LB TC */ 338 STORE_RT_REG(p_hwfn, PBF_BTB_GUARANTEED_RT_OFFSET(LB_VOQ(port_id)), pure_lb_blocks); 339 } 340 } 341 342 /* Prepare Tx PQ mapping runtime init values for the specified PF */ 343 static void ecore_tx_pq_map_rt_init(struct ecore_hwfn *p_hwfn, 344 struct ecore_ptt *p_ptt, 345 u8 port_id, 346 u8 pf_id, 347 u8 max_phys_tcs_per_port, 348 bool is_first_pf, 349 u32 num_pf_cids, 350 u32 num_vf_cids, 351 u16 start_pq, 352 u16 num_pf_pqs, 353 u16 num_vf_pqs, 354 u8 start_vport, 355 u32 base_mem_addr_4kb, 356 struct init_qm_pq_params *pq_params, 357 struct init_qm_vport_params *vport_params) 358 { 359 /* A bit per Tx PQ indicating if the PQ is associated with a VF */ 360 u32 tx_pq_vf_mask[MAX_QM_TX_QUEUES / QM_PF_QUEUE_GROUP_SIZE] = { 0 }; 361 u32 num_tx_pq_vf_masks = MAX_QM_TX_QUEUES / QM_PF_QUEUE_GROUP_SIZE; 362 u16 num_pqs, first_pq_group, last_pq_group, i, pq_id, pq_group; 363 u32 pq_mem_4kb, vport_pq_mem_4kb, mem_addr_4kb; 364 365 num_pqs = num_pf_pqs + num_vf_pqs; 366 367 first_pq_group = start_pq / QM_PF_QUEUE_GROUP_SIZE; 368 last_pq_group = (start_pq + num_pqs - 1) / QM_PF_QUEUE_GROUP_SIZE; 369 370 pq_mem_4kb = QM_PQ_MEM_4KB(num_pf_cids); 371 vport_pq_mem_4kb = QM_PQ_MEM_4KB(num_vf_cids); 372 mem_addr_4kb = base_mem_addr_4kb; 373 374 /* Set mapping from PQ group to PF */ 375 for (pq_group = first_pq_group; pq_group <= last_pq_group; pq_group++) 376 STORE_RT_REG(p_hwfn, QM_REG_PQTX2PF_0_RT_OFFSET + pq_group, (u32)(pf_id)); 377 378 /* Set PQ sizes */ 379 STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_0_RT_OFFSET, QM_PQ_SIZE_256B(num_pf_cids)); 380 STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_1_RT_OFFSET, QM_PQ_SIZE_256B(num_vf_cids)); 381 382 /* Go over all Tx PQs */ 383 for (i = 0, pq_id = start_pq; i < num_pqs; i++, pq_id++) { 384 u32 max_qm_global_rls = MAX_QM_GLOBAL_RLS; 385 struct qm_rf_pq_map tx_pq_map; 386 bool is_vf_pq, rl_valid; 387 u8 voq, vport_id_in_pf; 388 u16 first_tx_pq_id; 389 390 voq = VOQ(port_id, pq_params[i].tc_id, max_phys_tcs_per_port); 391 is_vf_pq = (i >= num_pf_pqs); 392 rl_valid = pq_params[i].rl_valid && pq_params[i].vport_id < max_qm_global_rls; 393 394 /* Update first Tx PQ of VPORT/TC */ 395 vport_id_in_pf = pq_params[i].vport_id - start_vport; 396 first_tx_pq_id = vport_params[vport_id_in_pf].first_tx_pq_id[pq_params[i].tc_id]; 397 if (first_tx_pq_id == QM_INVALID_PQ_ID) { 398 399 /* Create new VP PQ */ 400 vport_params[vport_id_in_pf].first_tx_pq_id[pq_params[i].tc_id] = pq_id; 401 first_tx_pq_id = pq_id; 402 403 /* Map VP PQ to VOQ and PF */ 404 STORE_RT_REG(p_hwfn, QM_REG_WFQVPMAP_RT_OFFSET + first_tx_pq_id, (voq << QM_WFQ_VP_PQ_VOQ_SHIFT) | (pf_id << QM_WFQ_VP_PQ_PF_SHIFT)); 405 } 406 407 /* Check RL ID */ 408 if (pq_params[i].rl_valid && pq_params[i].vport_id >= max_qm_global_rls) 409 DP_NOTICE(p_hwfn, true, "Invalid VPORT ID for rate limiter configuration\n"); 410 411 /* Fill PQ map entry */ 412 OSAL_MEMSET(&tx_pq_map, 0, sizeof(tx_pq_map)); 413 SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_PQ_VALID, 1); 414 SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_RL_VALID, rl_valid ? 1 : 0); 415 SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_VP_PQ_ID, first_tx_pq_id); 416 SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_RL_ID, rl_valid ? pq_params[i].vport_id : 0); 417 SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_VOQ, voq); 418 SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_WRR_WEIGHT_GROUP, pq_params[i].wrr_group); 419 420 /* Write PQ map entry to CAM */ 421 STORE_RT_REG(p_hwfn, QM_REG_TXPQMAP_RT_OFFSET + pq_id, *((u32*)&tx_pq_map)); 422 423 /* Set base address */ 424 STORE_RT_REG(p_hwfn, QM_REG_BASEADDRTXPQ_RT_OFFSET + pq_id, mem_addr_4kb); 425 426 /* If VF PQ, add indication to PQ VF mask */ 427 if (is_vf_pq) { 428 tx_pq_vf_mask[pq_id / QM_PF_QUEUE_GROUP_SIZE] |= (1 << (pq_id % QM_PF_QUEUE_GROUP_SIZE)); 429 mem_addr_4kb += vport_pq_mem_4kb; 430 } 431 else { 432 mem_addr_4kb += pq_mem_4kb; 433 } 434 } 435 436 /* Store Tx PQ VF mask to size select register */ 437 for (i = 0; i < num_tx_pq_vf_masks; i++) 438 if (tx_pq_vf_mask[i]) 439 STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZETXSEL_0_RT_OFFSET + i, tx_pq_vf_mask[i]); 440 } 441 442 /* Prepare Other PQ mapping runtime init values for the specified PF */ 443 static void ecore_other_pq_map_rt_init(struct ecore_hwfn *p_hwfn, 444 u8 port_id, 445 u8 pf_id, 446 u32 num_pf_cids, 447 u32 num_tids, 448 u32 base_mem_addr_4kb) 449 { 450 u32 pq_size, pq_mem_4kb, mem_addr_4kb; 451 u16 i, pq_id, pq_group; 452 453 /* A single other PQ group is used in each PF, where PQ group i is used 454 * in PF i. 455 */ 456 pq_group = pf_id; 457 pq_size = num_pf_cids + num_tids; 458 pq_mem_4kb = QM_PQ_MEM_4KB(pq_size); 459 mem_addr_4kb = base_mem_addr_4kb; 460 461 /* Map PQ group to PF */ 462 STORE_RT_REG(p_hwfn, QM_REG_PQOTHER2PF_0_RT_OFFSET + pq_group, (u32)(pf_id)); 463 464 /* Set PQ sizes */ 465 STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_2_RT_OFFSET, QM_PQ_SIZE_256B(pq_size)); 466 467 /* Set base address */ 468 for (i = 0, pq_id = pf_id * QM_PF_QUEUE_GROUP_SIZE; i < QM_OTHER_PQS_PER_PF; i++, pq_id++) { 469 STORE_RT_REG(p_hwfn, QM_REG_BASEADDROTHERPQ_RT_OFFSET + pq_id, mem_addr_4kb); 470 mem_addr_4kb += pq_mem_4kb; 471 } 472 } 473 474 /* Prepare PF WFQ runtime init values for the specified PF. 475 * Return -1 on error. 476 */ 477 static int ecore_pf_wfq_rt_init(struct ecore_hwfn *p_hwfn, 478 u8 port_id, 479 u8 pf_id, 480 u16 pf_wfq, 481 u8 max_phys_tcs_per_port, 482 u16 num_tx_pqs, 483 struct init_qm_pq_params *pq_params) 484 { 485 u32 inc_val, crd_reg_offset; 486 u8 voq; 487 u16 i; 488 489 crd_reg_offset = (pf_id < MAX_NUM_PFS_BB ? QM_REG_WFQPFCRD_RT_OFFSET : QM_REG_WFQPFCRD_MSB_RT_OFFSET) + (pf_id % MAX_NUM_PFS_BB); 490 491 inc_val = QM_WFQ_INC_VAL(pf_wfq); 492 if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) { 493 DP_NOTICE(p_hwfn, true, "Invalid PF WFQ weight configuration\n"); 494 return -1; 495 } 496 497 for(i = 0; i < num_tx_pqs; i++) { 498 voq = VOQ(port_id, pq_params[i].tc_id, max_phys_tcs_per_port); 499 OVERWRITE_RT_REG(p_hwfn, crd_reg_offset + voq * MAX_NUM_PFS_BB, (u32)QM_WFQ_CRD_REG_SIGN_BIT); 500 } 501 502 STORE_RT_REG(p_hwfn, QM_REG_WFQPFUPPERBOUND_RT_OFFSET + pf_id, QM_WFQ_UPPER_BOUND | (u32)QM_WFQ_CRD_REG_SIGN_BIT); 503 STORE_RT_REG(p_hwfn, QM_REG_WFQPFWEIGHT_RT_OFFSET + pf_id, inc_val); 504 505 return 0; 506 } 507 508 /* Prepare PF RL runtime init values for the specified PF. 509 * Return -1 on error. 510 */ 511 static int ecore_pf_rl_rt_init(struct ecore_hwfn *p_hwfn, 512 u8 pf_id, 513 u32 pf_rl) 514 { 515 u32 inc_val; 516 517 inc_val = QM_RL_INC_VAL(pf_rl); 518 if (inc_val > QM_RL_MAX_INC_VAL) { 519 DP_NOTICE(p_hwfn, true, "Invalid PF rate limit configuration\n"); 520 return -1; 521 } 522 523 STORE_RT_REG(p_hwfn, QM_REG_RLPFCRD_RT_OFFSET + pf_id, (u32)QM_RL_CRD_REG_SIGN_BIT); 524 STORE_RT_REG(p_hwfn, QM_REG_RLPFUPPERBOUND_RT_OFFSET + pf_id, QM_RL_UPPER_BOUND | (u32)QM_RL_CRD_REG_SIGN_BIT); 525 STORE_RT_REG(p_hwfn, QM_REG_RLPFINCVAL_RT_OFFSET + pf_id, inc_val); 526 527 return 0; 528 } 529 530 /* Prepare VPORT WFQ runtime init values for the specified VPORTs. 531 * Return -1 on error. 532 */ 533 static int ecore_vp_wfq_rt_init(struct ecore_hwfn *p_hwfn, 534 u8 num_vports, 535 struct init_qm_vport_params *vport_params) 536 { 537 u16 vport_pq_id; 538 u32 inc_val; 539 u8 tc, i; 540 541 /* Go over all PF VPORTs */ 542 for (i = 0; i < num_vports; i++) { 543 if (!vport_params[i].vport_wfq) 544 continue; 545 546 inc_val = QM_WFQ_INC_VAL(vport_params[i].vport_wfq); 547 if (inc_val > QM_WFQ_MAX_INC_VAL) { 548 DP_NOTICE(p_hwfn, true, "Invalid VPORT WFQ weight configuration\n"); 549 return -1; 550 } 551 552 /* Each VPORT can have several VPORT PQ IDs for various TCs */ 553 for (tc = 0; tc < NUM_OF_TCS; tc++) { 554 vport_pq_id = vport_params[i].first_tx_pq_id[tc]; 555 if (vport_pq_id != QM_INVALID_PQ_ID) { 556 STORE_RT_REG(p_hwfn, QM_REG_WFQVPCRD_RT_OFFSET + vport_pq_id, (u32)QM_WFQ_CRD_REG_SIGN_BIT); 557 STORE_RT_REG(p_hwfn, QM_REG_WFQVPWEIGHT_RT_OFFSET + vport_pq_id, inc_val); 558 } 559 } 560 } 561 562 return 0; 563 } 564 565 /* Prepare VPORT RL runtime init values for the specified VPORTs. 566 * Return -1 on error. 567 */ 568 static int ecore_vport_rl_rt_init(struct ecore_hwfn *p_hwfn, 569 u8 start_vport, 570 u8 num_vports, 571 struct init_qm_vport_params *vport_params) 572 { 573 u8 i, vport_id; 574 u32 inc_val; 575 576 if (start_vport + num_vports >= MAX_QM_GLOBAL_RLS) { 577 DP_NOTICE(p_hwfn, true, "Invalid VPORT ID for rate limiter configuration\n"); 578 return -1; 579 } 580 581 /* Go over all PF VPORTs */ 582 for (i = 0, vport_id = start_vport; i < num_vports; i++, vport_id++) { 583 inc_val = QM_RL_INC_VAL(vport_params[i].vport_rl); 584 if (inc_val > QM_RL_MAX_INC_VAL) { 585 DP_NOTICE(p_hwfn, true, "Invalid VPORT rate-limit configuration\n"); 586 return -1; 587 } 588 589 STORE_RT_REG(p_hwfn, QM_REG_RLGLBLCRD_RT_OFFSET + vport_id, (u32)QM_RL_CRD_REG_SIGN_BIT); 590 STORE_RT_REG(p_hwfn, QM_REG_RLGLBLUPPERBOUND_RT_OFFSET + vport_id, QM_RL_UPPER_BOUND | (u32)QM_RL_CRD_REG_SIGN_BIT); 591 STORE_RT_REG(p_hwfn, QM_REG_RLGLBLINCVAL_RT_OFFSET + vport_id, inc_val); 592 } 593 594 return 0; 595 } 596 597 static bool ecore_poll_on_qm_cmd_ready(struct ecore_hwfn *p_hwfn, 598 struct ecore_ptt *p_ptt) 599 { 600 u32 reg_val, i; 601 602 for (i = 0, reg_val = 0; i < QM_STOP_CMD_MAX_POLL_COUNT && !reg_val; i++) { 603 OSAL_UDELAY(QM_STOP_CMD_POLL_PERIOD_US); 604 reg_val = ecore_rd(p_hwfn, p_ptt, QM_REG_SDMCMDREADY); 605 } 606 607 /* Check if timeout while waiting for SDM command ready */ 608 if (i == QM_STOP_CMD_MAX_POLL_COUNT) { 609 DP_VERBOSE(p_hwfn, ECORE_MSG_DEBUG, "Timeout when waiting for QM SDM command ready signal\n"); 610 return false; 611 } 612 613 return true; 614 } 615 616 static bool ecore_send_qm_cmd(struct ecore_hwfn *p_hwfn, 617 struct ecore_ptt *p_ptt, 618 u32 cmd_addr, 619 u32 cmd_data_lsb, 620 u32 cmd_data_msb) 621 { 622 if (!ecore_poll_on_qm_cmd_ready(p_hwfn, p_ptt)) 623 return false; 624 625 ecore_wr(p_hwfn, p_ptt, QM_REG_SDMCMDADDR, cmd_addr); 626 ecore_wr(p_hwfn, p_ptt, QM_REG_SDMCMDDATALSB, cmd_data_lsb); 627 ecore_wr(p_hwfn, p_ptt, QM_REG_SDMCMDDATAMSB, cmd_data_msb); 628 ecore_wr(p_hwfn, p_ptt, QM_REG_SDMCMDGO, 1); 629 ecore_wr(p_hwfn, p_ptt, QM_REG_SDMCMDGO, 0); 630 631 return ecore_poll_on_qm_cmd_ready(p_hwfn, p_ptt); 632 } 633 634 635 /******************** INTERFACE IMPLEMENTATION *********************/ 636 637 u32 ecore_qm_pf_mem_size(u8 pf_id, 638 u32 num_pf_cids, 639 u32 num_vf_cids, 640 u32 num_tids, 641 u16 num_pf_pqs, 642 u16 num_vf_pqs) 643 { 644 return QM_PQ_MEM_4KB(num_pf_cids) * num_pf_pqs + 645 QM_PQ_MEM_4KB(num_vf_cids) * num_vf_pqs + 646 QM_PQ_MEM_4KB(num_pf_cids + num_tids) * QM_OTHER_PQS_PER_PF; 647 } 648 649 int ecore_qm_common_rt_init(struct ecore_hwfn *p_hwfn, 650 u8 max_ports_per_engine, 651 u8 max_phys_tcs_per_port, 652 bool pf_rl_en, 653 bool pf_wfq_en, 654 bool vport_rl_en, 655 bool vport_wfq_en, 656 struct init_qm_port_params port_params[MAX_NUM_PORTS]) 657 { 658 u32 mask; 659 660 /* Init AFullOprtnstcCrdMask */ 661 mask = (QM_OPPOR_LINE_VOQ_DEF << QM_RF_OPPORTUNISTIC_MASK_LINEVOQ_SHIFT) | 662 (QM_BYTE_CRD_EN << QM_RF_OPPORTUNISTIC_MASK_BYTEVOQ_SHIFT) | 663 (pf_wfq_en << QM_RF_OPPORTUNISTIC_MASK_PFWFQ_SHIFT) | 664 (vport_wfq_en << QM_RF_OPPORTUNISTIC_MASK_VPWFQ_SHIFT) | 665 (pf_rl_en << QM_RF_OPPORTUNISTIC_MASK_PFRL_SHIFT) | 666 (vport_rl_en << QM_RF_OPPORTUNISTIC_MASK_VPQCNRL_SHIFT) | 667 (QM_OPPOR_FW_STOP_DEF << QM_RF_OPPORTUNISTIC_MASK_FWPAUSE_SHIFT) | 668 (QM_OPPOR_PQ_EMPTY_DEF << QM_RF_OPPORTUNISTIC_MASK_QUEUEEMPTY_SHIFT); 669 STORE_RT_REG(p_hwfn, QM_REG_AFULLOPRTNSTCCRDMASK_RT_OFFSET, mask); 670 671 /* Enable/disable PF RL */ 672 ecore_enable_pf_rl(p_hwfn, pf_rl_en); 673 674 /* Enable/disable PF WFQ */ 675 ecore_enable_pf_wfq(p_hwfn, pf_wfq_en); 676 677 /* Enable/disable VPORT RL */ 678 ecore_enable_vport_rl(p_hwfn, vport_rl_en); 679 680 /* Enable/disable VPORT WFQ */ 681 ecore_enable_vport_wfq(p_hwfn, vport_wfq_en); 682 683 /* Init PBF CMDQ line credit */ 684 ecore_cmdq_lines_rt_init(p_hwfn, max_ports_per_engine, max_phys_tcs_per_port, port_params); 685 686 /* Init BTB blocks in PBF */ 687 ecore_btb_blocks_rt_init(p_hwfn, max_ports_per_engine, max_phys_tcs_per_port, port_params); 688 689 return 0; 690 } 691 692 int ecore_qm_pf_rt_init(struct ecore_hwfn *p_hwfn, 693 struct ecore_ptt *p_ptt, 694 u8 port_id, 695 u8 pf_id, 696 u8 max_phys_tcs_per_port, 697 bool is_first_pf, 698 u32 num_pf_cids, 699 u32 num_vf_cids, 700 u32 num_tids, 701 u16 start_pq, 702 u16 num_pf_pqs, 703 u16 num_vf_pqs, 704 u8 start_vport, 705 u8 num_vports, 706 u16 pf_wfq, 707 u32 pf_rl, 708 struct init_qm_pq_params *pq_params, 709 struct init_qm_vport_params *vport_params) 710 { 711 u32 other_mem_size_4kb; 712 u8 tc, i; 713 714 other_mem_size_4kb = QM_PQ_MEM_4KB(num_pf_cids + num_tids) * QM_OTHER_PQS_PER_PF; 715 716 /* Clear first Tx PQ ID array for each VPORT */ 717 for(i = 0; i < num_vports; i++) 718 for(tc = 0; tc < NUM_OF_TCS; tc++) 719 vport_params[i].first_tx_pq_id[tc] = QM_INVALID_PQ_ID; 720 721 /* Map Other PQs (if any) */ 722 #if QM_OTHER_PQS_PER_PF > 0 723 ecore_other_pq_map_rt_init(p_hwfn, port_id, pf_id, num_pf_cids, num_tids, 0); 724 #endif 725 726 /* Map Tx PQs */ 727 ecore_tx_pq_map_rt_init(p_hwfn, p_ptt, port_id, pf_id, max_phys_tcs_per_port, is_first_pf, num_pf_cids, num_vf_cids, 728 start_pq, num_pf_pqs, num_vf_pqs, start_vport, other_mem_size_4kb, pq_params, vport_params); 729 730 /* Init PF WFQ */ 731 if (pf_wfq) 732 if (ecore_pf_wfq_rt_init(p_hwfn, port_id, pf_id, pf_wfq, max_phys_tcs_per_port, num_pf_pqs + num_vf_pqs, pq_params)) 733 return -1; 734 735 /* Init PF RL */ 736 if (ecore_pf_rl_rt_init(p_hwfn, pf_id, pf_rl)) 737 return -1; 738 739 /* Set VPORT WFQ */ 740 if (ecore_vp_wfq_rt_init(p_hwfn, num_vports, vport_params)) 741 return -1; 742 743 /* Set VPORT RL */ 744 if (ecore_vport_rl_rt_init(p_hwfn, start_vport, num_vports, vport_params)) 745 return -1; 746 747 return 0; 748 } 749 750 int ecore_init_pf_wfq(struct ecore_hwfn *p_hwfn, 751 struct ecore_ptt *p_ptt, 752 u8 pf_id, 753 u16 pf_wfq) 754 { 755 u32 inc_val; 756 757 inc_val = QM_WFQ_INC_VAL(pf_wfq); 758 if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) { 759 DP_NOTICE(p_hwfn, true, "Invalid PF WFQ weight configuration\n"); 760 return -1; 761 } 762 763 ecore_wr(p_hwfn, p_ptt, QM_REG_WFQPFWEIGHT + pf_id * 4, inc_val); 764 765 return 0; 766 } 767 768 int ecore_init_pf_rl(struct ecore_hwfn *p_hwfn, 769 struct ecore_ptt *p_ptt, 770 u8 pf_id, 771 u32 pf_rl) 772 { 773 u32 inc_val; 774 775 inc_val = QM_RL_INC_VAL(pf_rl); 776 if (inc_val > QM_RL_MAX_INC_VAL) { 777 DP_NOTICE(p_hwfn, true, "Invalid PF rate limit configuration\n"); 778 return -1; 779 } 780 781 ecore_wr(p_hwfn, p_ptt, QM_REG_RLPFCRD + pf_id * 4, (u32)QM_RL_CRD_REG_SIGN_BIT); 782 ecore_wr(p_hwfn, p_ptt, QM_REG_RLPFINCVAL + pf_id * 4, inc_val); 783 784 return 0; 785 } 786 787 int ecore_init_vport_wfq(struct ecore_hwfn *p_hwfn, 788 struct ecore_ptt *p_ptt, 789 u16 first_tx_pq_id[NUM_OF_TCS], 790 u16 vport_wfq) 791 { 792 u16 vport_pq_id; 793 u32 inc_val; 794 u8 tc; 795 796 inc_val = QM_WFQ_INC_VAL(vport_wfq); 797 if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) { 798 DP_NOTICE(p_hwfn, true, "Invalid VPORT WFQ weight configuration\n"); 799 return -1; 800 } 801 802 for (tc = 0; tc < NUM_OF_TCS; tc++) { 803 vport_pq_id = first_tx_pq_id[tc]; 804 if (vport_pq_id != QM_INVALID_PQ_ID) { 805 ecore_wr(p_hwfn, p_ptt, QM_REG_WFQVPWEIGHT + vport_pq_id * 4, inc_val); 806 } 807 } 808 809 return 0; 810 } 811 812 int ecore_init_vport_rl(struct ecore_hwfn *p_hwfn, 813 struct ecore_ptt *p_ptt, 814 u8 vport_id, 815 u32 vport_rl) 816 { 817 u32 inc_val, max_qm_global_rls = MAX_QM_GLOBAL_RLS; 818 819 if (vport_id >= max_qm_global_rls) { 820 DP_NOTICE(p_hwfn, true, "Invalid VPORT ID for rate limiter configuration\n"); 821 return -1; 822 } 823 824 inc_val = QM_RL_INC_VAL(vport_rl); 825 if (inc_val > QM_RL_MAX_INC_VAL) { 826 DP_NOTICE(p_hwfn, true, "Invalid VPORT rate-limit configuration\n"); 827 return -1; 828 } 829 830 ecore_wr(p_hwfn, p_ptt, QM_REG_RLGLBLCRD + vport_id * 4, (u32)QM_RL_CRD_REG_SIGN_BIT); 831 ecore_wr(p_hwfn, p_ptt, QM_REG_RLGLBLINCVAL + vport_id * 4, inc_val); 832 833 return 0; 834 } 835 836 bool ecore_send_qm_stop_cmd(struct ecore_hwfn *p_hwfn, 837 struct ecore_ptt *p_ptt, 838 bool is_release_cmd, 839 bool is_tx_pq, 840 u16 start_pq, 841 u16 num_pqs) 842 { 843 u32 cmd_arr[QM_CMD_STRUCT_SIZE(QM_STOP_CMD)] = {0}; 844 u32 pq_mask = 0, last_pq, pq_id; 845 846 last_pq = start_pq + num_pqs - 1; 847 848 /* Set command's PQ type */ 849 QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD, PQ_TYPE, is_tx_pq ? 0 : 1); 850 851 /* Go over requested PQs */ 852 for (pq_id = start_pq; pq_id <= last_pq; pq_id++) { 853 854 /* Set PQ bit in mask (stop command only) */ 855 if (!is_release_cmd) 856 pq_mask |= (1 << (pq_id % QM_STOP_PQ_MASK_WIDTH)); 857 858 /* If last PQ or end of PQ mask, write command */ 859 if ((pq_id == last_pq) || (pq_id % QM_STOP_PQ_MASK_WIDTH == (QM_STOP_PQ_MASK_WIDTH - 1))) { 860 QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD, PAUSE_MASK, pq_mask); 861 QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD, GROUP_ID, pq_id / QM_STOP_PQ_MASK_WIDTH); 862 if (!ecore_send_qm_cmd(p_hwfn, p_ptt, QM_STOP_CMD_ADDR, cmd_arr[0], cmd_arr[1])) 863 return false; 864 pq_mask = 0; 865 } 866 } 867 868 return true; 869 } 870 871 #ifndef UNUSED_HSI_FUNC 872 873 /* NIG: ETS configuration constants */ 874 #define NIG_TX_ETS_CLIENT_OFFSET 4 875 #define NIG_LB_ETS_CLIENT_OFFSET 1 876 #define NIG_ETS_MIN_WFQ_BYTES 1600 877 878 /* NIG: ETS constants */ 879 #define NIG_ETS_UP_BOUND(weight,mtu) (2 * ((weight) > (mtu) ? (weight) : (mtu))) 880 881 /* NIG: RL constants */ 882 883 /* Byte base type value */ 884 #define NIG_RL_BASE_TYPE 1 885 886 /* Period in us */ 887 #define NIG_RL_PERIOD 1 888 889 /* Period in 25MHz cycles */ 890 #define NIG_RL_PERIOD_CLK_25M (25 * NIG_RL_PERIOD) 891 892 /* Rate in mbps */ 893 #define NIG_RL_INC_VAL(rate) (((rate) * NIG_RL_PERIOD) / 8) 894 895 #define NIG_RL_MAX_VAL(inc_val,mtu) (2 * ((inc_val) > (mtu) ? (inc_val) : (mtu))) 896 897 /* NIG: packet prioritry configuration constants */ 898 #define NIG_PRIORITY_MAP_TC_BITS 4 899 900 901 void ecore_init_nig_ets(struct ecore_hwfn *p_hwfn, 902 struct ecore_ptt *p_ptt, 903 struct init_ets_req* req, 904 bool is_lb) 905 { 906 u32 min_weight, tc_weight_base_addr, tc_weight_addr_diff; 907 u32 tc_bound_base_addr, tc_bound_addr_diff; 908 u8 sp_tc_map = 0, wfq_tc_map = 0; 909 u8 tc, num_tc, tc_client_offset; 910 911 num_tc = is_lb ? NUM_OF_TCS : NUM_OF_PHYS_TCS; 912 tc_client_offset = is_lb ? NIG_LB_ETS_CLIENT_OFFSET : NIG_TX_ETS_CLIENT_OFFSET; 913 min_weight = 0xffffffff; 914 tc_weight_base_addr = is_lb ? NIG_REG_LB_ARB_CREDIT_WEIGHT_0 : NIG_REG_TX_ARB_CREDIT_WEIGHT_0; 915 tc_weight_addr_diff = is_lb ? NIG_REG_LB_ARB_CREDIT_WEIGHT_1 - NIG_REG_LB_ARB_CREDIT_WEIGHT_0 : 916 NIG_REG_TX_ARB_CREDIT_WEIGHT_1 - NIG_REG_TX_ARB_CREDIT_WEIGHT_0; 917 tc_bound_base_addr = is_lb ? NIG_REG_LB_ARB_CREDIT_UPPER_BOUND_0 : NIG_REG_TX_ARB_CREDIT_UPPER_BOUND_0; 918 tc_bound_addr_diff = is_lb ? NIG_REG_LB_ARB_CREDIT_UPPER_BOUND_1 - NIG_REG_LB_ARB_CREDIT_UPPER_BOUND_0 : 919 NIG_REG_TX_ARB_CREDIT_UPPER_BOUND_1 - NIG_REG_TX_ARB_CREDIT_UPPER_BOUND_0; 920 921 for (tc = 0; tc < num_tc; tc++) { 922 struct init_ets_tc_req *tc_req = &req->tc_req[tc]; 923 924 /* Update SP map */ 925 if (tc_req->use_sp) 926 sp_tc_map |= (1 << tc); 927 928 if (!tc_req->use_wfq) 929 continue; 930 931 /* Update WFQ map */ 932 wfq_tc_map |= (1 << tc); 933 934 /* Find minimal weight */ 935 if (tc_req->weight < min_weight) 936 min_weight = tc_req->weight; 937 } 938 939 /* Write SP map */ 940 ecore_wr(p_hwfn, p_ptt, is_lb ? NIG_REG_LB_ARB_CLIENT_IS_STRICT : NIG_REG_TX_ARB_CLIENT_IS_STRICT, (sp_tc_map << tc_client_offset)); 941 942 /* Write WFQ map */ 943 ecore_wr(p_hwfn, p_ptt, is_lb ? NIG_REG_LB_ARB_CLIENT_IS_SUBJECT2WFQ : NIG_REG_TX_ARB_CLIENT_IS_SUBJECT2WFQ, (wfq_tc_map << tc_client_offset)); 944 945 /* Write WFQ weights */ 946 for (tc = 0; tc < num_tc; tc++, tc_client_offset++) { 947 struct init_ets_tc_req *tc_req = &req->tc_req[tc]; 948 u32 byte_weight; 949 950 if (!tc_req->use_wfq) 951 continue; 952 953 /* Translate weight to bytes */ 954 byte_weight = (NIG_ETS_MIN_WFQ_BYTES * tc_req->weight) / min_weight; 955 956 /* Write WFQ weight */ 957 ecore_wr(p_hwfn, p_ptt, tc_weight_base_addr + tc_weight_addr_diff * tc_client_offset, byte_weight); 958 959 /* Write WFQ upper bound */ 960 ecore_wr(p_hwfn, p_ptt, tc_bound_base_addr + tc_bound_addr_diff * tc_client_offset, NIG_ETS_UP_BOUND(byte_weight, req->mtu)); 961 } 962 } 963 964 void ecore_init_nig_lb_rl(struct ecore_hwfn *p_hwfn, 965 struct ecore_ptt *p_ptt, 966 struct init_nig_lb_rl_req* req) 967 { 968 u32 ctrl, inc_val, reg_offset; 969 u8 tc; 970 971 /* Disable global MAC+LB RL */ 972 ctrl = NIG_RL_BASE_TYPE << NIG_REG_TX_LB_GLBRATELIMIT_CTRL_TX_LB_GLBRATELIMIT_BASE_TYPE_SHIFT; 973 ecore_wr(p_hwfn, p_ptt, NIG_REG_TX_LB_GLBRATELIMIT_CTRL, ctrl); 974 975 /* Configure and enable global MAC+LB RL */ 976 if (req->lb_mac_rate) { 977 978 /* Configure */ 979 ecore_wr(p_hwfn, p_ptt, NIG_REG_TX_LB_GLBRATELIMIT_INC_PERIOD, NIG_RL_PERIOD_CLK_25M); 980 inc_val = NIG_RL_INC_VAL(req->lb_mac_rate); 981 ecore_wr(p_hwfn, p_ptt, NIG_REG_TX_LB_GLBRATELIMIT_INC_VALUE, inc_val); 982 ecore_wr(p_hwfn, p_ptt, NIG_REG_TX_LB_GLBRATELIMIT_MAX_VALUE, NIG_RL_MAX_VAL(inc_val, req->mtu)); 983 984 /* Enable */ 985 ctrl |= 1 << NIG_REG_TX_LB_GLBRATELIMIT_CTRL_TX_LB_GLBRATELIMIT_EN_SHIFT; 986 ecore_wr(p_hwfn, p_ptt, NIG_REG_TX_LB_GLBRATELIMIT_CTRL, ctrl); 987 } 988 989 /* Disable global LB-only RL */ 990 ctrl = NIG_RL_BASE_TYPE << NIG_REG_LB_BRBRATELIMIT_CTRL_LB_BRBRATELIMIT_BASE_TYPE_SHIFT; 991 ecore_wr(p_hwfn, p_ptt, NIG_REG_LB_BRBRATELIMIT_CTRL, ctrl); 992 993 /* Configure and enable global LB-only RL */ 994 if (req->lb_rate) { 995 996 /* Configure */ 997 ecore_wr(p_hwfn, p_ptt, NIG_REG_LB_BRBRATELIMIT_INC_PERIOD, NIG_RL_PERIOD_CLK_25M); 998 inc_val = NIG_RL_INC_VAL(req->lb_rate); 999 ecore_wr(p_hwfn, p_ptt, NIG_REG_LB_BRBRATELIMIT_INC_VALUE, inc_val); 1000 ecore_wr(p_hwfn, p_ptt, NIG_REG_LB_BRBRATELIMIT_MAX_VALUE, NIG_RL_MAX_VAL(inc_val, req->mtu)); 1001 1002 /* Enable */ 1003 ctrl |= 1 << NIG_REG_LB_BRBRATELIMIT_CTRL_LB_BRBRATELIMIT_EN_SHIFT; 1004 ecore_wr(p_hwfn, p_ptt, NIG_REG_LB_BRBRATELIMIT_CTRL, ctrl); 1005 } 1006 1007 /* Per-TC RLs */ 1008 for (tc = 0, reg_offset = 0; tc < NUM_OF_PHYS_TCS; tc++, reg_offset += 4) { 1009 1010 /* Disable TC RL */ 1011 ctrl = NIG_RL_BASE_TYPE << NIG_REG_LB_TCRATELIMIT_CTRL_0_LB_TCRATELIMIT_BASE_TYPE_0_SHIFT; 1012 ecore_wr(p_hwfn, p_ptt, NIG_REG_LB_TCRATELIMIT_CTRL_0 + reg_offset, ctrl); 1013 1014 /* Configure and enable TC RL */ 1015 if (!req->tc_rate[tc]) 1016 continue; 1017 1018 /* Configure */ 1019 ecore_wr(p_hwfn, p_ptt, NIG_REG_LB_TCRATELIMIT_INC_PERIOD_0 + reg_offset, NIG_RL_PERIOD_CLK_25M); 1020 inc_val = NIG_RL_INC_VAL(req->tc_rate[tc]); 1021 ecore_wr(p_hwfn, p_ptt, NIG_REG_LB_TCRATELIMIT_INC_VALUE_0 + reg_offset, inc_val); 1022 ecore_wr(p_hwfn, p_ptt, NIG_REG_LB_TCRATELIMIT_MAX_VALUE_0 + reg_offset, NIG_RL_MAX_VAL(inc_val, req->mtu)); 1023 1024 /* Enable */ 1025 ctrl |= 1 << NIG_REG_LB_TCRATELIMIT_CTRL_0_LB_TCRATELIMIT_EN_0_SHIFT; 1026 ecore_wr(p_hwfn, p_ptt, NIG_REG_LB_TCRATELIMIT_CTRL_0 + reg_offset, ctrl); 1027 } 1028 } 1029 1030 void ecore_init_nig_pri_tc_map(struct ecore_hwfn *p_hwfn, 1031 struct ecore_ptt *p_ptt, 1032 struct init_nig_pri_tc_map_req* req) 1033 { 1034 u8 tc_pri_mask[NUM_OF_PHYS_TCS] = { 0 }; 1035 u32 pri_tc_mask = 0; 1036 u8 pri, tc; 1037 1038 for (pri = 0; pri < NUM_OF_VLAN_PRIORITIES; pri++) { 1039 if (!req->pri[pri].valid) 1040 continue; 1041 1042 pri_tc_mask |= (req->pri[pri].tc_id << (pri * NIG_PRIORITY_MAP_TC_BITS)); 1043 tc_pri_mask[req->pri[pri].tc_id] |= (1 << pri); 1044 } 1045 1046 /* Write priority -> TC mask */ 1047 ecore_wr(p_hwfn, p_ptt, NIG_REG_PKT_PRIORITY_TO_TC, pri_tc_mask); 1048 1049 /* Write TC -> priority mask */ 1050 for (tc = 0; tc < NUM_OF_PHYS_TCS; tc++) { 1051 ecore_wr(p_hwfn, p_ptt, NIG_REG_PRIORITY_FOR_TC_0 + tc * 4, tc_pri_mask[tc]); 1052 ecore_wr(p_hwfn, p_ptt, NIG_REG_RX_TC0_PRIORITY_MASK + tc * 4, tc_pri_mask[tc]); 1053 } 1054 } 1055 1056 #endif /* UNUSED_HSI_FUNC */ 1057 1058 #ifndef UNUSED_HSI_FUNC 1059 1060 /* PRS: ETS configuration constants */ 1061 #define PRS_ETS_MIN_WFQ_BYTES 1600 1062 #define PRS_ETS_UP_BOUND(weight,mtu) (2 * ((weight) > (mtu) ? (weight) : (mtu))) 1063 1064 1065 void ecore_init_prs_ets(struct ecore_hwfn *p_hwfn, 1066 struct ecore_ptt *p_ptt, 1067 struct init_ets_req* req) 1068 { 1069 u32 tc_weight_addr_diff, tc_bound_addr_diff, min_weight = 0xffffffff; 1070 u8 tc, sp_tc_map = 0, wfq_tc_map = 0; 1071 1072 tc_weight_addr_diff = PRS_REG_ETS_ARB_CREDIT_WEIGHT_1 - PRS_REG_ETS_ARB_CREDIT_WEIGHT_0; 1073 tc_bound_addr_diff = PRS_REG_ETS_ARB_CREDIT_UPPER_BOUND_1 - PRS_REG_ETS_ARB_CREDIT_UPPER_BOUND_0; 1074 1075 for (tc = 0; tc < NUM_OF_TCS; tc++) { 1076 struct init_ets_tc_req *tc_req = &req->tc_req[tc]; 1077 1078 /* Update SP map */ 1079 if (tc_req->use_sp) 1080 sp_tc_map |= (1 << tc); 1081 1082 if (!tc_req->use_wfq) 1083 continue; 1084 1085 /* Update WFQ map */ 1086 wfq_tc_map |= (1 << tc); 1087 1088 /* Find minimal weight */ 1089 if (tc_req->weight < min_weight) 1090 min_weight = tc_req->weight; 1091 } 1092 1093 /* Write SP map */ 1094 ecore_wr(p_hwfn, p_ptt, PRS_REG_ETS_ARB_CLIENT_IS_STRICT, sp_tc_map); 1095 1096 /* Write WFQ map */ 1097 ecore_wr(p_hwfn, p_ptt, PRS_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ, wfq_tc_map); 1098 1099 /* Write WFQ weights */ 1100 for (tc = 0; tc < NUM_OF_TCS; tc++) { 1101 struct init_ets_tc_req *tc_req = &req->tc_req[tc]; 1102 u32 byte_weight; 1103 1104 if (!tc_req->use_wfq) 1105 continue; 1106 1107 /* Translate weight to bytes */ 1108 byte_weight = (PRS_ETS_MIN_WFQ_BYTES * tc_req->weight) / min_weight; 1109 1110 /* Write WFQ weight */ 1111 ecore_wr(p_hwfn, p_ptt, PRS_REG_ETS_ARB_CREDIT_WEIGHT_0 + tc * tc_weight_addr_diff, byte_weight); 1112 1113 /* Write WFQ upper bound */ 1114 ecore_wr(p_hwfn, p_ptt, PRS_REG_ETS_ARB_CREDIT_UPPER_BOUND_0 + tc * tc_bound_addr_diff, PRS_ETS_UP_BOUND(byte_weight, req->mtu)); 1115 } 1116 } 1117 1118 #endif /* UNUSED_HSI_FUNC */ 1119 #ifndef UNUSED_HSI_FUNC 1120 1121 /* BRB: RAM configuration constants */ 1122 #define BRB_TOTAL_RAM_BLOCKS_BB 4800 1123 #define BRB_TOTAL_RAM_BLOCKS_K2 5632 1124 #define BRB_BLOCK_SIZE 128 1125 #define BRB_MIN_BLOCKS_PER_TC 9 1126 #define BRB_HYST_BYTES 10240 1127 #define BRB_HYST_BLOCKS (BRB_HYST_BYTES / BRB_BLOCK_SIZE) 1128 1129 /* Temporary big RAM allocation - should be updated */ 1130 void ecore_init_brb_ram(struct ecore_hwfn *p_hwfn, 1131 struct ecore_ptt *p_ptt, 1132 struct init_brb_ram_req* req) 1133 { 1134 u32 tc_headroom_blocks, min_pkt_size_blocks, total_blocks; 1135 u32 active_port_blocks, reg_offset = 0; 1136 u8 port, active_ports = 0; 1137 1138 tc_headroom_blocks = (u32)DIV_ROUND_UP(req->headroom_per_tc, BRB_BLOCK_SIZE); 1139 min_pkt_size_blocks = (u32)DIV_ROUND_UP(req->min_pkt_size, BRB_BLOCK_SIZE); 1140 total_blocks = ECORE_IS_K2(p_hwfn->p_dev) ? BRB_TOTAL_RAM_BLOCKS_K2 : BRB_TOTAL_RAM_BLOCKS_BB; 1141 1142 /* Find number of active ports */ 1143 for (port = 0; port < MAX_NUM_PORTS; port++) 1144 if (req->num_active_tcs[port]) 1145 active_ports++; 1146 1147 active_port_blocks = (u32)(total_blocks / active_ports); 1148 1149 for (port = 0; port < req->max_ports_per_engine; port++) { 1150 u32 port_blocks, port_shared_blocks, port_guaranteed_blocks; 1151 u32 full_xoff_th, full_xon_th, pause_xoff_th, pause_xon_th; 1152 u32 tc_guaranteed_blocks; 1153 u8 tc; 1154 1155 /* Calculate per-port sizes */ 1156 tc_guaranteed_blocks = (u32)DIV_ROUND_UP(req->guranteed_per_tc, BRB_BLOCK_SIZE); 1157 port_blocks = req->num_active_tcs[port] ? active_port_blocks : 0; 1158 port_guaranteed_blocks = req->num_active_tcs[port] * tc_guaranteed_blocks; 1159 port_shared_blocks = port_blocks - port_guaranteed_blocks; 1160 full_xoff_th = req->num_active_tcs[port] * BRB_MIN_BLOCKS_PER_TC; 1161 full_xon_th = full_xoff_th + min_pkt_size_blocks; 1162 pause_xoff_th = tc_headroom_blocks; 1163 pause_xon_th = pause_xoff_th + min_pkt_size_blocks; 1164 1165 /* Init total size per port */ 1166 ecore_wr(p_hwfn, p_ptt, BRB_REG_TOTAL_MAC_SIZE + port * 4, port_blocks); 1167 1168 /* Init shared size per port */ 1169 ecore_wr(p_hwfn, p_ptt, BRB_REG_SHARED_HR_AREA + port * 4, port_shared_blocks); 1170 1171 for (tc = 0; tc < NUM_OF_TCS; tc++, reg_offset += 4) { 1172 /* Clear init values for non-active TCs */ 1173 if (tc == req->num_active_tcs[port]) { 1174 tc_guaranteed_blocks = 0; 1175 full_xoff_th = 0; 1176 full_xon_th = 0; 1177 pause_xoff_th = 0; 1178 pause_xon_th = 0; 1179 } 1180 1181 /* Init guaranteed size per TC */ 1182 ecore_wr(p_hwfn, p_ptt, BRB_REG_TC_GUARANTIED_0 + reg_offset, tc_guaranteed_blocks); 1183 ecore_wr(p_hwfn, p_ptt, BRB_REG_MAIN_TC_GUARANTIED_HYST_0 + reg_offset, BRB_HYST_BLOCKS); 1184 1185 /* Init pause/full thresholds per physical TC - for 1186 * loopback traffic. 1187 */ 1188 ecore_wr(p_hwfn, p_ptt, BRB_REG_LB_TC_FULL_XOFF_THRESHOLD_0 + reg_offset, full_xoff_th); 1189 ecore_wr(p_hwfn, p_ptt, BRB_REG_LB_TC_FULL_XON_THRESHOLD_0 + reg_offset, full_xon_th); 1190 ecore_wr(p_hwfn, p_ptt, BRB_REG_LB_TC_PAUSE_XOFF_THRESHOLD_0 + reg_offset, pause_xoff_th); 1191 ecore_wr(p_hwfn, p_ptt, BRB_REG_LB_TC_PAUSE_XON_THRESHOLD_0 + reg_offset, pause_xon_th); 1192 1193 /* Init pause/full thresholds per physical TC - for 1194 * main traffic. 1195 */ 1196 ecore_wr(p_hwfn, p_ptt, BRB_REG_MAIN_TC_FULL_XOFF_THRESHOLD_0 + reg_offset, full_xoff_th); 1197 ecore_wr(p_hwfn, p_ptt, BRB_REG_MAIN_TC_FULL_XON_THRESHOLD_0 + reg_offset, full_xon_th); 1198 ecore_wr(p_hwfn, p_ptt, BRB_REG_MAIN_TC_PAUSE_XOFF_THRESHOLD_0 + reg_offset, pause_xoff_th); 1199 ecore_wr(p_hwfn, p_ptt, BRB_REG_MAIN_TC_PAUSE_XON_THRESHOLD_0 + reg_offset, pause_xon_th); 1200 } 1201 } 1202 } 1203 1204 #endif /* UNUSED_HSI_FUNC */ 1205 #ifndef UNUSED_HSI_FUNC 1206 1207 /* In MF, should be called once per engine to set EtherType of OuterTag */ 1208 void ecore_set_engine_mf_ovlan_eth_type(struct ecore_hwfn *p_hwfn, 1209 struct ecore_ptt *p_ptt, u32 ethType) 1210 { 1211 /* Update PRS register */ 1212 STORE_RT_REG(p_hwfn, PRS_REG_TAG_ETHERTYPE_0_RT_OFFSET, ethType); 1213 1214 /* Update NIG register */ 1215 STORE_RT_REG(p_hwfn, NIG_REG_TAG_ETHERTYPE_0_RT_OFFSET, ethType); 1216 1217 /* Update PBF register */ 1218 STORE_RT_REG(p_hwfn, PBF_REG_TAG_ETHERTYPE_0_RT_OFFSET, ethType); 1219 } 1220 1221 /* In MF, should be called once per port to set EtherType of OuterTag */ 1222 void ecore_set_port_mf_ovlan_eth_type(struct ecore_hwfn *p_hwfn, 1223 struct ecore_ptt *p_ptt, u32 ethType) 1224 { 1225 /* Update DORQ register */ 1226 STORE_RT_REG(p_hwfn, DORQ_REG_TAG1_ETHERTYPE_RT_OFFSET, ethType); 1227 } 1228 1229 #endif /* UNUSED_HSI_FUNC */ 1230 1231 1232 #define SET_TUNNEL_TYPE_ENABLE_BIT(var,offset,enable) var = ((var) & ~(1 << (offset))) | ( (enable) ? (1 << (offset)) : 0) 1233 #define PRS_ETH_TUNN_FIC_FORMAT -188897008 1234 1235 void ecore_set_vxlan_dest_port(struct ecore_hwfn *p_hwfn, 1236 struct ecore_ptt *p_ptt, 1237 u16 dest_port) 1238 { 1239 /* Update PRS register */ 1240 ecore_wr(p_hwfn, p_ptt, PRS_REG_VXLAN_PORT, dest_port); 1241 1242 /* Update NIG register */ 1243 ecore_wr(p_hwfn, p_ptt, NIG_REG_VXLAN_CTRL, dest_port); 1244 1245 /* Update PBF register */ 1246 ecore_wr(p_hwfn, p_ptt, PBF_REG_VXLAN_PORT, dest_port); 1247 } 1248 1249 void ecore_set_vxlan_enable(struct ecore_hwfn *p_hwfn, 1250 struct ecore_ptt *p_ptt, 1251 bool vxlan_enable) 1252 { 1253 u32 reg_val; 1254 1255 /* Update PRS register */ 1256 reg_val = ecore_rd(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN); 1257 SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, PRS_REG_ENCAPSULATION_TYPE_EN_VXLAN_ENABLE_SHIFT, vxlan_enable); 1258 ecore_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val); 1259 if (reg_val) /* TODO: handle E5 init */ 1260 ecore_wr(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0_BB_K2, (u32)PRS_ETH_TUNN_FIC_FORMAT); 1261 1262 /* Update NIG register */ 1263 reg_val = ecore_rd(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE); 1264 SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, NIG_REG_ENC_TYPE_ENABLE_VXLAN_ENABLE_SHIFT, vxlan_enable); 1265 ecore_wr(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE, reg_val); 1266 1267 /* Update DORQ register */ 1268 ecore_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_VXLAN_EN, vxlan_enable ? 1 : 0); 1269 } 1270 1271 void ecore_set_gre_enable(struct ecore_hwfn *p_hwfn, 1272 struct ecore_ptt *p_ptt, 1273 bool eth_gre_enable, 1274 bool ip_gre_enable) 1275 { 1276 u32 reg_val; 1277 1278 /* Update PRS register */ 1279 reg_val = ecore_rd(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN); 1280 SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GRE_ENABLE_SHIFT, eth_gre_enable); 1281 SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GRE_ENABLE_SHIFT, ip_gre_enable); 1282 ecore_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val); 1283 if (reg_val) /* TODO: handle E5 init */ 1284 ecore_wr(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0_BB_K2, (u32)PRS_ETH_TUNN_FIC_FORMAT); 1285 1286 /* Update NIG register */ 1287 reg_val = ecore_rd(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE); 1288 SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, NIG_REG_ENC_TYPE_ENABLE_ETH_OVER_GRE_ENABLE_SHIFT, eth_gre_enable); 1289 SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, NIG_REG_ENC_TYPE_ENABLE_IP_OVER_GRE_ENABLE_SHIFT, ip_gre_enable); 1290 ecore_wr(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE, reg_val); 1291 1292 /* Update DORQ registers */ 1293 ecore_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_GRE_ETH_EN, eth_gre_enable ? 1 : 0); 1294 ecore_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_GRE_IP_EN, ip_gre_enable ? 1 : 0); 1295 } 1296 1297 void ecore_set_geneve_dest_port(struct ecore_hwfn *p_hwfn, 1298 struct ecore_ptt *p_ptt, 1299 u16 dest_port) 1300 1301 { 1302 /* Update PRS register */ 1303 ecore_wr(p_hwfn, p_ptt, PRS_REG_NGE_PORT, dest_port); 1304 1305 /* Update NIG register */ 1306 ecore_wr(p_hwfn, p_ptt, NIG_REG_NGE_PORT, dest_port); 1307 1308 /* Update PBF register */ 1309 ecore_wr(p_hwfn, p_ptt, PBF_REG_NGE_PORT, dest_port); 1310 } 1311 1312 void ecore_set_geneve_enable(struct ecore_hwfn *p_hwfn, 1313 struct ecore_ptt *p_ptt, 1314 bool eth_geneve_enable, 1315 bool ip_geneve_enable) 1316 { 1317 u32 reg_val; 1318 1319 /* Update PRS register */ 1320 reg_val = ecore_rd(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN); 1321 SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GENEVE_ENABLE_SHIFT, eth_geneve_enable); 1322 SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GENEVE_ENABLE_SHIFT, ip_geneve_enable); 1323 ecore_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val); 1324 if (reg_val) /* TODO: handle E5 init */ 1325 ecore_wr(p_hwfn, p_ptt, PRS_REG_OUTPUT_FORMAT_4_0_BB_K2, (u32)PRS_ETH_TUNN_FIC_FORMAT); 1326 1327 /* Update NIG register */ 1328 ecore_wr(p_hwfn, p_ptt, NIG_REG_NGE_ETH_ENABLE, eth_geneve_enable ? 1 : 0); 1329 ecore_wr(p_hwfn, p_ptt, NIG_REG_NGE_IP_ENABLE, ip_geneve_enable ? 1 : 0); 1330 1331 /* EDPM with geneve tunnel not supported in BB */ 1332 if (ECORE_IS_BB_B0(p_hwfn->p_dev)) 1333 return; 1334 1335 /* Update DORQ registers */ 1336 ecore_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_NGE_ETH_EN_K2_E5, eth_geneve_enable ? 1 : 0); 1337 ecore_wr(p_hwfn, p_ptt, DORQ_REG_L2_EDPM_TUNNEL_NGE_IP_EN_K2_E5, ip_geneve_enable ? 1 : 0); 1338 } 1339 1340 #ifndef UNUSED_HSI_FUNC 1341 1342 #define T_ETH_PACKET_ACTION_GFT_EVENTID 23 1343 #define PARSER_ETH_CONN_GFT_ACTION_CM_HDR 272 1344 #define T_ETH_PACKET_MATCH_RFS_EVENTID 25 1345 #define PARSER_ETH_CONN_CM_HDR 0 1346 #define CAM_LINE_SIZE sizeof(u32) 1347 #define RAM_LINE_SIZE sizeof(u64) 1348 #define REG_SIZE sizeof(u32) 1349 1350 1351 void ecore_set_rfs_mode_disable(struct ecore_hwfn *p_hwfn, 1352 struct ecore_ptt *p_ptt, 1353 u16 pf_id) 1354 { 1355 union gft_cam_line_union cam_line; 1356 struct gft_ram_line ram_line; 1357 u32 i, *ram_line_ptr; 1358 1359 ram_line_ptr = (u32*)&ram_line; 1360 1361 /* Stop using gft logic, disable gft search */ 1362 ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_GFT, 0); 1363 ecore_wr(p_hwfn, p_ptt, PRS_REG_CM_HDR_GFT, 0x0); 1364 1365 /* Clean ram & cam for next rfs/gft session*/ 1366 1367 /* Zero camline */ 1368 OSAL_MEMSET(&cam_line, 0, sizeof(cam_line)); 1369 ecore_wr(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE*pf_id, cam_line.cam_line_mapped.camline); 1370 1371 /* Zero ramline */ 1372 OSAL_MEMSET(&ram_line, 0, sizeof(ram_line)); 1373 1374 /* Each iteration write to reg */ 1375 for (i = 0; i < RAM_LINE_SIZE / REG_SIZE; i++) 1376 ecore_wr(p_hwfn, p_ptt, PRS_REG_GFT_PROFILE_MASK_RAM + RAM_LINE_SIZE*pf_id + i*REG_SIZE, *(ram_line_ptr + i)); 1377 } 1378 1379 1380 void ecore_set_gft_event_id_cm_hdr (struct ecore_hwfn *p_hwfn, 1381 struct ecore_ptt *p_ptt) 1382 { 1383 u32 rfs_cm_hdr_event_id; 1384 1385 /* Set RFS event ID to be awakened i Tstorm By Prs */ 1386 rfs_cm_hdr_event_id = ecore_rd(p_hwfn, p_ptt, PRS_REG_CM_HDR_GFT); 1387 rfs_cm_hdr_event_id |= T_ETH_PACKET_ACTION_GFT_EVENTID << PRS_REG_CM_HDR_GFT_EVENT_ID_SHIFT; 1388 rfs_cm_hdr_event_id |= PARSER_ETH_CONN_GFT_ACTION_CM_HDR << PRS_REG_CM_HDR_GFT_CM_HDR_SHIFT; 1389 ecore_wr(p_hwfn, p_ptt, PRS_REG_CM_HDR_GFT, rfs_cm_hdr_event_id); 1390 } 1391 1392 void ecore_set_rfs_mode_enable(struct ecore_hwfn *p_hwfn, 1393 struct ecore_ptt *p_ptt, 1394 u16 pf_id, 1395 bool tcp, 1396 bool udp, 1397 bool ipv4, 1398 bool ipv6) 1399 { 1400 u32 rfs_cm_hdr_event_id, *ram_line_ptr; 1401 union gft_cam_line_union cam_line; 1402 struct gft_ram_line ram_line; 1403 int i; 1404 1405 rfs_cm_hdr_event_id = ecore_rd(p_hwfn, p_ptt, PRS_REG_CM_HDR_GFT); 1406 ram_line_ptr = (u32*)&ram_line; 1407 1408 if (!ipv6 && !ipv4) 1409 DP_NOTICE(p_hwfn, true, "set_rfs_mode_enable: must accept at least on of - ipv4 or ipv6\n"); 1410 if (!tcp && !udp) 1411 DP_NOTICE(p_hwfn, true, "set_rfs_mode_enable: must accept at least on of - udp or tcp\n"); 1412 1413 /* Set RFS event ID to be awakened i Tstorm By Prs */ 1414 rfs_cm_hdr_event_id |= T_ETH_PACKET_MATCH_RFS_EVENTID << PRS_REG_CM_HDR_GFT_EVENT_ID_SHIFT; 1415 rfs_cm_hdr_event_id |= PARSER_ETH_CONN_CM_HDR << PRS_REG_CM_HDR_GFT_CM_HDR_SHIFT; 1416 ecore_wr(p_hwfn, p_ptt, PRS_REG_CM_HDR_GFT, rfs_cm_hdr_event_id); 1417 1418 /* Configure Registers for RFS mode */ 1419 1420 /* Enable gft search */ 1421 ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_GFT, 1); 1422 1423 /* Do not load context only cid in PRS on match. */ 1424 ecore_wr(p_hwfn, p_ptt, PRS_REG_LOAD_L2_FILTER, 0); 1425 1426 /* Cam line is now valid!! */ 1427 cam_line.cam_line_mapped.camline = 0; 1428 SET_FIELD(cam_line.cam_line_mapped.camline, GFT_CAM_LINE_MAPPED_VALID, 1); 1429 1430 /* Filters are per PF!! */ 1431 SET_FIELD(cam_line.cam_line_mapped.camline, GFT_CAM_LINE_MAPPED_PF_ID_MASK, GFT_CAM_LINE_MAPPED_PF_ID_MASK_MASK); 1432 SET_FIELD(cam_line.cam_line_mapped.camline, GFT_CAM_LINE_MAPPED_PF_ID, pf_id); 1433 1434 if (!(tcp && udp)) { 1435 SET_FIELD(cam_line.cam_line_mapped.camline, GFT_CAM_LINE_MAPPED_UPPER_PROTOCOL_TYPE_MASK, GFT_CAM_LINE_MAPPED_UPPER_PROTOCOL_TYPE_MASK_MASK); 1436 if (tcp) 1437 SET_FIELD(cam_line.cam_line_mapped.camline, GFT_CAM_LINE_MAPPED_UPPER_PROTOCOL_TYPE, GFT_PROFILE_TCP_PROTOCOL); 1438 else 1439 SET_FIELD(cam_line.cam_line_mapped.camline, GFT_CAM_LINE_MAPPED_UPPER_PROTOCOL_TYPE, GFT_PROFILE_UDP_PROTOCOL); 1440 } 1441 1442 if (!(ipv4 && ipv6)) { 1443 SET_FIELD(cam_line.cam_line_mapped.camline, GFT_CAM_LINE_MAPPED_IP_VERSION_MASK, 1); 1444 if (ipv4) 1445 SET_FIELD(cam_line.cam_line_mapped.camline, GFT_CAM_LINE_MAPPED_IP_VERSION, GFT_PROFILE_IPV4); 1446 else 1447 SET_FIELD(cam_line.cam_line_mapped.camline, GFT_CAM_LINE_MAPPED_IP_VERSION, GFT_PROFILE_IPV6); 1448 } 1449 1450 /* Write characteristics to cam */ 1451 ecore_wr(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE*pf_id, cam_line.cam_line_mapped.camline); 1452 cam_line.cam_line_mapped.camline = ecore_rd(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE*pf_id); 1453 1454 /* Write line to RAM - compare to filter 4 tuple */ 1455 ram_line.lo = 0; 1456 ram_line.hi= 0; 1457 SET_FIELD(ram_line.hi, GFT_RAM_LINE_DST_IP, 1); 1458 SET_FIELD(ram_line.hi, GFT_RAM_LINE_SRC_IP, 1); 1459 SET_FIELD(ram_line.hi, GFT_RAM_LINE_OVER_IP_PROTOCOL, 1); 1460 SET_FIELD(ram_line.lo, GFT_RAM_LINE_ETHERTYPE, 1); 1461 SET_FIELD(ram_line.lo, GFT_RAM_LINE_SRC_PORT, 1); 1462 SET_FIELD(ram_line.lo, GFT_RAM_LINE_DST_PORT, 1); 1463 1464 1465 /* Each iteration write to reg */ 1466 for (i = 0; i < RAM_LINE_SIZE / REG_SIZE; i++) 1467 ecore_wr(p_hwfn, p_ptt, PRS_REG_GFT_PROFILE_MASK_RAM + RAM_LINE_SIZE*pf_id + i*REG_SIZE, *(ram_line_ptr + i)); 1468 1469 /* Set default profile so that no filter match will happen */ 1470 ram_line.lo = 0xffffffff; 1471 ram_line.hi = 0x3ff; 1472 1473 for (i = 0; i < RAM_LINE_SIZE / REG_SIZE; i++) 1474 ecore_wr(p_hwfn, p_ptt, PRS_REG_GFT_PROFILE_MASK_RAM + RAM_LINE_SIZE*PRS_GFT_CAM_LINES_NO_MATCH + i*REG_SIZE, *(ram_line_ptr + i)); 1475 } 1476 1477 1478 #endif /* UNUSED_HSI_FUNC */ 1479 1480 /* Configure VF zone size mode*/ 1481 void ecore_config_vf_zone_size_mode(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, u16 mode, bool runtime_init) 1482 { 1483 u32 msdm_vf_size_log = MSTORM_VF_ZONE_DEFAULT_SIZE_LOG; 1484 u32 msdm_vf_offset_mask; 1485 1486 if (mode == VF_ZONE_SIZE_MODE_DOUBLE) 1487 msdm_vf_size_log += 1; 1488 else if (mode == VF_ZONE_SIZE_MODE_QUAD) 1489 msdm_vf_size_log += 2; 1490 1491 msdm_vf_offset_mask = (1 << msdm_vf_size_log) - 1; 1492 1493 if (runtime_init) { 1494 STORE_RT_REG(p_hwfn, PGLUE_REG_B_MSDM_VF_SHIFT_B_RT_OFFSET, msdm_vf_size_log); 1495 STORE_RT_REG(p_hwfn, PGLUE_REG_B_MSDM_OFFSET_MASK_B_RT_OFFSET, msdm_vf_offset_mask); 1496 } 1497 else { 1498 ecore_wr(p_hwfn, p_ptt, PGLUE_B_REG_MSDM_VF_SHIFT_B, msdm_vf_size_log); 1499 ecore_wr(p_hwfn, p_ptt, PGLUE_B_REG_MSDM_OFFSET_MASK_B, msdm_vf_offset_mask); 1500 } 1501 } 1502 1503 /* Get mstorm statistics for offset by VF zone size mode */ 1504 u32 ecore_get_mstorm_queue_stat_offset(struct ecore_hwfn *p_hwfn, u16 stat_cnt_id, u16 vf_zone_size_mode) 1505 { 1506 u32 offset = MSTORM_QUEUE_STAT_OFFSET(stat_cnt_id); 1507 1508 if ((vf_zone_size_mode != VF_ZONE_SIZE_MODE_DEFAULT) && (stat_cnt_id > MAX_NUM_PFS)) { 1509 if (vf_zone_size_mode == VF_ZONE_SIZE_MODE_DOUBLE) 1510 offset += (1 << MSTORM_VF_ZONE_DEFAULT_SIZE_LOG) * (stat_cnt_id - MAX_NUM_PFS); 1511 else if (vf_zone_size_mode == VF_ZONE_SIZE_MODE_QUAD) 1512 offset += 3 * (1 << MSTORM_VF_ZONE_DEFAULT_SIZE_LOG) * (stat_cnt_id - MAX_NUM_PFS); 1513 } 1514 1515 return offset; 1516 } 1517 1518 /* Get mstorm VF producer offset by VF zone size mode */ 1519 u32 ecore_get_mstorm_eth_vf_prods_offset(struct ecore_hwfn *p_hwfn, u8 vf_id, u8 vf_queue_id, u16 vf_zone_size_mode) 1520 { 1521 u32 offset = MSTORM_ETH_VF_PRODS_OFFSET(vf_id, vf_queue_id); 1522 1523 if (vf_zone_size_mode != VF_ZONE_SIZE_MODE_DEFAULT) { 1524 if (vf_zone_size_mode == VF_ZONE_SIZE_MODE_DOUBLE) 1525 offset += (1 << MSTORM_VF_ZONE_DEFAULT_SIZE_LOG) * vf_id; 1526 else if (vf_zone_size_mode == VF_ZONE_SIZE_MODE_QUAD) 1527 offset += 3 * (1 << MSTORM_VF_ZONE_DEFAULT_SIZE_LOG) * vf_id; 1528 } 1529 1530 return offset; 1531 } 1532 1533 #ifndef LINUX_REMOVE 1534 #define CRC8_INIT_VALUE 0xFF 1535 #endif 1536 static u8 cdu_crc8_table[CRC8_TABLE_SIZE]; 1537 1538 /* Calculate and return CDU validation byte per connection type/region/cid */ 1539 static u8 ecore_calc_cdu_validation_byte(struct ecore_hwfn * p_hwfn, u8 conn_type, 1540 u8 region, u32 cid) 1541 { 1542 const u8 validation_cfg = CDU_VALIDATION_DEFAULT_CFG; 1543 1544 static u8 crc8_table_valid; /*automatically initialized to 0*/ 1545 u8 crc, validation_byte = 0; 1546 u32 validation_string = 0; 1547 u32 data_to_crc; 1548 1549 if (crc8_table_valid == 0) { 1550 OSAL_CRC8_POPULATE(cdu_crc8_table, 0x07); 1551 crc8_table_valid = 1; 1552 } 1553 1554 /* The CRC is calculated on the String-to-compress: 1555 * [31:8] = {CID[31:20],CID[11:0]} 1556 * [7:4] = Region 1557 * [3:0] = Type 1558 */ 1559 if ((validation_cfg >> CDU_CONTEXT_VALIDATION_CFG_USE_CID) & 1) 1560 validation_string |= (cid & 0xFFF00000) | ((cid & 0xFFF) << 8); 1561 1562 if ((validation_cfg >> CDU_CONTEXT_VALIDATION_CFG_USE_REGION) & 1) 1563 validation_string |= ((region & 0xF) << 4); 1564 1565 if ((validation_cfg >> CDU_CONTEXT_VALIDATION_CFG_USE_TYPE) & 1) 1566 validation_string |= (conn_type & 0xF); 1567 1568 /* Convert to big-endian and calculate CRC8*/ 1569 data_to_crc = OSAL_BE32_TO_CPU(validation_string); 1570 1571 crc = OSAL_CRC8(cdu_crc8_table, (u8 *)&data_to_crc, sizeof(data_to_crc), CRC8_INIT_VALUE); 1572 1573 /* The validation byte [7:0] is composed: 1574 * for type A validation 1575 * [7] = active configuration bit 1576 * [6:0] = crc[6:0] 1577 * 1578 * for type B validation 1579 * [7] = active configuration bit 1580 * [6:3] = connection_type[3:0] 1581 * [2:0] = crc[2:0] 1582 */ 1583 validation_byte |= ((validation_cfg >> CDU_CONTEXT_VALIDATION_CFG_USE_ACTIVE) & 1) << 7; 1584 1585 if ((validation_cfg >> CDU_CONTEXT_VALIDATION_CFG_VALIDATION_TYPE_SHIFT) & 1) 1586 validation_byte |= ((conn_type & 0xF) << 3) | (crc & 0x7); 1587 else 1588 validation_byte |= crc & 0x7F; 1589 1590 return validation_byte; 1591 } 1592 1593 /* Calcualte and set validation bytes for session context */ 1594 void ecore_calc_session_ctx_validation(struct ecore_hwfn * p_hwfn, void *p_ctx_mem, 1595 u16 ctx_size, u8 ctx_type, u32 cid) 1596 { 1597 u8 *x_val_ptr, *t_val_ptr, *u_val_ptr, *p_ctx; 1598 1599 p_ctx = (u8* const)p_ctx_mem; 1600 x_val_ptr = &p_ctx[con_region_offsets[0][ctx_type]]; 1601 t_val_ptr = &p_ctx[con_region_offsets[1][ctx_type]]; 1602 u_val_ptr = &p_ctx[con_region_offsets[2][ctx_type]]; 1603 1604 OSAL_MEMSET(p_ctx, 0, ctx_size); 1605 1606 *x_val_ptr = ecore_calc_cdu_validation_byte(p_hwfn, ctx_type, 3, cid); 1607 *t_val_ptr = ecore_calc_cdu_validation_byte(p_hwfn, ctx_type, 4, cid); 1608 *u_val_ptr = ecore_calc_cdu_validation_byte(p_hwfn, ctx_type, 5, cid); 1609 } 1610 1611 /* Calcualte and set validation bytes for task context */ 1612 void ecore_calc_task_ctx_validation(struct ecore_hwfn * p_hwfn, void *p_ctx_mem, 1613 u16 ctx_size, u8 ctx_type, u32 tid) 1614 { 1615 u8 *p_ctx, *region1_val_ptr; 1616 1617 p_ctx = (u8* const)p_ctx_mem; 1618 region1_val_ptr = &p_ctx[task_region_offsets[0][ctx_type]]; 1619 1620 OSAL_MEMSET(p_ctx, 0, ctx_size); 1621 1622 *region1_val_ptr = ecore_calc_cdu_validation_byte(p_hwfn, ctx_type, 1623 1, tid); 1624 } 1625 1626 /* Memset session context to 0 while preserving validation bytes */ 1627 void ecore_memset_session_ctx(void *p_ctx_mem, u32 ctx_size, u8 ctx_type) 1628 { 1629 u8 *x_val_ptr, *t_val_ptr, *u_val_ptr, *p_ctx; 1630 u8 x_val, t_val, u_val; 1631 1632 p_ctx = (u8* const)p_ctx_mem; 1633 x_val_ptr = &p_ctx[con_region_offsets[0][ctx_type]]; 1634 t_val_ptr = &p_ctx[con_region_offsets[1][ctx_type]]; 1635 u_val_ptr = &p_ctx[con_region_offsets[2][ctx_type]]; 1636 1637 x_val = *x_val_ptr; 1638 t_val = *t_val_ptr; 1639 u_val = *u_val_ptr; 1640 1641 OSAL_MEMSET(p_ctx, 0, ctx_size); 1642 1643 *x_val_ptr = x_val; 1644 *t_val_ptr = t_val; 1645 *u_val_ptr = u_val; 1646 } 1647 1648 /* Memset task context to 0 while preserving validation bytes */ 1649 void ecore_memset_task_ctx(void *p_ctx_mem, u32 ctx_size, u8 ctx_type) 1650 { 1651 u8 *p_ctx, *region1_val_ptr; 1652 u8 region1_val; 1653 1654 p_ctx = (u8* const)p_ctx_mem; 1655 region1_val_ptr = &p_ctx[task_region_offsets[0][ctx_type]]; 1656 1657 region1_val = *region1_val_ptr; 1658 1659 OSAL_MEMSET(p_ctx, 0, ctx_size); 1660 1661 *region1_val_ptr = region1_val; 1662 } 1663 1664 /* Enable and configure context validation */ 1665 void ecore_enable_context_validation(struct ecore_hwfn * p_hwfn, struct ecore_ptt *p_ptt) 1666 { 1667 u32 ctx_validation; 1668 1669 /* Enable validation for connection region 3: CCFC_CTX_VALID0[31:24] */ 1670 ctx_validation = CDU_VALIDATION_DEFAULT_CFG << 24; 1671 ecore_wr(p_hwfn, p_ptt, CDU_REG_CCFC_CTX_VALID0, ctx_validation); 1672 1673 /* Enable validation for connection region 5: CCFC_CTX_VALID1[15:8] */ 1674 ctx_validation = CDU_VALIDATION_DEFAULT_CFG << 8; 1675 ecore_wr(p_hwfn, p_ptt, CDU_REG_CCFC_CTX_VALID1, ctx_validation); 1676 1677 /* Enable validation for connection region 1: TCFC_CTX_VALID0[15:8] */ 1678 ctx_validation = CDU_VALIDATION_DEFAULT_CFG << 8; 1679 ecore_wr(p_hwfn, p_ptt, CDU_REG_TCFC_CTX_VALID0, ctx_validation); 1680 } 1681