Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2001-2023 Intel Corporation
3 : : */
4 : :
5 : : #include "ice_common.h"
6 : : #include "ice_ddp.h"
7 : : #include "ice_flex_pipe.h"
8 : : #include "ice_protocol_type.h"
9 : : #include "ice_flow.h"
10 : :
11 : : static const struct ice_tunnel_type_scan tnls[] = {
12 : : { TNL_VXLAN, "TNL_VXLAN_PF" },
13 : : { TNL_GENEVE, "TNL_GENEVE_PF" },
14 : : { TNL_ECPRI, "TNL_UDP_ECPRI_PF" },
15 : : { TNL_LAST, "" }
16 : : };
17 : :
18 : : static const u32 ice_sect_lkup[ICE_BLK_COUNT][ICE_SECT_COUNT] = {
19 : : /* SWITCH */
20 : : {
21 : : ICE_SID_XLT0_SW,
22 : : ICE_SID_XLT_KEY_BUILDER_SW,
23 : : ICE_SID_XLT1_SW,
24 : : ICE_SID_XLT2_SW,
25 : : ICE_SID_PROFID_TCAM_SW,
26 : : ICE_SID_PROFID_REDIR_SW,
27 : : ICE_SID_FLD_VEC_SW,
28 : : ICE_SID_CDID_KEY_BUILDER_SW,
29 : : ICE_SID_CDID_REDIR_SW
30 : : },
31 : :
32 : : /* ACL */
33 : : {
34 : : ICE_SID_XLT0_ACL,
35 : : ICE_SID_XLT_KEY_BUILDER_ACL,
36 : : ICE_SID_XLT1_ACL,
37 : : ICE_SID_XLT2_ACL,
38 : : ICE_SID_PROFID_TCAM_ACL,
39 : : ICE_SID_PROFID_REDIR_ACL,
40 : : ICE_SID_FLD_VEC_ACL,
41 : : ICE_SID_CDID_KEY_BUILDER_ACL,
42 : : ICE_SID_CDID_REDIR_ACL
43 : : },
44 : :
45 : : /* FD */
46 : : {
47 : : ICE_SID_XLT0_FD,
48 : : ICE_SID_XLT_KEY_BUILDER_FD,
49 : : ICE_SID_XLT1_FD,
50 : : ICE_SID_XLT2_FD,
51 : : ICE_SID_PROFID_TCAM_FD,
52 : : ICE_SID_PROFID_REDIR_FD,
53 : : ICE_SID_FLD_VEC_FD,
54 : : ICE_SID_CDID_KEY_BUILDER_FD,
55 : : ICE_SID_CDID_REDIR_FD
56 : : },
57 : :
58 : : /* RSS */
59 : : {
60 : : ICE_SID_XLT0_RSS,
61 : : ICE_SID_XLT_KEY_BUILDER_RSS,
62 : : ICE_SID_XLT1_RSS,
63 : : ICE_SID_XLT2_RSS,
64 : : ICE_SID_PROFID_TCAM_RSS,
65 : : ICE_SID_PROFID_REDIR_RSS,
66 : : ICE_SID_FLD_VEC_RSS,
67 : : ICE_SID_CDID_KEY_BUILDER_RSS,
68 : : ICE_SID_CDID_REDIR_RSS
69 : : },
70 : :
71 : : /* PE */
72 : : {
73 : : ICE_SID_XLT0_PE,
74 : : ICE_SID_XLT_KEY_BUILDER_PE,
75 : : ICE_SID_XLT1_PE,
76 : : ICE_SID_XLT2_PE,
77 : : ICE_SID_PROFID_TCAM_PE,
78 : : ICE_SID_PROFID_REDIR_PE,
79 : : ICE_SID_FLD_VEC_PE,
80 : : ICE_SID_CDID_KEY_BUILDER_PE,
81 : : ICE_SID_CDID_REDIR_PE
82 : : }
83 : : };
84 : :
85 : : /**
86 : : * ice_sect_id - returns section ID
87 : : * @blk: block type
88 : : * @sect: section type
89 : : *
90 : : * This helper function returns the proper section ID given a block type and a
91 : : * section type.
92 : : */
93 : : static u32 ice_sect_id(enum ice_block blk, enum ice_sect sect)
94 : : {
95 : 0 : return ice_sect_lkup[blk][sect];
96 : : }
97 : :
98 : : /**
99 : : * ice_add_tunnel_hint
100 : : * @hw: pointer to the HW structure
101 : : * @label_name: label text
102 : : * @val: value of the tunnel port boost entry
103 : : */
104 : 0 : void ice_add_tunnel_hint(struct ice_hw *hw, char *label_name, u16 val)
105 : : {
106 [ # # ]: 0 : if (hw->tnl.count < ICE_TUNNEL_MAX_ENTRIES) {
107 : : u16 i;
108 : :
109 [ # # ]: 0 : for (i = 0; tnls[i].type != TNL_LAST; i++) {
110 : 0 : size_t len = strlen(tnls[i].label_prefix);
111 : :
112 : : /* Look for matching label start, before continuing */
113 [ # # ]: 0 : if (strncmp(label_name, tnls[i].label_prefix, len))
114 : 0 : continue;
115 : :
116 : : /* Make sure this label matches our PF. Note that the PF
117 : : * character ('0' - '7') will be located where our
118 : : * prefix string's null terminator is located.
119 : : */
120 [ # # ]: 0 : if ((label_name[len] - '0') == hw->pf_id) {
121 : 0 : hw->tnl.tbl[hw->tnl.count].type = tnls[i].type;
122 : 0 : hw->tnl.tbl[hw->tnl.count].valid = false;
123 : 0 : hw->tnl.tbl[hw->tnl.count].in_use = false;
124 : 0 : hw->tnl.tbl[hw->tnl.count].marked = false;
125 : 0 : hw->tnl.tbl[hw->tnl.count].boost_addr = val;
126 : 0 : hw->tnl.tbl[hw->tnl.count].port = 0;
127 : 0 : hw->tnl.count++;
128 : 0 : break;
129 : : }
130 : : }
131 : : }
132 : 0 : }
133 : :
134 : : /**
135 : : * ice_add_dvm_hint
136 : : * @hw: pointer to the HW structure
137 : : * @val: value of the boost entry
138 : : * @enable: true if entry needs to be enabled, or false if needs to be disabled
139 : : */
140 : 0 : void ice_add_dvm_hint(struct ice_hw *hw, u16 val, bool enable)
141 : : {
142 [ # # ]: 0 : if (hw->dvm_upd.count < ICE_DVM_MAX_ENTRIES) {
143 : 0 : hw->dvm_upd.tbl[hw->dvm_upd.count].boost_addr = val;
144 : 0 : hw->dvm_upd.tbl[hw->dvm_upd.count].enable = enable;
145 : 0 : hw->dvm_upd.count++;
146 : : }
147 : 0 : }
148 : :
149 : : /* Key creation */
150 : :
151 : : #define ICE_DC_KEY 0x1 /* don't care */
152 : : #define ICE_DC_KEYINV 0x1
153 : : #define ICE_NM_KEY 0x0 /* never match */
154 : : #define ICE_NM_KEYINV 0x0
155 : : #define ICE_0_KEY 0x1 /* match 0 */
156 : : #define ICE_0_KEYINV 0x0
157 : : #define ICE_1_KEY 0x0 /* match 1 */
158 : : #define ICE_1_KEYINV 0x1
159 : :
160 : : /**
161 : : * ice_gen_key_word - generate 16-bits of a key/mask word
162 : : * @val: the value
163 : : * @valid: valid bits mask (change only the valid bits)
164 : : * @dont_care: don't care mask
165 : : * @nvr_mtch: never match mask
166 : : * @key: pointer to an array of where the resulting key portion
167 : : * @key_inv: pointer to an array of where the resulting key invert portion
168 : : *
169 : : * This function generates 16-bits from a 8-bit value, an 8-bit don't care mask
170 : : * and an 8-bit never match mask. The 16-bits of output are divided into 8 bits
171 : : * of key and 8 bits of key invert.
172 : : *
173 : : * '0' = b01, always match a 0 bit
174 : : * '1' = b10, always match a 1 bit
175 : : * '?' = b11, don't care bit (always matches)
176 : : * '~' = b00, never match bit
177 : : *
178 : : * Input:
179 : : * val: b0 1 0 1 0 1
180 : : * dont_care: b0 0 1 1 0 0
181 : : * never_mtch: b0 0 0 0 1 1
182 : : * ------------------------------
183 : : * Result: key: b01 10 11 11 00 00
184 : : */
185 : : static enum ice_status
186 : 0 : ice_gen_key_word(u8 val, u8 valid, u8 dont_care, u8 nvr_mtch, u8 *key,
187 : : u8 *key_inv)
188 : : {
189 : 0 : u8 in_key = *key, in_key_inv = *key_inv;
190 : : u8 i;
191 : :
192 : : /* 'dont_care' and 'nvr_mtch' masks cannot overlap */
193 [ # # ]: 0 : if ((dont_care ^ nvr_mtch) != (dont_care | nvr_mtch))
194 : : return ICE_ERR_CFG;
195 : :
196 : 0 : *key = 0;
197 : 0 : *key_inv = 0;
198 : :
199 : : /* encode the 8 bits into 8-bit key and 8-bit key invert */
200 [ # # ]: 0 : for (i = 0; i < 8; i++) {
201 : 0 : *key >>= 1;
202 : 0 : *key_inv >>= 1;
203 : :
204 [ # # ]: 0 : if (!(valid & 0x1)) { /* change only valid bits */
205 : 0 : *key |= (in_key & 0x1) << 7;
206 : 0 : *key_inv |= (in_key_inv & 0x1) << 7;
207 [ # # ]: 0 : } else if (dont_care & 0x1) { /* don't care bit */
208 : 0 : *key |= ICE_DC_KEY << 7;
209 : 0 : *key_inv |= ICE_DC_KEYINV << 7;
210 [ # # ]: 0 : } else if (nvr_mtch & 0x1) { /* never match bit */
211 : : *key |= ICE_NM_KEY << 7;
212 : : *key_inv |= ICE_NM_KEYINV << 7;
213 [ # # ]: 0 : } else if (val & 0x01) { /* exact 1 match */
214 : : *key |= ICE_1_KEY << 7;
215 : 0 : *key_inv |= ICE_1_KEYINV << 7;
216 : : } else { /* exact 0 match */
217 : 0 : *key |= ICE_0_KEY << 7;
218 : : *key_inv |= ICE_0_KEYINV << 7;
219 : : }
220 : :
221 : 0 : dont_care >>= 1;
222 : 0 : nvr_mtch >>= 1;
223 : 0 : valid >>= 1;
224 : 0 : val >>= 1;
225 : 0 : in_key >>= 1;
226 : 0 : in_key_inv >>= 1;
227 : : }
228 : :
229 : : return ICE_SUCCESS;
230 : : }
231 : :
232 : : /**
233 : : * ice_bits_max_set - determine if the number of bits set is within a maximum
234 : : * @mask: pointer to the byte array which is the mask
235 : : * @size: the number of bytes in the mask
236 : : * @max: the max number of set bits
237 : : *
238 : : * This function determines if there are at most 'max' number of bits set in an
239 : : * array. Returns true if the number for bits set is <= max or will return false
240 : : * otherwise.
241 : : */
242 : : static bool ice_bits_max_set(const u8 *mask, u16 size, u16 max)
243 : : {
244 : : u16 count = 0;
245 : : u16 i;
246 : :
247 : : /* check each byte */
248 [ # # ]: 0 : for (i = 0; i < size; i++) {
249 : : /* if 0, go to next byte */
250 [ # # ]: 0 : if (!mask[i])
251 : 0 : continue;
252 : :
253 : : /* We know there is at least one set bit in this byte because of
254 : : * the above check; if we already have found 'max' number of
255 : : * bits set, then we can return failure now.
256 : : */
257 [ # # ]: 0 : if (count == max)
258 : : return false;
259 : :
260 : : /* count the bits in this byte, checking threshold */
261 : 0 : count += ice_hweight8(mask[i]);
262 [ # # ]: 0 : if (count > max)
263 : : return false;
264 : : }
265 : :
266 : : return true;
267 : : }
268 : :
269 : : /**
270 : : * ice_set_key - generate a variable sized key with multiples of 16-bits
271 : : * @key: pointer to where the key will be stored
272 : : * @size: the size of the complete key in bytes (must be even)
273 : : * @val: array of 8-bit values that makes up the value portion of the key
274 : : * @upd: array of 8-bit masks that determine what key portion to update
275 : : * @dc: array of 8-bit masks that make up the don't care mask
276 : : * @nm: array of 8-bit masks that make up the never match mask
277 : : * @off: the offset of the first byte in the key to update
278 : : * @len: the number of bytes in the key update
279 : : *
280 : : * This function generates a key from a value, a don't care mask and a never
281 : : * match mask.
282 : : * upd, dc, and nm are optional parameters, and can be NULL:
283 : : * upd == NULL --> upd mask is all 1's (update all bits)
284 : : * dc == NULL --> dc mask is all 0's (no don't care bits)
285 : : * nm == NULL --> nm mask is all 0's (no never match bits)
286 : : */
287 : : enum ice_status
288 : 0 : ice_set_key(u8 *key, u16 size, u8 *val, u8 *upd, u8 *dc, u8 *nm, u16 off,
289 : : u16 len)
290 : : {
291 : : u16 half_size;
292 : : u16 i;
293 : :
294 : : /* size must be a multiple of 2 bytes. */
295 [ # # ]: 0 : if (size % 2)
296 : : return ICE_ERR_CFG;
297 : 0 : half_size = size / 2;
298 : :
299 [ # # ]: 0 : if (off + len > half_size)
300 : : return ICE_ERR_CFG;
301 : :
302 : : /* Make sure at most one bit is set in the never match mask. Having more
303 : : * than one never match mask bit set will cause HW to consume excessive
304 : : * power otherwise; this is a power management efficiency check.
305 : : */
306 : : #define ICE_NVR_MTCH_BITS_MAX 1
307 [ # # # # ]: 0 : if (nm && !ice_bits_max_set(nm, len, ICE_NVR_MTCH_BITS_MAX))
308 : : return ICE_ERR_CFG;
309 : :
310 [ # # ]: 0 : for (i = 0; i < len; i++)
311 [ # # # # : 0 : if (ice_gen_key_word(val[i], upd ? upd[i] : 0xff,
# # ]
312 : 0 : dc ? dc[i] : 0, nm ? nm[i] : 0,
313 [ # # ]: 0 : key + off + i, key + half_size + off + i))
314 : : return ICE_ERR_CFG;
315 : :
316 : : return ICE_SUCCESS;
317 : : }
318 : :
319 : : /**
320 : : * ice_tunnel_port_in_use_hlpr - helper function to determine tunnel usage
321 : : * @hw: pointer to the HW structure
322 : : * @port: port to search for
323 : : * @index: optionally returns index
324 : : *
325 : : * Returns whether a port is already in use as a tunnel, and optionally its
326 : : * index
327 : : */
328 : : static bool ice_tunnel_port_in_use_hlpr(struct ice_hw *hw, u16 port, u16 *index)
329 : : {
330 : : u16 i;
331 : :
332 [ # # # # : 0 : for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
# # # # #
# # # ]
333 [ # # # # : 0 : if (hw->tnl.tbl[i].in_use && hw->tnl.tbl[i].port == port) {
# # # # #
# # # ]
334 [ # # ]: 0 : if (index)
335 : 0 : *index = i;
336 : : return true;
337 : : }
338 : :
339 : : return false;
340 : : }
341 : :
342 : : /**
343 : : * ice_tunnel_port_in_use
344 : : * @hw: pointer to the HW structure
345 : : * @port: port to search for
346 : : * @index: optionally returns index
347 : : *
348 : : * Returns whether a port is already in use as a tunnel, and optionally its
349 : : * index
350 : : */
351 : 0 : bool ice_tunnel_port_in_use(struct ice_hw *hw, u16 port, u16 *index)
352 : : {
353 : : bool res;
354 : :
355 : 0 : ice_acquire_lock(&hw->tnl_lock);
356 : : res = ice_tunnel_port_in_use_hlpr(hw, port, index);
357 : : ice_release_lock(&hw->tnl_lock);
358 : :
359 : 0 : return res;
360 : : }
361 : :
362 : : /**
363 : : * ice_tunnel_get_type
364 : : * @hw: pointer to the HW structure
365 : : * @port: port to search for
366 : : * @type: returns tunnel index
367 : : *
368 : : * For a given port number, will return the type of tunnel.
369 : : */
370 : : bool
371 : 0 : ice_tunnel_get_type(struct ice_hw *hw, u16 port, enum ice_tunnel_type *type)
372 : : {
373 : : bool res = false;
374 : : u16 i;
375 : :
376 : 0 : ice_acquire_lock(&hw->tnl_lock);
377 : :
378 [ # # # # ]: 0 : for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
379 [ # # # # ]: 0 : if (hw->tnl.tbl[i].in_use && hw->tnl.tbl[i].port == port) {
380 : 0 : *type = hw->tnl.tbl[i].type;
381 : : res = true;
382 : 0 : break;
383 : : }
384 : :
385 : : ice_release_lock(&hw->tnl_lock);
386 : :
387 : 0 : return res;
388 : : }
389 : :
390 : : /**
391 : : * ice_find_free_tunnel_entry
392 : : * @hw: pointer to the HW structure
393 : : * @type: tunnel type
394 : : * @index: optionally returns index
395 : : *
396 : : * Returns whether there is a free tunnel entry, and optionally its index
397 : : */
398 : : static bool
399 : : ice_find_free_tunnel_entry(struct ice_hw *hw, enum ice_tunnel_type type,
400 : : u16 *index)
401 : : {
402 : : u16 i;
403 : :
404 [ # # # # ]: 0 : for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
405 [ # # # # ]: 0 : if (hw->tnl.tbl[i].valid && !hw->tnl.tbl[i].in_use &&
406 [ # # ]: 0 : hw->tnl.tbl[i].type == type) {
407 : : if (index)
408 : : *index = i;
409 : : return true;
410 : : }
411 : :
412 : : return false;
413 : : }
414 : :
415 : : /**
416 : : * ice_get_open_tunnel_port - retrieve an open tunnel port
417 : : * @hw: pointer to the HW structure
418 : : * @type: tunnel type (TNL_ALL will return any open port)
419 : : * @port: returns open port
420 : : */
421 : : bool
422 : 0 : ice_get_open_tunnel_port(struct ice_hw *hw, enum ice_tunnel_type type,
423 : : u16 *port)
424 : : {
425 : : bool res = false;
426 : : u16 i;
427 : :
428 : 0 : ice_acquire_lock(&hw->tnl_lock);
429 : :
430 [ # # # # ]: 0 : for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
431 [ # # # # : 0 : if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].in_use &&
# # ]
432 [ # # ]: 0 : (type == TNL_ALL || hw->tnl.tbl[i].type == type)) {
433 : 0 : *port = hw->tnl.tbl[i].port;
434 : : res = true;
435 : 0 : break;
436 : : }
437 : :
438 : : ice_release_lock(&hw->tnl_lock);
439 : :
440 : 0 : return res;
441 : : }
442 : :
443 : : /**
444 : : * ice_upd_dvm_boost_entry
445 : : * @hw: pointer to the HW structure
446 : : * @entry: pointer to double vlan boost entry info
447 : : */
448 : : static enum ice_status
449 : 0 : ice_upd_dvm_boost_entry(struct ice_hw *hw, struct ice_dvm_entry *entry)
450 : : {
451 : : struct ice_boost_tcam_section *sect_rx, *sect_tx;
452 : : enum ice_status status = ICE_ERR_MAX_LIMIT;
453 : : struct ice_buf_build *bld;
454 : : u8 val, dc, nm;
455 : :
456 : 0 : bld = ice_pkg_buf_alloc(hw);
457 [ # # ]: 0 : if (!bld)
458 : : return ICE_ERR_NO_MEMORY;
459 : :
460 : : /* allocate 2 sections, one for Rx parser, one for Tx parser */
461 [ # # ]: 0 : if (ice_pkg_buf_reserve_section(bld, 2))
462 : 0 : goto ice_upd_dvm_boost_entry_err;
463 : :
464 : : sect_rx = (struct ice_boost_tcam_section *)
465 : 0 : ice_pkg_buf_alloc_section(bld, ICE_SID_RXPARSER_BOOST_TCAM,
466 : : ice_struct_size(sect_rx, tcam, 1));
467 [ # # ]: 0 : if (!sect_rx)
468 : 0 : goto ice_upd_dvm_boost_entry_err;
469 : 0 : sect_rx->count = CPU_TO_LE16(1);
470 : :
471 : : sect_tx = (struct ice_boost_tcam_section *)
472 : 0 : ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM,
473 : : ice_struct_size(sect_tx, tcam, 1));
474 [ # # ]: 0 : if (!sect_tx)
475 : 0 : goto ice_upd_dvm_boost_entry_err;
476 : 0 : sect_tx->count = CPU_TO_LE16(1);
477 : :
478 : : /* copy original boost entry to update package buffer */
479 [ # # ]: 0 : ice_memcpy(sect_rx->tcam, entry->boost_entry, sizeof(*sect_rx->tcam),
480 : : ICE_NONDMA_TO_NONDMA);
481 : :
482 : : /* re-write the don't care and never match bits accordingly */
483 [ # # ]: 0 : if (entry->enable) {
484 : : /* all bits are don't care */
485 : 0 : val = 0x00;
486 : 0 : dc = 0xFF;
487 : 0 : nm = 0x00;
488 : : } else {
489 : : /* disable, one never match bit, the rest are don't care */
490 : 0 : val = 0x00;
491 : 0 : dc = 0xF7;
492 : 0 : nm = 0x08;
493 : : }
494 : :
495 : 0 : ice_set_key((u8 *)§_rx->tcam[0].key, sizeof(sect_rx->tcam[0].key),
496 : : &val, NULL, &dc, &nm, 0, sizeof(u8));
497 : :
498 : : /* exact copy of entry to Tx section entry */
499 [ # # ]: 0 : ice_memcpy(sect_tx->tcam, sect_rx->tcam, sizeof(*sect_tx->tcam),
500 : : ICE_NONDMA_TO_NONDMA);
501 : :
502 : 0 : status = ice_update_pkg_no_lock(hw, ice_pkg_buf(bld), 1);
503 : :
504 : 0 : ice_upd_dvm_boost_entry_err:
505 : 0 : ice_pkg_buf_free(hw, bld);
506 : :
507 : 0 : return status;
508 : : }
509 : :
510 : : /**
511 : : * ice_set_dvm_boost_entries
512 : : * @hw: pointer to the HW structure
513 : : *
514 : : * Enable double vlan by updating the appropriate boost tcam entries.
515 : : */
516 : 0 : enum ice_status ice_set_dvm_boost_entries(struct ice_hw *hw)
517 : : {
518 : : u16 i;
519 : :
520 [ # # ]: 0 : for (i = 0; i < hw->dvm_upd.count; i++) {
521 : : enum ice_status status;
522 : :
523 : 0 : status = ice_upd_dvm_boost_entry(hw, &hw->dvm_upd.tbl[i]);
524 [ # # ]: 0 : if (status)
525 : 0 : return status;
526 : : }
527 : :
528 : : return ICE_SUCCESS;
529 : : }
530 : :
531 : : /**
532 : : * ice_create_tunnel
533 : : * @hw: pointer to the HW structure
534 : : * @type: type of tunnel
535 : : * @port: port of tunnel to create
536 : : *
537 : : * Create a tunnel by updating the parse graph in the parser. We do that by
538 : : * creating a package buffer with the tunnel info and issuing an update package
539 : : * command.
540 : : */
541 : : enum ice_status
542 : 0 : ice_create_tunnel(struct ice_hw *hw, enum ice_tunnel_type type, u16 port)
543 : : {
544 : : struct ice_boost_tcam_section *sect_rx, *sect_tx;
545 : : enum ice_status status = ICE_ERR_MAX_LIMIT;
546 : : struct ice_buf_build *bld;
547 : : u16 index;
548 : :
549 : 0 : ice_acquire_lock(&hw->tnl_lock);
550 : :
551 : 0 : if (ice_tunnel_port_in_use_hlpr(hw, port, &index)) {
552 : 0 : hw->tnl.tbl[index].ref++;
553 : : status = ICE_SUCCESS;
554 : 0 : goto ice_create_tunnel_end;
555 : : }
556 : :
557 [ # # ]: 0 : if (!ice_find_free_tunnel_entry(hw, type, &index)) {
558 : : status = ICE_ERR_OUT_OF_RANGE;
559 : 0 : goto ice_create_tunnel_end;
560 : : }
561 : :
562 : 0 : bld = ice_pkg_buf_alloc(hw);
563 [ # # ]: 0 : if (!bld) {
564 : : status = ICE_ERR_NO_MEMORY;
565 : 0 : goto ice_create_tunnel_end;
566 : : }
567 : :
568 : : /* allocate 2 sections, one for Rx parser, one for Tx parser */
569 [ # # ]: 0 : if (ice_pkg_buf_reserve_section(bld, 2))
570 : 0 : goto ice_create_tunnel_err;
571 : :
572 : : sect_rx = (struct ice_boost_tcam_section *)
573 : 0 : ice_pkg_buf_alloc_section(bld, ICE_SID_RXPARSER_BOOST_TCAM,
574 : : ice_struct_size(sect_rx, tcam, 1));
575 [ # # ]: 0 : if (!sect_rx)
576 : 0 : goto ice_create_tunnel_err;
577 : 0 : sect_rx->count = CPU_TO_LE16(1);
578 : :
579 : : sect_tx = (struct ice_boost_tcam_section *)
580 : 0 : ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM,
581 : : ice_struct_size(sect_tx, tcam, 1));
582 [ # # ]: 0 : if (!sect_tx)
583 : 0 : goto ice_create_tunnel_err;
584 : 0 : sect_tx->count = CPU_TO_LE16(1);
585 : :
586 : : /* copy original boost entry to update package buffer */
587 [ # # ]: 0 : ice_memcpy(sect_rx->tcam, hw->tnl.tbl[index].boost_entry,
588 : : sizeof(*sect_rx->tcam), ICE_NONDMA_TO_NONDMA);
589 : :
590 : : /* over-write the never-match dest port key bits with the encoded port
591 : : * bits
592 : : */
593 : 0 : ice_set_key((u8 *)§_rx->tcam[0].key, sizeof(sect_rx->tcam[0].key),
594 : : (u8 *)&port, NULL, NULL, NULL,
595 : : (u16)offsetof(struct ice_boost_key_value, hv_dst_port_key),
596 : : sizeof(sect_rx->tcam[0].key.key.hv_dst_port_key));
597 : :
598 : : /* exact copy of entry to Tx section entry */
599 [ # # ]: 0 : ice_memcpy(sect_tx->tcam, sect_rx->tcam, sizeof(*sect_tx->tcam),
600 : : ICE_NONDMA_TO_NONDMA);
601 : :
602 : 0 : status = ice_update_pkg(hw, ice_pkg_buf(bld), 1);
603 [ # # ]: 0 : if (!status) {
604 : 0 : hw->tnl.tbl[index].port = port;
605 : 0 : hw->tnl.tbl[index].in_use = true;
606 : 0 : hw->tnl.tbl[index].ref = 1;
607 : : }
608 : :
609 : 0 : ice_create_tunnel_err:
610 : 0 : ice_pkg_buf_free(hw, bld);
611 : :
612 : 0 : ice_create_tunnel_end:
613 : : ice_release_lock(&hw->tnl_lock);
614 : :
615 : 0 : return status;
616 : : }
617 : :
618 : : /**
619 : : * ice_destroy_tunnel
620 : : * @hw: pointer to the HW structure
621 : : * @port: port of tunnel to destroy (ignored if the all parameter is true)
622 : : * @all: flag that states to destroy all tunnels
623 : : *
624 : : * Destroys a tunnel or all tunnels by creating an update package buffer
625 : : * targeting the specific updates requested and then performing an update
626 : : * package.
627 : : */
628 : 0 : enum ice_status ice_destroy_tunnel(struct ice_hw *hw, u16 port, bool all)
629 : : {
630 : : struct ice_boost_tcam_section *sect_rx, *sect_tx;
631 : : enum ice_status status = ICE_ERR_MAX_LIMIT;
632 : : struct ice_buf_build *bld;
633 : : u16 count = 0;
634 : : u16 index;
635 : : u16 size;
636 : : u16 i, j;
637 : :
638 : 0 : ice_acquire_lock(&hw->tnl_lock);
639 : :
640 [ # # ]: 0 : if (!all && ice_tunnel_port_in_use_hlpr(hw, port, &index))
641 [ # # ]: 0 : if (hw->tnl.tbl[index].ref > 1) {
642 : 0 : hw->tnl.tbl[index].ref--;
643 : : status = ICE_SUCCESS;
644 : 0 : goto ice_destroy_tunnel_end;
645 : : }
646 : :
647 : : /* determine count */
648 [ # # # # ]: 0 : for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
649 [ # # # # : 0 : if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].in_use &&
# # ]
650 [ # # ]: 0 : (all || hw->tnl.tbl[i].port == port))
651 : 0 : count++;
652 : :
653 [ # # ]: 0 : if (!count) {
654 : : status = ICE_ERR_PARAM;
655 : 0 : goto ice_destroy_tunnel_end;
656 : : }
657 : :
658 : : /* size of section - there is at least one entry */
659 : 0 : size = ice_struct_size(sect_rx, tcam, count);
660 : :
661 : 0 : bld = ice_pkg_buf_alloc(hw);
662 [ # # ]: 0 : if (!bld) {
663 : : status = ICE_ERR_NO_MEMORY;
664 : 0 : goto ice_destroy_tunnel_end;
665 : : }
666 : :
667 : : /* allocate 2 sections, one for Rx parser, one for Tx parser */
668 [ # # ]: 0 : if (ice_pkg_buf_reserve_section(bld, 2))
669 : 0 : goto ice_destroy_tunnel_err;
670 : :
671 : : sect_rx = (struct ice_boost_tcam_section *)
672 : 0 : ice_pkg_buf_alloc_section(bld, ICE_SID_RXPARSER_BOOST_TCAM,
673 : : size);
674 [ # # ]: 0 : if (!sect_rx)
675 : 0 : goto ice_destroy_tunnel_err;
676 : 0 : sect_rx->count = CPU_TO_LE16(count);
677 : :
678 : : sect_tx = (struct ice_boost_tcam_section *)
679 : 0 : ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM,
680 : : size);
681 [ # # ]: 0 : if (!sect_tx)
682 : 0 : goto ice_destroy_tunnel_err;
683 : 0 : sect_tx->count = CPU_TO_LE16(count);
684 : :
685 : : /* copy original boost entry to update package buffer, one copy to Rx
686 : : * section, another copy to the Tx section
687 : : */
688 [ # # # # ]: 0 : for (i = 0, j = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
689 [ # # # # : 0 : if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].in_use &&
# # ]
690 [ # # ]: 0 : (all || hw->tnl.tbl[i].port == port)) {
691 [ # # ]: 0 : ice_memcpy(sect_rx->tcam + j,
692 : : hw->tnl.tbl[i].boost_entry,
693 : : sizeof(*sect_rx->tcam),
694 : : ICE_NONDMA_TO_NONDMA);
695 [ # # ]: 0 : ice_memcpy(sect_tx->tcam + j,
696 : : hw->tnl.tbl[i].boost_entry,
697 : : sizeof(*sect_tx->tcam),
698 : : ICE_NONDMA_TO_NONDMA);
699 : 0 : hw->tnl.tbl[i].marked = true;
700 : 0 : j++;
701 : : }
702 : :
703 : 0 : status = ice_update_pkg(hw, ice_pkg_buf(bld), 1);
704 [ # # ]: 0 : if (!status)
705 [ # # # # ]: 0 : for (i = 0; i < hw->tnl.count &&
706 : 0 : i < ICE_TUNNEL_MAX_ENTRIES; i++)
707 [ # # ]: 0 : if (hw->tnl.tbl[i].marked) {
708 : 0 : hw->tnl.tbl[i].ref = 0;
709 : 0 : hw->tnl.tbl[i].port = 0;
710 : 0 : hw->tnl.tbl[i].in_use = false;
711 : 0 : hw->tnl.tbl[i].marked = false;
712 : : }
713 : :
714 : 0 : ice_destroy_tunnel_err:
715 : 0 : ice_pkg_buf_free(hw, bld);
716 : :
717 : 0 : ice_destroy_tunnel_end:
718 : : ice_release_lock(&hw->tnl_lock);
719 : :
720 : 0 : return status;
721 : : }
722 : :
723 : : /**
724 : : * ice_find_prot_off - find prot ID and offset pair, based on prof and FV index
725 : : * @hw: pointer to the hardware structure
726 : : * @blk: hardware block
727 : : * @prof: profile ID
728 : : * @fv_idx: field vector word index
729 : : * @prot: variable to receive the protocol ID
730 : : * @off: variable to receive the protocol offset
731 : : */
732 : : enum ice_status
733 : 0 : ice_find_prot_off(struct ice_hw *hw, enum ice_block blk, u8 prof, u8 fv_idx,
734 : : u8 *prot, u16 *off)
735 : : {
736 : : struct ice_fv_word *fv_ext;
737 : :
738 [ # # ]: 0 : if (prof >= hw->blk[blk].es.count)
739 : : return ICE_ERR_PARAM;
740 : :
741 [ # # ]: 0 : if (fv_idx >= hw->blk[blk].es.fvw)
742 : : return ICE_ERR_PARAM;
743 : :
744 : 0 : fv_ext = hw->blk[blk].es.t + (prof * hw->blk[blk].es.fvw);
745 : :
746 : 0 : *prot = fv_ext[fv_idx].prot_id;
747 : 0 : *off = fv_ext[fv_idx].off;
748 : :
749 : 0 : return ICE_SUCCESS;
750 : : }
751 : :
752 : : /* PTG Management */
753 : :
754 : : /**
755 : : * ice_ptg_find_ptype - Search for packet type group using packet type (ptype)
756 : : * @hw: pointer to the hardware structure
757 : : * @blk: HW block
758 : : * @ptype: the ptype to search for
759 : : * @ptg: pointer to variable that receives the PTG
760 : : *
761 : : * This function will search the PTGs for a particular ptype, returning the
762 : : * PTG ID that contains it through the PTG parameter, with the value of
763 : : * ICE_DEFAULT_PTG (0) meaning it is part the default PTG.
764 : : */
765 : : static enum ice_status
766 : : ice_ptg_find_ptype(struct ice_hw *hw, enum ice_block blk, u16 ptype, u8 *ptg)
767 : : {
768 : : if (ptype >= ICE_XLT1_CNT || !ptg)
769 : : return ICE_ERR_PARAM;
770 : :
771 [ # # ]: 0 : *ptg = hw->blk[blk].xlt1.ptypes[ptype].ptg;
772 : : return ICE_SUCCESS;
773 : : }
774 : :
775 : : /**
776 : : * ice_ptg_alloc_val - Allocates a new packet type group ID by value
777 : : * @hw: pointer to the hardware structure
778 : : * @blk: HW block
779 : : * @ptg: the PTG to allocate
780 : : *
781 : : * This function allocates a given packet type group ID specified by the PTG
782 : : * parameter.
783 : : */
784 : : static void ice_ptg_alloc_val(struct ice_hw *hw, enum ice_block blk, u8 ptg)
785 : : {
786 : 0 : hw->blk[blk].xlt1.ptg_tbl[ptg].in_use = true;
787 : : }
788 : :
789 : : /**
790 : : * ice_ptg_remove_ptype - Removes ptype from a particular packet type group
791 : : * @hw: pointer to the hardware structure
792 : : * @blk: HW block
793 : : * @ptype: the ptype to remove
794 : : * @ptg: the PTG to remove the ptype from
795 : : *
796 : : * This function will remove the ptype from the specific PTG, and move it to
797 : : * the default PTG (ICE_DEFAULT_PTG).
798 : : */
799 : : static enum ice_status
800 : 0 : ice_ptg_remove_ptype(struct ice_hw *hw, enum ice_block blk, u16 ptype, u8 ptg)
801 : : {
802 : : struct ice_ptg_ptype **ch;
803 : : struct ice_ptg_ptype *p;
804 : :
805 [ # # ]: 0 : if (ptype > ICE_XLT1_CNT - 1)
806 : : return ICE_ERR_PARAM;
807 : :
808 [ # # ]: 0 : if (!hw->blk[blk].xlt1.ptg_tbl[ptg].in_use)
809 : : return ICE_ERR_DOES_NOT_EXIST;
810 : :
811 : : /* Should not happen if .in_use is set, bad config */
812 [ # # ]: 0 : if (!hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype)
813 : : return ICE_ERR_CFG;
814 : :
815 : : /* find the ptype within this PTG, and bypass the link over it */
816 : : p = hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype;
817 : 0 : ch = &hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype;
818 [ # # ]: 0 : while (p) {
819 [ # # ]: 0 : if (ptype == (p - hw->blk[blk].xlt1.ptypes)) {
820 : 0 : *ch = p->next_ptype;
821 : 0 : break;
822 : : }
823 : :
824 : 0 : ch = &p->next_ptype;
825 : 0 : p = p->next_ptype;
826 : : }
827 : :
828 : 0 : hw->blk[blk].xlt1.ptypes[ptype].ptg = ICE_DEFAULT_PTG;
829 : 0 : hw->blk[blk].xlt1.ptypes[ptype].next_ptype = NULL;
830 : :
831 : 0 : return ICE_SUCCESS;
832 : : }
833 : :
834 : : /**
835 : : * ice_ptg_add_mv_ptype - Adds/moves ptype to a particular packet type group
836 : : * @hw: pointer to the hardware structure
837 : : * @blk: HW block
838 : : * @ptype: the ptype to add or move
839 : : * @ptg: the PTG to add or move the ptype to
840 : : *
841 : : * This function will either add or move a ptype to a particular PTG depending
842 : : * on if the ptype is already part of another group. Note that using a
843 : : * a destination PTG ID of ICE_DEFAULT_PTG (0) will move the ptype to the
844 : : * default PTG.
845 : : */
846 : : static enum ice_status
847 : 0 : ice_ptg_add_mv_ptype(struct ice_hw *hw, enum ice_block blk, u16 ptype, u8 ptg)
848 : : {
849 : : enum ice_status status;
850 : : u8 original_ptg;
851 : :
852 [ # # ]: 0 : if (ptype > ICE_XLT1_CNT - 1)
853 : : return ICE_ERR_PARAM;
854 : :
855 [ # # # # ]: 0 : if (!hw->blk[blk].xlt1.ptg_tbl[ptg].in_use && ptg != ICE_DEFAULT_PTG)
856 : : return ICE_ERR_DOES_NOT_EXIST;
857 : :
858 : 0 : status = ice_ptg_find_ptype(hw, blk, ptype, &original_ptg);
859 : : if (status)
860 : : return status;
861 : :
862 : : /* Is ptype already in the correct PTG? */
863 [ # # ]: 0 : if (original_ptg == ptg)
864 : : return ICE_SUCCESS;
865 : :
866 : : /* Remove from original PTG and move back to the default PTG */
867 [ # # ]: 0 : if (original_ptg != ICE_DEFAULT_PTG)
868 : 0 : ice_ptg_remove_ptype(hw, blk, ptype, original_ptg);
869 : :
870 : : /* Moving to default PTG? Then we're done with this request */
871 [ # # ]: 0 : if (ptg == ICE_DEFAULT_PTG)
872 : : return ICE_SUCCESS;
873 : :
874 : : /* Add ptype to PTG at beginning of list */
875 : 0 : hw->blk[blk].xlt1.ptypes[ptype].next_ptype =
876 : 0 : hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype;
877 : 0 : hw->blk[blk].xlt1.ptg_tbl[ptg].first_ptype =
878 : : &hw->blk[blk].xlt1.ptypes[ptype];
879 : :
880 : 0 : hw->blk[blk].xlt1.ptypes[ptype].ptg = ptg;
881 : 0 : hw->blk[blk].xlt1.t[ptype] = ptg;
882 : :
883 : 0 : return ICE_SUCCESS;
884 : : }
885 : :
886 : : /* Block / table size info */
887 : : struct ice_blk_size_details {
888 : : u16 xlt1; /* # XLT1 entries */
889 : : u16 xlt2; /* # XLT2 entries */
890 : : u16 prof_tcam; /* # profile ID TCAM entries */
891 : : u16 prof_id; /* # profile IDs */
892 : : u8 prof_cdid_bits; /* # CDID one-hot bits used in key */
893 : : u16 prof_redir; /* # profile redirection entries */
894 : : u16 es; /* # extraction sequence entries */
895 : : u16 fvw; /* # field vector words */
896 : : u8 overwrite; /* overwrite existing entries allowed */
897 : : u8 reverse; /* reverse FV order */
898 : : };
899 : :
900 : : static const struct ice_blk_size_details blk_sizes[ICE_BLK_COUNT] = {
901 : : /**
902 : : * Table Definitions
903 : : * XLT1 - Number of entries in XLT1 table
904 : : * XLT2 - Number of entries in XLT2 table
905 : : * TCAM - Number of entries Profile ID TCAM table
906 : : * CDID - Control Domain ID of the hardware block
907 : : * PRED - Number of entries in the Profile Redirection Table
908 : : * FV - Number of entries in the Field Vector
909 : : * FVW - Width (in WORDs) of the Field Vector
910 : : * OVR - Overwrite existing table entries
911 : : * REV - Reverse FV
912 : : */
913 : : /* XLT1 , XLT2 ,TCAM, PID,CDID,PRED, FV, FVW */
914 : : /* Overwrite , Reverse FV */
915 : : /* SW */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 512, 256, 0, 256, 256, 48,
916 : : false, false },
917 : : /* ACL */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 512, 128, 0, 128, 128, 32,
918 : : false, false },
919 : : /* FD */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 512, 128, 0, 128, 128, 24,
920 : : false, true },
921 : : /* RSS */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 512, 128, 0, 128, 128, 24,
922 : : true, true },
923 : : /* PE */ { ICE_XLT1_CNT, ICE_XLT2_CNT, 64, 32, 0, 32, 32, 24,
924 : : false, false },
925 : : };
926 : :
927 : : enum ice_sid_all {
928 : : ICE_SID_XLT1_OFF = 0,
929 : : ICE_SID_XLT2_OFF,
930 : : ICE_SID_PR_OFF,
931 : : ICE_SID_PR_REDIR_OFF,
932 : : ICE_SID_ES_OFF,
933 : : ICE_SID_OFF_COUNT,
934 : : };
935 : :
936 : : /* Characteristic handling */
937 : :
938 : : /**
939 : : * ice_match_prop_lst - determine if properties of two lists match
940 : : * @list1: first properties list
941 : : * @list2: second properties list
942 : : *
943 : : * Count, cookies and the order must match in order to be considered equivalent.
944 : : */
945 : : static bool
946 : 0 : ice_match_prop_lst(struct LIST_HEAD_TYPE *list1, struct LIST_HEAD_TYPE *list2)
947 : : {
948 : : struct ice_vsig_prof *tmp1;
949 : : struct ice_vsig_prof *tmp2;
950 : : u16 chk_count = 0;
951 : : u16 count = 0;
952 : :
953 : : /* compare counts */
954 [ # # # # ]: 0 : LIST_FOR_EACH_ENTRY(tmp1, list1, ice_vsig_prof, list)
955 [ # # ]: 0 : count++;
956 [ # # # # ]: 0 : LIST_FOR_EACH_ENTRY(tmp2, list2, ice_vsig_prof, list)
957 [ # # ]: 0 : chk_count++;
958 [ # # ]: 0 : if (!count || count != chk_count)
959 : : return false;
960 : :
961 : : tmp1 = LIST_FIRST_ENTRY(list1, struct ice_vsig_prof, list);
962 : : tmp2 = LIST_FIRST_ENTRY(list2, struct ice_vsig_prof, list);
963 : :
964 : : /* profile cookies must compare, and in the exact same order to take
965 : : * into account priority
966 : : */
967 [ # # ]: 0 : while (count--) {
968 [ # # ]: 0 : if (tmp2->profile_cookie != tmp1->profile_cookie)
969 : : return false;
970 : :
971 : 0 : tmp1 = LIST_NEXT_ENTRY(tmp1, struct ice_vsig_prof, list);
972 : 0 : tmp2 = LIST_NEXT_ENTRY(tmp2, struct ice_vsig_prof, list);
973 : : }
974 : :
975 : : return true;
976 : : }
977 : :
978 : : /* VSIG Management */
979 : :
980 : : /**
981 : : * ice_vsig_find_vsi - find a VSIG that contains a specified VSI
982 : : * @hw: pointer to the hardware structure
983 : : * @blk: HW block
984 : : * @vsi: VSI of interest
985 : : * @vsig: pointer to receive the VSI group
986 : : *
987 : : * This function will lookup the VSI entry in the XLT2 list and return
988 : : * the VSI group its associated with.
989 : : */
990 : : enum ice_status
991 : 0 : ice_vsig_find_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 *vsig)
992 : : {
993 [ # # ]: 0 : if (!vsig || vsi >= ICE_MAX_VSI)
994 : : return ICE_ERR_PARAM;
995 : :
996 : : /* As long as there's a default or valid VSIG associated with the input
997 : : * VSI, the functions returns a success. Any handling of VSIG will be
998 : : * done by the following add, update or remove functions.
999 : : */
1000 : 0 : *vsig = hw->blk[blk].xlt2.vsis[vsi].vsig;
1001 : :
1002 : 0 : return ICE_SUCCESS;
1003 : : }
1004 : :
1005 : : /**
1006 : : * ice_vsig_alloc_val - allocate a new VSIG by value
1007 : : * @hw: pointer to the hardware structure
1008 : : * @blk: HW block
1009 : : * @vsig: the VSIG to allocate
1010 : : *
1011 : : * This function will allocate a given VSIG specified by the VSIG parameter.
1012 : : */
1013 : : static u16 ice_vsig_alloc_val(struct ice_hw *hw, enum ice_block blk, u16 vsig)
1014 : : {
1015 : 0 : u16 idx = vsig & ICE_VSIG_IDX_M;
1016 : :
1017 [ # # ]: 0 : if (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use) {
1018 : 0 : INIT_LIST_HEAD(&hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst);
1019 : 0 : hw->blk[blk].xlt2.vsig_tbl[idx].in_use = true;
1020 : : }
1021 : :
1022 : 0 : return ICE_VSIG_VALUE(idx, hw->pf_id);
1023 : : }
1024 : :
1025 : : /**
1026 : : * ice_vsig_alloc - Finds a free entry and allocates a new VSIG
1027 : : * @hw: pointer to the hardware structure
1028 : : * @blk: HW block
1029 : : *
1030 : : * This function will iterate through the VSIG list and mark the first
1031 : : * unused entry for the new VSIG entry as used and return that value.
1032 : : */
1033 : 0 : static u16 ice_vsig_alloc(struct ice_hw *hw, enum ice_block blk)
1034 : : {
1035 : : u16 i;
1036 : :
1037 [ # # ]: 0 : for (i = 1; i < ICE_MAX_VSIGS; i++)
1038 [ # # ]: 0 : if (!hw->blk[blk].xlt2.vsig_tbl[i].in_use)
1039 : 0 : return ice_vsig_alloc_val(hw, blk, i);
1040 : :
1041 : : return ICE_DEFAULT_VSIG;
1042 : : }
1043 : :
1044 : : /**
1045 : : * ice_find_dup_props_vsig - find VSI group with a specified set of properties
1046 : : * @hw: pointer to the hardware structure
1047 : : * @blk: HW block
1048 : : * @chs: characteristic list
1049 : : * @vsig: returns the VSIG with the matching profiles, if found
1050 : : *
1051 : : * Each VSIG is associated with a characteristic set; i.e. all VSIs under
1052 : : * a group have the same characteristic set. To check if there exists a VSIG
1053 : : * which has the same characteristics as the input characteristics; this
1054 : : * function will iterate through the XLT2 list and return the VSIG that has a
1055 : : * matching configuration. In order to make sure that priorities are accounted
1056 : : * for, the list must match exactly, including the order in which the
1057 : : * characteristics are listed.
1058 : : */
1059 : : static enum ice_status
1060 : 0 : ice_find_dup_props_vsig(struct ice_hw *hw, enum ice_block blk,
1061 : : struct LIST_HEAD_TYPE *chs, u16 *vsig)
1062 : : {
1063 : : struct ice_xlt2 *xlt2 = &hw->blk[blk].xlt2;
1064 : : u16 i;
1065 : :
1066 [ # # ]: 0 : for (i = 0; i < xlt2->count; i++)
1067 [ # # # # ]: 0 : if (xlt2->vsig_tbl[i].in_use &&
1068 : 0 : ice_match_prop_lst(chs, &xlt2->vsig_tbl[i].prop_lst)) {
1069 : 0 : *vsig = ICE_VSIG_VALUE(i, hw->pf_id);
1070 : 0 : return ICE_SUCCESS;
1071 : : }
1072 : :
1073 : : return ICE_ERR_DOES_NOT_EXIST;
1074 : : }
1075 : :
1076 : : /**
1077 : : * ice_vsig_free - free VSI group
1078 : : * @hw: pointer to the hardware structure
1079 : : * @blk: HW block
1080 : : * @vsig: VSIG to remove
1081 : : *
1082 : : * The function will remove all VSIs associated with the input VSIG and move
1083 : : * them to the DEFAULT_VSIG and mark the VSIG available.
1084 : : */
1085 : : static enum ice_status
1086 : 0 : ice_vsig_free(struct ice_hw *hw, enum ice_block blk, u16 vsig)
1087 : : {
1088 : : struct ice_vsig_prof *dtmp, *del;
1089 : : struct ice_vsig_vsi *vsi_cur;
1090 : : u16 idx;
1091 : :
1092 : 0 : idx = vsig & ICE_VSIG_IDX_M;
1093 [ # # ]: 0 : if (idx >= ICE_MAX_VSIGS)
1094 : : return ICE_ERR_PARAM;
1095 : :
1096 [ # # ]: 0 : if (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use)
1097 : : return ICE_ERR_DOES_NOT_EXIST;
1098 : :
1099 : 0 : hw->blk[blk].xlt2.vsig_tbl[idx].in_use = false;
1100 : :
1101 : 0 : vsi_cur = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi;
1102 : : /* If the VSIG has at least 1 VSI then iterate through the
1103 : : * list and remove the VSIs before deleting the group.
1104 : : */
1105 [ # # ]: 0 : if (vsi_cur) {
1106 : : /* remove all vsis associated with this VSIG XLT2 entry */
1107 : : do {
1108 : 0 : struct ice_vsig_vsi *tmp = vsi_cur->next_vsi;
1109 : :
1110 : 0 : vsi_cur->vsig = ICE_DEFAULT_VSIG;
1111 : 0 : vsi_cur->changed = 1;
1112 : 0 : vsi_cur->next_vsi = NULL;
1113 : : vsi_cur = tmp;
1114 [ # # ]: 0 : } while (vsi_cur);
1115 : :
1116 : : /* NULL terminate head of VSI list */
1117 : 0 : hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi = NULL;
1118 : : }
1119 : :
1120 : : /* free characteristic list */
1121 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(del, dtmp,
# # # # #
# ]
1122 : : &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst,
1123 : : ice_vsig_prof, list) {
1124 [ # # ]: 0 : LIST_DEL(&del->list);
1125 : 0 : ice_free(hw, del);
1126 : : }
1127 : :
1128 : : /* if VSIG characteristic list was cleared for reset
1129 : : * re-initialize the list head
1130 : : */
1131 : 0 : INIT_LIST_HEAD(&hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst);
1132 : :
1133 : 0 : return ICE_SUCCESS;
1134 : : }
1135 : :
1136 : : /**
1137 : : * ice_vsig_remove_vsi - remove VSI from VSIG
1138 : : * @hw: pointer to the hardware structure
1139 : : * @blk: HW block
1140 : : * @vsi: VSI to remove
1141 : : * @vsig: VSI group to remove from
1142 : : *
1143 : : * The function will remove the input VSI from its VSI group and move it
1144 : : * to the DEFAULT_VSIG.
1145 : : */
1146 : : static enum ice_status
1147 : 0 : ice_vsig_remove_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig)
1148 : : {
1149 : : struct ice_vsig_vsi **vsi_head, *vsi_cur, *vsi_tgt;
1150 : : u16 idx;
1151 : :
1152 : 0 : idx = vsig & ICE_VSIG_IDX_M;
1153 : :
1154 [ # # ]: 0 : if (vsi >= ICE_MAX_VSI || idx >= ICE_MAX_VSIGS)
1155 : : return ICE_ERR_PARAM;
1156 : :
1157 [ # # ]: 0 : if (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use)
1158 : : return ICE_ERR_DOES_NOT_EXIST;
1159 : :
1160 : : /* entry already in default VSIG, don't have to remove */
1161 [ # # ]: 0 : if (idx == ICE_DEFAULT_VSIG)
1162 : : return ICE_SUCCESS;
1163 : :
1164 : 0 : vsi_head = &hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi;
1165 [ # # ]: 0 : if (!(*vsi_head))
1166 : : return ICE_ERR_CFG;
1167 : :
1168 : 0 : vsi_tgt = &hw->blk[blk].xlt2.vsis[vsi];
1169 : : vsi_cur = (*vsi_head);
1170 : :
1171 : : /* iterate the VSI list, skip over the entry to be removed */
1172 [ # # ]: 0 : while (vsi_cur) {
1173 [ # # ]: 0 : if (vsi_tgt == vsi_cur) {
1174 : 0 : (*vsi_head) = vsi_cur->next_vsi;
1175 : 0 : break;
1176 : : }
1177 : 0 : vsi_head = &vsi_cur->next_vsi;
1178 : 0 : vsi_cur = vsi_cur->next_vsi;
1179 : : }
1180 : :
1181 : : /* verify if VSI was removed from group list */
1182 [ # # ]: 0 : if (!vsi_cur)
1183 : : return ICE_ERR_DOES_NOT_EXIST;
1184 : :
1185 : 0 : vsi_cur->vsig = ICE_DEFAULT_VSIG;
1186 : 0 : vsi_cur->changed = 1;
1187 : 0 : vsi_cur->next_vsi = NULL;
1188 : :
1189 : 0 : return ICE_SUCCESS;
1190 : : }
1191 : :
1192 : : /**
1193 : : * ice_vsig_add_mv_vsi - add or move a VSI to a VSI group
1194 : : * @hw: pointer to the hardware structure
1195 : : * @blk: HW block
1196 : : * @vsi: VSI to move
1197 : : * @vsig: destination VSI group
1198 : : *
1199 : : * This function will move or add the input VSI to the target VSIG.
1200 : : * The function will find the original VSIG the VSI belongs to and
1201 : : * move the entry to the DEFAULT_VSIG, update the original VSIG and
1202 : : * then move entry to the new VSIG.
1203 : : */
1204 : : static enum ice_status
1205 : 0 : ice_vsig_add_mv_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig)
1206 : : {
1207 : : struct ice_vsig_vsi *tmp;
1208 : : enum ice_status status;
1209 : : u16 orig_vsig, idx;
1210 : :
1211 : 0 : idx = vsig & ICE_VSIG_IDX_M;
1212 : :
1213 [ # # ]: 0 : if (vsi >= ICE_MAX_VSI || idx >= ICE_MAX_VSIGS)
1214 : : return ICE_ERR_PARAM;
1215 : :
1216 : : /* if VSIG not in use and VSIG is not default type this VSIG
1217 : : * doesn't exist.
1218 : : */
1219 [ # # # # ]: 0 : if (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use &&
1220 : : vsig != ICE_DEFAULT_VSIG)
1221 : : return ICE_ERR_DOES_NOT_EXIST;
1222 : :
1223 : 0 : status = ice_vsig_find_vsi(hw, blk, vsi, &orig_vsig);
1224 [ # # ]: 0 : if (status)
1225 : : return status;
1226 : :
1227 : : /* no update required if vsigs match */
1228 [ # # ]: 0 : if (orig_vsig == vsig)
1229 : : return ICE_SUCCESS;
1230 : :
1231 [ # # ]: 0 : if (orig_vsig != ICE_DEFAULT_VSIG) {
1232 : : /* remove entry from orig_vsig and add to default VSIG */
1233 : 0 : status = ice_vsig_remove_vsi(hw, blk, vsi, orig_vsig);
1234 [ # # ]: 0 : if (status)
1235 : : return status;
1236 : : }
1237 : :
1238 [ # # ]: 0 : if (idx == ICE_DEFAULT_VSIG)
1239 : : return ICE_SUCCESS;
1240 : :
1241 : : /* Create VSI entry and add VSIG and prop_mask values */
1242 : 0 : hw->blk[blk].xlt2.vsis[vsi].vsig = vsig;
1243 : 0 : hw->blk[blk].xlt2.vsis[vsi].changed = 1;
1244 : :
1245 : : /* Add new entry to the head of the VSIG list */
1246 : 0 : tmp = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi;
1247 : 0 : hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi =
1248 : : &hw->blk[blk].xlt2.vsis[vsi];
1249 : 0 : hw->blk[blk].xlt2.vsis[vsi].next_vsi = tmp;
1250 : 0 : hw->blk[blk].xlt2.t[vsi] = vsig;
1251 : :
1252 : 0 : return ICE_SUCCESS;
1253 : : }
1254 : :
1255 : : /**
1256 : : * ice_prof_has_mask_idx - determine if profile index masking is identical
1257 : : * @hw: pointer to the hardware structure
1258 : : * @blk: HW block
1259 : : * @prof: profile to check
1260 : : * @idx: profile index to check
1261 : : * @mask: mask to match
1262 : : */
1263 : : static bool
1264 : 0 : ice_prof_has_mask_idx(struct ice_hw *hw, enum ice_block blk, u8 prof, u16 idx,
1265 : : u16 mask)
1266 : : {
1267 : : bool expect_no_mask = false;
1268 : : bool found = false;
1269 : : bool match = false;
1270 : : u16 i;
1271 : :
1272 : : /* If mask is 0x0000 or 0xffff, then there is no masking */
1273 [ # # ]: 0 : if (mask == 0 || mask == 0xffff)
1274 : : expect_no_mask = true;
1275 : :
1276 : : /* Scan the enabled masks on this profile, for the specified idx */
1277 : 0 : for (i = hw->blk[blk].masks.first; i < hw->blk[blk].masks.first +
1278 [ # # ]: 0 : hw->blk[blk].masks.count; i++)
1279 [ # # ]: 0 : if (hw->blk[blk].es.mask_ena[prof] & BIT(i))
1280 [ # # ]: 0 : if (hw->blk[blk].masks.masks[i].in_use &&
1281 [ # # ]: 0 : hw->blk[blk].masks.masks[i].idx == idx) {
1282 : : found = true;
1283 [ # # ]: 0 : if (hw->blk[blk].masks.masks[i].mask == mask)
1284 : : match = true;
1285 : : break;
1286 : : }
1287 : :
1288 [ # # ]: 0 : if (expect_no_mask) {
1289 [ # # ]: 0 : if (found)
1290 : 0 : return false;
1291 : : } else {
1292 [ # # ]: 0 : if (!match)
1293 : 0 : return false;
1294 : : }
1295 : :
1296 : : return true;
1297 : : }
1298 : :
1299 : : /**
1300 : : * ice_prof_has_mask - determine if profile masking is identical
1301 : : * @hw: pointer to the hardware structure
1302 : : * @blk: HW block
1303 : : * @prof: profile to check
1304 : : * @masks: masks to match
1305 : : */
1306 : : static bool
1307 : 0 : ice_prof_has_mask(struct ice_hw *hw, enum ice_block blk, u8 prof, u16 *masks)
1308 : : {
1309 : : u16 i;
1310 : :
1311 : : /* es->mask_ena[prof] will have the mask */
1312 [ # # ]: 0 : for (i = 0; i < hw->blk[blk].es.fvw; i++)
1313 [ # # ]: 0 : if (!ice_prof_has_mask_idx(hw, blk, prof, i, masks[i]))
1314 : : return false;
1315 : :
1316 : : return true;
1317 : : }
1318 : :
1319 : : /**
1320 : : * ice_find_prof_id_with_mask - find profile ID for a given field vector
1321 : : * @hw: pointer to the hardware structure
1322 : : * @blk: HW block
1323 : : * @fv: field vector to search for
1324 : : * @masks: masks for fv
1325 : : * @prof_id: receives the profile ID
1326 : : */
1327 : : static enum ice_status
1328 : 0 : ice_find_prof_id_with_mask(struct ice_hw *hw, enum ice_block blk,
1329 : : struct ice_fv_word *fv, u16 *masks, u8 *prof_id)
1330 : : {
1331 : : struct ice_es *es = &hw->blk[blk].es;
1332 : : u8 i;
1333 : :
1334 : : /* For FD and RSS, we don't want to re-use an existed profile with the
1335 : : * same field vector and mask. This will cause rule interference.
1336 : : */
1337 [ # # ]: 0 : if (blk == ICE_BLK_FD || blk == ICE_BLK_RSS)
1338 : : return ICE_ERR_DOES_NOT_EXIST;
1339 : :
1340 [ # # ]: 0 : for (i = 0; i < (u8)es->count; i++) {
1341 : 0 : u16 off = i * es->fvw;
1342 : :
1343 [ # # ]: 0 : if (memcmp(&es->t[off], fv, es->fvw * sizeof(*fv)))
1344 : 0 : continue;
1345 : :
1346 : : /* check if masks settings are the same for this profile */
1347 [ # # # # ]: 0 : if (masks && !ice_prof_has_mask(hw, blk, i, masks))
1348 : 0 : continue;
1349 : :
1350 : 0 : *prof_id = i;
1351 : 0 : return ICE_SUCCESS;
1352 : : }
1353 : :
1354 : : return ICE_ERR_DOES_NOT_EXIST;
1355 : : }
1356 : :
1357 : : /**
1358 : : * ice_prof_id_rsrc_type - get profile ID resource type for a block type
1359 : : * @blk: the block type
1360 : : * @rsrc_type: pointer to variable to receive the resource type
1361 : : */
1362 : : static bool ice_prof_id_rsrc_type(enum ice_block blk, u16 *rsrc_type)
1363 : : {
1364 : : switch (blk) {
1365 : : case ICE_BLK_SW:
1366 : : *rsrc_type = ICE_AQC_RES_TYPE_SWITCH_PROF_BLDR_PROFID;
1367 : : break;
1368 : : case ICE_BLK_ACL:
1369 : : *rsrc_type = ICE_AQC_RES_TYPE_ACL_PROF_BLDR_PROFID;
1370 : : break;
1371 : : case ICE_BLK_FD:
1372 : : *rsrc_type = ICE_AQC_RES_TYPE_FD_PROF_BLDR_PROFID;
1373 : : break;
1374 : : case ICE_BLK_RSS:
1375 : : *rsrc_type = ICE_AQC_RES_TYPE_HASH_PROF_BLDR_PROFID;
1376 : : break;
1377 : : case ICE_BLK_PE:
1378 : : *rsrc_type = ICE_AQC_RES_TYPE_QHASH_PROF_BLDR_PROFID;
1379 : : break;
1380 : : default:
1381 : : return false;
1382 : : }
1383 : : return true;
1384 : : }
1385 : :
1386 : : /**
1387 : : * ice_tcam_ent_rsrc_type - get TCAM entry resource type for a block type
1388 : : * @blk: the block type
1389 : : * @rsrc_type: pointer to variable to receive the resource type
1390 : : */
1391 : : static bool ice_tcam_ent_rsrc_type(enum ice_block blk, u16 *rsrc_type)
1392 : : {
1393 : : switch (blk) {
1394 : : case ICE_BLK_SW:
1395 : : *rsrc_type = ICE_AQC_RES_TYPE_SWITCH_PROF_BLDR_TCAM;
1396 : : break;
1397 : : case ICE_BLK_ACL:
1398 : : *rsrc_type = ICE_AQC_RES_TYPE_ACL_PROF_BLDR_TCAM;
1399 : : break;
1400 : : case ICE_BLK_FD:
1401 : : *rsrc_type = ICE_AQC_RES_TYPE_FD_PROF_BLDR_TCAM;
1402 : : break;
1403 : : case ICE_BLK_RSS:
1404 : : *rsrc_type = ICE_AQC_RES_TYPE_HASH_PROF_BLDR_TCAM;
1405 : : break;
1406 : : case ICE_BLK_PE:
1407 : : *rsrc_type = ICE_AQC_RES_TYPE_QHASH_PROF_BLDR_TCAM;
1408 : : break;
1409 : : default:
1410 : : return false;
1411 : : }
1412 : : return true;
1413 : : }
1414 : :
1415 : : /**
1416 : : * ice_alloc_tcam_ent - allocate hardware TCAM entry
1417 : : * @hw: pointer to the HW struct
1418 : : * @blk: the block to allocate the TCAM for
1419 : : * @btm: true to allocate from bottom of table, false to allocate from top
1420 : : * @tcam_idx: pointer to variable to receive the TCAM entry
1421 : : *
1422 : : * This function allocates a new entry in a Profile ID TCAM for a specific
1423 : : * block.
1424 : : */
1425 : : static enum ice_status
1426 : : ice_alloc_tcam_ent(struct ice_hw *hw, enum ice_block blk, bool btm,
1427 : : u16 *tcam_idx)
1428 : : {
1429 : : u16 res_type;
1430 : :
1431 : : if (!ice_tcam_ent_rsrc_type(blk, &res_type))
1432 : : return ICE_ERR_PARAM;
1433 : :
1434 : 0 : return ice_alloc_hw_res(hw, res_type, 1, btm, tcam_idx);
1435 : : }
1436 : :
1437 : : /**
1438 : : * ice_free_tcam_ent - free hardware TCAM entry
1439 : : * @hw: pointer to the HW struct
1440 : : * @blk: the block from which to free the TCAM entry
1441 : : * @tcam_idx: the TCAM entry to free
1442 : : *
1443 : : * This function frees an entry in a Profile ID TCAM for a specific block.
1444 : : */
1445 : : static enum ice_status
1446 : : ice_free_tcam_ent(struct ice_hw *hw, enum ice_block blk, u16 tcam_idx)
1447 : : {
1448 : : u16 res_type;
1449 : :
1450 : : if (!ice_tcam_ent_rsrc_type(blk, &res_type))
1451 : : return ICE_ERR_PARAM;
1452 : :
1453 : 0 : return ice_free_hw_res(hw, res_type, 1, &tcam_idx);
1454 : : }
1455 : :
1456 : : /**
1457 : : * ice_alloc_prof_id - allocate profile ID
1458 : : * @hw: pointer to the HW struct
1459 : : * @blk: the block to allocate the profile ID for
1460 : : * @prof_id: pointer to variable to receive the profile ID
1461 : : *
1462 : : * This function allocates a new profile ID, which also corresponds to a Field
1463 : : * Vector (Extraction Sequence) entry.
1464 : : */
1465 : : static enum ice_status
1466 [ # # ]: 0 : ice_alloc_prof_id(struct ice_hw *hw, enum ice_block blk, u8 *prof_id)
1467 : : {
1468 : : enum ice_status status;
1469 : : u16 res_type;
1470 : : u16 get_prof;
1471 : :
1472 [ # # ]: 0 : if (!ice_prof_id_rsrc_type(blk, &res_type))
1473 : : return ICE_ERR_PARAM;
1474 : :
1475 : 0 : status = ice_alloc_hw_res(hw, res_type, 1, false, &get_prof);
1476 [ # # ]: 0 : if (!status)
1477 : 0 : *prof_id = (u8)get_prof;
1478 : :
1479 : : return status;
1480 : : }
1481 : :
1482 : : /**
1483 : : * ice_free_prof_id - free profile ID
1484 : : * @hw: pointer to the HW struct
1485 : : * @blk: the block from which to free the profile ID
1486 : : * @prof_id: the profile ID to free
1487 : : *
1488 : : * This function frees a profile ID, which also corresponds to a Field Vector.
1489 : : */
1490 : : static enum ice_status
1491 : 0 : ice_free_prof_id(struct ice_hw *hw, enum ice_block blk, u8 prof_id)
1492 : : {
1493 [ # # ]: 0 : u16 tmp_prof_id = (u16)prof_id;
1494 : : u16 res_type;
1495 : :
1496 [ # # ]: 0 : if (!ice_prof_id_rsrc_type(blk, &res_type))
1497 : : return ICE_ERR_PARAM;
1498 : :
1499 : 0 : return ice_free_hw_res(hw, res_type, 1, &tmp_prof_id);
1500 : : }
1501 : :
1502 : : /**
1503 : : * ice_prof_inc_ref - increment reference count for profile
1504 : : * @hw: pointer to the HW struct
1505 : : * @blk: the block from which to free the profile ID
1506 : : * @prof_id: the profile ID for which to increment the reference count
1507 : : */
1508 : : static enum ice_status
1509 : : ice_prof_inc_ref(struct ice_hw *hw, enum ice_block blk, u8 prof_id)
1510 : : {
1511 : 0 : if (prof_id > hw->blk[blk].es.count)
1512 : : return ICE_ERR_PARAM;
1513 : :
1514 : 0 : hw->blk[blk].es.ref_count[prof_id]++;
1515 : :
1516 : 0 : return ICE_SUCCESS;
1517 : : }
1518 : :
1519 : : /**
1520 : : * ice_write_prof_mask_reg - write profile mask register
1521 : : * @hw: pointer to the HW struct
1522 : : * @blk: hardware block
1523 : : * @mask_idx: mask index
1524 : : * @idx: index of the FV which will use the mask
1525 : : * @mask: the 16-bit mask
1526 : : */
1527 : : static void
1528 : 0 : ice_write_prof_mask_reg(struct ice_hw *hw, enum ice_block blk, u16 mask_idx,
1529 : : u16 idx, u16 mask)
1530 : : {
1531 : : u32 offset;
1532 : : u32 val;
1533 : :
1534 [ # # # ]: 0 : switch (blk) {
1535 : 0 : case ICE_BLK_RSS:
1536 : 0 : offset = GLQF_HMASK(mask_idx);
1537 : 0 : val = (idx << GLQF_HMASK_MSK_INDEX_S) &
1538 : : GLQF_HMASK_MSK_INDEX_M;
1539 : 0 : val |= (mask << GLQF_HMASK_MASK_S) & GLQF_HMASK_MASK_M;
1540 : 0 : break;
1541 : 0 : case ICE_BLK_FD:
1542 : 0 : offset = GLQF_FDMASK(mask_idx);
1543 : 0 : val = (idx << GLQF_FDMASK_MSK_INDEX_S) &
1544 : : GLQF_FDMASK_MSK_INDEX_M;
1545 : 0 : val |= (mask << GLQF_FDMASK_MASK_S) &
1546 : : GLQF_FDMASK_MASK_M;
1547 : 0 : break;
1548 : 0 : default:
1549 [ # # ]: 0 : ice_debug(hw, ICE_DBG_PKG, "No profile masks for block %d\n",
1550 : : blk);
1551 : : return;
1552 : : }
1553 : :
1554 : 0 : wr32(hw, offset, val);
1555 [ # # ]: 0 : ice_debug(hw, ICE_DBG_PKG, "write mask, blk %d (%d): %x = %x\n",
1556 : : blk, idx, offset, val);
1557 : : }
1558 : :
1559 : : /**
1560 : : * ice_write_prof_mask_enable_res - write profile mask enable register
1561 : : * @hw: pointer to the HW struct
1562 : : * @blk: hardware block
1563 : : * @prof_id: profile ID
1564 : : * @enable_mask: enable mask
1565 : : */
1566 : : static void
1567 : 0 : ice_write_prof_mask_enable_res(struct ice_hw *hw, enum ice_block blk,
1568 : : u16 prof_id, u32 enable_mask)
1569 : : {
1570 : : u32 offset;
1571 : :
1572 [ # # # ]: 0 : switch (blk) {
1573 : 0 : case ICE_BLK_RSS:
1574 : 0 : offset = GLQF_HMASK_SEL(prof_id);
1575 : 0 : break;
1576 : 0 : case ICE_BLK_FD:
1577 : 0 : offset = GLQF_FDMASK_SEL(prof_id);
1578 : 0 : break;
1579 : 0 : default:
1580 [ # # ]: 0 : ice_debug(hw, ICE_DBG_PKG, "No profile masks for block %d\n",
1581 : : blk);
1582 : : return;
1583 : : }
1584 : :
1585 : 0 : wr32(hw, offset, enable_mask);
1586 [ # # ]: 0 : ice_debug(hw, ICE_DBG_PKG, "write mask enable, blk %d (%d): %x = %x\n",
1587 : : blk, prof_id, offset, enable_mask);
1588 : : }
1589 : :
1590 : : /**
1591 : : * ice_init_prof_masks - initial prof masks
1592 : : * @hw: pointer to the HW struct
1593 : : * @blk: hardware block
1594 : : */
1595 : 0 : static void ice_init_prof_masks(struct ice_hw *hw, enum ice_block blk)
1596 : : {
1597 : : u16 per_pf;
1598 : : u16 i;
1599 : :
1600 : : ice_init_lock(&hw->blk[blk].masks.lock);
1601 : :
1602 : 0 : per_pf = ICE_PROF_MASK_COUNT / hw->dev_caps.num_funcs;
1603 : :
1604 : 0 : hw->blk[blk].masks.count = per_pf;
1605 : 0 : hw->blk[blk].masks.first = hw->logical_pf_id * per_pf;
1606 : :
1607 : 0 : ice_memset(hw->blk[blk].masks.masks, 0,
1608 : : sizeof(hw->blk[blk].masks.masks), ICE_NONDMA_MEM);
1609 : :
1610 : 0 : for (i = hw->blk[blk].masks.first;
1611 [ # # ]: 0 : i < hw->blk[blk].masks.first + hw->blk[blk].masks.count; i++)
1612 : 0 : ice_write_prof_mask_reg(hw, blk, i, 0, 0);
1613 : 0 : }
1614 : :
1615 : : /**
1616 : : * ice_init_all_prof_masks - initial all prof masks
1617 : : * @hw: pointer to the HW struct
1618 : : */
1619 : 0 : void ice_init_all_prof_masks(struct ice_hw *hw)
1620 : : {
1621 : 0 : ice_init_prof_masks(hw, ICE_BLK_RSS);
1622 : 0 : ice_init_prof_masks(hw, ICE_BLK_FD);
1623 : 0 : }
1624 : :
1625 : : /**
1626 : : * ice_alloc_prof_mask - allocate profile mask
1627 : : * @hw: pointer to the HW struct
1628 : : * @blk: hardware block
1629 : : * @idx: index of FV which will use the mask
1630 : : * @mask: the 16-bit mask
1631 : : * @mask_idx: variable to receive the mask index
1632 : : */
1633 : : static enum ice_status
1634 : 0 : ice_alloc_prof_mask(struct ice_hw *hw, enum ice_block blk, u16 idx, u16 mask,
1635 : : u16 *mask_idx)
1636 : : {
1637 : : bool found_unused = false, found_copy = false;
1638 : : enum ice_status status = ICE_ERR_MAX_LIMIT;
1639 : : u16 unused_idx = 0, copy_idx = 0;
1640 : : u16 i;
1641 : :
1642 [ # # ]: 0 : if (blk != ICE_BLK_RSS && blk != ICE_BLK_FD)
1643 : : return ICE_ERR_PARAM;
1644 : :
1645 : 0 : ice_acquire_lock(&hw->blk[blk].masks.lock);
1646 : :
1647 : 0 : for (i = hw->blk[blk].masks.first;
1648 [ # # ]: 0 : i < hw->blk[blk].masks.first + hw->blk[blk].masks.count; i++)
1649 [ # # ]: 0 : if (hw->blk[blk].masks.masks[i].in_use) {
1650 : : /* if mask is in use and it exactly duplicates the
1651 : : * desired mask and index, then in can be reused
1652 : : */
1653 [ # # ]: 0 : if (hw->blk[blk].masks.masks[i].mask == mask &&
1654 [ # # ]: 0 : hw->blk[blk].masks.masks[i].idx == idx) {
1655 : : found_copy = true;
1656 : : copy_idx = i;
1657 : : break;
1658 : : }
1659 : : } else {
1660 : : /* save off unused index, but keep searching in case
1661 : : * there is an exact match later on
1662 : : */
1663 [ # # ]: 0 : if (!found_unused) {
1664 : : found_unused = true;
1665 : : unused_idx = i;
1666 : : }
1667 : : }
1668 : :
1669 : : if (found_copy)
1670 : : i = copy_idx;
1671 [ # # ]: 0 : else if (found_unused)
1672 : : i = unused_idx;
1673 : : else
1674 : 0 : goto err_ice_alloc_prof_mask;
1675 : :
1676 : : /* update mask for a new entry */
1677 [ # # ]: 0 : if (found_unused) {
1678 : 0 : hw->blk[blk].masks.masks[i].in_use = true;
1679 : 0 : hw->blk[blk].masks.masks[i].mask = mask;
1680 : 0 : hw->blk[blk].masks.masks[i].idx = idx;
1681 : 0 : hw->blk[blk].masks.masks[i].ref = 0;
1682 : 0 : ice_write_prof_mask_reg(hw, blk, i, idx, mask);
1683 : : }
1684 : :
1685 : 0 : hw->blk[blk].masks.masks[i].ref++;
1686 : 0 : *mask_idx = i;
1687 : : status = ICE_SUCCESS;
1688 : :
1689 : 0 : err_ice_alloc_prof_mask:
1690 : : ice_release_lock(&hw->blk[blk].masks.lock);
1691 : :
1692 : 0 : return status;
1693 : : }
1694 : :
1695 : : /**
1696 : : * ice_free_prof_mask - free profile mask
1697 : : * @hw: pointer to the HW struct
1698 : : * @blk: hardware block
1699 : : * @mask_idx: index of mask
1700 : : */
1701 : : static enum ice_status
1702 : 0 : ice_free_prof_mask(struct ice_hw *hw, enum ice_block blk, u16 mask_idx)
1703 : : {
1704 [ # # ]: 0 : if (blk != ICE_BLK_RSS && blk != ICE_BLK_FD)
1705 : : return ICE_ERR_PARAM;
1706 : :
1707 [ # # ]: 0 : if (!(mask_idx >= hw->blk[blk].masks.first &&
1708 [ # # ]: 0 : mask_idx < hw->blk[blk].masks.first + hw->blk[blk].masks.count))
1709 : : return ICE_ERR_DOES_NOT_EXIST;
1710 : :
1711 : 0 : ice_acquire_lock(&hw->blk[blk].masks.lock);
1712 : :
1713 [ # # ]: 0 : if (!hw->blk[blk].masks.masks[mask_idx].in_use)
1714 : 0 : goto exit_ice_free_prof_mask;
1715 : :
1716 [ # # ]: 0 : if (hw->blk[blk].masks.masks[mask_idx].ref > 1) {
1717 : 0 : hw->blk[blk].masks.masks[mask_idx].ref--;
1718 : 0 : goto exit_ice_free_prof_mask;
1719 : : }
1720 : :
1721 : : /* remove mask */
1722 : 0 : hw->blk[blk].masks.masks[mask_idx].in_use = false;
1723 : 0 : hw->blk[blk].masks.masks[mask_idx].mask = 0;
1724 : 0 : hw->blk[blk].masks.masks[mask_idx].idx = 0;
1725 : :
1726 : : /* update mask as unused entry */
1727 [ # # ]: 0 : ice_debug(hw, ICE_DBG_PKG, "Free mask, blk %d, mask %d\n", blk,
1728 : : mask_idx);
1729 : 0 : ice_write_prof_mask_reg(hw, blk, mask_idx, 0, 0);
1730 : :
1731 : 0 : exit_ice_free_prof_mask:
1732 : : ice_release_lock(&hw->blk[blk].masks.lock);
1733 : :
1734 : 0 : return ICE_SUCCESS;
1735 : : }
1736 : :
1737 : : /**
1738 : : * ice_free_prof_masks - free all profile masks for a profile
1739 : : * @hw: pointer to the HW struct
1740 : : * @blk: hardware block
1741 : : * @prof_id: profile ID
1742 : : */
1743 : : static enum ice_status
1744 : 0 : ice_free_prof_masks(struct ice_hw *hw, enum ice_block blk, u16 prof_id)
1745 : : {
1746 : : u32 mask_bm;
1747 : : u16 i;
1748 : :
1749 [ # # ]: 0 : if (blk != ICE_BLK_RSS && blk != ICE_BLK_FD)
1750 : : return ICE_ERR_PARAM;
1751 : :
1752 : 0 : mask_bm = hw->blk[blk].es.mask_ena[prof_id];
1753 [ # # ]: 0 : for (i = 0; i < BITS_PER_BYTE * sizeof(mask_bm); i++)
1754 [ # # ]: 0 : if (mask_bm & BIT(i))
1755 : 0 : ice_free_prof_mask(hw, blk, i);
1756 : :
1757 : : return ICE_SUCCESS;
1758 : : }
1759 : :
1760 : : /**
1761 : : * ice_shutdown_prof_masks - releases lock for masking
1762 : : * @hw: pointer to the HW struct
1763 : : * @blk: hardware block
1764 : : *
1765 : : * This should be called before unloading the driver
1766 : : */
1767 : 0 : static void ice_shutdown_prof_masks(struct ice_hw *hw, enum ice_block blk)
1768 : : {
1769 : : u16 i;
1770 : :
1771 : 0 : ice_acquire_lock(&hw->blk[blk].masks.lock);
1772 : :
1773 : 0 : for (i = hw->blk[blk].masks.first;
1774 [ # # ]: 0 : i < hw->blk[blk].masks.first + hw->blk[blk].masks.count; i++) {
1775 : 0 : ice_write_prof_mask_reg(hw, blk, i, 0, 0);
1776 : :
1777 : 0 : hw->blk[blk].masks.masks[i].in_use = false;
1778 : 0 : hw->blk[blk].masks.masks[i].idx = 0;
1779 : 0 : hw->blk[blk].masks.masks[i].mask = 0;
1780 : : }
1781 : :
1782 : : ice_release_lock(&hw->blk[blk].masks.lock);
1783 : : ice_destroy_lock(&hw->blk[blk].masks.lock);
1784 : 0 : }
1785 : :
1786 : : /**
1787 : : * ice_shutdown_all_prof_masks - releases all locks for masking
1788 : : * @hw: pointer to the HW struct
1789 : : *
1790 : : * This should be called before unloading the driver
1791 : : */
1792 : 0 : void ice_shutdown_all_prof_masks(struct ice_hw *hw)
1793 : : {
1794 : 0 : ice_shutdown_prof_masks(hw, ICE_BLK_RSS);
1795 : 0 : ice_shutdown_prof_masks(hw, ICE_BLK_FD);
1796 : 0 : }
1797 : :
1798 : : /**
1799 : : * ice_update_prof_masking - set registers according to masking
1800 : : * @hw: pointer to the HW struct
1801 : : * @blk: hardware block
1802 : : * @prof_id: profile ID
1803 : : * @masks: masks
1804 : : */
1805 : : static enum ice_status
1806 : 0 : ice_update_prof_masking(struct ice_hw *hw, enum ice_block blk, u16 prof_id,
1807 : : u16 *masks)
1808 : : {
1809 : : bool err = false;
1810 : : u32 ena_mask = 0;
1811 : : u16 idx;
1812 : : u16 i;
1813 : :
1814 : : /* Only support FD and RSS masking, otherwise nothing to be done */
1815 [ # # ]: 0 : if (blk != ICE_BLK_RSS && blk != ICE_BLK_FD)
1816 : : return ICE_SUCCESS;
1817 : :
1818 [ # # ]: 0 : for (i = 0; i < hw->blk[blk].es.fvw; i++)
1819 [ # # ]: 0 : if (masks[i] && masks[i] != 0xFFFF) {
1820 [ # # ]: 0 : if (!ice_alloc_prof_mask(hw, blk, i, masks[i], &idx)) {
1821 : 0 : ena_mask |= BIT(idx);
1822 : : } else {
1823 : : /* not enough bitmaps */
1824 : : err = true;
1825 : : break;
1826 : : }
1827 : : }
1828 : :
1829 [ # # ]: 0 : if (err) {
1830 : : /* free any bitmaps we have allocated */
1831 [ # # ]: 0 : for (i = 0; i < BITS_PER_BYTE * sizeof(ena_mask); i++)
1832 [ # # ]: 0 : if (ena_mask & BIT(i))
1833 : 0 : ice_free_prof_mask(hw, blk, i);
1834 : :
1835 : : return ICE_ERR_OUT_OF_RANGE;
1836 : : }
1837 : :
1838 : : /* enable the masks for this profile */
1839 : 0 : ice_write_prof_mask_enable_res(hw, blk, prof_id, ena_mask);
1840 : :
1841 : : /* store enabled masks with profile so that they can be freed later */
1842 : 0 : hw->blk[blk].es.mask_ena[prof_id] = ena_mask;
1843 : :
1844 : 0 : return ICE_SUCCESS;
1845 : : }
1846 : :
1847 : : /**
1848 : : * ice_write_es - write an extraction sequence to hardware
1849 : : * @hw: pointer to the HW struct
1850 : : * @blk: the block in which to write the extraction sequence
1851 : : * @prof_id: the profile ID to write
1852 : : * @fv: pointer to the extraction sequence to write - NULL to clear extraction
1853 : : */
1854 : : static void
1855 : 0 : ice_write_es(struct ice_hw *hw, enum ice_block blk, u8 prof_id,
1856 : : struct ice_fv_word *fv)
1857 : : {
1858 : : u16 off;
1859 : :
1860 : 0 : off = prof_id * hw->blk[blk].es.fvw;
1861 [ # # ]: 0 : if (!fv) {
1862 : 0 : ice_memset(&hw->blk[blk].es.t[off], 0, hw->blk[blk].es.fvw *
1863 : : sizeof(*fv), ICE_NONDMA_MEM);
1864 : 0 : hw->blk[blk].es.written[prof_id] = false;
1865 : : } else {
1866 [ # # ]: 0 : ice_memcpy(&hw->blk[blk].es.t[off], fv, hw->blk[blk].es.fvw *
1867 : : sizeof(*fv), ICE_NONDMA_TO_NONDMA);
1868 : : }
1869 : 0 : }
1870 : :
1871 : : /**
1872 : : * ice_prof_dec_ref - decrement reference count for profile
1873 : : * @hw: pointer to the HW struct
1874 : : * @blk: the block from which to free the profile ID
1875 : : * @prof_id: the profile ID for which to decrement the reference count
1876 : : */
1877 : : static enum ice_status
1878 : 0 : ice_prof_dec_ref(struct ice_hw *hw, enum ice_block blk, u8 prof_id)
1879 : : {
1880 [ # # ]: 0 : if (prof_id > hw->blk[blk].es.count)
1881 : : return ICE_ERR_PARAM;
1882 : :
1883 [ # # ]: 0 : if (hw->blk[blk].es.ref_count[prof_id] > 0) {
1884 [ # # ]: 0 : if (!--hw->blk[blk].es.ref_count[prof_id]) {
1885 : 0 : ice_write_es(hw, blk, prof_id, NULL);
1886 : 0 : ice_free_prof_masks(hw, blk, prof_id);
1887 : 0 : return ice_free_prof_id(hw, blk, prof_id);
1888 : : }
1889 : : }
1890 : :
1891 : : return ICE_SUCCESS;
1892 : : }
1893 : :
1894 : : /* Block / table section IDs */
1895 : : static const u32 ice_blk_sids[ICE_BLK_COUNT][ICE_SID_OFF_COUNT] = {
1896 : : /* SWITCH */
1897 : : { ICE_SID_XLT1_SW,
1898 : : ICE_SID_XLT2_SW,
1899 : : ICE_SID_PROFID_TCAM_SW,
1900 : : ICE_SID_PROFID_REDIR_SW,
1901 : : ICE_SID_FLD_VEC_SW
1902 : : },
1903 : :
1904 : : /* ACL */
1905 : : { ICE_SID_XLT1_ACL,
1906 : : ICE_SID_XLT2_ACL,
1907 : : ICE_SID_PROFID_TCAM_ACL,
1908 : : ICE_SID_PROFID_REDIR_ACL,
1909 : : ICE_SID_FLD_VEC_ACL
1910 : : },
1911 : :
1912 : : /* FD */
1913 : : { ICE_SID_XLT1_FD,
1914 : : ICE_SID_XLT2_FD,
1915 : : ICE_SID_PROFID_TCAM_FD,
1916 : : ICE_SID_PROFID_REDIR_FD,
1917 : : ICE_SID_FLD_VEC_FD
1918 : : },
1919 : :
1920 : : /* RSS */
1921 : : { ICE_SID_XLT1_RSS,
1922 : : ICE_SID_XLT2_RSS,
1923 : : ICE_SID_PROFID_TCAM_RSS,
1924 : : ICE_SID_PROFID_REDIR_RSS,
1925 : : ICE_SID_FLD_VEC_RSS
1926 : : },
1927 : :
1928 : : /* PE */
1929 : : { ICE_SID_XLT1_PE,
1930 : : ICE_SID_XLT2_PE,
1931 : : ICE_SID_PROFID_TCAM_PE,
1932 : : ICE_SID_PROFID_REDIR_PE,
1933 : : ICE_SID_FLD_VEC_PE
1934 : : }
1935 : : };
1936 : :
1937 : : /**
1938 : : * ice_init_sw_xlt1_db - init software XLT1 database from HW tables
1939 : : * @hw: pointer to the hardware structure
1940 : : * @blk: the HW block to initialize
1941 : : */
1942 : 0 : static void ice_init_sw_xlt1_db(struct ice_hw *hw, enum ice_block blk)
1943 : : {
1944 : : u16 pt;
1945 : :
1946 [ # # ]: 0 : for (pt = 0; pt < hw->blk[blk].xlt1.count; pt++) {
1947 : : u8 ptg;
1948 : :
1949 : 0 : ptg = hw->blk[blk].xlt1.t[pt];
1950 [ # # ]: 0 : if (ptg != ICE_DEFAULT_PTG) {
1951 : 0 : ice_ptg_alloc_val(hw, blk, ptg);
1952 : 0 : ice_ptg_add_mv_ptype(hw, blk, pt, ptg);
1953 : : }
1954 : : }
1955 : 0 : }
1956 : :
1957 : : /**
1958 : : * ice_init_sw_xlt2_db - init software XLT2 database from HW tables
1959 : : * @hw: pointer to the hardware structure
1960 : : * @blk: the HW block to initialize
1961 : : */
1962 : 0 : static void ice_init_sw_xlt2_db(struct ice_hw *hw, enum ice_block blk)
1963 : : {
1964 : : u16 vsi;
1965 : :
1966 [ # # ]: 0 : for (vsi = 0; vsi < hw->blk[blk].xlt2.count; vsi++) {
1967 : : u16 vsig;
1968 : :
1969 : 0 : vsig = hw->blk[blk].xlt2.t[vsi];
1970 [ # # ]: 0 : if (vsig) {
1971 [ # # ]: 0 : ice_vsig_alloc_val(hw, blk, vsig);
1972 : 0 : ice_vsig_add_mv_vsi(hw, blk, vsi, vsig);
1973 : : /* no changes at this time, since this has been
1974 : : * initialized from the original package
1975 : : */
1976 : 0 : hw->blk[blk].xlt2.vsis[vsi].changed = 0;
1977 : : }
1978 : : }
1979 : 0 : }
1980 : :
1981 : : /**
1982 : : * ice_init_sw_db - init software database from HW tables
1983 : : * @hw: pointer to the hardware structure
1984 : : */
1985 : 0 : static void ice_init_sw_db(struct ice_hw *hw)
1986 : : {
1987 : : u16 i;
1988 : :
1989 [ # # ]: 0 : for (i = 0; i < ICE_BLK_COUNT; i++) {
1990 : 0 : ice_init_sw_xlt1_db(hw, (enum ice_block)i);
1991 : 0 : ice_init_sw_xlt2_db(hw, (enum ice_block)i);
1992 : : }
1993 : 0 : }
1994 : :
1995 : : /**
1996 : : * ice_fill_tbl - Reads content of a single table type into database
1997 : : * @hw: pointer to the hardware structure
1998 : : * @block_id: Block ID of the table to copy
1999 : : * @sid: Section ID of the table to copy
2000 : : *
2001 : : * Will attempt to read the entire content of a given table of a single block
2002 : : * into the driver database. We assume that the buffer will always
2003 : : * be as large or larger than the data contained in the package. If
2004 : : * this condition is not met, there is most likely an error in the package
2005 : : * contents.
2006 : : */
2007 : 0 : static void ice_fill_tbl(struct ice_hw *hw, enum ice_block block_id, u32 sid)
2008 : : {
2009 : : u32 dst_len, sect_len, offset = 0;
2010 : : struct ice_prof_redir_section *pr;
2011 : : struct ice_prof_id_section *pid;
2012 : : struct ice_xlt1_section *xlt1;
2013 : : struct ice_xlt2_section *xlt2;
2014 : : struct ice_sw_fv_section *es;
2015 : : struct ice_pkg_enum state;
2016 : : u8 *src, *dst;
2017 : : void *sect;
2018 : :
2019 : : /* if the HW segment pointer is null then the first iteration of
2020 : : * ice_pkg_enum_section() will fail. In this case the HW tables will
2021 : : * not be filled and return success.
2022 : : */
2023 [ # # ]: 0 : if (!hw->seg) {
2024 [ # # ]: 0 : ice_debug(hw, ICE_DBG_PKG, "hw->seg is NULL, tables are not filled\n");
2025 : 0 : return;
2026 : : }
2027 : :
2028 : : ice_memset(&state, 0, sizeof(state), ICE_NONDMA_MEM);
2029 : :
2030 : 0 : sect = ice_pkg_enum_section(hw->seg, &state, sid);
2031 : :
2032 [ # # ]: 0 : while (sect) {
2033 [ # # # # : 0 : switch (sid) {
# # ]
2034 : 0 : case ICE_SID_XLT1_SW:
2035 : : case ICE_SID_XLT1_FD:
2036 : : case ICE_SID_XLT1_RSS:
2037 : : case ICE_SID_XLT1_ACL:
2038 : : case ICE_SID_XLT1_PE:
2039 : : xlt1 = (struct ice_xlt1_section *)sect;
2040 : 0 : src = xlt1->value;
2041 : 0 : sect_len = LE16_TO_CPU(xlt1->count) *
2042 : : sizeof(*hw->blk[block_id].xlt1.t);
2043 : 0 : dst = hw->blk[block_id].xlt1.t;
2044 : 0 : dst_len = hw->blk[block_id].xlt1.count *
2045 : : sizeof(*hw->blk[block_id].xlt1.t);
2046 : 0 : break;
2047 : 0 : case ICE_SID_XLT2_SW:
2048 : : case ICE_SID_XLT2_FD:
2049 : : case ICE_SID_XLT2_RSS:
2050 : : case ICE_SID_XLT2_ACL:
2051 : : case ICE_SID_XLT2_PE:
2052 : : xlt2 = (struct ice_xlt2_section *)sect;
2053 : 0 : src = (_FORCE_ u8 *)xlt2->value;
2054 : 0 : sect_len = LE16_TO_CPU(xlt2->count) *
2055 : : sizeof(*hw->blk[block_id].xlt2.t);
2056 : 0 : dst = (u8 *)hw->blk[block_id].xlt2.t;
2057 : 0 : dst_len = hw->blk[block_id].xlt2.count *
2058 : : sizeof(*hw->blk[block_id].xlt2.t);
2059 : 0 : break;
2060 : 0 : case ICE_SID_PROFID_TCAM_SW:
2061 : : case ICE_SID_PROFID_TCAM_FD:
2062 : : case ICE_SID_PROFID_TCAM_RSS:
2063 : : case ICE_SID_PROFID_TCAM_ACL:
2064 : : case ICE_SID_PROFID_TCAM_PE:
2065 : : pid = (struct ice_prof_id_section *)sect;
2066 : 0 : src = (u8 *)pid->entry;
2067 : 0 : sect_len = LE16_TO_CPU(pid->count) *
2068 : : sizeof(*hw->blk[block_id].prof.t);
2069 : 0 : dst = (u8 *)hw->blk[block_id].prof.t;
2070 : 0 : dst_len = hw->blk[block_id].prof.count *
2071 : : sizeof(*hw->blk[block_id].prof.t);
2072 : 0 : break;
2073 : 0 : case ICE_SID_PROFID_REDIR_SW:
2074 : : case ICE_SID_PROFID_REDIR_FD:
2075 : : case ICE_SID_PROFID_REDIR_RSS:
2076 : : case ICE_SID_PROFID_REDIR_ACL:
2077 : : case ICE_SID_PROFID_REDIR_PE:
2078 : : pr = (struct ice_prof_redir_section *)sect;
2079 : 0 : src = pr->redir_value;
2080 : 0 : sect_len = LE16_TO_CPU(pr->count) *
2081 : : sizeof(*hw->blk[block_id].prof_redir.t);
2082 : 0 : dst = hw->blk[block_id].prof_redir.t;
2083 : 0 : dst_len = hw->blk[block_id].prof_redir.count *
2084 : : sizeof(*hw->blk[block_id].prof_redir.t);
2085 : 0 : break;
2086 : 0 : case ICE_SID_FLD_VEC_SW:
2087 : : case ICE_SID_FLD_VEC_FD:
2088 : : case ICE_SID_FLD_VEC_RSS:
2089 : : case ICE_SID_FLD_VEC_ACL:
2090 : : case ICE_SID_FLD_VEC_PE:
2091 : : es = (struct ice_sw_fv_section *)sect;
2092 : 0 : src = (u8 *)es->fv;
2093 : 0 : sect_len = (u32)(LE16_TO_CPU(es->count) *
2094 : 0 : hw->blk[block_id].es.fvw) *
2095 : : sizeof(*hw->blk[block_id].es.t);
2096 : 0 : dst = (u8 *)hw->blk[block_id].es.t;
2097 : 0 : dst_len = (u32)(hw->blk[block_id].es.count *
2098 : : hw->blk[block_id].es.fvw) *
2099 : : sizeof(*hw->blk[block_id].es.t);
2100 : 0 : break;
2101 : : default:
2102 : : return;
2103 : : }
2104 : :
2105 : : /* if the section offset exceeds destination length, terminate
2106 : : * table fill.
2107 : : */
2108 [ # # ]: 0 : if (offset > dst_len)
2109 : : return;
2110 : :
2111 : : /* if the sum of section size and offset exceed destination size
2112 : : * then we are out of bounds of the HW table size for that PF.
2113 : : * Changing section length to fill the remaining table space
2114 : : * of that PF.
2115 : : */
2116 [ # # ]: 0 : if ((offset + sect_len) > dst_len)
2117 : 0 : sect_len = dst_len - offset;
2118 : :
2119 [ # # ]: 0 : ice_memcpy(dst + offset, src, sect_len, ICE_NONDMA_TO_NONDMA);
2120 : 0 : offset += sect_len;
2121 : 0 : sect = ice_pkg_enum_section(NULL, &state, sid);
2122 : : }
2123 : : }
2124 : :
2125 : : /**
2126 : : * ice_init_flow_profs - init flow profile locks and list heads
2127 : : * @hw: pointer to the hardware structure
2128 : : * @blk_idx: HW block index
2129 : : */
2130 : : static
2131 : : void ice_init_flow_profs(struct ice_hw *hw, u8 blk_idx)
2132 : : {
2133 : : ice_init_lock(&hw->fl_profs_locks[blk_idx]);
2134 : 0 : INIT_LIST_HEAD(&hw->fl_profs[blk_idx]);
2135 : : }
2136 : :
2137 : : /**
2138 : : * ice_init_hw_tbls - init hardware table memory
2139 : : * @hw: pointer to the hardware structure
2140 : : */
2141 [ # # ]: 0 : enum ice_status ice_init_hw_tbls(struct ice_hw *hw)
2142 : : {
2143 : : u8 i;
2144 : :
2145 : : ice_init_lock(&hw->rss_locks);
2146 : 0 : INIT_LIST_HEAD(&hw->rss_list_head);
2147 [ # # ]: 0 : if (!hw->dcf_enabled)
2148 : 0 : ice_init_all_prof_masks(hw);
2149 [ # # ]: 0 : for (i = 0; i < ICE_BLK_COUNT; i++) {
2150 : 0 : struct ice_prof_redir *prof_redir = &hw->blk[i].prof_redir;
2151 : : struct ice_prof_tcam *prof = &hw->blk[i].prof;
2152 : : struct ice_xlt1 *xlt1 = &hw->blk[i].xlt1;
2153 : : struct ice_xlt2 *xlt2 = &hw->blk[i].xlt2;
2154 : : struct ice_es *es = &hw->blk[i].es;
2155 : : u16 j;
2156 : :
2157 [ # # ]: 0 : if (hw->blk[i].is_list_init)
2158 : 0 : continue;
2159 : :
2160 : : ice_init_flow_profs(hw, i);
2161 : : ice_init_lock(&es->prof_map_lock);
2162 : 0 : INIT_LIST_HEAD(&es->prof_map);
2163 : 0 : hw->blk[i].is_list_init = true;
2164 : :
2165 : 0 : hw->blk[i].overwrite = blk_sizes[i].overwrite;
2166 : 0 : es->reverse = blk_sizes[i].reverse;
2167 : :
2168 : 0 : xlt1->sid = ice_blk_sids[i][ICE_SID_XLT1_OFF];
2169 : 0 : xlt1->count = blk_sizes[i].xlt1;
2170 : :
2171 : 0 : xlt1->ptypes = (struct ice_ptg_ptype *)
2172 : 0 : ice_calloc(hw, xlt1->count, sizeof(*xlt1->ptypes));
2173 : :
2174 [ # # ]: 0 : if (!xlt1->ptypes)
2175 : 0 : goto err;
2176 : :
2177 : 0 : xlt1->ptg_tbl = (struct ice_ptg_entry *)
2178 : 0 : ice_calloc(hw, ICE_MAX_PTGS, sizeof(*xlt1->ptg_tbl));
2179 : :
2180 [ # # ]: 0 : if (!xlt1->ptg_tbl)
2181 : 0 : goto err;
2182 : :
2183 : 0 : xlt1->t = (u8 *)ice_calloc(hw, xlt1->count, sizeof(*xlt1->t));
2184 [ # # ]: 0 : if (!xlt1->t)
2185 : 0 : goto err;
2186 : :
2187 : 0 : xlt2->sid = ice_blk_sids[i][ICE_SID_XLT2_OFF];
2188 : 0 : xlt2->count = blk_sizes[i].xlt2;
2189 : :
2190 : 0 : xlt2->vsis = (struct ice_vsig_vsi *)
2191 : 0 : ice_calloc(hw, xlt2->count, sizeof(*xlt2->vsis));
2192 : :
2193 [ # # ]: 0 : if (!xlt2->vsis)
2194 : 0 : goto err;
2195 : :
2196 : 0 : xlt2->vsig_tbl = (struct ice_vsig_entry *)
2197 : 0 : ice_calloc(hw, xlt2->count, sizeof(*xlt2->vsig_tbl));
2198 [ # # ]: 0 : if (!xlt2->vsig_tbl)
2199 : 0 : goto err;
2200 : :
2201 [ # # ]: 0 : for (j = 0; j < xlt2->count; j++)
2202 : 0 : INIT_LIST_HEAD(&xlt2->vsig_tbl[j].prop_lst);
2203 : :
2204 : 0 : xlt2->t = (u16 *)ice_calloc(hw, xlt2->count, sizeof(*xlt2->t));
2205 [ # # ]: 0 : if (!xlt2->t)
2206 : 0 : goto err;
2207 : :
2208 : 0 : prof->sid = ice_blk_sids[i][ICE_SID_PR_OFF];
2209 : 0 : prof->count = blk_sizes[i].prof_tcam;
2210 : 0 : prof->max_prof_id = blk_sizes[i].prof_id;
2211 : 0 : prof->cdid_bits = blk_sizes[i].prof_cdid_bits;
2212 : 0 : prof->t = (struct ice_prof_tcam_entry *)
2213 : 0 : ice_calloc(hw, prof->count, sizeof(*prof->t));
2214 : :
2215 [ # # ]: 0 : if (!prof->t)
2216 : 0 : goto err;
2217 : :
2218 : 0 : prof_redir->sid = ice_blk_sids[i][ICE_SID_PR_REDIR_OFF];
2219 : 0 : prof_redir->count = blk_sizes[i].prof_redir;
2220 : 0 : prof_redir->t = (u8 *)ice_calloc(hw, prof_redir->count,
2221 : : sizeof(*prof_redir->t));
2222 : :
2223 [ # # ]: 0 : if (!prof_redir->t)
2224 : 0 : goto err;
2225 : :
2226 : 0 : es->sid = ice_blk_sids[i][ICE_SID_ES_OFF];
2227 : 0 : es->count = blk_sizes[i].es;
2228 : 0 : es->fvw = blk_sizes[i].fvw;
2229 : 0 : es->t = (struct ice_fv_word *)
2230 : 0 : ice_calloc(hw, (u32)(es->count * es->fvw),
2231 : : sizeof(*es->t));
2232 [ # # ]: 0 : if (!es->t)
2233 : 0 : goto err;
2234 : :
2235 : 0 : es->ref_count = (u16 *)
2236 : 0 : ice_calloc(hw, es->count, sizeof(*es->ref_count));
2237 : :
2238 [ # # ]: 0 : if (!es->ref_count)
2239 : 0 : goto err;
2240 : :
2241 : 0 : es->written = (u8 *)
2242 : 0 : ice_calloc(hw, es->count, sizeof(*es->written));
2243 : :
2244 [ # # ]: 0 : if (!es->written)
2245 : 0 : goto err;
2246 : :
2247 : 0 : es->mask_ena = (u32 *)
2248 : 0 : ice_calloc(hw, es->count, sizeof(*es->mask_ena));
2249 : :
2250 [ # # ]: 0 : if (!es->mask_ena)
2251 : 0 : goto err;
2252 : : }
2253 : : return ICE_SUCCESS;
2254 : :
2255 : 0 : err:
2256 : 0 : ice_free_hw_tbls(hw);
2257 : 0 : return ICE_ERR_NO_MEMORY;
2258 : : }
2259 : :
2260 : : /**
2261 : : * ice_fill_blk_tbls - Read package context for tables
2262 : : * @hw: pointer to the hardware structure
2263 : : *
2264 : : * Reads the current package contents and populates the driver
2265 : : * database with the data iteratively for all advanced feature
2266 : : * blocks. Assume that the HW tables have been allocated.
2267 : : */
2268 : 0 : void ice_fill_blk_tbls(struct ice_hw *hw)
2269 : : {
2270 : : u8 i;
2271 : :
2272 [ # # ]: 0 : for (i = 0; i < ICE_BLK_COUNT; i++) {
2273 : 0 : enum ice_block blk_id = (enum ice_block)i;
2274 : :
2275 : 0 : ice_fill_tbl(hw, blk_id, hw->blk[blk_id].xlt1.sid);
2276 : 0 : ice_fill_tbl(hw, blk_id, hw->blk[blk_id].xlt2.sid);
2277 : 0 : ice_fill_tbl(hw, blk_id, hw->blk[blk_id].prof.sid);
2278 : 0 : ice_fill_tbl(hw, blk_id, hw->blk[blk_id].prof_redir.sid);
2279 : 0 : ice_fill_tbl(hw, blk_id, hw->blk[blk_id].es.sid);
2280 : : }
2281 : :
2282 : 0 : ice_init_sw_db(hw);
2283 : 0 : }
2284 : :
2285 : : /**
2286 : : * ice_free_prof_map - free profile map
2287 : : * @hw: pointer to the hardware structure
2288 : : * @blk_idx: HW block index
2289 : : */
2290 : 0 : static void ice_free_prof_map(struct ice_hw *hw, u8 blk_idx)
2291 : : {
2292 : 0 : struct ice_es *es = &hw->blk[blk_idx].es;
2293 : : struct ice_prof_map *del, *tmp;
2294 : :
2295 : 0 : ice_acquire_lock(&es->prof_map_lock);
2296 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &es->prof_map,
# # # # #
# ]
2297 : : ice_prof_map, list) {
2298 [ # # ]: 0 : LIST_DEL(&del->list);
2299 : 0 : ice_free(hw, del);
2300 : : }
2301 : 0 : INIT_LIST_HEAD(&es->prof_map);
2302 : : ice_release_lock(&es->prof_map_lock);
2303 : 0 : }
2304 : :
2305 : : /**
2306 : : * ice_free_flow_profs - free flow profile entries
2307 : : * @hw: pointer to the hardware structure
2308 : : * @blk_idx: HW block index
2309 : : */
2310 : 0 : static void ice_free_flow_profs(struct ice_hw *hw, u8 blk_idx)
2311 : : {
2312 : : struct ice_flow_prof *p, *tmp;
2313 : :
2314 : 0 : ice_acquire_lock(&hw->fl_profs_locks[blk_idx]);
2315 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(p, tmp, &hw->fl_profs[blk_idx],
# # # # #
# ]
2316 : : ice_flow_prof, l_entry) {
2317 : : struct ice_flow_entry *e, *t;
2318 : :
2319 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(e, t, &p->entries,
# # # # #
# ]
2320 : : ice_flow_entry, l_entry)
2321 : 0 : ice_flow_rem_entry(hw, (enum ice_block)blk_idx,
2322 : : ICE_FLOW_ENTRY_HNDL(e));
2323 : :
2324 [ # # ]: 0 : LIST_DEL(&p->l_entry);
2325 [ # # ]: 0 : if (p->acts)
2326 : 0 : ice_free(hw, p->acts);
2327 : :
2328 : : ice_destroy_lock(&p->entries_lock);
2329 : 0 : ice_free(hw, p);
2330 : : }
2331 : : ice_release_lock(&hw->fl_profs_locks[blk_idx]);
2332 : :
2333 : : /* if driver is in reset and tables are being cleared
2334 : : * re-initialize the flow profile list heads
2335 : : */
2336 : 0 : INIT_LIST_HEAD(&hw->fl_profs[blk_idx]);
2337 : 0 : }
2338 : :
2339 : : /**
2340 : : * ice_free_vsig_tbl - free complete VSIG table entries
2341 : : * @hw: pointer to the hardware structure
2342 : : * @blk: the HW block on which to free the VSIG table entries
2343 : : */
2344 : 0 : static void ice_free_vsig_tbl(struct ice_hw *hw, enum ice_block blk)
2345 : : {
2346 : : u16 i;
2347 : :
2348 [ # # ]: 0 : if (!hw->blk[blk].xlt2.vsig_tbl)
2349 : : return;
2350 : :
2351 [ # # ]: 0 : for (i = 1; i < ICE_MAX_VSIGS; i++)
2352 [ # # ]: 0 : if (hw->blk[blk].xlt2.vsig_tbl[i].in_use)
2353 : 0 : ice_vsig_free(hw, blk, i);
2354 : : }
2355 : :
2356 : : /**
2357 : : * ice_free_hw_tbls - free hardware table memory
2358 : : * @hw: pointer to the hardware structure
2359 : : */
2360 : 0 : void ice_free_hw_tbls(struct ice_hw *hw)
2361 : : {
2362 : : struct ice_rss_cfg *r, *rt;
2363 : : u8 i;
2364 : :
2365 [ # # ]: 0 : for (i = 0; i < ICE_BLK_COUNT; i++) {
2366 [ # # ]: 0 : if (hw->blk[i].is_list_init) {
2367 : : struct ice_es *es = &hw->blk[i].es;
2368 : :
2369 : 0 : ice_free_prof_map(hw, i);
2370 : : ice_destroy_lock(&es->prof_map_lock);
2371 : 0 : ice_free_flow_profs(hw, i);
2372 : : ice_destroy_lock(&hw->fl_profs_locks[i]);
2373 : :
2374 : 0 : hw->blk[i].is_list_init = false;
2375 : : }
2376 : 0 : ice_free_vsig_tbl(hw, (enum ice_block)i);
2377 : 0 : ice_free(hw, hw->blk[i].xlt1.ptypes);
2378 : 0 : ice_free(hw, hw->blk[i].xlt1.ptg_tbl);
2379 : 0 : ice_free(hw, hw->blk[i].xlt1.t);
2380 : 0 : ice_free(hw, hw->blk[i].xlt2.t);
2381 : 0 : ice_free(hw, hw->blk[i].xlt2.vsig_tbl);
2382 : 0 : ice_free(hw, hw->blk[i].xlt2.vsis);
2383 : 0 : ice_free(hw, hw->blk[i].prof.t);
2384 : 0 : ice_free(hw, hw->blk[i].prof_redir.t);
2385 : 0 : ice_free(hw, hw->blk[i].es.t);
2386 : 0 : ice_free(hw, hw->blk[i].es.ref_count);
2387 : 0 : ice_free(hw, hw->blk[i].es.written);
2388 : 0 : ice_free(hw, hw->blk[i].es.mask_ena);
2389 : : }
2390 : :
2391 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(r, rt, &hw->rss_list_head,
# # # # #
# ]
2392 : : ice_rss_cfg, l_entry) {
2393 [ # # ]: 0 : LIST_DEL(&r->l_entry);
2394 : 0 : ice_free(hw, r);
2395 : : }
2396 : : ice_destroy_lock(&hw->rss_locks);
2397 [ # # ]: 0 : if (!hw->dcf_enabled)
2398 : 0 : ice_shutdown_all_prof_masks(hw);
2399 : 0 : ice_memset(hw->blk, 0, sizeof(hw->blk), ICE_NONDMA_MEM);
2400 : 0 : }
2401 : :
2402 : : /**
2403 : : * ice_clear_hw_tbls - clear HW tables and flow profiles
2404 : : * @hw: pointer to the hardware structure
2405 : : */
2406 : 0 : void ice_clear_hw_tbls(struct ice_hw *hw)
2407 : : {
2408 : : u8 i;
2409 : :
2410 [ # # ]: 0 : for (i = 0; i < ICE_BLK_COUNT; i++) {
2411 : 0 : struct ice_prof_redir *prof_redir = &hw->blk[i].prof_redir;
2412 : : struct ice_prof_tcam *prof = &hw->blk[i].prof;
2413 : : struct ice_xlt1 *xlt1 = &hw->blk[i].xlt1;
2414 : : struct ice_xlt2 *xlt2 = &hw->blk[i].xlt2;
2415 : : struct ice_es *es = &hw->blk[i].es;
2416 : :
2417 [ # # ]: 0 : if (hw->blk[i].is_list_init) {
2418 : 0 : ice_free_prof_map(hw, i);
2419 : 0 : ice_free_flow_profs(hw, i);
2420 : : }
2421 : :
2422 : 0 : ice_free_vsig_tbl(hw, (enum ice_block)i);
2423 : :
2424 [ # # ]: 0 : if (xlt1->ptypes)
2425 : 0 : ice_memset(xlt1->ptypes, 0,
2426 : : xlt1->count * sizeof(*xlt1->ptypes),
2427 : : ICE_NONDMA_MEM);
2428 : :
2429 [ # # ]: 0 : if (xlt1->ptg_tbl)
2430 : : ice_memset(xlt1->ptg_tbl, 0,
2431 : : ICE_MAX_PTGS * sizeof(*xlt1->ptg_tbl),
2432 : : ICE_NONDMA_MEM);
2433 : :
2434 [ # # ]: 0 : if (xlt1->t)
2435 : 0 : ice_memset(xlt1->t, 0, xlt1->count * sizeof(*xlt1->t),
2436 : : ICE_NONDMA_MEM);
2437 : :
2438 [ # # ]: 0 : if (xlt2->vsis)
2439 : 0 : ice_memset(xlt2->vsis, 0,
2440 : : xlt2->count * sizeof(*xlt2->vsis),
2441 : : ICE_NONDMA_MEM);
2442 : :
2443 [ # # ]: 0 : if (xlt2->vsig_tbl)
2444 : 0 : ice_memset(xlt2->vsig_tbl, 0,
2445 : : xlt2->count * sizeof(*xlt2->vsig_tbl),
2446 : : ICE_NONDMA_MEM);
2447 : :
2448 [ # # ]: 0 : if (xlt2->t)
2449 : 0 : ice_memset(xlt2->t, 0, xlt2->count * sizeof(*xlt2->t),
2450 : : ICE_NONDMA_MEM);
2451 : :
2452 [ # # ]: 0 : if (prof->t)
2453 : 0 : ice_memset(prof->t, 0, prof->count * sizeof(*prof->t),
2454 : : ICE_NONDMA_MEM);
2455 : :
2456 [ # # ]: 0 : if (prof_redir->t)
2457 : 0 : ice_memset(prof_redir->t, 0,
2458 : : prof_redir->count * sizeof(*prof_redir->t),
2459 : : ICE_NONDMA_MEM);
2460 : :
2461 [ # # ]: 0 : if (es->t)
2462 : 0 : ice_memset(es->t, 0,
2463 : : es->count * sizeof(*es->t) * es->fvw,
2464 : : ICE_NONDMA_MEM);
2465 : :
2466 [ # # ]: 0 : if (es->ref_count)
2467 : 0 : ice_memset(es->ref_count, 0,
2468 : : es->count * sizeof(*es->ref_count),
2469 : : ICE_NONDMA_MEM);
2470 : :
2471 [ # # ]: 0 : if (es->written)
2472 : 0 : ice_memset(es->written, 0,
2473 : : es->count * sizeof(*es->written),
2474 : : ICE_NONDMA_MEM);
2475 : :
2476 [ # # ]: 0 : if (es->mask_ena)
2477 : 0 : ice_memset(es->mask_ena, 0,
2478 : : es->count * sizeof(*es->mask_ena),
2479 : : ICE_NONDMA_MEM);
2480 : : }
2481 : 0 : }
2482 : :
2483 : : /**
2484 : : * ice_prof_gen_key - generate profile ID key
2485 : : * @hw: pointer to the HW struct
2486 : : * @blk: the block in which to write profile ID to
2487 : : * @ptg: packet type group (PTG) portion of key
2488 : : * @vsig: VSIG portion of key
2489 : : * @cdid: CDID portion of key
2490 : : * @flags: flag portion of key
2491 : : * @vl_msk: valid mask
2492 : : * @dc_msk: don't care mask
2493 : : * @nm_msk: never match mask
2494 : : * @key: output of profile ID key
2495 : : */
2496 : : static enum ice_status
2497 : 0 : ice_prof_gen_key(struct ice_hw *hw, enum ice_block blk, u8 ptg, u16 vsig,
2498 : : u8 cdid, u16 flags, u8 vl_msk[ICE_TCAM_KEY_VAL_SZ],
2499 : : u8 dc_msk[ICE_TCAM_KEY_VAL_SZ], u8 nm_msk[ICE_TCAM_KEY_VAL_SZ],
2500 : : u8 key[ICE_TCAM_KEY_SZ])
2501 : : {
2502 : : struct ice_prof_id_key inkey;
2503 : :
2504 : 0 : inkey.xlt1 = ptg;
2505 : 0 : inkey.xlt2_cdid = CPU_TO_LE16(vsig);
2506 : 0 : inkey.flags = CPU_TO_LE16(flags);
2507 : :
2508 [ # # # # : 0 : switch (hw->blk[blk].prof.cdid_bits) {
# ]
2509 : : case 0:
2510 : : break;
2511 : 0 : case 2:
2512 : : #define ICE_CD_2_M 0xC000U
2513 : : #define ICE_CD_2_S 14
2514 : 0 : inkey.xlt2_cdid &= ~CPU_TO_LE16(ICE_CD_2_M);
2515 : 0 : inkey.xlt2_cdid |= CPU_TO_LE16(BIT(cdid) << ICE_CD_2_S);
2516 : 0 : break;
2517 : 0 : case 4:
2518 : : #define ICE_CD_4_M 0xF000U
2519 : : #define ICE_CD_4_S 12
2520 : 0 : inkey.xlt2_cdid &= ~CPU_TO_LE16(ICE_CD_4_M);
2521 : 0 : inkey.xlt2_cdid |= CPU_TO_LE16(BIT(cdid) << ICE_CD_4_S);
2522 : 0 : break;
2523 : 0 : case 8:
2524 : : #define ICE_CD_8_M 0xFF00U
2525 : : #define ICE_CD_8_S 16
2526 : 0 : inkey.xlt2_cdid &= ~CPU_TO_LE16(ICE_CD_8_M);
2527 : : inkey.xlt2_cdid |= CPU_TO_LE16(BIT(cdid) << ICE_CD_8_S);
2528 : 0 : break;
2529 : 0 : default:
2530 [ # # ]: 0 : ice_debug(hw, ICE_DBG_PKG, "Error in profile config\n");
2531 : : break;
2532 : : }
2533 : :
2534 : 0 : return ice_set_key(key, ICE_TCAM_KEY_SZ, (u8 *)&inkey, vl_msk, dc_msk,
2535 : : nm_msk, 0, ICE_TCAM_KEY_SZ / 2);
2536 : : }
2537 : :
2538 : : /**
2539 : : * ice_tcam_write_entry - write TCAM entry
2540 : : * @hw: pointer to the HW struct
2541 : : * @blk: the block in which to write profile ID to
2542 : : * @idx: the entry index to write to
2543 : : * @prof_id: profile ID
2544 : : * @ptg: packet type group (PTG) portion of key
2545 : : * @vsig: VSIG portion of key
2546 : : * @cdid: CDID portion of key
2547 : : * @flags: flag portion of key
2548 : : * @vl_msk: valid mask
2549 : : * @dc_msk: don't care mask
2550 : : * @nm_msk: never match mask
2551 : : */
2552 : : static enum ice_status
2553 : 0 : ice_tcam_write_entry(struct ice_hw *hw, enum ice_block blk, u16 idx,
2554 : : u8 prof_id, u8 ptg, u16 vsig, u8 cdid, u16 flags,
2555 : : u8 vl_msk[ICE_TCAM_KEY_VAL_SZ],
2556 : : u8 dc_msk[ICE_TCAM_KEY_VAL_SZ],
2557 : : u8 nm_msk[ICE_TCAM_KEY_VAL_SZ])
2558 : : {
2559 : : struct ice_prof_tcam_entry;
2560 : : enum ice_status status;
2561 : :
2562 : 0 : status = ice_prof_gen_key(hw, blk, ptg, vsig, cdid, flags, vl_msk,
2563 : 0 : dc_msk, nm_msk, hw->blk[blk].prof.t[idx].key);
2564 [ # # ]: 0 : if (!status) {
2565 : 0 : hw->blk[blk].prof.t[idx].addr = CPU_TO_LE16(idx);
2566 : 0 : hw->blk[blk].prof.t[idx].prof_id = prof_id;
2567 : : }
2568 : :
2569 : 0 : return status;
2570 : : }
2571 : :
2572 : : /**
2573 : : * ice_vsig_get_ref - returns number of VSIs belong to a VSIG
2574 : : * @hw: pointer to the hardware structure
2575 : : * @blk: HW block
2576 : : * @vsig: VSIG to query
2577 : : * @refs: pointer to variable to receive the reference count
2578 : : */
2579 : : static enum ice_status
2580 : : ice_vsig_get_ref(struct ice_hw *hw, enum ice_block blk, u16 vsig, u16 *refs)
2581 : : {
2582 : 0 : u16 idx = vsig & ICE_VSIG_IDX_M;
2583 : : struct ice_vsig_vsi *ptr;
2584 : :
2585 : : *refs = 0;
2586 : :
2587 [ # # ]: 0 : if (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use)
2588 : : return ICE_ERR_DOES_NOT_EXIST;
2589 : :
2590 : 0 : ptr = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi;
2591 [ # # # # ]: 0 : while (ptr) {
2592 : 0 : (*refs)++;
2593 : 0 : ptr = ptr->next_vsi;
2594 : : }
2595 : :
2596 : : return ICE_SUCCESS;
2597 : : }
2598 : :
2599 : : /**
2600 : : * ice_has_prof_vsig - check to see if VSIG has a specific profile
2601 : : * @hw: pointer to the hardware structure
2602 : : * @blk: HW block
2603 : : * @vsig: VSIG to check against
2604 : : * @hdl: profile handle
2605 : : */
2606 : : static bool
2607 : 0 : ice_has_prof_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl)
2608 : : {
2609 : 0 : u16 idx = vsig & ICE_VSIG_IDX_M;
2610 : : struct ice_vsig_prof *ent;
2611 : :
2612 [ # # # # : 0 : LIST_FOR_EACH_ENTRY(ent, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst,
# # ]
2613 : : ice_vsig_prof, list)
2614 [ # # ]: 0 : if (ent->profile_cookie == hdl)
2615 : : return true;
2616 : :
2617 [ # # ]: 0 : ice_debug(hw, ICE_DBG_INIT, "Characteristic list for VSI group %d not found.\n",
2618 : : vsig);
2619 : : return false;
2620 : : }
2621 : :
2622 : : /**
2623 : : * ice_prof_bld_es - build profile ID extraction sequence changes
2624 : : * @hw: pointer to the HW struct
2625 : : * @blk: hardware block
2626 : : * @bld: the update package buffer build to add to
2627 : : * @chgs: the list of changes to make in hardware
2628 : : */
2629 : : static enum ice_status
2630 : 0 : ice_prof_bld_es(struct ice_hw *hw, enum ice_block blk,
2631 : : struct ice_buf_build *bld, struct LIST_HEAD_TYPE *chgs)
2632 : : {
2633 : 0 : u16 vec_size = hw->blk[blk].es.fvw * sizeof(struct ice_fv_word);
2634 : : struct ice_chs_chg *tmp;
2635 : :
2636 [ # # # # : 0 : LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry)
# # ]
2637 [ # # # # ]: 0 : if (tmp->type == ICE_PTG_ES_ADD && tmp->add_prof) {
2638 : 0 : u16 off = tmp->prof_id * hw->blk[blk].es.fvw;
2639 : : struct ice_pkg_es *p;
2640 : : u32 id;
2641 : :
2642 : : id = ice_sect_id(blk, ICE_VEC_TBL);
2643 : : p = (struct ice_pkg_es *)
2644 : 0 : ice_pkg_buf_alloc_section(bld, id,
2645 : : ice_struct_size(p, es,
2646 : : 1) +
2647 : 0 : vec_size -
2648 : : sizeof(p->es[0]));
2649 : :
2650 [ # # ]: 0 : if (!p)
2651 : : return ICE_ERR_MAX_LIMIT;
2652 : :
2653 : 0 : p->count = CPU_TO_LE16(1);
2654 : 0 : p->offset = CPU_TO_LE16(tmp->prof_id);
2655 : :
2656 [ # # ]: 0 : ice_memcpy(p->es, &hw->blk[blk].es.t[off], vec_size,
2657 : : ICE_NONDMA_TO_NONDMA);
2658 : : }
2659 : :
2660 : : return ICE_SUCCESS;
2661 : : }
2662 : :
2663 : : /**
2664 : : * ice_prof_bld_tcam - build profile ID TCAM changes
2665 : : * @hw: pointer to the HW struct
2666 : : * @blk: hardware block
2667 : : * @bld: the update package buffer build to add to
2668 : : * @chgs: the list of changes to make in hardware
2669 : : */
2670 : : static enum ice_status
2671 : 0 : ice_prof_bld_tcam(struct ice_hw *hw, enum ice_block blk,
2672 : : struct ice_buf_build *bld, struct LIST_HEAD_TYPE *chgs)
2673 : : {
2674 : : struct ice_chs_chg *tmp;
2675 : :
2676 [ # # # # : 0 : LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry)
# # ]
2677 [ # # # # ]: 0 : if (tmp->type == ICE_TCAM_ADD && tmp->add_tcam_idx) {
2678 : : struct ice_prof_id_section *p;
2679 : : u32 id;
2680 : :
2681 : : id = ice_sect_id(blk, ICE_PROF_TCAM);
2682 : : p = (struct ice_prof_id_section *)
2683 : 0 : ice_pkg_buf_alloc_section(bld, id,
2684 : : ice_struct_size(p,
2685 : : entry,
2686 : : 1));
2687 : :
2688 [ # # ]: 0 : if (!p)
2689 : : return ICE_ERR_MAX_LIMIT;
2690 : :
2691 : 0 : p->count = CPU_TO_LE16(1);
2692 : 0 : p->entry[0].addr = CPU_TO_LE16(tmp->tcam_idx);
2693 : 0 : p->entry[0].prof_id = tmp->prof_id;
2694 : :
2695 [ # # ]: 0 : ice_memcpy(p->entry[0].key,
2696 : : &hw->blk[blk].prof.t[tmp->tcam_idx].key,
2697 : : sizeof(hw->blk[blk].prof.t->key),
2698 : : ICE_NONDMA_TO_NONDMA);
2699 : : }
2700 : :
2701 : : return ICE_SUCCESS;
2702 : : }
2703 : :
2704 : : /**
2705 : : * ice_prof_bld_xlt1 - build XLT1 changes
2706 : : * @blk: hardware block
2707 : : * @bld: the update package buffer build to add to
2708 : : * @chgs: the list of changes to make in hardware
2709 : : */
2710 : : static enum ice_status
2711 : 0 : ice_prof_bld_xlt1(enum ice_block blk, struct ice_buf_build *bld,
2712 : : struct LIST_HEAD_TYPE *chgs)
2713 : : {
2714 : : struct ice_chs_chg *tmp;
2715 : :
2716 [ # # # # : 0 : LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry)
# # ]
2717 [ # # # # ]: 0 : if (tmp->type == ICE_PTG_ES_ADD && tmp->add_ptg) {
2718 : : struct ice_xlt1_section *p;
2719 : : u32 id;
2720 : :
2721 : : id = ice_sect_id(blk, ICE_XLT1);
2722 : : p = (struct ice_xlt1_section *)
2723 : 0 : ice_pkg_buf_alloc_section(bld, id,
2724 : : ice_struct_size(p,
2725 : : value,
2726 : : 1));
2727 : :
2728 [ # # ]: 0 : if (!p)
2729 : : return ICE_ERR_MAX_LIMIT;
2730 : :
2731 : 0 : p->count = CPU_TO_LE16(1);
2732 : 0 : p->offset = CPU_TO_LE16(tmp->ptype);
2733 : 0 : p->value[0] = tmp->ptg;
2734 : : }
2735 : :
2736 : : return ICE_SUCCESS;
2737 : : }
2738 : :
2739 : : /**
2740 : : * ice_prof_bld_xlt2 - build XLT2 changes
2741 : : * @blk: hardware block
2742 : : * @bld: the update package buffer build to add to
2743 : : * @chgs: the list of changes to make in hardware
2744 : : */
2745 : : static enum ice_status
2746 : 0 : ice_prof_bld_xlt2(enum ice_block blk, struct ice_buf_build *bld,
2747 : : struct LIST_HEAD_TYPE *chgs)
2748 : : {
2749 : : struct ice_chs_chg *tmp;
2750 : :
2751 [ # # # # : 0 : LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) {
# # ]
2752 : : struct ice_xlt2_section *p;
2753 : : u32 id;
2754 : :
2755 [ # # ]: 0 : switch (tmp->type) {
2756 : : case ICE_VSIG_ADD:
2757 : : case ICE_VSI_MOVE:
2758 : : case ICE_VSIG_REM:
2759 : : id = ice_sect_id(blk, ICE_XLT2);
2760 : : p = (struct ice_xlt2_section *)
2761 : 0 : ice_pkg_buf_alloc_section(bld, id,
2762 : : ice_struct_size(p,
2763 : : value,
2764 : : 1));
2765 : :
2766 [ # # ]: 0 : if (!p)
2767 : : return ICE_ERR_MAX_LIMIT;
2768 : :
2769 : 0 : p->count = CPU_TO_LE16(1);
2770 : 0 : p->offset = CPU_TO_LE16(tmp->vsi);
2771 : 0 : p->value[0] = CPU_TO_LE16(tmp->vsig);
2772 : 0 : break;
2773 : : default:
2774 : : break;
2775 : : }
2776 : : }
2777 : :
2778 : : return ICE_SUCCESS;
2779 : : }
2780 : :
2781 : : /**
2782 : : * ice_upd_prof_hw - update hardware using the change list
2783 : : * @hw: pointer to the HW struct
2784 : : * @blk: hardware block
2785 : : * @chgs: the list of changes to make in hardware
2786 : : */
2787 : : static enum ice_status
2788 : 0 : ice_upd_prof_hw(struct ice_hw *hw, enum ice_block blk,
2789 : : struct LIST_HEAD_TYPE *chgs)
2790 : : {
2791 : : struct ice_buf_build *b;
2792 : : struct ice_chs_chg *tmp;
2793 : : enum ice_status status;
2794 : : u16 pkg_sects;
2795 : : u16 xlt1 = 0;
2796 : : u16 xlt2 = 0;
2797 : : u16 tcam = 0;
2798 : : u16 es = 0;
2799 : : u16 sects;
2800 : :
2801 : : /* count number of sections we need */
2802 [ # # # # : 0 : LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) {
# # ]
2803 [ # # # # ]: 0 : switch (tmp->type) {
2804 : 0 : case ICE_PTG_ES_ADD:
2805 [ # # ]: 0 : if (tmp->add_ptg)
2806 : 0 : xlt1++;
2807 [ # # ]: 0 : if (tmp->add_prof)
2808 : 0 : es++;
2809 : : break;
2810 : 0 : case ICE_TCAM_ADD:
2811 : 0 : tcam++;
2812 : 0 : break;
2813 : 0 : case ICE_VSIG_ADD:
2814 : : case ICE_VSI_MOVE:
2815 : : case ICE_VSIG_REM:
2816 : 0 : xlt2++;
2817 : 0 : break;
2818 : : default:
2819 : : break;
2820 : : }
2821 : : }
2822 : 0 : sects = xlt1 + xlt2 + tcam + es;
2823 : :
2824 [ # # ]: 0 : if (!sects)
2825 : : return ICE_SUCCESS;
2826 : :
2827 : : /* Build update package buffer */
2828 : 0 : b = ice_pkg_buf_alloc(hw);
2829 [ # # ]: 0 : if (!b)
2830 : : return ICE_ERR_NO_MEMORY;
2831 : :
2832 : 0 : status = ice_pkg_buf_reserve_section(b, sects);
2833 [ # # ]: 0 : if (status)
2834 : 0 : goto error_tmp;
2835 : :
2836 : : /* Preserve order of table update: ES, TCAM, PTG, VSIG */
2837 [ # # ]: 0 : if (es) {
2838 : 0 : status = ice_prof_bld_es(hw, blk, b, chgs);
2839 [ # # ]: 0 : if (status)
2840 : 0 : goto error_tmp;
2841 : : }
2842 : :
2843 [ # # ]: 0 : if (tcam) {
2844 : 0 : status = ice_prof_bld_tcam(hw, blk, b, chgs);
2845 [ # # ]: 0 : if (status)
2846 : 0 : goto error_tmp;
2847 : : }
2848 : :
2849 [ # # ]: 0 : if (xlt1) {
2850 : 0 : status = ice_prof_bld_xlt1(blk, b, chgs);
2851 [ # # ]: 0 : if (status)
2852 : 0 : goto error_tmp;
2853 : : }
2854 : :
2855 [ # # ]: 0 : if (xlt2) {
2856 : 0 : status = ice_prof_bld_xlt2(blk, b, chgs);
2857 [ # # ]: 0 : if (status)
2858 : 0 : goto error_tmp;
2859 : : }
2860 : :
2861 : : /* After package buffer build check if the section count in buffer is
2862 : : * non-zero and matches the number of sections detected for package
2863 : : * update.
2864 : : */
2865 : 0 : pkg_sects = ice_pkg_buf_get_active_sections(b);
2866 [ # # ]: 0 : if (!pkg_sects || pkg_sects != sects) {
2867 : : status = ICE_ERR_INVAL_SIZE;
2868 : 0 : goto error_tmp;
2869 : : }
2870 : :
2871 : : /* update package */
2872 : 0 : status = ice_update_pkg(hw, ice_pkg_buf(b), 1);
2873 [ # # ]: 0 : if (status == ICE_ERR_AQ_ERROR)
2874 [ # # ]: 0 : ice_debug(hw, ICE_DBG_INIT, "Unable to update HW profile\n");
2875 : :
2876 : 0 : error_tmp:
2877 : 0 : ice_pkg_buf_free(hw, b);
2878 : 0 : return status;
2879 : : }
2880 : :
2881 : : /**
2882 : : * ice_update_fd_mask - set Flow Director Field Vector mask for a profile
2883 : : * @hw: pointer to the HW struct
2884 : : * @prof_id: profile ID
2885 : : * @mask_sel: mask select
2886 : : *
2887 : : * This function enable any of the masks selected by the mask select parameter
2888 : : * for the profile specified.
2889 : : */
2890 : 0 : static void ice_update_fd_mask(struct ice_hw *hw, u16 prof_id, u32 mask_sel)
2891 : : {
2892 : 0 : wr32(hw, GLQF_FDMASK_SEL(prof_id), mask_sel);
2893 : :
2894 [ # # ]: 0 : ice_debug(hw, ICE_DBG_INIT, "fd mask(%d): %x = %x\n", prof_id,
2895 : : GLQF_FDMASK_SEL(prof_id), mask_sel);
2896 : 0 : }
2897 : :
2898 : : struct ice_fd_src_dst_pair {
2899 : : u8 prot_id;
2900 : : u8 count;
2901 : : u16 off;
2902 : : };
2903 : :
2904 : : static const struct ice_fd_src_dst_pair ice_fd_pairs[] = {
2905 : : /* These are defined in pairs */
2906 : : { ICE_PROT_IPV4_OF_OR_S, 2, 12 },
2907 : : { ICE_PROT_IPV4_OF_OR_S, 2, 16 },
2908 : :
2909 : : { ICE_PROT_IPV4_IL, 2, 12 },
2910 : : { ICE_PROT_IPV4_IL, 2, 16 },
2911 : :
2912 : : { ICE_PROT_IPV4_IL_IL, 2, 12 },
2913 : : { ICE_PROT_IPV4_IL_IL, 2, 16 },
2914 : :
2915 : : { ICE_PROT_IPV6_OF_OR_S, 8, 8 },
2916 : : { ICE_PROT_IPV6_OF_OR_S, 8, 24 },
2917 : :
2918 : : { ICE_PROT_IPV6_IL, 8, 8 },
2919 : : { ICE_PROT_IPV6_IL, 8, 24 },
2920 : :
2921 : : { ICE_PROT_IPV6_IL_IL, 8, 8 },
2922 : : { ICE_PROT_IPV6_IL_IL, 8, 24 },
2923 : :
2924 : : { ICE_PROT_TCP_IL, 1, 0 },
2925 : : { ICE_PROT_TCP_IL, 1, 2 },
2926 : :
2927 : : { ICE_PROT_UDP_OF, 1, 0 },
2928 : : { ICE_PROT_UDP_OF, 1, 2 },
2929 : :
2930 : : { ICE_PROT_UDP_IL_OR_S, 1, 0 },
2931 : : { ICE_PROT_UDP_IL_OR_S, 1, 2 },
2932 : :
2933 : : { ICE_PROT_SCTP_IL, 1, 0 },
2934 : : { ICE_PROT_SCTP_IL, 1, 2 }
2935 : : };
2936 : :
2937 : : #define ICE_FD_SRC_DST_PAIR_COUNT ARRAY_SIZE(ice_fd_pairs)
2938 : :
2939 : : /**
2940 : : * ice_update_fd_swap - set register appropriately for a FD FV extraction
2941 : : * @hw: pointer to the HW struct
2942 : : * @prof_id: profile ID
2943 : : * @es: extraction sequence (length of array is determined by the block)
2944 : : */
2945 : : static enum ice_status
2946 : 0 : ice_update_fd_swap(struct ice_hw *hw, u16 prof_id, struct ice_fv_word *es)
2947 : : {
2948 : : ice_declare_bitmap(pair_list, ICE_FD_SRC_DST_PAIR_COUNT);
2949 : 0 : u8 pair_start[ICE_FD_SRC_DST_PAIR_COUNT] = { 0 };
2950 : : #define ICE_FD_FV_NOT_FOUND (-2)
2951 : : s8 first_free = ICE_FD_FV_NOT_FOUND;
2952 : 0 : u8 used[ICE_MAX_FV_WORDS] = { 0 };
2953 : : s8 orig_free, si;
2954 : : u32 mask_sel = 0;
2955 : : u8 i, j, k;
2956 : :
2957 : : ice_zero_bitmap(pair_list, ICE_FD_SRC_DST_PAIR_COUNT);
2958 : :
2959 : : /* This code assumes that the Flow Director field vectors are assigned
2960 : : * from the end of the FV indexes working towards the zero index, that
2961 : : * only complete fields will be included and will be consecutive, and
2962 : : * that there are no gaps between valid indexes.
2963 : : */
2964 : :
2965 : : /* Determine swap fields present */
2966 [ # # ]: 0 : for (i = 0; i < hw->blk[ICE_BLK_FD].es.fvw; i++) {
2967 : : /* Find the first free entry, assuming right to left population.
2968 : : * This is where we can start adding additional pairs if needed.
2969 : : */
2970 [ # # # # ]: 0 : if (first_free == ICE_FD_FV_NOT_FOUND && es[i].prot_id !=
2971 : : ICE_PROT_INVALID)
2972 : 0 : first_free = i - 1;
2973 : :
2974 [ # # ]: 0 : for (j = 0; j < ICE_FD_SRC_DST_PAIR_COUNT; j++)
2975 [ # # ]: 0 : if (es[i].prot_id == ice_fd_pairs[j].prot_id &&
2976 [ # # ]: 0 : es[i].off == ice_fd_pairs[j].off) {
2977 : : ice_set_bit(j, pair_list);
2978 : 0 : pair_start[j] = i;
2979 : : }
2980 : : }
2981 : :
2982 : : orig_free = first_free;
2983 : :
2984 : : /* determine missing swap fields that need to be added */
2985 [ # # ]: 0 : for (i = 0; i < ICE_FD_SRC_DST_PAIR_COUNT; i += 2) {
2986 [ # # ]: 0 : u8 bit1 = ice_is_bit_set(pair_list, i + 1);
2987 : : u8 bit0 = ice_is_bit_set(pair_list, i);
2988 : :
2989 [ # # ]: 0 : if (bit0 ^ bit1) {
2990 : : u8 index;
2991 : :
2992 : : /* add the appropriate 'paired' entry */
2993 [ # # ]: 0 : if (!bit0)
2994 : : index = i;
2995 : : else
2996 : 0 : index = i + 1;
2997 : :
2998 : : /* check for room */
2999 [ # # ]: 0 : if (first_free + 1 < (s8)ice_fd_pairs[index].count)
3000 : : return ICE_ERR_MAX_LIMIT;
3001 : :
3002 : : /* place in extraction sequence */
3003 [ # # ]: 0 : for (k = 0; k < ice_fd_pairs[index].count; k++) {
3004 : 0 : es[first_free - k].prot_id =
3005 : 0 : ice_fd_pairs[index].prot_id;
3006 : 0 : es[first_free - k].off =
3007 : 0 : ice_fd_pairs[index].off + (k * 2);
3008 : :
3009 [ # # ]: 0 : if (k > first_free)
3010 : : return ICE_ERR_OUT_OF_RANGE;
3011 : :
3012 : : /* keep track of non-relevant fields */
3013 : 0 : mask_sel |= BIT(first_free - k);
3014 : : }
3015 : :
3016 : 0 : pair_start[index] = first_free;
3017 : 0 : first_free -= ice_fd_pairs[index].count;
3018 : : }
3019 : : }
3020 : :
3021 : : /* fill in the swap array */
3022 : 0 : si = hw->blk[ICE_BLK_FD].es.fvw - 1;
3023 [ # # ]: 0 : while (si >= 0) {
3024 : : u8 indexes_used = 1;
3025 : :
3026 : : /* assume flat at this index */
3027 : : #define ICE_SWAP_VALID 0x80
3028 : 0 : used[si] = si | ICE_SWAP_VALID;
3029 : :
3030 [ # # ]: 0 : if (orig_free == ICE_FD_FV_NOT_FOUND || si <= orig_free) {
3031 : 0 : si -= indexes_used;
3032 : 0 : continue;
3033 : : }
3034 : :
3035 : : /* check for a swap location */
3036 [ # # ]: 0 : for (j = 0; j < ICE_FD_SRC_DST_PAIR_COUNT; j++)
3037 [ # # ]: 0 : if (es[si].prot_id == ice_fd_pairs[j].prot_id &&
3038 [ # # ]: 0 : es[si].off == ice_fd_pairs[j].off) {
3039 : : u8 idx;
3040 : :
3041 : : /* determine the appropriate matching field */
3042 [ # # ]: 0 : idx = j + ((j % 2) ? -1 : 1);
3043 : :
3044 : 0 : indexes_used = ice_fd_pairs[idx].count;
3045 [ # # ]: 0 : for (k = 0; k < indexes_used; k++) {
3046 : 0 : used[si - k] = (pair_start[idx] - k) |
3047 : : ICE_SWAP_VALID;
3048 : : }
3049 : :
3050 : : break;
3051 : : }
3052 : :
3053 : 0 : si -= indexes_used;
3054 : : }
3055 : :
3056 : : /* for each set of 4 swap and 4 inset indexes, write the appropriate
3057 : : * register
3058 : : */
3059 [ # # ]: 0 : for (j = 0; j < hw->blk[ICE_BLK_FD].es.fvw / 4; j++) {
3060 : : u32 raw_swap = 0;
3061 : : u32 raw_in = 0;
3062 : :
3063 [ # # ]: 0 : for (k = 0; k < 4; k++) {
3064 : : u8 idx;
3065 : :
3066 : 0 : idx = (j * 4) + k;
3067 [ # # # # ]: 0 : if (used[idx] && !(mask_sel & BIT(idx))) {
3068 : 0 : raw_swap |= used[idx] << (k * BITS_PER_BYTE);
3069 : : #define ICE_INSET_DFLT 0x9f
3070 : 0 : raw_in |= ICE_INSET_DFLT << (k * BITS_PER_BYTE);
3071 : : }
3072 : : }
3073 : :
3074 : : /* write the appropriate swap register set */
3075 : 0 : wr32(hw, GLQF_FDSWAP(prof_id, j), raw_swap);
3076 : :
3077 [ # # ]: 0 : ice_debug(hw, ICE_DBG_INIT, "swap wr(%d, %d): %x = %08x\n",
3078 : : prof_id, j, GLQF_FDSWAP(prof_id, j), raw_swap);
3079 : :
3080 : : /* write the appropriate inset register set */
3081 : 0 : wr32(hw, GLQF_FDINSET(prof_id, j), raw_in);
3082 : :
3083 [ # # ]: 0 : ice_debug(hw, ICE_DBG_INIT, "inset wr(%d, %d): %x = %08x\n",
3084 : : prof_id, j, GLQF_FDINSET(prof_id, j), raw_in);
3085 : : }
3086 : :
3087 : : /* initially clear the mask select for this profile */
3088 : 0 : ice_update_fd_mask(hw, prof_id, 0);
3089 : :
3090 : 0 : return ICE_SUCCESS;
3091 : : }
3092 : :
3093 : : /* The entries here needs to match the order of enum ice_ptype_attrib */
3094 : : static const struct ice_ptype_attrib_info ice_ptype_attributes[] = {
3095 : : { ICE_GTP_PDU_EH, ICE_GTP_PDU_FLAG_MASK },
3096 : : { ICE_GTP_SESSION, ICE_GTP_FLAGS_MASK },
3097 : : { ICE_GTP_DOWNLINK, ICE_GTP_FLAGS_MASK },
3098 : : { ICE_GTP_UPLINK, ICE_GTP_FLAGS_MASK },
3099 : : };
3100 : :
3101 : : /**
3102 : : * ice_get_ptype_attrib_info - get ptype attribute information
3103 : : * @type: attribute type
3104 : : * @info: pointer to variable to the attribute information
3105 : : */
3106 : : static void
3107 : : ice_get_ptype_attrib_info(enum ice_ptype_attrib_type type,
3108 : : struct ice_ptype_attrib_info *info)
3109 : : {
3110 : 0 : *info = ice_ptype_attributes[type];
3111 : : }
3112 : :
3113 : : /**
3114 : : * ice_add_prof_attrib - add any PTG with attributes to profile
3115 : : * @prof: pointer to the profile to which PTG entries will be added
3116 : : * @ptg: PTG to be added
3117 : : * @ptype: PTYPE that needs to be looked up
3118 : : * @attr: array of attributes that will be considered
3119 : : * @attr_cnt: number of elements in the attribute array
3120 : : */
3121 : : static enum ice_status
3122 : : ice_add_prof_attrib(struct ice_prof_map *prof, u8 ptg, u16 ptype,
3123 : : const struct ice_ptype_attributes *attr, u16 attr_cnt)
3124 : : {
3125 : : bool found = false;
3126 : : u16 i;
3127 : :
3128 [ # # ]: 0 : for (i = 0; i < attr_cnt; i++) {
3129 [ # # ]: 0 : if (attr[i].ptype == ptype) {
3130 : : found = true;
3131 : :
3132 : 0 : prof->ptg[prof->ptg_cnt] = ptg;
3133 : 0 : ice_get_ptype_attrib_info(attr[i].attrib,
3134 : : &prof->attr[prof->ptg_cnt]);
3135 : :
3136 [ # # ]: 0 : if (++prof->ptg_cnt >= ICE_MAX_PTG_PER_PROFILE)
3137 : : return ICE_ERR_MAX_LIMIT;
3138 : : }
3139 : : }
3140 : :
3141 [ # # ]: 0 : if (!found)
3142 : : return ICE_ERR_DOES_NOT_EXIST;
3143 : :
3144 : : return ICE_SUCCESS;
3145 : : }
3146 : :
3147 : : /**
3148 : : * ice_disable_fd_swap - set register appropriately to disable FD swap
3149 : : * @hw: pointer to the HW struct
3150 : : * @prof_id: profile ID
3151 : : */
3152 : 0 : static void ice_disable_fd_swap(struct ice_hw *hw, u16 prof_id)
3153 : : {
3154 : : u8 swap_val = ICE_SWAP_VALID;
3155 : : u8 i;
3156 : : /* Since the SWAP Flag in the Programming Desc doesn't work,
3157 : : * here add method to disable the SWAP Option via setting
3158 : : * certain SWAP and INSET register set.
3159 : : */
3160 [ # # ]: 0 : for (i = 0; i < hw->blk[ICE_BLK_FD].es.fvw / 4; i++) {
3161 : : u32 raw_swap = 0;
3162 : : u32 raw_in = 0;
3163 : : u8 j;
3164 : :
3165 [ # # ]: 0 : for (j = 0; j < 4; j++) {
3166 : 0 : raw_swap |= (swap_val++) << (j * BITS_PER_BYTE);
3167 : 0 : raw_in |= ICE_INSET_DFLT << (j * BITS_PER_BYTE);
3168 : : }
3169 : :
3170 : : /* write the FDIR swap register set */
3171 : 0 : wr32(hw, GLQF_FDSWAP(prof_id, i), raw_swap);
3172 : :
3173 [ # # ]: 0 : ice_debug(hw, ICE_DBG_INIT, "swap wr(%d, %d): %x = %08x\n",
3174 : : prof_id, i, GLQF_FDSWAP(prof_id, i), raw_swap);
3175 : :
3176 : : /* write the FDIR inset register set */
3177 : 0 : wr32(hw, GLQF_FDINSET(prof_id, i), raw_in);
3178 : :
3179 [ # # ]: 0 : ice_debug(hw, ICE_DBG_INIT, "inset wr(%d, %d): %x = %08x\n",
3180 : : prof_id, i, GLQF_FDINSET(prof_id, i), raw_in);
3181 : : }
3182 : 0 : }
3183 : :
3184 : : /**
3185 : : * ice_add_prof - add profile
3186 : : * @hw: pointer to the HW struct
3187 : : * @blk: hardware block
3188 : : * @id: profile tracking ID
3189 : : * @ptypes: bitmap indicating ptypes (ICE_FLOW_PTYPE_MAX bits)
3190 : : * @attr: array of attributes
3191 : : * @attr_cnt: number of elements in attrib array
3192 : : * @es: extraction sequence (length of array is determined by the block)
3193 : : * @masks: mask for extraction sequence
3194 : : * @fd_swap: enable/disable FDIR paired src/dst fields swap option
3195 : : *
3196 : : * This function registers a profile, which matches a set of PTYPES with a
3197 : : * particular extraction sequence. While the hardware profile is allocated
3198 : : * it will not be written until the first call to ice_add_flow that specifies
3199 : : * the ID value used here.
3200 : : */
3201 : : enum ice_status
3202 : 0 : ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id,
3203 : : ice_bitmap_t *ptypes, const struct ice_ptype_attributes *attr,
3204 : : u16 attr_cnt, struct ice_fv_word *es, u16 *masks, bool fd_swap)
3205 : : {
3206 : : ice_declare_bitmap(ptgs_used, ICE_XLT1_CNT);
3207 : : struct ice_prof_map *prof;
3208 : : enum ice_status status;
3209 : : u8 prof_id;
3210 : : u16 ptype;
3211 : :
3212 : : ice_zero_bitmap(ptgs_used, ICE_XLT1_CNT);
3213 : :
3214 : 0 : ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
3215 : :
3216 : : /* search for existing profile */
3217 : 0 : status = ice_find_prof_id_with_mask(hw, blk, es, masks, &prof_id);
3218 [ # # ]: 0 : if (status) {
3219 : : /* allocate profile ID */
3220 : 0 : status = ice_alloc_prof_id(hw, blk, &prof_id);
3221 [ # # ]: 0 : if (status)
3222 : 0 : goto err_ice_add_prof;
3223 [ # # ]: 0 : if (blk == ICE_BLK_FD && fd_swap) {
3224 : : /* For Flow Director block, the extraction sequence may
3225 : : * need to be altered in the case where there are paired
3226 : : * fields that have no match. This is necessary because
3227 : : * for Flow Director, src and dest fields need to paired
3228 : : * for filter programming and these values are swapped
3229 : : * during Tx.
3230 : : */
3231 : 0 : status = ice_update_fd_swap(hw, prof_id, es);
3232 [ # # ]: 0 : if (status)
3233 : 0 : goto err_ice_add_prof;
3234 [ # # ]: 0 : } else if (blk == ICE_BLK_FD) {
3235 : 0 : ice_disable_fd_swap(hw, prof_id);
3236 : : }
3237 : 0 : status = ice_update_prof_masking(hw, blk, prof_id, masks);
3238 [ # # ]: 0 : if (status)
3239 : 0 : goto err_ice_add_prof;
3240 : :
3241 : : /* and write new es */
3242 : 0 : ice_write_es(hw, blk, prof_id, es);
3243 : : }
3244 : :
3245 [ # # ]: 0 : ice_prof_inc_ref(hw, blk, prof_id);
3246 : :
3247 : : /* add profile info */
3248 : :
3249 : 0 : prof = (struct ice_prof_map *)ice_malloc(hw, sizeof(*prof));
3250 [ # # ]: 0 : if (!prof)
3251 : 0 : goto err_ice_add_prof;
3252 : :
3253 : 0 : prof->profile_cookie = id;
3254 : 0 : prof->prof_id = prof_id;
3255 : 0 : prof->ptg_cnt = 0;
3256 : 0 : prof->context = 0;
3257 : :
3258 : : /* build list of ptgs */
3259 [ # # ]: 0 : ice_for_each_set_bit(ptype, ptypes, ICE_FLOW_PTYPE_MAX) {
3260 : : u8 ptg;
3261 : :
3262 : : /* The package should place all ptypes in a non-zero
3263 : : * PTG, so the following call should never fail.
3264 : : */
3265 : : if (ice_ptg_find_ptype(hw, blk, ptype, &ptg))
3266 : : continue;
3267 : :
3268 : : /* If PTG is already added, skip and continue */
3269 [ # # ]: 0 : if (ice_is_bit_set(ptgs_used, ptg))
3270 : : continue;
3271 : :
3272 : : ice_set_bit(ptg, ptgs_used);
3273 : : /* Check to see there are any attributes for this ptype, and
3274 : : * add them if found.
3275 : : */
3276 : : status = ice_add_prof_attrib(prof, ptg, ptype, attr, attr_cnt);
3277 : : if (status == ICE_ERR_MAX_LIMIT)
3278 : : break;
3279 [ # # ]: 0 : if (status) {
3280 : : /* This is simple a ptype/PTG with no attribute */
3281 : 0 : prof->ptg[prof->ptg_cnt] = ptg;
3282 : 0 : prof->attr[prof->ptg_cnt].flags = 0;
3283 : 0 : prof->attr[prof->ptg_cnt].mask = 0;
3284 : :
3285 [ # # ]: 0 : if (++prof->ptg_cnt >= ICE_MAX_PTG_PER_PROFILE)
3286 : : break;
3287 : : }
3288 : : }
3289 : :
3290 [ # # ]: 0 : LIST_ADD(&prof->list, &hw->blk[blk].es.prof_map);
3291 : : status = ICE_SUCCESS;
3292 : :
3293 : 0 : err_ice_add_prof:
3294 : : ice_release_lock(&hw->blk[blk].es.prof_map_lock);
3295 : 0 : return status;
3296 : : }
3297 : :
3298 : : /**
3299 : : * ice_search_prof_id - Search for a profile tracking ID
3300 : : * @hw: pointer to the HW struct
3301 : : * @blk: hardware block
3302 : : * @id: profile tracking ID
3303 : : *
3304 : : * This will search for a profile tracking ID which was previously added.
3305 : : * The profile map lock should be held before calling this function.
3306 : : */
3307 : : struct ice_prof_map *
3308 : 0 : ice_search_prof_id(struct ice_hw *hw, enum ice_block blk, u64 id)
3309 : : {
3310 : : struct ice_prof_map *entry = NULL;
3311 : : struct ice_prof_map *map;
3312 : :
3313 [ # # # # : 0 : LIST_FOR_EACH_ENTRY(map, &hw->blk[blk].es.prof_map, ice_prof_map, list)
# # ]
3314 [ # # ]: 0 : if (map->profile_cookie == id) {
3315 : : entry = map;
3316 : : break;
3317 : : }
3318 : :
3319 : 0 : return entry;
3320 : : }
3321 : :
3322 : : /**
3323 : : * ice_vsig_prof_id_count - count profiles in a VSIG
3324 : : * @hw: pointer to the HW struct
3325 : : * @blk: hardware block
3326 : : * @vsig: VSIG to remove the profile from
3327 : : */
3328 : : static u16
3329 : : ice_vsig_prof_id_count(struct ice_hw *hw, enum ice_block blk, u16 vsig)
3330 : : {
3331 : 0 : u16 idx = vsig & ICE_VSIG_IDX_M, count = 0;
3332 : : struct ice_vsig_prof *p;
3333 : :
3334 [ # # # # ]: 0 : LIST_FOR_EACH_ENTRY(p, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst,
3335 : : ice_vsig_prof, list)
3336 [ # # # # ]: 0 : count++;
3337 : :
3338 : : return count;
3339 : : }
3340 : :
3341 : : /**
3342 : : * ice_rel_tcam_idx - release a TCAM index
3343 : : * @hw: pointer to the HW struct
3344 : : * @blk: hardware block
3345 : : * @idx: the index to release
3346 : : */
3347 : : static enum ice_status
3348 : 0 : ice_rel_tcam_idx(struct ice_hw *hw, enum ice_block blk, u16 idx)
3349 : : {
3350 : : /* Masks to invoke a never match entry */
3351 : 0 : u8 vl_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
3352 : 0 : u8 dc_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF };
3353 : 0 : u8 nm_msk[ICE_TCAM_KEY_VAL_SZ] = { 0x01, 0x00, 0x00, 0x00, 0x00 };
3354 : : enum ice_status status;
3355 : :
3356 : : /* write the TCAM entry */
3357 : 0 : status = ice_tcam_write_entry(hw, blk, idx, 0, 0, 0, 0, 0, vl_msk,
3358 : : dc_msk, nm_msk);
3359 [ # # ]: 0 : if (status)
3360 : : return status;
3361 : :
3362 : : /* release the TCAM entry */
3363 : 0 : status = ice_free_tcam_ent(hw, blk, idx);
3364 : :
3365 : 0 : return status;
3366 : : }
3367 : :
3368 : : /**
3369 : : * ice_rem_prof_id - remove one profile from a VSIG
3370 : : * @hw: pointer to the HW struct
3371 : : * @blk: hardware block
3372 : : * @prof: pointer to profile structure to remove
3373 : : */
3374 : : static enum ice_status
3375 : 0 : ice_rem_prof_id(struct ice_hw *hw, enum ice_block blk,
3376 : : struct ice_vsig_prof *prof)
3377 : : {
3378 : : enum ice_status status;
3379 : : u16 i;
3380 : :
3381 [ # # ]: 0 : for (i = 0; i < prof->tcam_count; i++)
3382 [ # # ]: 0 : if (prof->tcam[i].in_use) {
3383 : 0 : prof->tcam[i].in_use = false;
3384 : 0 : status = ice_rel_tcam_idx(hw, blk,
3385 : 0 : prof->tcam[i].tcam_idx);
3386 [ # # ]: 0 : if (status)
3387 : : return ICE_ERR_HW_TABLE;
3388 : : }
3389 : :
3390 : : return ICE_SUCCESS;
3391 : : }
3392 : :
3393 : : /**
3394 : : * ice_rem_vsig - remove VSIG
3395 : : * @hw: pointer to the HW struct
3396 : : * @blk: hardware block
3397 : : * @vsig: the VSIG to remove
3398 : : * @chg: the change list
3399 : : */
3400 : : static enum ice_status
3401 : 0 : ice_rem_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig,
3402 : : struct LIST_HEAD_TYPE *chg)
3403 : : {
3404 : 0 : u16 idx = vsig & ICE_VSIG_IDX_M;
3405 : : struct ice_vsig_vsi *vsi_cur;
3406 : : struct ice_vsig_prof *d, *t;
3407 : :
3408 : : /* remove TCAM entries */
3409 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(d, t,
# # # # #
# ]
3410 : : &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst,
3411 : : ice_vsig_prof, list) {
3412 : : enum ice_status status;
3413 : :
3414 : 0 : status = ice_rem_prof_id(hw, blk, d);
3415 [ # # ]: 0 : if (status)
3416 : 0 : return status;
3417 : :
3418 [ # # ]: 0 : LIST_DEL(&d->list);
3419 : 0 : ice_free(hw, d);
3420 : : }
3421 : :
3422 : : /* Move all VSIS associated with this VSIG to the default VSIG */
3423 : 0 : vsi_cur = hw->blk[blk].xlt2.vsig_tbl[idx].first_vsi;
3424 : : /* If the VSIG has at least 1 VSI then iterate through the list
3425 : : * and remove the VSIs before deleting the group.
3426 : : */
3427 [ # # ]: 0 : if (vsi_cur)
3428 : : do {
3429 : 0 : struct ice_vsig_vsi *tmp = vsi_cur->next_vsi;
3430 : : struct ice_chs_chg *p;
3431 : :
3432 : 0 : p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p));
3433 [ # # ]: 0 : if (!p)
3434 : : return ICE_ERR_NO_MEMORY;
3435 : :
3436 : 0 : p->type = ICE_VSIG_REM;
3437 : 0 : p->orig_vsig = vsig;
3438 : 0 : p->vsig = ICE_DEFAULT_VSIG;
3439 : 0 : p->vsi = (u16)(vsi_cur - hw->blk[blk].xlt2.vsis);
3440 : :
3441 [ # # ]: 0 : LIST_ADD(&p->list_entry, chg);
3442 : :
3443 : : vsi_cur = tmp;
3444 [ # # ]: 0 : } while (vsi_cur);
3445 : :
3446 : 0 : return ice_vsig_free(hw, blk, vsig);
3447 : : }
3448 : :
3449 : : /**
3450 : : * ice_rem_prof_id_vsig - remove a specific profile from a VSIG
3451 : : * @hw: pointer to the HW struct
3452 : : * @blk: hardware block
3453 : : * @vsig: VSIG to remove the profile from
3454 : : * @hdl: profile handle indicating which profile to remove
3455 : : * @chg: list to receive a record of changes
3456 : : */
3457 : : static enum ice_status
3458 : 0 : ice_rem_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl,
3459 : : struct LIST_HEAD_TYPE *chg)
3460 : : {
3461 : 0 : u16 idx = vsig & ICE_VSIG_IDX_M;
3462 : : struct ice_vsig_prof *p, *t;
3463 : :
3464 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(p, t,
# # # # #
# ]
3465 : : &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst,
3466 : : ice_vsig_prof, list)
3467 [ # # ]: 0 : if (p->profile_cookie == hdl) {
3468 : : enum ice_status status;
3469 : :
3470 [ # # # # ]: 0 : if (ice_vsig_prof_id_count(hw, blk, vsig) == 1)
3471 : : /* this is the last profile, remove the VSIG */
3472 : 0 : return ice_rem_vsig(hw, blk, vsig, chg);
3473 : :
3474 : 0 : status = ice_rem_prof_id(hw, blk, p);
3475 [ # # ]: 0 : if (!status) {
3476 [ # # ]: 0 : LIST_DEL(&p->list);
3477 : 0 : ice_free(hw, p);
3478 : : }
3479 : 0 : return status;
3480 : : }
3481 : :
3482 : : return ICE_ERR_DOES_NOT_EXIST;
3483 : : }
3484 : :
3485 : : /**
3486 : : * ice_rem_flow_all - remove all flows with a particular profile
3487 : : * @hw: pointer to the HW struct
3488 : : * @blk: hardware block
3489 : : * @id: profile tracking ID
3490 : : */
3491 : : static enum ice_status
3492 : 0 : ice_rem_flow_all(struct ice_hw *hw, enum ice_block blk, u64 id)
3493 : : {
3494 : : struct ice_chs_chg *del, *tmp;
3495 : : struct LIST_HEAD_TYPE chg;
3496 : : enum ice_status status;
3497 : : u16 i;
3498 : :
3499 : 0 : INIT_LIST_HEAD(&chg);
3500 : :
3501 [ # # ]: 0 : for (i = 1; i < ICE_MAX_VSIGS; i++)
3502 [ # # ]: 0 : if (hw->blk[blk].xlt2.vsig_tbl[i].in_use) {
3503 [ # # ]: 0 : if (ice_has_prof_vsig(hw, blk, i, id)) {
3504 : 0 : status = ice_rem_prof_id_vsig(hw, blk, i, id,
3505 : : &chg);
3506 [ # # ]: 0 : if (status)
3507 : 0 : goto err_ice_rem_flow_all;
3508 : : }
3509 : : }
3510 : :
3511 : 0 : status = ice_upd_prof_hw(hw, blk, &chg);
3512 : :
3513 : 0 : err_ice_rem_flow_all:
3514 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &chg, ice_chs_chg, list_entry) {
# # # # #
# ]
3515 [ # # ]: 0 : LIST_DEL(&del->list_entry);
3516 : 0 : ice_free(hw, del);
3517 : : }
3518 : :
3519 : 0 : return status;
3520 : : }
3521 : :
3522 : : /**
3523 : : * ice_rem_prof - remove profile
3524 : : * @hw: pointer to the HW struct
3525 : : * @blk: hardware block
3526 : : * @id: profile tracking ID
3527 : : *
3528 : : * This will remove the profile specified by the ID parameter, which was
3529 : : * previously created through ice_add_prof. If any existing entries
3530 : : * are associated with this profile, they will be removed as well.
3531 : : */
3532 : 0 : enum ice_status ice_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 id)
3533 : : {
3534 : : struct ice_prof_map *pmap;
3535 : : enum ice_status status;
3536 : :
3537 : 0 : ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
3538 : :
3539 : 0 : pmap = ice_search_prof_id(hw, blk, id);
3540 [ # # ]: 0 : if (!pmap) {
3541 : : status = ICE_ERR_DOES_NOT_EXIST;
3542 : 0 : goto err_ice_rem_prof;
3543 : : }
3544 : :
3545 : : /* remove all flows with this profile */
3546 : 0 : status = ice_rem_flow_all(hw, blk, pmap->profile_cookie);
3547 [ # # ]: 0 : if (status)
3548 : 0 : goto err_ice_rem_prof;
3549 : :
3550 : : /* dereference profile, and possibly remove */
3551 : 0 : ice_prof_dec_ref(hw, blk, pmap->prof_id);
3552 : :
3553 [ # # ]: 0 : LIST_DEL(&pmap->list);
3554 : 0 : ice_free(hw, pmap);
3555 : :
3556 : 0 : err_ice_rem_prof:
3557 : : ice_release_lock(&hw->blk[blk].es.prof_map_lock);
3558 : 0 : return status;
3559 : : }
3560 : :
3561 : : /**
3562 : : * ice_get_prof - get profile
3563 : : * @hw: pointer to the HW struct
3564 : : * @blk: hardware block
3565 : : * @hdl: profile handle
3566 : : * @chg: change list
3567 : : */
3568 : : static enum ice_status
3569 : 0 : ice_get_prof(struct ice_hw *hw, enum ice_block blk, u64 hdl,
3570 : : struct LIST_HEAD_TYPE *chg)
3571 : : {
3572 : : enum ice_status status = ICE_SUCCESS;
3573 : : struct ice_prof_map *map;
3574 : : struct ice_chs_chg *p;
3575 : : u16 i;
3576 : :
3577 : 0 : ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
3578 : : /* Get the details on the profile specified by the handle ID */
3579 : 0 : map = ice_search_prof_id(hw, blk, hdl);
3580 [ # # ]: 0 : if (!map) {
3581 : : status = ICE_ERR_DOES_NOT_EXIST;
3582 : 0 : goto err_ice_get_prof;
3583 : : }
3584 : :
3585 [ # # ]: 0 : for (i = 0; i < map->ptg_cnt; i++)
3586 [ # # ]: 0 : if (!hw->blk[blk].es.written[map->prof_id]) {
3587 : : /* add ES to change list */
3588 : 0 : p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p));
3589 [ # # ]: 0 : if (!p) {
3590 : : status = ICE_ERR_NO_MEMORY;
3591 : 0 : goto err_ice_get_prof;
3592 : : }
3593 : :
3594 : 0 : p->type = ICE_PTG_ES_ADD;
3595 : 0 : p->ptype = 0;
3596 : 0 : p->ptg = map->ptg[i];
3597 : 0 : p->attr = map->attr[i];
3598 : 0 : p->add_ptg = 0;
3599 : :
3600 : 0 : p->add_prof = 1;
3601 : 0 : p->prof_id = map->prof_id;
3602 : :
3603 : 0 : hw->blk[blk].es.written[map->prof_id] = true;
3604 : :
3605 [ # # ]: 0 : LIST_ADD(&p->list_entry, chg);
3606 : : }
3607 : :
3608 : 0 : err_ice_get_prof:
3609 : : ice_release_lock(&hw->blk[blk].es.prof_map_lock);
3610 : : /* let caller clean up the change list */
3611 : 0 : return status;
3612 : : }
3613 : :
3614 : : /**
3615 : : * ice_get_profs_vsig - get a copy of the list of profiles from a VSIG
3616 : : * @hw: pointer to the HW struct
3617 : : * @blk: hardware block
3618 : : * @vsig: VSIG from which to copy the list
3619 : : * @lst: output list
3620 : : *
3621 : : * This routine makes a copy of the list of profiles in the specified VSIG.
3622 : : */
3623 : : static enum ice_status
3624 : 0 : ice_get_profs_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig,
3625 : : struct LIST_HEAD_TYPE *lst)
3626 : : {
3627 : : struct ice_vsig_prof *ent1, *ent2;
3628 : 0 : u16 idx = vsig & ICE_VSIG_IDX_M;
3629 : :
3630 [ # # # # : 0 : LIST_FOR_EACH_ENTRY(ent1, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst,
# # ]
3631 : : ice_vsig_prof, list) {
3632 : : struct ice_vsig_prof *p;
3633 : :
3634 : : /* copy to the input list */
3635 : : p = (struct ice_vsig_prof *)ice_memdup(hw, ent1, sizeof(*p),
3636 : : ICE_NONDMA_TO_NONDMA);
3637 [ # # ]: 0 : if (!p)
3638 : 0 : goto err_ice_get_profs_vsig;
3639 : :
3640 [ # # ]: 0 : LIST_ADD_TAIL(&p->list, lst);
3641 : : }
3642 : :
3643 : : return ICE_SUCCESS;
3644 : :
3645 : : err_ice_get_profs_vsig:
3646 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(ent1, ent2, lst, ice_vsig_prof, list) {
# # # # #
# ]
3647 [ # # ]: 0 : LIST_DEL(&ent1->list);
3648 : 0 : ice_free(hw, ent1);
3649 : : }
3650 : :
3651 : : return ICE_ERR_NO_MEMORY;
3652 : : }
3653 : :
3654 : : /**
3655 : : * ice_add_prof_to_lst - add profile entry to a list
3656 : : * @hw: pointer to the HW struct
3657 : : * @blk: hardware block
3658 : : * @lst: the list to be added to
3659 : : * @hdl: profile handle of entry to add
3660 : : */
3661 : : static enum ice_status
3662 : 0 : ice_add_prof_to_lst(struct ice_hw *hw, enum ice_block blk,
3663 : : struct LIST_HEAD_TYPE *lst, u64 hdl)
3664 : : {
3665 : : enum ice_status status = ICE_SUCCESS;
3666 : : struct ice_prof_map *map;
3667 : : struct ice_vsig_prof *p;
3668 : : u16 i;
3669 : :
3670 : 0 : ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
3671 : 0 : map = ice_search_prof_id(hw, blk, hdl);
3672 [ # # ]: 0 : if (!map) {
3673 : : status = ICE_ERR_DOES_NOT_EXIST;
3674 : 0 : goto err_ice_add_prof_to_lst;
3675 : : }
3676 : :
3677 : 0 : p = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*p));
3678 [ # # ]: 0 : if (!p) {
3679 : : status = ICE_ERR_NO_MEMORY;
3680 : 0 : goto err_ice_add_prof_to_lst;
3681 : : }
3682 : :
3683 : 0 : p->profile_cookie = map->profile_cookie;
3684 : 0 : p->prof_id = map->prof_id;
3685 : 0 : p->tcam_count = map->ptg_cnt;
3686 : :
3687 [ # # ]: 0 : for (i = 0; i < map->ptg_cnt; i++) {
3688 : 0 : p->tcam[i].prof_id = map->prof_id;
3689 : 0 : p->tcam[i].tcam_idx = ICE_INVALID_TCAM;
3690 : 0 : p->tcam[i].ptg = map->ptg[i];
3691 : 0 : p->tcam[i].attr = map->attr[i];
3692 : : }
3693 : :
3694 [ # # ]: 0 : LIST_ADD(&p->list, lst);
3695 : :
3696 : 0 : err_ice_add_prof_to_lst:
3697 : : ice_release_lock(&hw->blk[blk].es.prof_map_lock);
3698 : 0 : return status;
3699 : : }
3700 : :
3701 : : /**
3702 : : * ice_move_vsi - move VSI to another VSIG
3703 : : * @hw: pointer to the HW struct
3704 : : * @blk: hardware block
3705 : : * @vsi: the VSI to move
3706 : : * @vsig: the VSIG to move the VSI to
3707 : : * @chg: the change list
3708 : : */
3709 : : static enum ice_status
3710 : 0 : ice_move_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig,
3711 : : struct LIST_HEAD_TYPE *chg)
3712 : : {
3713 : : enum ice_status status;
3714 : : struct ice_chs_chg *p;
3715 : : u16 orig_vsig;
3716 : :
3717 : 0 : p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p));
3718 [ # # ]: 0 : if (!p)
3719 : : return ICE_ERR_NO_MEMORY;
3720 : :
3721 : 0 : status = ice_vsig_find_vsi(hw, blk, vsi, &orig_vsig);
3722 [ # # ]: 0 : if (!status)
3723 : 0 : status = ice_vsig_add_mv_vsi(hw, blk, vsi, vsig);
3724 : :
3725 [ # # ]: 0 : if (status) {
3726 : 0 : ice_free(hw, p);
3727 : 0 : return status;
3728 : : }
3729 : :
3730 : 0 : p->type = ICE_VSI_MOVE;
3731 : 0 : p->vsi = vsi;
3732 : 0 : p->orig_vsig = orig_vsig;
3733 : 0 : p->vsig = vsig;
3734 : :
3735 [ # # ]: 0 : LIST_ADD(&p->list_entry, chg);
3736 : :
3737 : 0 : return ICE_SUCCESS;
3738 : : }
3739 : :
3740 : : /**
3741 : : * ice_set_tcam_flags - set TCAM flag don't care mask
3742 : : * @mask: mask for flags
3743 : : * @dc_mask: pointer to the don't care mask
3744 : : */
3745 : : static void ice_set_tcam_flags(u16 mask, u8 dc_mask[ICE_TCAM_KEY_VAL_SZ])
3746 : : {
3747 : : u16 *flag_word;
3748 : :
3749 : : /* flags are lowest u16 */
3750 : : flag_word = (u16 *)dc_mask;
3751 : 0 : *flag_word = ~mask;
3752 : : }
3753 : :
3754 : : /**
3755 : : * ice_rem_chg_tcam_ent - remove a specific TCAM entry from change list
3756 : : * @hw: pointer to the HW struct
3757 : : * @idx: the index of the TCAM entry to remove
3758 : : * @chg: the list of change structures to search
3759 : : */
3760 : : static void
3761 : 0 : ice_rem_chg_tcam_ent(struct ice_hw *hw, u16 idx, struct LIST_HEAD_TYPE *chg)
3762 : : {
3763 : : struct ice_chs_chg *pos, *tmp;
3764 : :
3765 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(tmp, pos, chg, ice_chs_chg, list_entry)
# # # # #
# ]
3766 [ # # # # ]: 0 : if (tmp->type == ICE_TCAM_ADD && tmp->tcam_idx == idx) {
3767 [ # # ]: 0 : LIST_DEL(&tmp->list_entry);
3768 : 0 : ice_free(hw, tmp);
3769 : : }
3770 : 0 : }
3771 : :
3772 : : /**
3773 : : * ice_prof_tcam_ena_dis - add enable or disable TCAM change
3774 : : * @hw: pointer to the HW struct
3775 : : * @blk: hardware block
3776 : : * @enable: true to enable, false to disable
3777 : : * @vsig: the VSIG of the TCAM entry
3778 : : * @tcam: pointer the TCAM info structure of the TCAM to disable
3779 : : * @chg: the change list
3780 : : *
3781 : : * This function appends an enable or disable TCAM entry in the change log
3782 : : */
3783 : : static enum ice_status
3784 : 0 : ice_prof_tcam_ena_dis(struct ice_hw *hw, enum ice_block blk, bool enable,
3785 : : u16 vsig, struct ice_tcam_inf *tcam,
3786 : : struct LIST_HEAD_TYPE *chg)
3787 : : {
3788 : : enum ice_status status;
3789 : : struct ice_chs_chg *p;
3790 : :
3791 : 0 : u8 vl_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
3792 : 0 : u8 dc_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0x00, 0x00, 0x00 };
3793 : 0 : u8 nm_msk[ICE_TCAM_KEY_VAL_SZ] = { 0x00, 0x00, 0x00, 0x00, 0x00 };
3794 : :
3795 : : /* if disabling, free the TCAM */
3796 [ # # ]: 0 : if (!enable) {
3797 : 0 : status = ice_rel_tcam_idx(hw, blk, tcam->tcam_idx);
3798 : :
3799 : : /* if we have already created a change for this TCAM entry, then
3800 : : * we need to remove that entry, in order to prevent writing to
3801 : : * a TCAM entry we no longer will have ownership of.
3802 : : */
3803 : 0 : ice_rem_chg_tcam_ent(hw, tcam->tcam_idx, chg);
3804 : 0 : tcam->tcam_idx = 0;
3805 : 0 : tcam->in_use = 0;
3806 : 0 : return status;
3807 : : }
3808 : :
3809 : : /* for re-enabling, reallocate a TCAM */
3810 : : /* for entries with empty attribute masks, allocate entry from
3811 : : * the bottom of the TCAM table; otherwise, allocate from the
3812 : : * top of the table in order to give it higher priority
3813 : : */
3814 [ # # ]: 0 : status = ice_alloc_tcam_ent(hw, blk, tcam->attr.mask == 0,
3815 : : &tcam->tcam_idx);
3816 [ # # ]: 0 : if (status)
3817 : : return status;
3818 : :
3819 : : /* add TCAM to change list */
3820 : 0 : p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p));
3821 [ # # ]: 0 : if (!p)
3822 : : return ICE_ERR_NO_MEMORY;
3823 : :
3824 : : /* set don't care masks for TCAM flags */
3825 : 0 : ice_set_tcam_flags(tcam->attr.mask, dc_msk);
3826 : :
3827 : 0 : status = ice_tcam_write_entry(hw, blk, tcam->tcam_idx, tcam->prof_id,
3828 : 0 : tcam->ptg, vsig, 0, tcam->attr.flags,
3829 : : vl_msk, dc_msk, nm_msk);
3830 [ # # ]: 0 : if (status)
3831 : 0 : goto err_ice_prof_tcam_ena_dis;
3832 : :
3833 : 0 : tcam->in_use = 1;
3834 : :
3835 : 0 : p->type = ICE_TCAM_ADD;
3836 : 0 : p->add_tcam_idx = true;
3837 : 0 : p->prof_id = tcam->prof_id;
3838 : 0 : p->ptg = tcam->ptg;
3839 : 0 : p->vsig = 0;
3840 : 0 : p->tcam_idx = tcam->tcam_idx;
3841 : :
3842 : : /* log change */
3843 [ # # ]: 0 : LIST_ADD(&p->list_entry, chg);
3844 : :
3845 : 0 : return ICE_SUCCESS;
3846 : :
3847 : : err_ice_prof_tcam_ena_dis:
3848 : 0 : ice_free(hw, p);
3849 : 0 : return status;
3850 : : }
3851 : :
3852 : : /**
3853 : : * ice_ptg_attr_in_use - determine if PTG and attribute pair is in use
3854 : : * @ptg_attr: pointer to the PTG and attribute pair to check
3855 : : * @ptgs_used: bitmap that denotes which PTGs are in use
3856 : : * @attr_used: array of PTG and attributes pairs already used
3857 : : * @attr_cnt: count of entries in the attr_used array
3858 : : */
3859 : : static bool
3860 : 0 : ice_ptg_attr_in_use(struct ice_tcam_inf *ptg_attr, ice_bitmap_t *ptgs_used,
3861 : : struct ice_tcam_inf *attr_used[], u16 attr_cnt)
3862 : : {
3863 : : u16 i;
3864 : :
3865 [ # # ]: 0 : if (!ice_is_bit_set(ptgs_used, ptg_attr->ptg))
3866 : : return false;
3867 : :
3868 : : /* the PTG is used, so now look for correct attributes */
3869 [ # # ]: 0 : for (i = 0; i < attr_cnt; i++)
3870 [ # # ]: 0 : if (attr_used[i]->ptg == ptg_attr->ptg &&
3871 [ # # ]: 0 : attr_used[i]->attr.flags == ptg_attr->attr.flags &&
3872 [ # # ]: 0 : attr_used[i]->attr.mask == ptg_attr->attr.mask)
3873 : : return true;
3874 : :
3875 : : return false;
3876 : : }
3877 : :
3878 : : /**
3879 : : * ice_adj_prof_priorities - adjust profile based on priorities
3880 : : * @hw: pointer to the HW struct
3881 : : * @blk: hardware block
3882 : : * @vsig: the VSIG for which to adjust profile priorities
3883 : : * @chg: the change list
3884 : : */
3885 : : static enum ice_status
3886 : 0 : ice_adj_prof_priorities(struct ice_hw *hw, enum ice_block blk, u16 vsig,
3887 : : struct LIST_HEAD_TYPE *chg)
3888 : : {
3889 : : ice_declare_bitmap(ptgs_used, ICE_XLT1_CNT);
3890 : : struct ice_tcam_inf **attr_used;
3891 : : enum ice_status status = ICE_SUCCESS;
3892 : : struct ice_vsig_prof *t;
3893 : : u16 attr_used_cnt = 0;
3894 : : u16 idx;
3895 : :
3896 : : #define ICE_MAX_PTG_ATTRS 1024
3897 : 0 : attr_used = (struct ice_tcam_inf **)ice_calloc(hw, ICE_MAX_PTG_ATTRS,
3898 : : sizeof(*attr_used));
3899 [ # # ]: 0 : if (!attr_used)
3900 : : return ICE_ERR_NO_MEMORY;
3901 : :
3902 : : ice_zero_bitmap(ptgs_used, ICE_XLT1_CNT);
3903 : 0 : idx = vsig & ICE_VSIG_IDX_M;
3904 : :
3905 : : /* Priority is based on the order in which the profiles are added. The
3906 : : * newest added profile has highest priority and the oldest added
3907 : : * profile has the lowest priority. Since the profile property list for
3908 : : * a VSIG is sorted from newest to oldest, this code traverses the list
3909 : : * in order and enables the first of each PTG that it finds (that is not
3910 : : * already enabled); it also disables any duplicate PTGs that it finds
3911 : : * in the older profiles (that are currently enabled).
3912 : : */
3913 : :
3914 [ # # # # : 0 : LIST_FOR_EACH_ENTRY(t, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst,
# # ]
3915 : : ice_vsig_prof, list) {
3916 : : u16 i;
3917 : :
3918 [ # # ]: 0 : for (i = 0; i < t->tcam_count; i++) {
3919 : : bool used;
3920 : :
3921 : : /* Scan the priorities from newest to oldest.
3922 : : * Make sure that the newest profiles take priority.
3923 : : */
3924 : 0 : used = ice_ptg_attr_in_use(&t->tcam[i], ptgs_used,
3925 : : attr_used, attr_used_cnt);
3926 : :
3927 [ # # # # ]: 0 : if (used && t->tcam[i].in_use) {
3928 : : /* need to mark this PTG as never match, as it
3929 : : * was already in use and therefore duplicate
3930 : : * (and lower priority)
3931 : : */
3932 : 0 : status = ice_prof_tcam_ena_dis(hw, blk, false,
3933 : : vsig,
3934 : : &t->tcam[i],
3935 : : chg);
3936 [ # # ]: 0 : if (status)
3937 : 0 : goto err_ice_adj_prof_priorities;
3938 [ # # # # ]: 0 : } else if (!used && !t->tcam[i].in_use) {
3939 : : /* need to enable this PTG, as it in not in use
3940 : : * and not enabled (highest priority)
3941 : : */
3942 : 0 : status = ice_prof_tcam_ena_dis(hw, blk, true,
3943 : : vsig,
3944 : : &t->tcam[i],
3945 : : chg);
3946 [ # # ]: 0 : if (status)
3947 : 0 : goto err_ice_adj_prof_priorities;
3948 : : }
3949 : :
3950 : : /* keep track of used ptgs */
3951 [ # # ]: 0 : ice_set_bit(t->tcam[i].ptg, ptgs_used);
3952 [ # # ]: 0 : if (attr_used_cnt < ICE_MAX_PTG_ATTRS)
3953 : 0 : attr_used[attr_used_cnt++] = &t->tcam[i];
3954 : : else
3955 [ # # ]: 0 : ice_debug(hw, ICE_DBG_INIT, "Warn: ICE_MAX_PTG_ATTRS exceeded\n");
3956 : : }
3957 : : }
3958 : :
3959 : 0 : err_ice_adj_prof_priorities:
3960 : 0 : ice_free(hw, attr_used);
3961 : 0 : return status;
3962 : : }
3963 : :
3964 : : /**
3965 : : * ice_add_prof_id_vsig - add profile to VSIG
3966 : : * @hw: pointer to the HW struct
3967 : : * @blk: hardware block
3968 : : * @vsig: the VSIG to which this profile is to be added
3969 : : * @hdl: the profile handle indicating the profile to add
3970 : : * @rev: true to add entries to the end of the list
3971 : : * @chg: the change list
3972 : : */
3973 : : static enum ice_status
3974 : 0 : ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl,
3975 : : bool rev, struct LIST_HEAD_TYPE *chg)
3976 : : {
3977 : : /* Masks that ignore flags */
3978 : 0 : u8 vl_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
3979 : 0 : u8 dc_msk[ICE_TCAM_KEY_VAL_SZ] = { 0xFF, 0xFF, 0x00, 0x00, 0x00 };
3980 : 0 : u8 nm_msk[ICE_TCAM_KEY_VAL_SZ] = { 0x00, 0x00, 0x00, 0x00, 0x00 };
3981 : : enum ice_status status = ICE_SUCCESS;
3982 : : struct ice_prof_map *map;
3983 : : struct ice_vsig_prof *t;
3984 : : struct ice_chs_chg *p;
3985 : : u16 vsig_idx, i;
3986 : :
3987 : : /* Error, if this VSIG already has this profile */
3988 [ # # ]: 0 : if (ice_has_prof_vsig(hw, blk, vsig, hdl))
3989 : : return ICE_ERR_ALREADY_EXISTS;
3990 : :
3991 : : /* new VSIG profile structure */
3992 : 0 : t = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*t));
3993 [ # # ]: 0 : if (!t)
3994 : : return ICE_ERR_NO_MEMORY;
3995 : :
3996 : 0 : ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
3997 : : /* Get the details on the profile specified by the handle ID */
3998 : 0 : map = ice_search_prof_id(hw, blk, hdl);
3999 [ # # ]: 0 : if (!map) {
4000 : : status = ICE_ERR_DOES_NOT_EXIST;
4001 : 0 : goto err_ice_add_prof_id_vsig;
4002 : : }
4003 : :
4004 : 0 : t->profile_cookie = map->profile_cookie;
4005 : 0 : t->prof_id = map->prof_id;
4006 : 0 : t->tcam_count = map->ptg_cnt;
4007 : :
4008 : : /* create TCAM entries */
4009 [ # # ]: 0 : for (i = 0; i < map->ptg_cnt; i++) {
4010 : : u16 tcam_idx;
4011 : :
4012 : : /* add TCAM to change list */
4013 : 0 : p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p));
4014 [ # # ]: 0 : if (!p) {
4015 : : status = ICE_ERR_NO_MEMORY;
4016 : 0 : goto err_ice_add_prof_id_vsig;
4017 : : }
4018 : :
4019 : : /* allocate the TCAM entry index */
4020 : : /* for entries with empty attribute masks, allocate entry from
4021 : : * the bottom of the TCAM table; otherwise, allocate from the
4022 : : * top of the table in order to give it higher priority
4023 : : */
4024 [ # # ]: 0 : status = ice_alloc_tcam_ent(hw, blk, map->attr[i].mask == 0,
4025 : : &tcam_idx);
4026 [ # # ]: 0 : if (status) {
4027 : 0 : ice_free(hw, p);
4028 : 0 : goto err_ice_add_prof_id_vsig;
4029 : : }
4030 : :
4031 : 0 : t->tcam[i].ptg = map->ptg[i];
4032 : 0 : t->tcam[i].prof_id = map->prof_id;
4033 : 0 : t->tcam[i].tcam_idx = tcam_idx;
4034 : 0 : t->tcam[i].attr = map->attr[i];
4035 : 0 : t->tcam[i].in_use = true;
4036 : :
4037 : 0 : p->type = ICE_TCAM_ADD;
4038 : 0 : p->add_tcam_idx = true;
4039 : 0 : p->prof_id = t->tcam[i].prof_id;
4040 : 0 : p->ptg = t->tcam[i].ptg;
4041 : 0 : p->vsig = vsig;
4042 : 0 : p->tcam_idx = t->tcam[i].tcam_idx;
4043 : :
4044 : : /* set don't care masks for TCAM flags */
4045 : 0 : ice_set_tcam_flags(t->tcam[i].attr.mask, dc_msk);
4046 : :
4047 : : /* write the TCAM entry */
4048 : 0 : status = ice_tcam_write_entry(hw, blk, t->tcam[i].tcam_idx,
4049 : : t->tcam[i].prof_id,
4050 : : t->tcam[i].ptg, vsig, 0,
4051 : 0 : t->tcam[i].attr.flags, vl_msk,
4052 : : dc_msk, nm_msk);
4053 [ # # ]: 0 : if (status) {
4054 : 0 : ice_free(hw, p);
4055 : 0 : goto err_ice_add_prof_id_vsig;
4056 : : }
4057 : :
4058 : : /* log change */
4059 [ # # ]: 0 : LIST_ADD(&p->list_entry, chg);
4060 : : }
4061 : :
4062 : : /* add profile to VSIG */
4063 : 0 : vsig_idx = vsig & ICE_VSIG_IDX_M;
4064 [ # # ]: 0 : if (rev)
4065 [ # # ]: 0 : LIST_ADD_TAIL(&t->list,
4066 : : &hw->blk[blk].xlt2.vsig_tbl[vsig_idx].prop_lst);
4067 : : else
4068 [ # # ]: 0 : LIST_ADD(&t->list,
4069 : : &hw->blk[blk].xlt2.vsig_tbl[vsig_idx].prop_lst);
4070 : :
4071 : : ice_release_lock(&hw->blk[blk].es.prof_map_lock);
4072 : 0 : return status;
4073 : :
4074 : 0 : err_ice_add_prof_id_vsig:
4075 : : ice_release_lock(&hw->blk[blk].es.prof_map_lock);
4076 : : /* let caller clean up the change list */
4077 : 0 : ice_free(hw, t);
4078 : 0 : return status;
4079 : : }
4080 : :
4081 : : /**
4082 : : * ice_create_prof_id_vsig - add a new VSIG with a single profile
4083 : : * @hw: pointer to the HW struct
4084 : : * @blk: hardware block
4085 : : * @vsi: the initial VSI that will be in VSIG
4086 : : * @hdl: the profile handle of the profile that will be added to the VSIG
4087 : : * @chg: the change list
4088 : : */
4089 : : static enum ice_status
4090 : 0 : ice_create_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl,
4091 : : struct LIST_HEAD_TYPE *chg)
4092 : : {
4093 : : enum ice_status status;
4094 : : struct ice_chs_chg *p;
4095 : : u16 new_vsig;
4096 : :
4097 : 0 : p = (struct ice_chs_chg *)ice_malloc(hw, sizeof(*p));
4098 [ # # ]: 0 : if (!p)
4099 : : return ICE_ERR_NO_MEMORY;
4100 : :
4101 : 0 : new_vsig = ice_vsig_alloc(hw, blk);
4102 [ # # ]: 0 : if (!new_vsig) {
4103 : : status = ICE_ERR_HW_TABLE;
4104 : 0 : goto err_ice_create_prof_id_vsig;
4105 : : }
4106 : :
4107 : 0 : status = ice_move_vsi(hw, blk, vsi, new_vsig, chg);
4108 [ # # ]: 0 : if (status)
4109 : 0 : goto err_ice_create_prof_id_vsig;
4110 : :
4111 : 0 : status = ice_add_prof_id_vsig(hw, blk, new_vsig, hdl, false, chg);
4112 [ # # ]: 0 : if (status)
4113 : 0 : goto err_ice_create_prof_id_vsig;
4114 : :
4115 : 0 : p->type = ICE_VSIG_ADD;
4116 : 0 : p->vsi = vsi;
4117 : 0 : p->orig_vsig = ICE_DEFAULT_VSIG;
4118 : 0 : p->vsig = new_vsig;
4119 : :
4120 [ # # ]: 0 : LIST_ADD(&p->list_entry, chg);
4121 : :
4122 : 0 : return ICE_SUCCESS;
4123 : :
4124 : 0 : err_ice_create_prof_id_vsig:
4125 : : /* let caller clean up the change list */
4126 : 0 : ice_free(hw, p);
4127 : 0 : return status;
4128 : : }
4129 : :
4130 : : /**
4131 : : * ice_create_vsig_from_lst - create a new VSIG with a list of profiles
4132 : : * @hw: pointer to the HW struct
4133 : : * @blk: hardware block
4134 : : * @vsi: the initial VSI that will be in VSIG
4135 : : * @lst: the list of profile that will be added to the VSIG
4136 : : * @new_vsig: return of new VSIG
4137 : : * @chg: the change list
4138 : : */
4139 : : static enum ice_status
4140 : 0 : ice_create_vsig_from_lst(struct ice_hw *hw, enum ice_block blk, u16 vsi,
4141 : : struct LIST_HEAD_TYPE *lst, u16 *new_vsig,
4142 : : struct LIST_HEAD_TYPE *chg)
4143 : : {
4144 : : struct ice_vsig_prof *t;
4145 : : enum ice_status status;
4146 : : u16 vsig;
4147 : :
4148 : 0 : vsig = ice_vsig_alloc(hw, blk);
4149 [ # # ]: 0 : if (!vsig)
4150 : : return ICE_ERR_HW_TABLE;
4151 : :
4152 : 0 : status = ice_move_vsi(hw, blk, vsi, vsig, chg);
4153 [ # # ]: 0 : if (status)
4154 : : return status;
4155 : :
4156 [ # # # # : 0 : LIST_FOR_EACH_ENTRY(t, lst, ice_vsig_prof, list) {
# # ]
4157 : : /* Reverse the order here since we are copying the list */
4158 : 0 : status = ice_add_prof_id_vsig(hw, blk, vsig, t->profile_cookie,
4159 : : true, chg);
4160 [ # # ]: 0 : if (status)
4161 : 0 : return status;
4162 : : }
4163 : :
4164 : 0 : *new_vsig = vsig;
4165 : :
4166 : 0 : return ICE_SUCCESS;
4167 : : }
4168 : :
4169 : : /**
4170 : : * ice_find_prof_vsig - find a VSIG with a specific profile handle
4171 : : * @hw: pointer to the HW struct
4172 : : * @blk: hardware block
4173 : : * @hdl: the profile handle of the profile to search for
4174 : : * @vsig: returns the VSIG with the matching profile
4175 : : */
4176 : : static bool
4177 : 0 : ice_find_prof_vsig(struct ice_hw *hw, enum ice_block blk, u64 hdl, u16 *vsig)
4178 : : {
4179 : : struct ice_vsig_prof *t;
4180 : : struct LIST_HEAD_TYPE lst;
4181 : : enum ice_status status;
4182 : :
4183 : 0 : INIT_LIST_HEAD(&lst);
4184 : :
4185 : 0 : t = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*t));
4186 [ # # ]: 0 : if (!t)
4187 : : return false;
4188 : :
4189 : 0 : t->profile_cookie = hdl;
4190 [ # # ]: 0 : LIST_ADD(&t->list, &lst);
4191 : :
4192 : 0 : status = ice_find_dup_props_vsig(hw, blk, &lst, vsig);
4193 : :
4194 [ # # ]: 0 : LIST_DEL(&t->list);
4195 : 0 : ice_free(hw, t);
4196 : :
4197 : 0 : return status == ICE_SUCCESS;
4198 : : }
4199 : :
4200 : : /**
4201 : : * ice_add_vsi_flow - add VSI flow
4202 : : * @hw: pointer to the HW struct
4203 : : * @blk: hardware block
4204 : : * @vsi: input VSI
4205 : : * @vsig: target VSIG to include the input VSI
4206 : : *
4207 : : * Calling this function will add the VSI to a given VSIG and
4208 : : * update the HW tables accordingly. This call can be used to
4209 : : * add multiple VSIs to a VSIG if we know beforehand that those
4210 : : * VSIs have the same characteristics of the VSIG. This will
4211 : : * save time in generating a new VSIG and TCAMs till a match is
4212 : : * found and subsequent rollback when a matching VSIG is found.
4213 : : */
4214 : : enum ice_status
4215 : 0 : ice_add_vsi_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig)
4216 : : {
4217 : : struct ice_chs_chg *tmp, *del;
4218 : : struct LIST_HEAD_TYPE chg;
4219 : : enum ice_status status;
4220 : :
4221 : : /* if target VSIG is default the move is invalid */
4222 [ # # ]: 0 : if ((vsig & ICE_VSIG_IDX_M) == ICE_DEFAULT_VSIG)
4223 : : return ICE_ERR_PARAM;
4224 : :
4225 : 0 : INIT_LIST_HEAD(&chg);
4226 : :
4227 : : /* move VSI to the VSIG that matches */
4228 : 0 : status = ice_move_vsi(hw, blk, vsi, vsig, &chg);
4229 : : /* update hardware if success */
4230 [ # # ]: 0 : if (!status)
4231 : 0 : status = ice_upd_prof_hw(hw, blk, &chg);
4232 : :
4233 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &chg, ice_chs_chg, list_entry) {
# # # # #
# ]
4234 [ # # ]: 0 : LIST_DEL(&del->list_entry);
4235 : 0 : ice_free(hw, del);
4236 : : }
4237 : :
4238 : : return status;
4239 : : }
4240 : :
4241 : : /**
4242 : : * ice_add_prof_id_flow - add profile flow
4243 : : * @hw: pointer to the HW struct
4244 : : * @blk: hardware block
4245 : : * @vsi: the VSI to enable with the profile specified by ID
4246 : : * @hdl: profile handle
4247 : : *
4248 : : * Calling this function will update the hardware tables to enable the
4249 : : * profile indicated by the ID parameter for the VSIs specified in the VSI
4250 : : * array. Once successfully called, the flow will be enabled.
4251 : : */
4252 : : enum ice_status
4253 : 0 : ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl)
4254 : : {
4255 : : struct ice_vsig_prof *tmp1, *del1;
4256 : : struct LIST_HEAD_TYPE union_lst;
4257 : : struct ice_chs_chg *tmp, *del;
4258 : : struct LIST_HEAD_TYPE chg;
4259 : : enum ice_status status;
4260 : : u16 vsig;
4261 : :
4262 : 0 : INIT_LIST_HEAD(&union_lst);
4263 : 0 : INIT_LIST_HEAD(&chg);
4264 : :
4265 : : /* Get profile */
4266 : 0 : status = ice_get_prof(hw, blk, hdl, &chg);
4267 [ # # ]: 0 : if (status)
4268 : : return status;
4269 : :
4270 : : /* determine if VSI is already part of a VSIG */
4271 : 0 : status = ice_vsig_find_vsi(hw, blk, vsi, &vsig);
4272 [ # # # # ]: 0 : if (!status && vsig) {
4273 : : bool only_vsi;
4274 : : u16 or_vsig;
4275 : : u16 ref;
4276 : :
4277 : : /* found in VSIG */
4278 : : or_vsig = vsig;
4279 : :
4280 : : /* make sure that there is no overlap/conflict between the new
4281 : : * characteristics and the existing ones; we don't support that
4282 : : * scenario
4283 : : */
4284 [ # # ]: 0 : if (ice_has_prof_vsig(hw, blk, vsig, hdl)) {
4285 : : status = ICE_ERR_ALREADY_EXISTS;
4286 : 0 : goto err_ice_add_prof_id_flow;
4287 : : }
4288 : :
4289 : : /* last VSI in the VSIG? */
4290 [ # # ]: 0 : status = ice_vsig_get_ref(hw, blk, vsig, &ref);
4291 : : if (status)
4292 : 0 : goto err_ice_add_prof_id_flow;
4293 : : only_vsi = (ref == 1);
4294 : :
4295 : : /* create a union of the current profiles and the one being
4296 : : * added
4297 : : */
4298 : 0 : status = ice_get_profs_vsig(hw, blk, vsig, &union_lst);
4299 [ # # ]: 0 : if (status)
4300 : 0 : goto err_ice_add_prof_id_flow;
4301 : :
4302 : 0 : status = ice_add_prof_to_lst(hw, blk, &union_lst, hdl);
4303 [ # # ]: 0 : if (status)
4304 : 0 : goto err_ice_add_prof_id_flow;
4305 : :
4306 : : /* search for an existing VSIG with an exact charc match */
4307 : 0 : status = ice_find_dup_props_vsig(hw, blk, &union_lst, &vsig);
4308 [ # # ]: 0 : if (!status) {
4309 : : /* move VSI to the VSIG that matches */
4310 : 0 : status = ice_move_vsi(hw, blk, vsi, vsig, &chg);
4311 [ # # ]: 0 : if (status)
4312 : 0 : goto err_ice_add_prof_id_flow;
4313 : :
4314 : : /* VSI has been moved out of or_vsig. If the or_vsig had
4315 : : * only that VSI it is now empty and can be removed.
4316 : : */
4317 [ # # ]: 0 : if (only_vsi) {
4318 : 0 : status = ice_rem_vsig(hw, blk, or_vsig, &chg);
4319 [ # # ]: 0 : if (status)
4320 : 0 : goto err_ice_add_prof_id_flow;
4321 : : }
4322 [ # # ]: 0 : } else if (only_vsi) {
4323 : : /* If the original VSIG only contains one VSI, then it
4324 : : * will be the requesting VSI. In this case the VSI is
4325 : : * not sharing entries and we can simply add the new
4326 : : * profile to the VSIG.
4327 : : */
4328 : 0 : status = ice_add_prof_id_vsig(hw, blk, vsig, hdl, false,
4329 : : &chg);
4330 [ # # ]: 0 : if (status)
4331 : 0 : goto err_ice_add_prof_id_flow;
4332 : :
4333 : : /* Adjust priorities */
4334 : 0 : status = ice_adj_prof_priorities(hw, blk, vsig, &chg);
4335 [ # # ]: 0 : if (status)
4336 : 0 : goto err_ice_add_prof_id_flow;
4337 : : } else {
4338 : : /* No match, so we need a new VSIG */
4339 : 0 : status = ice_create_vsig_from_lst(hw, blk, vsi,
4340 : : &union_lst, &vsig,
4341 : : &chg);
4342 [ # # ]: 0 : if (status)
4343 : 0 : goto err_ice_add_prof_id_flow;
4344 : :
4345 : : /* Adjust priorities */
4346 : 0 : status = ice_adj_prof_priorities(hw, blk, vsig, &chg);
4347 [ # # ]: 0 : if (status)
4348 : 0 : goto err_ice_add_prof_id_flow;
4349 : : }
4350 : : } else {
4351 : : /* need to find or add a VSIG */
4352 : : /* search for an existing VSIG with an exact charc match */
4353 [ # # ]: 0 : if (ice_find_prof_vsig(hw, blk, hdl, &vsig)) {
4354 : : /* found an exact match */
4355 : : /* add or move VSI to the VSIG that matches */
4356 : 0 : status = ice_move_vsi(hw, blk, vsi, vsig, &chg);
4357 [ # # ]: 0 : if (status)
4358 : 0 : goto err_ice_add_prof_id_flow;
4359 : : } else {
4360 : : /* we did not find an exact match */
4361 : : /* we need to add a VSIG */
4362 : 0 : status = ice_create_prof_id_vsig(hw, blk, vsi, hdl,
4363 : : &chg);
4364 [ # # ]: 0 : if (status)
4365 : 0 : goto err_ice_add_prof_id_flow;
4366 : : }
4367 : : }
4368 : :
4369 : : /* update hardware */
4370 : : if (!status)
4371 : 0 : status = ice_upd_prof_hw(hw, blk, &chg);
4372 : :
4373 : 0 : err_ice_add_prof_id_flow:
4374 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &chg, ice_chs_chg, list_entry) {
# # # # #
# ]
4375 [ # # ]: 0 : LIST_DEL(&del->list_entry);
4376 : 0 : ice_free(hw, del);
4377 : : }
4378 : :
4379 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(del1, tmp1, &union_lst, ice_vsig_prof, list) {
# # # # #
# ]
4380 [ # # ]: 0 : LIST_DEL(&del1->list);
4381 : 0 : ice_free(hw, del1);
4382 : : }
4383 : :
4384 : : return status;
4385 : : }
4386 : :
4387 : : /**
4388 : : * ice_rem_prof_from_list - remove a profile from list
4389 : : * @hw: pointer to the HW struct
4390 : : * @lst: list to remove the profile from
4391 : : * @hdl: the profile handle indicating the profile to remove
4392 : : */
4393 : : static enum ice_status
4394 : 0 : ice_rem_prof_from_list(struct ice_hw *hw, struct LIST_HEAD_TYPE *lst, u64 hdl)
4395 : : {
4396 : : struct ice_vsig_prof *ent, *tmp;
4397 : :
4398 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(ent, tmp, lst, ice_vsig_prof, list)
# # # # #
# ]
4399 [ # # ]: 0 : if (ent->profile_cookie == hdl) {
4400 [ # # ]: 0 : LIST_DEL(&ent->list);
4401 : 0 : ice_free(hw, ent);
4402 : 0 : return ICE_SUCCESS;
4403 : : }
4404 : :
4405 : : return ICE_ERR_DOES_NOT_EXIST;
4406 : : }
4407 : :
4408 : : /**
4409 : : * ice_rem_prof_id_flow - remove flow
4410 : : * @hw: pointer to the HW struct
4411 : : * @blk: hardware block
4412 : : * @vsi: the VSI from which to remove the profile specified by ID
4413 : : * @hdl: profile tracking handle
4414 : : *
4415 : : * Calling this function will update the hardware tables to remove the
4416 : : * profile indicated by the ID parameter for the VSIs specified in the VSI
4417 : : * array. Once successfully called, the flow will be disabled.
4418 : : */
4419 : : enum ice_status
4420 : 0 : ice_rem_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl)
4421 : : {
4422 : : struct ice_vsig_prof *tmp1, *del1;
4423 : : struct LIST_HEAD_TYPE chg, copy;
4424 : : struct ice_chs_chg *tmp, *del;
4425 : : enum ice_status status;
4426 : : u16 vsig;
4427 : :
4428 : 0 : INIT_LIST_HEAD(©);
4429 : 0 : INIT_LIST_HEAD(&chg);
4430 : :
4431 : : /* determine if VSI is already part of a VSIG */
4432 : 0 : status = ice_vsig_find_vsi(hw, blk, vsi, &vsig);
4433 [ # # # # ]: 0 : if (!status && vsig) {
4434 : : bool last_profile;
4435 : : bool only_vsi;
4436 : : u16 ref;
4437 : :
4438 : : /* found in VSIG */
4439 [ # # ]: 0 : last_profile = ice_vsig_prof_id_count(hw, blk, vsig) == 1;
4440 : : status = ice_vsig_get_ref(hw, blk, vsig, &ref);
4441 : : if (status)
4442 : 0 : goto err_ice_rem_prof_id_flow;
4443 : : only_vsi = (ref == 1);
4444 : :
4445 [ # # ]: 0 : if (only_vsi) {
4446 : : /* If the original VSIG only contains one reference,
4447 : : * which will be the requesting VSI, then the VSI is not
4448 : : * sharing entries and we can simply remove the specific
4449 : : * characteristics from the VSIG.
4450 : : */
4451 : :
4452 [ # # ]: 0 : if (last_profile) {
4453 : : /* If there are no profiles left for this VSIG,
4454 : : * then simply remove the VSIG.
4455 : : */
4456 : 0 : status = ice_rem_vsig(hw, blk, vsig, &chg);
4457 [ # # ]: 0 : if (status)
4458 : 0 : goto err_ice_rem_prof_id_flow;
4459 : : } else {
4460 : 0 : status = ice_rem_prof_id_vsig(hw, blk, vsig,
4461 : : hdl, &chg);
4462 [ # # ]: 0 : if (status)
4463 : 0 : goto err_ice_rem_prof_id_flow;
4464 : :
4465 : : /* Adjust priorities */
4466 : 0 : status = ice_adj_prof_priorities(hw, blk, vsig,
4467 : : &chg);
4468 [ # # ]: 0 : if (status)
4469 : 0 : goto err_ice_rem_prof_id_flow;
4470 : : }
4471 : :
4472 : : } else {
4473 : : /* Make a copy of the VSIG's list of Profiles */
4474 : 0 : status = ice_get_profs_vsig(hw, blk, vsig, ©);
4475 [ # # ]: 0 : if (status)
4476 : 0 : goto err_ice_rem_prof_id_flow;
4477 : :
4478 : : /* Remove specified profile entry from the list */
4479 : 0 : status = ice_rem_prof_from_list(hw, ©, hdl);
4480 [ # # ]: 0 : if (status)
4481 : 0 : goto err_ice_rem_prof_id_flow;
4482 : :
4483 [ # # ]: 0 : if (LIST_EMPTY(©)) {
4484 : 0 : status = ice_move_vsi(hw, blk, vsi,
4485 : : ICE_DEFAULT_VSIG, &chg);
4486 [ # # ]: 0 : if (status)
4487 : 0 : goto err_ice_rem_prof_id_flow;
4488 : :
4489 [ # # ]: 0 : } else if (!ice_find_dup_props_vsig(hw, blk, ©,
4490 : : &vsig)) {
4491 : : /* found an exact match */
4492 : : /* add or move VSI to the VSIG that matches */
4493 : : /* Search for a VSIG with a matching profile
4494 : : * list
4495 : : */
4496 : :
4497 : : /* Found match, move VSI to the matching VSIG */
4498 : 0 : status = ice_move_vsi(hw, blk, vsi, vsig, &chg);
4499 [ # # ]: 0 : if (status)
4500 : 0 : goto err_ice_rem_prof_id_flow;
4501 : : } else {
4502 : : /* since no existing VSIG supports this
4503 : : * characteristic pattern, we need to create a
4504 : : * new VSIG and TCAM entries
4505 : : */
4506 : 0 : status = ice_create_vsig_from_lst(hw, blk, vsi,
4507 : : ©, &vsig,
4508 : : &chg);
4509 [ # # ]: 0 : if (status)
4510 : 0 : goto err_ice_rem_prof_id_flow;
4511 : :
4512 : : /* Adjust priorities */
4513 : 0 : status = ice_adj_prof_priorities(hw, blk, vsig,
4514 : : &chg);
4515 [ # # ]: 0 : if (status)
4516 : 0 : goto err_ice_rem_prof_id_flow;
4517 : : }
4518 : : }
4519 : : } else {
4520 : : status = ICE_ERR_DOES_NOT_EXIST;
4521 : : }
4522 : :
4523 : : /* update hardware tables */
4524 : : if (!status)
4525 : 0 : status = ice_upd_prof_hw(hw, blk, &chg);
4526 : :
4527 : 0 : err_ice_rem_prof_id_flow:
4528 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(del, tmp, &chg, ice_chs_chg, list_entry) {
# # # # #
# ]
4529 [ # # ]: 0 : LIST_DEL(&del->list_entry);
4530 : 0 : ice_free(hw, del);
4531 : : }
4532 : :
4533 [ # # # # : 0 : LIST_FOR_EACH_ENTRY_SAFE(del1, tmp1, ©, ice_vsig_prof, list) {
# # # # #
# ]
4534 [ # # ]: 0 : LIST_DEL(&del1->list);
4535 : 0 : ice_free(hw, del1);
4536 : : }
4537 : :
4538 : 0 : return status;
4539 : : }
4540 : :
4541 : : /**
4542 : : * ice_flow_assoc_hw_prof - add profile id flow for main/ctrl VSI flow entry
4543 : : * @hw: pointer to the HW struct
4544 : : * @blk: HW block
4545 : : * @dest_vsi_handle: dest VSI handle
4546 : : * @fdir_vsi_handle: fdir programming VSI handle
4547 : : * @id: profile id (handle)
4548 : : *
4549 : : * Calling this function will update the hardware tables to enable the
4550 : : * profile indicated by the ID parameter for the VSIs specified in the VSI
4551 : : * array. Once successfully called, the flow will be enabled.
4552 : : */
4553 : : enum ice_status
4554 : 0 : ice_flow_assoc_hw_prof(struct ice_hw *hw, enum ice_block blk,
4555 : : u16 dest_vsi_handle, u16 fdir_vsi_handle, int id)
4556 : : {
4557 : : enum ice_status status = ICE_SUCCESS;
4558 : : u16 vsi_num;
4559 : :
4560 : 0 : vsi_num = ice_get_hw_vsi_num(hw, dest_vsi_handle);
4561 : 0 : status = ice_add_prof_id_flow(hw, blk, vsi_num, id);
4562 [ # # ]: 0 : if (status) {
4563 [ # # ]: 0 : ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed for main VSI flow entry, %d\n",
4564 : : status);
4565 : 0 : goto err_add_prof;
4566 : : }
4567 : :
4568 [ # # ]: 0 : if (blk != ICE_BLK_FD)
4569 : : return status;
4570 : :
4571 : 0 : vsi_num = ice_get_hw_vsi_num(hw, fdir_vsi_handle);
4572 : 0 : status = ice_add_prof_id_flow(hw, blk, vsi_num, id);
4573 [ # # ]: 0 : if (status) {
4574 [ # # ]: 0 : ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed for ctrl VSI flow entry, %d\n",
4575 : : status);
4576 : 0 : goto err_add_entry;
4577 : : }
4578 : :
4579 : : return status;
4580 : :
4581 : : err_add_entry:
4582 : 0 : vsi_num = ice_get_hw_vsi_num(hw, dest_vsi_handle);
4583 : 0 : ice_rem_prof_id_flow(hw, blk, vsi_num, id);
4584 : 0 : err_add_prof:
4585 : 0 : ice_flow_rem_prof(hw, blk, id);
4586 : :
4587 : 0 : return status;
4588 : : }
|