Commit | Line | Data |
---|---|---|
fe56b9e6 | 1 | /* QLogic qed NIC Driver |
e8f1cb50 | 2 | * Copyright (c) 2015-2017 QLogic Corporation |
fe56b9e6 | 3 | * |
e8f1cb50 MY |
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. | |
fe56b9e6 YM |
31 | */ |
32 | ||
33 | #include <linux/types.h> | |
da090917 | 34 | #include <linux/crc8.h> |
fe56b9e6 YM |
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 | ||
da090917 TT |
44 | #define CDU_VALIDATION_DEFAULT_CFG 61 |
45 | ||
46 | static 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 | ||
52 | static u16 task_region_offsets[1][NUM_OF_CONNECTION_TYPES_E4] = { | |
53 | {240, 240, 112, 0, 0, 0, 0, 96} /* region 1 offsets */ | |
54 | }; | |
55 | ||
7b6859fb | 56 | /* General constants */ |
fe56b9e6 YM |
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) | |
a2e7699e TT |
62 | #define QM_INVALID_PQ_ID 0xffff |
63 | ||
7b6859fb | 64 | /* Feature enable */ |
a2e7699e TT |
65 | #define QM_BYPASS_EN 1 |
66 | #define QM_BYTE_CRD_EN 1 | |
67 | ||
7b6859fb | 68 | /* Other PQ constants */ |
a2e7699e TT |
69 | #define QM_OTHER_PQS_PER_PF 4 |
70 | ||
fe56b9e6 | 71 | /* WFQ constants */ |
a2e7699e TT |
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 */ | |
21dd79e8 | 80 | #define QM_WFQ_VP_PQ_PF_E4_SHIFT 5 |
a2e7699e TT |
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 */ | |
da090917 | 86 | #define QM_WFQ_MAX_INC_VAL ((QM_WFQ_UPPER_BOUND * 7) / 10) |
351a4ded | 87 | |
fe56b9e6 | 88 | /* RL constants */ |
a2e7699e TT |
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 */ | |
da090917 TT |
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); }) | |
a2e7699e TT |
103 | |
104 | /* PF RL Upper bound is set to 10 * burst size of 1ms in 50Gbps */ | |
da090917 | 105 | #define QM_PF_RL_UPPER_BOUND 62500000 |
a2e7699e TT |
106 | |
107 | /* Max PF RL increment value is 0.7 * upper bound */ | |
da090917 TT |
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) | |
a2e7699e | 120 | |
fe56b9e6 | 121 | /* AFullOprtnstcCrdMask constants */ |
a2e7699e TT |
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 | ||
fe56b9e6 | 126 | /* Command Queue constants */ |
a2e7699e TT |
127 | |
128 | /* Pure LB CmdQ lines (+spare) */ | |
129 | #define PBF_CMDQ_PURE_LB_LINES 150 | |
130 | ||
da090917 TT |
131 | #define PBF_CMDQ_LINES_E5_RSVD_RATIO 8 |
132 | ||
a2e7699e TT |
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 | ||
fe56b9e6 | 146 | /* BTB: blocks constants (block size = 256B) */ |
a2e7699e TT |
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 | ||
fe56b9e6 | 158 | /* QM stop command constants */ |
a2e7699e TT |
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 | |
7b6859fb | 173 | |
fe56b9e6 | 174 | /* QM command macros */ |
a2e7699e TT |
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) | |
da090917 TT |
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 | ||
fe56b9e6 | 207 | /******************** INTERNAL IMPLEMENTATION *********************/ |
a2e7699e | 208 | |
da090917 TT |
209 | /* Returns the external VOQ number */ |
210 | static 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 | ||
fe56b9e6 | 219 | /* Prepare PF RL enable/disable runtime init values */ |
351a4ded | 220 | static void qed_enable_pf_rl(struct qed_hwfn *p_hwfn, bool pf_rl_en) |
fe56b9e6 YM |
221 | { |
222 | STORE_RT_REG(p_hwfn, QM_REG_RLPFENABLE_RT_OFFSET, pf_rl_en ? 1 : 0); | |
223 | if (pf_rl_en) { | |
da090917 TT |
224 | u8 num_ext_voqs = MAX_NUM_VOQS_E4; |
225 | u64 voq_bit_mask = ((u64)1 << num_ext_voqs) - 1; | |
226 | ||
7b6859fb | 227 | /* Enable RLs for all VOQs */ |
da090917 TT |
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 | ||
7b6859fb | 235 | /* Write RL period */ |
fe56b9e6 | 236 | STORE_RT_REG(p_hwfn, |
351a4ded | 237 | QM_REG_RLPFPERIOD_RT_OFFSET, QM_RL_PERIOD_CLK_25M); |
fe56b9e6 YM |
238 | STORE_RT_REG(p_hwfn, |
239 | QM_REG_RLPFPERIODTIMER_RT_OFFSET, | |
240 | QM_RL_PERIOD_CLK_25M); | |
7b6859fb MY |
241 | |
242 | /* Set credit threshold for QM bypass flow */ | |
fe56b9e6 YM |
243 | if (QM_BYPASS_EN) |
244 | STORE_RT_REG(p_hwfn, | |
245 | QM_REG_AFULLQMBYPTHRPFRL_RT_OFFSET, | |
da090917 | 246 | QM_PF_RL_UPPER_BOUND); |
fe56b9e6 YM |
247 | } |
248 | } | |
249 | ||
250 | /* Prepare PF WFQ enable/disable runtime init values */ | |
351a4ded | 251 | static void qed_enable_pf_wfq(struct qed_hwfn *p_hwfn, bool pf_wfq_en) |
fe56b9e6 YM |
252 | { |
253 | STORE_RT_REG(p_hwfn, QM_REG_WFQPFENABLE_RT_OFFSET, pf_wfq_en ? 1 : 0); | |
7b6859fb MY |
254 | |
255 | /* Set credit threshold for QM bypass flow */ | |
fe56b9e6 YM |
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 */ | |
351a4ded | 263 | static void qed_enable_vport_rl(struct qed_hwfn *p_hwfn, bool vport_rl_en) |
fe56b9e6 YM |
264 | { |
265 | STORE_RT_REG(p_hwfn, QM_REG_RLGLBLENABLE_RT_OFFSET, | |
266 | vport_rl_en ? 1 : 0); | |
267 | if (vport_rl_en) { | |
7b6859fb | 268 | /* Write RL period (use timer 0 only) */ |
fe56b9e6 YM |
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); | |
7b6859fb MY |
275 | |
276 | /* Set credit threshold for QM bypass flow */ | |
fe56b9e6 YM |
277 | if (QM_BYPASS_EN) |
278 | STORE_RT_REG(p_hwfn, | |
279 | QM_REG_AFULLQMBYPTHRGLBLRL_RT_OFFSET, | |
da090917 | 280 | QM_VP_RL_BYPASS_THRESH_SPEED); |
fe56b9e6 YM |
281 | } |
282 | } | |
283 | ||
284 | /* Prepare VPORT WFQ enable/disable runtime init values */ | |
351a4ded | 285 | static void qed_enable_vport_wfq(struct qed_hwfn *p_hwfn, bool vport_wfq_en) |
fe56b9e6 YM |
286 | { |
287 | STORE_RT_REG(p_hwfn, QM_REG_WFQVPENABLE_RT_OFFSET, | |
288 | vport_wfq_en ? 1 : 0); | |
7b6859fb MY |
289 | |
290 | /* Set credit threshold for QM bypass flow */ | |
fe56b9e6 YM |
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 | |
7b6859fb | 298 | * the specified VOQ. |
fe56b9e6 YM |
299 | */ |
300 | static void qed_cmdq_lines_voq_rt_init(struct qed_hwfn *p_hwfn, | |
da090917 | 301 | u8 ext_voq, u16 cmdq_lines) |
fe56b9e6 | 302 | { |
da090917 | 303 | u32 qm_line_crd = QM_VOQ_LINE_CRD(cmdq_lines); |
fe56b9e6 | 304 | |
da090917 | 305 | OVERWRITE_RT_REG(p_hwfn, PBF_CMDQ_LINES_RT_OFFSET(ext_voq), |
fe56b9e6 | 306 | (u32)cmdq_lines); |
da090917 TT |
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, | |
fe56b9e6 YM |
310 | qm_line_crd); |
311 | } | |
312 | ||
313 | /* Prepare runtime init values to allocate PBF command queue lines. */ | |
314 | static 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 | { | |
da090917 TT |
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); | |
fe56b9e6 | 326 | |
fe56b9e6 | 327 | for (port_id = 0; port_id < max_ports_per_engine; port_id++) { |
da090917 TT |
328 | u16 phys_lines, phys_lines_per_tc; |
329 | ||
330 | if (!port_params[port_id].active) | |
331 | continue; | |
351a4ded | 332 | |
da090917 TT |
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; | |
351a4ded | 339 | |
da090917 TT |
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; | |
351a4ded | 347 | |
da090917 TT |
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); | |
fe56b9e6 | 358 | } |
da090917 TT |
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); | |
fe56b9e6 YM |
366 | } |
367 | } | |
368 | ||
369 | static 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; | |
da090917 | 376 | u8 tc, ext_voq, port_id, num_tcs_in_port; |
fe56b9e6 YM |
377 | |
378 | for (port_id = 0; port_id < max_ports_per_engine; port_id++) { | |
fe56b9e6 YM |
379 | if (!port_params[port_id].active) |
380 | continue; | |
381 | ||
7b6859fb | 382 | /* Subtract headroom blocks */ |
fe56b9e6 YM |
383 | usable_blocks = port_params[port_id].num_btb_blocks - |
384 | BTB_HEADROOM_BLOCKS; | |
385 | ||
da090917 TT |
386 | /* Find blocks per physical TC. Use factor to avoid floating |
387 | * arithmethic. | |
388 | */ | |
351a4ded | 389 | num_tcs_in_port = 0; |
da090917 | 390 | for (tc = 0; tc < NUM_OF_PHYS_TCS; tc++) |
351a4ded YM |
391 | if (((port_params[port_id].active_phys_tcs >> |
392 | tc) & 0x1) == 1) | |
393 | num_tcs_in_port++; | |
351a4ded | 394 | |
fe56b9e6 | 395 | pure_lb_blocks = (usable_blocks * BTB_PURE_LB_FACTOR) / |
351a4ded | 396 | (num_tcs_in_port * BTB_PURE_LB_FACTOR + |
fe56b9e6 YM |
397 | BTB_PURE_LB_RATIO); |
398 | pure_lb_blocks = max_t(u32, BTB_JUMBO_PKT_BLOCKS, | |
399 | pure_lb_blocks / BTB_PURE_LB_FACTOR); | |
351a4ded YM |
400 | phys_blocks = (usable_blocks - pure_lb_blocks) / |
401 | num_tcs_in_port; | |
fe56b9e6 | 402 | |
7b6859fb | 403 | /* Init physical TCs */ |
351a4ded YM |
404 | for (tc = 0; tc < NUM_OF_PHYS_TCS; tc++) { |
405 | if (((port_params[port_id].active_phys_tcs >> | |
da090917 TT |
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 | } | |
fe56b9e6 YM |
416 | } |
417 | ||
7b6859fb | 418 | /* Init pure LB TC */ |
da090917 TT |
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), | |
fe56b9e6 YM |
423 | pure_lb_blocks); |
424 | } | |
425 | } | |
426 | ||
427 | /* Prepare Tx PQ mapping runtime init values for the specified PF */ | |
da090917 TT |
428 | static 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) | |
fe56b9e6 | 432 | { |
fe56b9e6 | 433 | u32 tx_pq_vf_mask[MAX_QM_TX_QUEUES / QM_PF_QUEUE_GROUP_SIZE] = { 0 }; |
da090917 | 434 | struct init_qm_vport_params *vport_params = p_params->vport_params; |
be086e7c | 435 | u32 num_tx_pq_vf_masks = MAX_QM_TX_QUEUES / QM_PF_QUEUE_GROUP_SIZE; |
da090917 TT |
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; | |
fe56b9e6 | 449 | |
7b6859fb | 450 | /* Set mapping from PQ group to PF */ |
fe56b9e6 YM |
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)); | |
da090917 | 454 | |
7b6859fb | 455 | /* Set PQ sizes */ |
fe56b9e6 YM |
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 | ||
7b6859fb | 461 | /* Go over all Tx PQs */ |
fe56b9e6 | 462 | for (i = 0, pq_id = p_params->start_pq; i < num_pqs; i++, pq_id++) { |
da090917 TT |
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; | |
21dd79e8 | 465 | struct qm_rf_pq_map_e4 tx_pq_map; |
da090917 TT |
466 | bool is_vf_pq, rl_valid; |
467 | u16 *p_first_tx_pq_id; | |
fe56b9e6 | 468 | |
da090917 | 469 | ext_voq = qed_get_ext_voq(p_hwfn, |
50bc60cb | 470 | pq_params[i].port_id, |
da090917 TT |
471 | tc_id, |
472 | p_params->max_phys_tcs_per_port); | |
473 | is_vf_pq = (i >= p_params->num_pf_pqs); | |
50bc60cb | 474 | rl_valid = pq_params[i].rl_valid > 0; |
be086e7c | 475 | |
7b6859fb | 476 | /* Update first Tx PQ of VPORT/TC */ |
da090917 TT |
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); | |
fe56b9e6 | 484 | |
7b6859fb | 485 | /* Create new VP PQ */ |
da090917 | 486 | *p_first_tx_pq_id = pq_id; |
7b6859fb MY |
487 | |
488 | /* Map VP PQ to VOQ and PF */ | |
fe56b9e6 YM |
489 | STORE_RT_REG(p_hwfn, |
490 | QM_REG_WFQVPMAP_RT_OFFSET + | |
da090917 TT |
491 | *p_first_tx_pq_id, |
492 | map_val); | |
fe56b9e6 | 493 | } |
be086e7c | 494 | |
da090917 | 495 | /* Check RL ID */ |
50bc60cb | 496 | if (rl_valid && pq_params[i].vport_id >= max_qm_global_rls) { |
be086e7c | 497 | DP_NOTICE(p_hwfn, |
da090917 | 498 | "Invalid VPORT ID for rate limiter configuration\n"); |
50bc60cb MK |
499 | rl_valid = false; |
500 | } | |
da090917 TT |
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 */ | |
fe56b9e6 YM |
513 | STORE_RT_REG(p_hwfn, |
514 | QM_REG_BASEADDRTXPQ_RT_OFFSET + pq_id, | |
515 | mem_addr_4kb); | |
7b6859fb | 516 | |
da090917 TT |
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, | |
50bc60cb | 531 | pq_params[i].port_id, |
da090917 TT |
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 | ||
7b6859fb | 539 | /* If VF PQ, add indication to PQ VF mask */ |
fe56b9e6 | 540 | if (is_vf_pq) { |
be086e7c MY |
541 | tx_pq_vf_mask[pq_id / |
542 | QM_PF_QUEUE_GROUP_SIZE] |= | |
543 | BIT((pq_id % QM_PF_QUEUE_GROUP_SIZE)); | |
fe56b9e6 YM |
544 | mem_addr_4kb += vport_pq_mem_4kb; |
545 | } else { | |
546 | mem_addr_4kb += pq_mem_4kb; | |
547 | } | |
548 | } | |
549 | ||
7b6859fb MY |
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, | |
351a4ded | 555 | tx_pq_vf_mask[i]); |
fe56b9e6 YM |
556 | } |
557 | ||
558 | /* Prepare Other PQ mapping runtime init values for the specified PF */ | |
559 | static void qed_other_pq_map_rt_init(struct qed_hwfn *p_hwfn, | |
fe56b9e6 | 560 | u8 pf_id, |
da090917 | 561 | bool is_pf_loading, |
fe56b9e6 | 562 | u32 num_pf_cids, |
351a4ded | 563 | u32 num_tids, u32 base_mem_addr_4kb) |
fe56b9e6 | 564 | { |
7b6859fb | 565 | u32 pq_size, pq_mem_4kb, mem_addr_4kb; |
da090917 | 566 | u16 i, j, pq_id, pq_group; |
fe56b9e6 | 567 | |
da090917 TT |
568 | /* A single other PQ group is used in each PF, where PQ group i is used |
569 | * in PF i. | |
fe56b9e6 | 570 | */ |
7b6859fb MY |
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; | |
fe56b9e6 | 575 | |
7b6859fb | 576 | /* Map PQ group to PF */ |
fe56b9e6 YM |
577 | STORE_RT_REG(p_hwfn, QM_REG_PQOTHER2PF_0_RT_OFFSET + pq_group, |
578 | (u32)(pf_id)); | |
da090917 | 579 | |
7b6859fb | 580 | /* Set PQ sizes */ |
fe56b9e6 YM |
581 | STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_2_RT_OFFSET, |
582 | QM_PQ_SIZE_256B(pq_size)); | |
7b6859fb | 583 | |
fe56b9e6 YM |
584 | for (i = 0, pq_id = pf_id * QM_PF_QUEUE_GROUP_SIZE; |
585 | i < QM_OTHER_PQS_PER_PF; i++, pq_id++) { | |
da090917 | 586 | /* Set PQ base address */ |
fe56b9e6 YM |
587 | STORE_RT_REG(p_hwfn, |
588 | QM_REG_BASEADDROTHERPQ_RT_OFFSET + pq_id, | |
589 | mem_addr_4kb); | |
da090917 TT |
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 | ||
fe56b9e6 YM |
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 | */ | |
605 | static int qed_pf_wfq_rt_init(struct qed_hwfn *p_hwfn, | |
50bc60cb | 606 | |
fe56b9e6 YM |
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; | |
da090917 TT |
610 | struct init_qm_pq_params *pq_params = p_params->pq_params; |
611 | u32 inc_val, crd_reg_offset; | |
612 | u8 ext_voq; | |
fe56b9e6 YM |
613 | u16 i; |
614 | ||
fe56b9e6 | 615 | inc_val = QM_WFQ_INC_VAL(p_params->pf_wfq); |
351a4ded | 616 | if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) { |
7b6859fb | 617 | DP_NOTICE(p_hwfn, "Invalid PF WFQ weight configuration\n"); |
fe56b9e6 YM |
618 | return -1; |
619 | } | |
fe56b9e6 YM |
620 | |
621 | for (i = 0; i < num_tx_pqs; i++) { | |
da090917 | 622 | ext_voq = qed_get_ext_voq(p_hwfn, |
50bc60cb | 623 | pq_params[i].port_id, |
da090917 TT |
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); | |
fe56b9e6 | 632 | OVERWRITE_RT_REG(p_hwfn, |
da090917 | 633 | crd_reg_offset, (u32)QM_WFQ_CRD_REG_SIGN_BIT); |
fe56b9e6 YM |
634 | } |
635 | ||
351a4ded YM |
636 | STORE_RT_REG(p_hwfn, |
637 | QM_REG_WFQPFUPPERBOUND_RT_OFFSET + p_params->pf_id, | |
da090917 | 638 | QM_WFQ_UPPER_BOUND | (u32)QM_WFQ_CRD_REG_SIGN_BIT); |
be086e7c MY |
639 | STORE_RT_REG(p_hwfn, QM_REG_WFQPFWEIGHT_RT_OFFSET + p_params->pf_id, |
640 | inc_val); | |
da090917 | 641 | |
fe56b9e6 YM |
642 | return 0; |
643 | } | |
644 | ||
645 | /* Prepare PF RL runtime init values for the specified PF. | |
646 | * Return -1 on error. | |
647 | */ | |
351a4ded | 648 | static int qed_pf_rl_rt_init(struct qed_hwfn *p_hwfn, u8 pf_id, u32 pf_rl) |
fe56b9e6 YM |
649 | { |
650 | u32 inc_val = QM_RL_INC_VAL(pf_rl); | |
651 | ||
da090917 | 652 | if (inc_val > QM_PF_RL_MAX_INC_VAL) { |
7b6859fb | 653 | DP_NOTICE(p_hwfn, "Invalid PF rate limit configuration\n"); |
fe56b9e6 YM |
654 | return -1; |
655 | } | |
da090917 TT |
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); | |
fe56b9e6 | 663 | STORE_RT_REG(p_hwfn, QM_REG_RLPFINCVAL_RT_OFFSET + pf_id, inc_val); |
da090917 | 664 | |
fe56b9e6 YM |
665 | return 0; |
666 | } | |
667 | ||
668 | /* Prepare VPORT WFQ runtime init values for the specified VPORTs. | |
669 | * Return -1 on error. | |
670 | */ | |
671 | static int qed_vp_wfq_rt_init(struct qed_hwfn *p_hwfn, | |
fe56b9e6 YM |
672 | u8 num_vports, |
673 | struct init_qm_vport_params *vport_params) | |
674 | { | |
da090917 | 675 | u16 vport_pq_id; |
fe56b9e6 | 676 | u32 inc_val; |
fc48b7a6 | 677 | u8 tc, i; |
fe56b9e6 | 678 | |
7b6859fb | 679 | /* Go over all PF VPORTs */ |
fc48b7a6 | 680 | for (i = 0; i < num_vports; i++) { |
fe56b9e6 YM |
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, | |
7b6859fb | 687 | "Invalid VPORT WFQ weight configuration\n"); |
fe56b9e6 YM |
688 | return -1; |
689 | } | |
690 | ||
da090917 | 691 | /* Each VPORT can have several VPORT PQ IDs for various TCs */ |
fe56b9e6 | 692 | for (tc = 0; tc < NUM_OF_TCS; tc++) { |
da090917 | 693 | vport_pq_id = vport_params[i].first_tx_pq_id[tc]; |
fe56b9e6 | 694 | if (vport_pq_id != QM_INVALID_PQ_ID) { |
fe56b9e6 YM |
695 | STORE_RT_REG(p_hwfn, |
696 | QM_REG_WFQVPCRD_RT_OFFSET + | |
697 | vport_pq_id, | |
da090917 | 698 | (u32)QM_WFQ_CRD_REG_SIGN_BIT); |
fc48b7a6 YM |
699 | STORE_RT_REG(p_hwfn, |
700 | QM_REG_WFQVPWEIGHT_RT_OFFSET + | |
701 | vport_pq_id, inc_val); | |
fe56b9e6 YM |
702 | } |
703 | } | |
704 | } | |
705 | ||
706 | return 0; | |
707 | } | |
708 | ||
da090917 TT |
709 | /* Prepare VPORT RL runtime init values for the specified VPORTs. |
710 | * Return -1 on error. | |
711 | */ | |
fe56b9e6 YM |
712 | static int qed_vport_rl_rt_init(struct qed_hwfn *p_hwfn, |
713 | u8 start_vport, | |
714 | u8 num_vports, | |
da090917 | 715 | u32 link_speed, |
fe56b9e6 YM |
716 | struct init_qm_vport_params *vport_params) |
717 | { | |
718 | u8 i, vport_id; | |
da090917 | 719 | u32 inc_val; |
fe56b9e6 | 720 | |
be086e7c MY |
721 | if (start_vport + num_vports >= MAX_QM_GLOBAL_RLS) { |
722 | DP_NOTICE(p_hwfn, | |
7b6859fb | 723 | "Invalid VPORT ID for rate limiter configuration\n"); |
be086e7c MY |
724 | return -1; |
725 | } | |
726 | ||
7b6859fb | 727 | /* Go over all PF VPORTs */ |
fe56b9e6 | 728 | for (i = 0, vport_id = start_vport; i < num_vports; i++, vport_id++) { |
da090917 TT |
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)) { | |
fe56b9e6 | 733 | DP_NOTICE(p_hwfn, |
7b6859fb | 734 | "Invalid VPORT rate-limit configuration\n"); |
fe56b9e6 YM |
735 | return -1; |
736 | } | |
737 | ||
da090917 TT |
738 | STORE_RT_REG(p_hwfn, QM_REG_RLGLBLCRD_RT_OFFSET + vport_id, |
739 | (u32)QM_RL_CRD_REG_SIGN_BIT); | |
fe56b9e6 YM |
740 | STORE_RT_REG(p_hwfn, |
741 | QM_REG_RLGLBLUPPERBOUND_RT_OFFSET + vport_id, | |
da090917 TT |
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, | |
fe56b9e6 YM |
745 | inc_val); |
746 | } | |
747 | ||
748 | return 0; | |
749 | } | |
750 | ||
751 | static 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 | ||
da090917 | 756 | for (i = 0, reg_val = 0; i < QM_STOP_CMD_MAX_POLL_COUNT && !reg_val; |
fe56b9e6 YM |
757 | i++) { |
758 | udelay(QM_STOP_CMD_POLL_PERIOD_US); | |
759 | reg_val = qed_rd(p_hwfn, p_ptt, QM_REG_SDMCMDREADY); | |
760 | } | |
761 | ||
7b6859fb | 762 | /* Check if timeout while waiting for SDM command ready */ |
fe56b9e6 YM |
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 | ||
772 | static bool qed_send_qm_cmd(struct qed_hwfn *p_hwfn, | |
773 | struct qed_ptt *p_ptt, | |
351a4ded | 774 | u32 cmd_addr, u32 cmd_data_lsb, u32 cmd_data_msb) |
fe56b9e6 YM |
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 *********************/ | |
da090917 TT |
789 | |
790 | u32 qed_qm_pf_mem_size(u32 num_pf_cids, | |
fe56b9e6 | 791 | u32 num_vf_cids, |
351a4ded | 792 | u32 num_tids, u16 num_pf_pqs, u16 num_vf_pqs) |
fe56b9e6 YM |
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 | ||
da090917 TT |
799 | int qed_qm_common_rt_init(struct qed_hwfn *p_hwfn, |
800 | struct qed_qm_common_rt_init_params *p_params) | |
fe56b9e6 | 801 | { |
da090917 | 802 | /* Init AFullOprtnstcCrdMask */ |
fe56b9e6 YM |
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); | |
da090917 TT |
820 | |
821 | /* Enable/disable PF RL */ | |
fe56b9e6 | 822 | qed_enable_pf_rl(p_hwfn, p_params->pf_rl_en); |
da090917 TT |
823 | |
824 | /* Enable/disable PF WFQ */ | |
fe56b9e6 | 825 | qed_enable_pf_wfq(p_hwfn, p_params->pf_wfq_en); |
da090917 TT |
826 | |
827 | /* Enable/disable VPORT RL */ | |
fe56b9e6 | 828 | qed_enable_vport_rl(p_hwfn, p_params->vport_rl_en); |
da090917 TT |
829 | |
830 | /* Enable/disable VPORT WFQ */ | |
fe56b9e6 | 831 | qed_enable_vport_wfq(p_hwfn, p_params->vport_wfq_en); |
da090917 TT |
832 | |
833 | /* Init PBF CMDQ line credit */ | |
fe56b9e6 YM |
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); | |
da090917 TT |
838 | |
839 | /* Init BTB blocks in PBF */ | |
fe56b9e6 YM |
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); | |
da090917 | 844 | |
fe56b9e6 YM |
845 | return 0; |
846 | } | |
847 | ||
848 | int 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 | ||
7b6859fb | 858 | /* Clear first Tx PQ ID array for each VPORT */ |
fe56b9e6 YM |
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 | ||
7b6859fb | 863 | /* Map Other PQs (if any) */ |
da090917 TT |
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); | |
fe56b9e6 | 868 | |
7b6859fb | 869 | /* Map Tx PQs */ |
fe56b9e6 YM |
870 | qed_tx_pq_map_rt_init(p_hwfn, p_ptt, p_params, other_mem_size_4kb); |
871 | ||
da090917 | 872 | /* Init PF WFQ */ |
fe56b9e6 YM |
873 | if (p_params->pf_wfq) |
874 | if (qed_pf_wfq_rt_init(p_hwfn, p_params)) | |
875 | return -1; | |
876 | ||
da090917 | 877 | /* Init PF RL */ |
fe56b9e6 YM |
878 | if (qed_pf_rl_rt_init(p_hwfn, p_params->pf_id, p_params->pf_rl)) |
879 | return -1; | |
880 | ||
da090917 | 881 | /* Set VPORT WFQ */ |
fc48b7a6 | 882 | if (qed_vp_wfq_rt_init(p_hwfn, p_params->num_vports, vport_params)) |
fe56b9e6 YM |
883 | return -1; |
884 | ||
da090917 | 885 | /* Set VPORT RL */ |
fe56b9e6 | 886 | if (qed_vport_rl_rt_init(p_hwfn, p_params->start_vport, |
da090917 TT |
887 | p_params->num_vports, p_params->link_speed, |
888 | vport_params)) | |
fe56b9e6 YM |
889 | return -1; |
890 | ||
891 | return 0; | |
892 | } | |
893 | ||
a64b02d5 | 894 | int qed_init_pf_wfq(struct qed_hwfn *p_hwfn, |
351a4ded | 895 | struct qed_ptt *p_ptt, u8 pf_id, u16 pf_wfq) |
a64b02d5 MC |
896 | { |
897 | u32 inc_val = QM_WFQ_INC_VAL(pf_wfq); | |
898 | ||
899 | if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) { | |
7b6859fb | 900 | DP_NOTICE(p_hwfn, "Invalid PF WFQ weight configuration\n"); |
a64b02d5 MC |
901 | return -1; |
902 | } | |
903 | ||
904 | qed_wr(p_hwfn, p_ptt, QM_REG_WFQPFWEIGHT + pf_id * 4, inc_val); | |
da090917 | 905 | |
a64b02d5 MC |
906 | return 0; |
907 | } | |
908 | ||
fe56b9e6 | 909 | int qed_init_pf_rl(struct qed_hwfn *p_hwfn, |
351a4ded | 910 | struct qed_ptt *p_ptt, u8 pf_id, u32 pf_rl) |
fe56b9e6 YM |
911 | { |
912 | u32 inc_val = QM_RL_INC_VAL(pf_rl); | |
913 | ||
da090917 | 914 | if (inc_val > QM_PF_RL_MAX_INC_VAL) { |
7b6859fb | 915 | DP_NOTICE(p_hwfn, "Invalid PF rate limit configuration\n"); |
fe56b9e6 YM |
916 | return -1; |
917 | } | |
918 | ||
da090917 TT |
919 | qed_wr(p_hwfn, |
920 | p_ptt, QM_REG_RLPFCRD + pf_id * 4, (u32)QM_RL_CRD_REG_SIGN_BIT); | |
fe56b9e6 YM |
921 | qed_wr(p_hwfn, p_ptt, QM_REG_RLPFINCVAL + pf_id * 4, inc_val); |
922 | ||
923 | return 0; | |
924 | } | |
925 | ||
bcd197c8 MC |
926 | int qed_init_vport_wfq(struct qed_hwfn *p_hwfn, |
927 | struct qed_ptt *p_ptt, | |
351a4ded | 928 | u16 first_tx_pq_id[NUM_OF_TCS], u16 vport_wfq) |
bcd197c8 | 929 | { |
7b6859fb MY |
930 | u16 vport_pq_id; |
931 | u32 inc_val; | |
bcd197c8 MC |
932 | u8 tc; |
933 | ||
7b6859fb | 934 | inc_val = QM_WFQ_INC_VAL(vport_wfq); |
bcd197c8 | 935 | if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) { |
7b6859fb | 936 | DP_NOTICE(p_hwfn, "Invalid VPORT WFQ weight configuration\n"); |
bcd197c8 MC |
937 | return -1; |
938 | } | |
939 | ||
940 | for (tc = 0; tc < NUM_OF_TCS; tc++) { | |
7b6859fb | 941 | vport_pq_id = first_tx_pq_id[tc]; |
bcd197c8 | 942 | if (vport_pq_id != QM_INVALID_PQ_ID) |
da090917 TT |
943 | qed_wr(p_hwfn, |
944 | p_ptt, | |
945 | QM_REG_WFQVPWEIGHT + vport_pq_id * 4, inc_val); | |
bcd197c8 MC |
946 | } |
947 | ||
948 | return 0; | |
949 | } | |
950 | ||
fe56b9e6 | 951 | int qed_init_vport_rl(struct qed_hwfn *p_hwfn, |
da090917 TT |
952 | struct qed_ptt *p_ptt, |
953 | u8 vport_id, u32 vport_rl, u32 link_speed) | |
fe56b9e6 | 954 | { |
da090917 | 955 | u32 inc_val, max_qm_global_rls = MAX_QM_GLOBAL_RLS; |
fe56b9e6 | 956 | |
da090917 | 957 | if (vport_id >= max_qm_global_rls) { |
be086e7c | 958 | DP_NOTICE(p_hwfn, |
7b6859fb | 959 | "Invalid VPORT ID for rate limiter configuration\n"); |
be086e7c MY |
960 | return -1; |
961 | } | |
962 | ||
da090917 TT |
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)) { | |
7b6859fb | 965 | DP_NOTICE(p_hwfn, "Invalid VPORT rate-limit configuration\n"); |
fe56b9e6 YM |
966 | return -1; |
967 | } | |
968 | ||
da090917 TT |
969 | qed_wr(p_hwfn, |
970 | p_ptt, | |
971 | QM_REG_RLGLBLCRD + vport_id * 4, (u32)QM_RL_CRD_REG_SIGN_BIT); | |
fe56b9e6 YM |
972 | qed_wr(p_hwfn, p_ptt, QM_REG_RLGLBLINCVAL + vport_id * 4, inc_val); |
973 | ||
974 | return 0; | |
975 | } | |
976 | ||
977 | bool qed_send_qm_stop_cmd(struct qed_hwfn *p_hwfn, | |
978 | struct qed_ptt *p_ptt, | |
979 | bool is_release_cmd, | |
351a4ded | 980 | bool is_tx_pq, u16 start_pq, u16 num_pqs) |
fe56b9e6 YM |
981 | { |
982 | u32 cmd_arr[QM_CMD_STRUCT_SIZE(QM_STOP_CMD)] = { 0 }; | |
da090917 TT |
983 | u32 pq_mask = 0, last_pq, pq_id; |
984 | ||
985 | last_pq = start_pq + num_pqs - 1; | |
fe56b9e6 | 986 | |
7b6859fb | 987 | /* Set command's PQ type */ |
fe56b9e6 YM |
988 | QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD, PQ_TYPE, is_tx_pq ? 0 : 1); |
989 | ||
da090917 | 990 | /* Go over requested PQs */ |
fe56b9e6 | 991 | for (pq_id = start_pq; pq_id <= last_pq; pq_id++) { |
7b6859fb | 992 | /* Set PQ bit in mask (stop command only) */ |
fe56b9e6 | 993 | if (!is_release_cmd) |
da090917 | 994 | pq_mask |= BIT((pq_id % QM_STOP_PQ_MASK_WIDTH)); |
fe56b9e6 | 995 | |
7b6859fb | 996 | /* If last PQ or end of PQ mask, write command */ |
fe56b9e6 YM |
997 | if ((pq_id == last_pq) || |
998 | (pq_id % QM_STOP_PQ_MASK_WIDTH == | |
999 | (QM_STOP_PQ_MASK_WIDTH - 1))) { | |
da090917 TT |
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, | |
fe56b9e6 YM |
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 | } | |
464f6645 | 1015 | |
464f6645 | 1016 | |
da090917 TT |
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) | |
50bc60cb MK |
1024 | #define PRS_ETH_TUNN_OUTPUT_FORMAT -188897008 |
1025 | #define PRS_ETH_OUTPUT_FORMAT -46832 | |
464f6645 MC |
1026 | |
1027 | void qed_set_vxlan_dest_port(struct qed_hwfn *p_hwfn, | |
351a4ded | 1028 | struct qed_ptt *p_ptt, u16 dest_port) |
464f6645 | 1029 | { |
da090917 | 1030 | /* Update PRS register */ |
464f6645 | 1031 | qed_wr(p_hwfn, p_ptt, PRS_REG_VXLAN_PORT, dest_port); |
da090917 TT |
1032 | |
1033 | /* Update NIG register */ | |
351a4ded | 1034 | qed_wr(p_hwfn, p_ptt, NIG_REG_VXLAN_CTRL, dest_port); |
da090917 TT |
1035 | |
1036 | /* Update PBF register */ | |
464f6645 MC |
1037 | qed_wr(p_hwfn, p_ptt, PBF_REG_VXLAN_PORT, dest_port); |
1038 | } | |
1039 | ||
1040 | void qed_set_vxlan_enable(struct qed_hwfn *p_hwfn, | |
351a4ded | 1041 | struct qed_ptt *p_ptt, bool vxlan_enable) |
464f6645 | 1042 | { |
da090917 | 1043 | u32 reg_val; |
464f6645 MC |
1044 | u8 shift; |
1045 | ||
da090917 | 1046 | /* Update PRS register */ |
464f6645 MC |
1047 | reg_val = qed_rd(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN); |
1048 | shift = PRS_REG_ENCAPSULATION_TYPE_EN_VXLAN_ENABLE_SHIFT; | |
da090917 | 1049 | SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, vxlan_enable); |
464f6645 | 1050 | qed_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val); |
50bc60cb MK |
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 | } | |
464f6645 | 1060 | |
da090917 | 1061 | /* Update NIG register */ |
464f6645 MC |
1062 | reg_val = qed_rd(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE); |
1063 | shift = NIG_REG_ENC_TYPE_ENABLE_VXLAN_ENABLE_SHIFT; | |
da090917 | 1064 | SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, vxlan_enable); |
464f6645 MC |
1065 | qed_wr(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE, reg_val); |
1066 | ||
da090917 TT |
1067 | /* Update DORQ register */ |
1068 | qed_wr(p_hwfn, | |
1069 | p_ptt, DORQ_REG_L2_EDPM_TUNNEL_VXLAN_EN, vxlan_enable ? 1 : 0); | |
464f6645 MC |
1070 | } |
1071 | ||
da090917 TT |
1072 | void qed_set_gre_enable(struct qed_hwfn *p_hwfn, |
1073 | struct qed_ptt *p_ptt, | |
464f6645 MC |
1074 | bool eth_gre_enable, bool ip_gre_enable) |
1075 | { | |
da090917 | 1076 | u32 reg_val; |
464f6645 MC |
1077 | u8 shift; |
1078 | ||
da090917 | 1079 | /* Update PRS register */ |
464f6645 MC |
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; | |
da090917 | 1082 | SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, eth_gre_enable); |
464f6645 | 1083 | shift = PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GRE_ENABLE_SHIFT; |
da090917 | 1084 | SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, ip_gre_enable); |
464f6645 | 1085 | qed_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val); |
50bc60cb MK |
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 | } | |
464f6645 | 1095 | |
da090917 | 1096 | /* Update NIG register */ |
464f6645 MC |
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; | |
da090917 | 1099 | SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, eth_gre_enable); |
464f6645 | 1100 | shift = NIG_REG_ENC_TYPE_ENABLE_IP_OVER_GRE_ENABLE_SHIFT; |
da090917 | 1101 | SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, ip_gre_enable); |
464f6645 MC |
1102 | qed_wr(p_hwfn, p_ptt, NIG_REG_ENC_TYPE_ENABLE, reg_val); |
1103 | ||
da090917 TT |
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); | |
464f6645 MC |
1110 | } |
1111 | ||
1112 | void qed_set_geneve_dest_port(struct qed_hwfn *p_hwfn, | |
351a4ded | 1113 | struct qed_ptt *p_ptt, u16 dest_port) |
464f6645 | 1114 | { |
da090917 | 1115 | /* Update PRS register */ |
464f6645 | 1116 | qed_wr(p_hwfn, p_ptt, PRS_REG_NGE_PORT, dest_port); |
da090917 TT |
1117 | |
1118 | /* Update NIG register */ | |
464f6645 | 1119 | qed_wr(p_hwfn, p_ptt, NIG_REG_NGE_PORT, dest_port); |
da090917 TT |
1120 | |
1121 | /* Update PBF register */ | |
464f6645 MC |
1122 | qed_wr(p_hwfn, p_ptt, PBF_REG_NGE_PORT, dest_port); |
1123 | } | |
1124 | ||
1125 | void qed_set_geneve_enable(struct qed_hwfn *p_hwfn, | |
1126 | struct qed_ptt *p_ptt, | |
351a4ded | 1127 | bool eth_geneve_enable, bool ip_geneve_enable) |
464f6645 | 1128 | { |
da090917 | 1129 | u32 reg_val; |
464f6645 MC |
1130 | u8 shift; |
1131 | ||
da090917 | 1132 | /* Update PRS register */ |
464f6645 MC |
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; | |
da090917 | 1135 | SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, eth_geneve_enable); |
464f6645 | 1136 | shift = PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GENEVE_ENABLE_SHIFT; |
da090917 | 1137 | SET_TUNNEL_TYPE_ENABLE_BIT(reg_val, shift, ip_geneve_enable); |
464f6645 | 1138 | qed_wr(p_hwfn, p_ptt, PRS_REG_ENCAPSULATION_TYPE_EN, reg_val); |
50bc60cb MK |
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 | } | |
464f6645 | 1148 | |
da090917 | 1149 | /* Update NIG register */ |
464f6645 MC |
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 | ||
da090917 | 1154 | /* EDPM with geneve tunnel not supported in BB */ |
464f6645 MC |
1155 | if (QED_IS_BB_B0(p_hwfn->cdev)) |
1156 | return; | |
1157 | ||
da090917 TT |
1158 | /* Update DORQ registers */ |
1159 | qed_wr(p_hwfn, | |
1160 | p_ptt, | |
1161 | DORQ_REG_L2_EDPM_TUNNEL_NGE_ETH_EN_K2_E5, | |
464f6645 | 1162 | eth_geneve_enable ? 1 : 0); |
da090917 TT |
1163 | qed_wr(p_hwfn, |
1164 | p_ptt, | |
1165 | DORQ_REG_L2_EDPM_TUNNEL_NGE_IP_EN_K2_E5, | |
464f6645 MC |
1166 | ip_geneve_enable ? 1 : 0); |
1167 | } | |
d51e4af5 | 1168 | |
50bc60cb MK |
1169 | #define PRS_ETH_VXLAN_NO_L2_ENABLE_OFFSET 4 |
1170 | #define PRS_ETH_VXLAN_NO_L2_OUTPUT_FORMAT -927094512 | |
1171 | ||
1172 | void 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 | ||
7b6859fb MY |
1201 | #define T_ETH_PACKET_ACTION_GFT_EVENTID 23 |
1202 | #define PARSER_ETH_CONN_GFT_ACTION_CM_HDR 272 | |
d51e4af5 | 1203 | #define T_ETH_PACKET_MATCH_RFS_EVENTID 25 |
7b6859fb | 1204 | #define PARSER_ETH_CONN_CM_HDR 0 |
d51e4af5 CM |
1205 | #define CAM_LINE_SIZE sizeof(u32) |
1206 | #define RAM_LINE_SIZE sizeof(u64) | |
1207 | #define REG_SIZE sizeof(u32) | |
1208 | ||
da090917 | 1209 | void qed_gft_disable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, u16 pf_id) |
d51e4af5 | 1210 | { |
da090917 | 1211 | /* Disable gft search for PF */ |
d51e4af5 | 1212 | qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_GFT, 0); |
da090917 TT |
1213 | |
1214 | /* Clean ram & cam for next gft session */ | |
1215 | ||
1216 | /* Zero camline */ | |
7b6859fb | 1217 | qed_wr(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE * pf_id, 0); |
da090917 TT |
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); | |
d51e4af5 CM |
1226 | } |
1227 | ||
da090917 | 1228 | void qed_set_gft_event_id_cm_hdr(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) |
d51e4af5 | 1229 | { |
7b6859fb | 1230 | u32 rfs_cm_hdr_event_id; |
d51e4af5 | 1231 | |
da090917 | 1232 | /* Set RFS event ID to be awakened i Tstorm By Prs */ |
d51e4af5 | 1233 | rfs_cm_hdr_event_id = qed_rd(p_hwfn, p_ptt, PRS_REG_CM_HDR_GFT); |
da090917 TT |
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 | ||
1241 | void 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 | { | |
d52c89f1 | 1248 | u32 reg_val, cam_line, ram_line_lo, ram_line_hi, search_non_ip_as_gft; |
d51e4af5 CM |
1249 | |
1250 | if (!ipv6 && !ipv4) | |
1251 | DP_NOTICE(p_hwfn, | |
da090917 | 1252 | "gft_config: must accept at least on of - ipv4 or ipv6'\n"); |
d51e4af5 CM |
1253 | if (!tcp && !udp) |
1254 | DP_NOTICE(p_hwfn, | |
da090917 TT |
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"); | |
d51e4af5 | 1258 | |
da090917 TT |
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); | |
d51e4af5 | 1264 | |
da090917 | 1265 | /* Do not load context only cid in PRS on match. */ |
d51e4af5 | 1266 | qed_wr(p_hwfn, p_ptt, PRS_REG_LOAD_L2_FILTER, 0); |
d51e4af5 | 1267 | |
da090917 TT |
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); | |
d51e4af5 | 1274 | |
da090917 TT |
1275 | /* Filters are per PF!! */ |
1276 | SET_FIELD(cam_line, | |
7b6859fb MY |
1277 | GFT_CAM_LINE_MAPPED_PF_ID_MASK, |
1278 | GFT_CAM_LINE_MAPPED_PF_ID_MASK_MASK); | |
da090917 TT |
1279 | SET_FIELD(cam_line, GFT_CAM_LINE_MAPPED_PF_ID, pf_id); |
1280 | ||
d51e4af5 | 1281 | if (!(tcp && udp)) { |
da090917 | 1282 | SET_FIELD(cam_line, |
7b6859fb MY |
1283 | GFT_CAM_LINE_MAPPED_UPPER_PROTOCOL_TYPE_MASK, |
1284 | GFT_CAM_LINE_MAPPED_UPPER_PROTOCOL_TYPE_MASK_MASK); | |
d51e4af5 | 1285 | if (tcp) |
da090917 | 1286 | SET_FIELD(cam_line, |
d51e4af5 CM |
1287 | GFT_CAM_LINE_MAPPED_UPPER_PROTOCOL_TYPE, |
1288 | GFT_PROFILE_TCP_PROTOCOL); | |
1289 | else | |
da090917 | 1290 | SET_FIELD(cam_line, |
d51e4af5 CM |
1291 | GFT_CAM_LINE_MAPPED_UPPER_PROTOCOL_TYPE, |
1292 | GFT_PROFILE_UDP_PROTOCOL); | |
1293 | } | |
1294 | ||
1295 | if (!(ipv4 && ipv6)) { | |
da090917 | 1296 | SET_FIELD(cam_line, GFT_CAM_LINE_MAPPED_IP_VERSION_MASK, 1); |
d51e4af5 | 1297 | if (ipv4) |
da090917 | 1298 | SET_FIELD(cam_line, |
d51e4af5 CM |
1299 | GFT_CAM_LINE_MAPPED_IP_VERSION, |
1300 | GFT_PROFILE_IPV4); | |
1301 | else | |
da090917 | 1302 | SET_FIELD(cam_line, |
d51e4af5 CM |
1303 | GFT_CAM_LINE_MAPPED_IP_VERSION, |
1304 | GFT_PROFILE_IPV6); | |
1305 | } | |
1306 | ||
7b6859fb | 1307 | /* Write characteristics to cam */ |
d51e4af5 | 1308 | qed_wr(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE * pf_id, |
da090917 TT |
1309 | cam_line); |
1310 | cam_line = | |
1311 | qed_rd(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE * pf_id); | |
d51e4af5 | 1312 | |
7b6859fb | 1313 | /* Write line to RAM - compare to filter 4 tuple */ |
da090917 TT |
1314 | ram_line_lo = 0; |
1315 | ram_line_hi = 0; | |
1316 | ||
d52c89f1 MK |
1317 | /* Search no IP as GFT */ |
1318 | search_non_ip_as_gft = 0; | |
1319 | ||
50bc60cb MK |
1320 | /* Tunnel type */ |
1321 | SET_FIELD(ram_line_lo, GFT_RAM_LINE_TUNNEL_DST_PORT, 1); | |
1322 | SET_FIELD(ram_line_lo, GFT_RAM_LINE_TUNNEL_OVER_IP_PROTOCOL, 1); | |
1323 | ||
da090917 TT |
1324 | if (profile_type == GFT_PROFILE_TYPE_4_TUPLE) { |
1325 | SET_FIELD(ram_line_hi, GFT_RAM_LINE_DST_IP, 1); | |
1326 | SET_FIELD(ram_line_hi, GFT_RAM_LINE_SRC_IP, 1); | |
1327 | SET_FIELD(ram_line_hi, GFT_RAM_LINE_OVER_IP_PROTOCOL, 1); | |
1328 | SET_FIELD(ram_line_lo, GFT_RAM_LINE_ETHERTYPE, 1); | |
1329 | SET_FIELD(ram_line_lo, GFT_RAM_LINE_SRC_PORT, 1); | |
1330 | SET_FIELD(ram_line_lo, GFT_RAM_LINE_DST_PORT, 1); | |
1331 | } else if (profile_type == GFT_PROFILE_TYPE_L4_DST_PORT) { | |
1332 | SET_FIELD(ram_line_hi, GFT_RAM_LINE_OVER_IP_PROTOCOL, 1); | |
1333 | SET_FIELD(ram_line_lo, GFT_RAM_LINE_ETHERTYPE, 1); | |
1334 | SET_FIELD(ram_line_lo, GFT_RAM_LINE_DST_PORT, 1); | |
50bc60cb | 1335 | } else if (profile_type == GFT_PROFILE_TYPE_IP_DST_ADDR) { |
da090917 TT |
1336 | SET_FIELD(ram_line_hi, GFT_RAM_LINE_DST_IP, 1); |
1337 | SET_FIELD(ram_line_lo, GFT_RAM_LINE_ETHERTYPE, 1); | |
50bc60cb MK |
1338 | } else if (profile_type == GFT_PROFILE_TYPE_IP_SRC_ADDR) { |
1339 | SET_FIELD(ram_line_hi, GFT_RAM_LINE_SRC_IP, 1); | |
1340 | SET_FIELD(ram_line_lo, GFT_RAM_LINE_ETHERTYPE, 1); | |
1341 | } else if (profile_type == GFT_PROFILE_TYPE_TUNNEL_TYPE) { | |
1342 | SET_FIELD(ram_line_lo, GFT_RAM_LINE_TUNNEL_ETHERTYPE, 1); | |
d52c89f1 MK |
1343 | |
1344 | /* Allow tunneled traffic without inner IP */ | |
1345 | search_non_ip_as_gft = 1; | |
da090917 TT |
1346 | } |
1347 | ||
d52c89f1 MK |
1348 | qed_wr(p_hwfn, |
1349 | p_ptt, PRS_REG_SEARCH_NON_IP_AS_GFT, search_non_ip_as_gft); | |
da090917 TT |
1350 | qed_wr(p_hwfn, |
1351 | p_ptt, | |
7b6859fb | 1352 | PRS_REG_GFT_PROFILE_MASK_RAM + RAM_LINE_SIZE * pf_id, |
da090917 TT |
1353 | ram_line_lo); |
1354 | qed_wr(p_hwfn, | |
1355 | p_ptt, | |
1356 | PRS_REG_GFT_PROFILE_MASK_RAM + RAM_LINE_SIZE * pf_id + REG_SIZE, | |
1357 | ram_line_hi); | |
7b6859fb MY |
1358 | |
1359 | /* Set default profile so that no filter match will happen */ | |
da090917 TT |
1360 | qed_wr(p_hwfn, |
1361 | p_ptt, | |
1362 | PRS_REG_GFT_PROFILE_MASK_RAM + RAM_LINE_SIZE * | |
1363 | PRS_GFT_CAM_LINES_NO_MATCH, 0xffffffff); | |
1364 | qed_wr(p_hwfn, | |
1365 | p_ptt, | |
1366 | PRS_REG_GFT_PROFILE_MASK_RAM + RAM_LINE_SIZE * | |
1367 | PRS_GFT_CAM_LINES_NO_MATCH + REG_SIZE, 0x3ff); | |
1368 | ||
1369 | /* Enable gft search */ | |
1370 | qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_GFT, 1); | |
1371 | } | |
1372 | ||
1373 | DECLARE_CRC8_TABLE(cdu_crc8_table); | |
1374 | ||
1375 | /* Calculate and return CDU validation byte per connection type/region/cid */ | |
1376 | static u8 qed_calc_cdu_validation_byte(u8 conn_type, u8 region, u32 cid) | |
1377 | { | |
1378 | const u8 validation_cfg = CDU_VALIDATION_DEFAULT_CFG; | |
1379 | u8 crc, validation_byte = 0; | |
1380 | static u8 crc8_table_valid; /* automatically initialized to 0 */ | |
1381 | u32 validation_string = 0; | |
1382 | u32 data_to_crc; | |
1383 | ||
1384 | if (!crc8_table_valid) { | |
1385 | crc8_populate_msb(cdu_crc8_table, 0x07); | |
1386 | crc8_table_valid = 1; | |
1387 | } | |
1388 | ||
1389 | /* The CRC is calculated on the String-to-compress: | |
1390 | * [31:8] = {CID[31:20],CID[11:0]} | |
1391 | * [7:4] = Region | |
1392 | * [3:0] = Type | |
1393 | */ | |
1394 | if ((validation_cfg >> CDU_CONTEXT_VALIDATION_CFG_USE_CID) & 1) | |
1395 | validation_string |= (cid & 0xFFF00000) | ((cid & 0xFFF) << 8); | |
1396 | ||
1397 | if ((validation_cfg >> CDU_CONTEXT_VALIDATION_CFG_USE_REGION) & 1) | |
1398 | validation_string |= ((region & 0xF) << 4); | |
1399 | ||
1400 | if ((validation_cfg >> CDU_CONTEXT_VALIDATION_CFG_USE_TYPE) & 1) | |
1401 | validation_string |= (conn_type & 0xF); | |
1402 | ||
1403 | /* Convert to big-endian and calculate CRC8 */ | |
1404 | data_to_crc = be32_to_cpu(validation_string); | |
1405 | ||
1406 | crc = crc8(cdu_crc8_table, | |
1407 | (u8 *)&data_to_crc, sizeof(data_to_crc), CRC8_INIT_VALUE); | |
1408 | ||
1409 | /* The validation byte [7:0] is composed: | |
1410 | * for type A validation | |
1411 | * [7] = active configuration bit | |
1412 | * [6:0] = crc[6:0] | |
1413 | * | |
1414 | * for type B validation | |
1415 | * [7] = active configuration bit | |
1416 | * [6:3] = connection_type[3:0] | |
1417 | * [2:0] = crc[2:0] | |
1418 | */ | |
1419 | validation_byte |= | |
1420 | ((validation_cfg >> | |
1421 | CDU_CONTEXT_VALIDATION_CFG_USE_ACTIVE) & 1) << 7; | |
1422 | ||
1423 | if ((validation_cfg >> | |
1424 | CDU_CONTEXT_VALIDATION_CFG_VALIDATION_TYPE_SHIFT) & 1) | |
1425 | validation_byte |= ((conn_type & 0xF) << 3) | (crc & 0x7); | |
1426 | else | |
1427 | validation_byte |= crc & 0x7F; | |
1428 | ||
1429 | return validation_byte; | |
1430 | } | |
1431 | ||
1432 | /* Calcualte and set validation bytes for session context */ | |
1433 | void qed_calc_session_ctx_validation(void *p_ctx_mem, | |
1434 | u16 ctx_size, u8 ctx_type, u32 cid) | |
1435 | { | |
1436 | u8 *x_val_ptr, *t_val_ptr, *u_val_ptr, *p_ctx; | |
1437 | ||
1438 | p_ctx = (u8 * const)p_ctx_mem; | |
1439 | x_val_ptr = &p_ctx[con_region_offsets[0][ctx_type]]; | |
1440 | t_val_ptr = &p_ctx[con_region_offsets[1][ctx_type]]; | |
1441 | u_val_ptr = &p_ctx[con_region_offsets[2][ctx_type]]; | |
1442 | ||
1443 | memset(p_ctx, 0, ctx_size); | |
1444 | ||
1445 | *x_val_ptr = qed_calc_cdu_validation_byte(ctx_type, 3, cid); | |
1446 | *t_val_ptr = qed_calc_cdu_validation_byte(ctx_type, 4, cid); | |
1447 | *u_val_ptr = qed_calc_cdu_validation_byte(ctx_type, 5, cid); | |
1448 | } | |
1449 | ||
1450 | /* Calcualte and set validation bytes for task context */ | |
1451 | void qed_calc_task_ctx_validation(void *p_ctx_mem, | |
1452 | u16 ctx_size, u8 ctx_type, u32 tid) | |
1453 | { | |
1454 | u8 *p_ctx, *region1_val_ptr; | |
1455 | ||
1456 | p_ctx = (u8 * const)p_ctx_mem; | |
1457 | region1_val_ptr = &p_ctx[task_region_offsets[0][ctx_type]]; | |
1458 | ||
1459 | memset(p_ctx, 0, ctx_size); | |
1460 | ||
1461 | *region1_val_ptr = qed_calc_cdu_validation_byte(ctx_type, 1, tid); | |
1462 | } | |
1463 | ||
1464 | /* Memset session context to 0 while preserving validation bytes */ | |
1465 | void qed_memset_session_ctx(void *p_ctx_mem, u32 ctx_size, u8 ctx_type) | |
1466 | { | |
1467 | u8 *x_val_ptr, *t_val_ptr, *u_val_ptr, *p_ctx; | |
1468 | u8 x_val, t_val, u_val; | |
1469 | ||
1470 | p_ctx = (u8 * const)p_ctx_mem; | |
1471 | x_val_ptr = &p_ctx[con_region_offsets[0][ctx_type]]; | |
1472 | t_val_ptr = &p_ctx[con_region_offsets[1][ctx_type]]; | |
1473 | u_val_ptr = &p_ctx[con_region_offsets[2][ctx_type]]; | |
1474 | ||
1475 | x_val = *x_val_ptr; | |
1476 | t_val = *t_val_ptr; | |
1477 | u_val = *u_val_ptr; | |
1478 | ||
1479 | memset(p_ctx, 0, ctx_size); | |
1480 | ||
1481 | *x_val_ptr = x_val; | |
1482 | *t_val_ptr = t_val; | |
1483 | *u_val_ptr = u_val; | |
1484 | } | |
1485 | ||
1486 | /* Memset task context to 0 while preserving validation bytes */ | |
1487 | void qed_memset_task_ctx(void *p_ctx_mem, u32 ctx_size, u8 ctx_type) | |
1488 | { | |
1489 | u8 *p_ctx, *region1_val_ptr; | |
1490 | u8 region1_val; | |
1491 | ||
1492 | p_ctx = (u8 * const)p_ctx_mem; | |
1493 | region1_val_ptr = &p_ctx[task_region_offsets[0][ctx_type]]; | |
1494 | ||
1495 | region1_val = *region1_val_ptr; | |
1496 | ||
1497 | memset(p_ctx, 0, ctx_size); | |
1498 | ||
1499 | *region1_val_ptr = region1_val; | |
1500 | } | |
1501 | ||
1502 | /* Enable and configure context validation */ | |
1503 | void qed_enable_context_validation(struct qed_hwfn *p_hwfn, | |
1504 | struct qed_ptt *p_ptt) | |
1505 | { | |
1506 | u32 ctx_validation; | |
1507 | ||
1508 | /* Enable validation for connection region 3: CCFC_CTX_VALID0[31:24] */ | |
1509 | ctx_validation = CDU_VALIDATION_DEFAULT_CFG << 24; | |
1510 | qed_wr(p_hwfn, p_ptt, CDU_REG_CCFC_CTX_VALID0, ctx_validation); | |
1511 | ||
1512 | /* Enable validation for connection region 5: CCFC_CTX_VALID1[15:8] */ | |
1513 | ctx_validation = CDU_VALIDATION_DEFAULT_CFG << 8; | |
1514 | qed_wr(p_hwfn, p_ptt, CDU_REG_CCFC_CTX_VALID1, ctx_validation); | |
1515 | ||
1516 | /* Enable validation for connection region 1: TCFC_CTX_VALID0[15:8] */ | |
1517 | ctx_validation = CDU_VALIDATION_DEFAULT_CFG << 8; | |
1518 | qed_wr(p_hwfn, p_ptt, CDU_REG_TCFC_CTX_VALID0, ctx_validation); | |
d51e4af5 | 1519 | } |
d52c89f1 MK |
1520 | |
1521 | static u32 qed_get_rdma_assert_ram_addr(struct qed_hwfn *p_hwfn, u8 storm_id) | |
1522 | { | |
1523 | switch (storm_id) { | |
1524 | case 0: | |
1525 | return TSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM + | |
1526 | TSTORM_RDMA_ASSERT_LEVEL_OFFSET(p_hwfn->rel_pf_id); | |
1527 | case 1: | |
1528 | return MSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM + | |
1529 | MSTORM_RDMA_ASSERT_LEVEL_OFFSET(p_hwfn->rel_pf_id); | |
1530 | case 2: | |
1531 | return USEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM + | |
1532 | USTORM_RDMA_ASSERT_LEVEL_OFFSET(p_hwfn->rel_pf_id); | |
1533 | case 3: | |
1534 | return XSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM + | |
1535 | XSTORM_RDMA_ASSERT_LEVEL_OFFSET(p_hwfn->rel_pf_id); | |
1536 | case 4: | |
1537 | return YSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM + | |
1538 | YSTORM_RDMA_ASSERT_LEVEL_OFFSET(p_hwfn->rel_pf_id); | |
1539 | case 5: | |
1540 | return PSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM + | |
1541 | PSTORM_RDMA_ASSERT_LEVEL_OFFSET(p_hwfn->rel_pf_id); | |
1542 | ||
1543 | default: | |
1544 | return 0; | |
1545 | } | |
1546 | } | |
1547 | ||
1548 | void qed_set_rdma_error_level(struct qed_hwfn *p_hwfn, | |
1549 | struct qed_ptt *p_ptt, | |
1550 | u8 assert_level[NUM_STORMS]) | |
1551 | { | |
1552 | u8 storm_id; | |
1553 | ||
1554 | for (storm_id = 0; storm_id < NUM_STORMS; storm_id++) { | |
1555 | u32 ram_addr = qed_get_rdma_assert_ram_addr(p_hwfn, storm_id); | |
1556 | ||
1557 | qed_wr(p_hwfn, p_ptt, ram_addr, assert_level[storm_id]); | |
1558 | } | |
1559 | } |