Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : : #include "roc_api.h"
5 : : #include "roc_priv.h"
6 : :
7 : : int
8 [ # # ]: 0 : npc_mcam_alloc_counter(struct mbox *mbox, uint16_t *ctr)
9 : : {
10 : : struct npc_mcam_alloc_counter_req *req;
11 : : struct npc_mcam_alloc_counter_rsp *rsp;
12 : : int rc = -ENOSPC;
13 : :
14 : : /* For CN20K, counters are enabled by default */
15 [ # # ]: 0 : if (roc_model_is_cn20k())
16 : : return 0;
17 : :
18 : 0 : req = mbox_alloc_msg_npc_mcam_alloc_counter(mbox_get(mbox));
19 [ # # ]: 0 : if (req == NULL)
20 : 0 : goto exit;
21 : 0 : req->count = 1;
22 : : rc = mbox_process_msg(mbox, (void *)&rsp);
23 [ # # ]: 0 : if (rc)
24 : 0 : goto exit;
25 : 0 : *ctr = rsp->cntr_list[0];
26 : 0 : exit:
27 : : mbox_put(mbox);
28 : 0 : return rc;
29 : : }
30 : :
31 : : int
32 [ # # ]: 0 : npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id)
33 : : {
34 : : struct npc_mcam_oper_counter_req *req;
35 : : int rc = -ENOSPC;
36 : :
37 [ # # ]: 0 : if (roc_model_is_cn20k())
38 : : return 0;
39 : :
40 : 0 : req = mbox_alloc_msg_npc_mcam_free_counter(mbox_get(mbox));
41 [ # # ]: 0 : if (req == NULL)
42 : 0 : goto exit;
43 : 0 : req->cntr = ctr_id;
44 : 0 : rc = mbox_process(mbox);
45 : 0 : exit:
46 : : mbox_put(mbox);
47 : 0 : return rc;
48 : : }
49 : :
50 : : int
51 [ # # ]: 0 : npc_mcam_get_stats(struct mbox *mbox, struct roc_npc_flow *flow, uint64_t *count)
52 : : {
53 : : struct npc_mcam_get_stats_req *req;
54 : : struct npc_mcam_get_stats_rsp *rsp;
55 : : int rc = -ENOSPC;
56 : :
57 : : /* valid only for cn20k */
58 [ # # ]: 0 : if (!roc_model_is_cn20k())
59 : : return 0;
60 : :
61 : 0 : req = mbox_alloc_msg_npc_mcam_entry_stats(mbox_get(mbox));
62 [ # # ]: 0 : if (req == NULL)
63 : 0 : goto exit;
64 : 0 : req->entry = flow->mcam_id;
65 : : rc = mbox_process_msg(mbox, (void *)&rsp);
66 [ # # ]: 0 : if (rc)
67 : 0 : goto exit;
68 : 0 : *count = rsp->stat;
69 : 0 : exit:
70 : : mbox_put(mbox);
71 : 0 : return rc;
72 : : }
73 : :
74 : : int
75 [ # # ]: 0 : npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count)
76 : : {
77 : : struct npc_mcam_oper_counter_req *req;
78 : : struct npc_mcam_oper_counter_rsp *rsp;
79 : : int rc = -ENOSPC;
80 : :
81 [ # # ]: 0 : if (roc_model_is_cn20k())
82 : : return 0;
83 : :
84 : 0 : req = mbox_alloc_msg_npc_mcam_counter_stats(mbox_get(mbox));
85 [ # # ]: 0 : if (req == NULL)
86 : 0 : goto exit;
87 : 0 : req->cntr = ctr_id;
88 : : rc = mbox_process_msg(mbox, (void *)&rsp);
89 [ # # ]: 0 : if (rc)
90 : 0 : goto exit;
91 : 0 : *count = rsp->stat;
92 : 0 : exit:
93 : : mbox_put(mbox);
94 : 0 : return rc;
95 : : }
96 : :
97 : : int
98 [ # # ]: 0 : npc_mcam_clear_counter(struct mbox *mbox, uint32_t ctr_id)
99 : : {
100 : : struct npc_mcam_oper_counter_req *req;
101 : : int rc = -ENOSPC;
102 : :
103 [ # # ]: 0 : if (roc_model_is_cn20k())
104 : : return 0;
105 : :
106 : 0 : req = mbox_alloc_msg_npc_mcam_clear_counter(mbox_get(mbox));
107 [ # # ]: 0 : if (req == NULL)
108 : 0 : goto exit;
109 : 0 : req->cntr = ctr_id;
110 : 0 : rc = mbox_process(mbox);
111 : 0 : exit:
112 : : mbox_put(mbox);
113 : 0 : return rc;
114 : : }
115 : :
116 : : int
117 : 0 : npc_mcam_free_entry(struct mbox *mbox, uint32_t entry)
118 : : {
119 : : struct npc_mcam_free_entry_req *req;
120 : : int rc = -ENOSPC;
121 : :
122 : 0 : req = mbox_alloc_msg_npc_mcam_free_entry(mbox_get(mbox));
123 [ # # ]: 0 : if (req == NULL)
124 : 0 : goto exit;
125 : 0 : req->entry = entry;
126 : 0 : rc = mbox_process(mbox);
127 : 0 : exit:
128 : : mbox_put(mbox);
129 : 0 : return rc;
130 : : }
131 : :
132 : : int
133 : 0 : npc_mcam_free_all_entries(struct npc *npc)
134 : : {
135 : : struct npc_mcam_free_entry_req *req;
136 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
137 : : int rc = -ENOSPC;
138 : :
139 : 0 : req = mbox_alloc_msg_npc_mcam_free_entry(mbox);
140 [ # # ]: 0 : if (req == NULL)
141 : 0 : goto exit;
142 : 0 : req->all = 1;
143 : 0 : rc = mbox_process(mbox);
144 : 0 : exit:
145 : : mbox_put(mbox);
146 : 0 : return rc;
147 : : }
148 : :
149 : : static int
150 : : npc_supp_key_len(uint32_t supp_mask)
151 : : {
152 : : int nib_count = 0;
153 : :
154 [ # # # # : 0 : while (supp_mask) {
# # # # ]
155 : 0 : nib_count++;
156 : 0 : supp_mask &= (supp_mask - 1);
157 : : }
158 : 0 : return nib_count * 4;
159 : : }
160 : :
161 : : /**
162 : : * Returns true if any LDATA bits are extracted for specific LID+LTYPE.
163 : : *
164 : : * No LFLAG extraction is taken into account.
165 : : */
166 : : static int
167 [ # # ]: 0 : npc_lid_lt_in_kex(struct npc *npc, uint8_t lid, uint8_t lt)
168 : : {
169 : : struct npc_xtract_info *x_info;
170 : : int i;
171 : :
172 [ # # ]: 0 : if (!roc_model_is_cn20k()) {
173 [ # # ]: 0 : for (i = 0; i < NPC_MAX_LD; i++) {
174 : 0 : x_info = &npc->prx_dxcfg[NIX_INTF_RX][lid][lt].xtract[i];
175 : : /* Check for LDATA */
176 [ # # # # ]: 0 : if (x_info->enable && x_info->len > 0)
177 : : return true;
178 : : }
179 : : } else {
180 [ # # ]: 0 : for (i = 0; i < NPC_MAX_EXTRACTOR; i++) {
181 : : union npc_kex_ldata_flags_cfg *lid_info = &npc->lid_cfg[NIX_INTF_RX][i];
182 : :
183 [ # # ]: 0 : if (lid_info->s.lid != lid)
184 : 0 : continue;
185 : 0 : x_info = &npc->prx_dxcfg_cn20k[NIX_INTF_RX][i][lt].xtract;
186 : : /* Check for LDATA */
187 [ # # # # ]: 0 : if (x_info->enable && x_info->len > 0)
188 : : return true;
189 : : }
190 : : }
191 : :
192 : : return false;
193 : : }
194 : :
195 : : static void
196 : 0 : npc_construct_ldata_mask_cn20k(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid, uint8_t lt)
197 : : {
198 : : struct npc_xtract_info *x_info;
199 : : int hdr_off, keylen;
200 : : int i, j;
201 : :
202 [ # # ]: 0 : for (i = 0; i < NPC_MAX_EXTRACTOR; i++) {
203 : : union npc_kex_ldata_flags_cfg *lid_conf = &npc->lid_cfg[NIX_INTF_RX][i];
204 : :
205 [ # # ]: 0 : if (lid_conf->s.lid != lid)
206 : 0 : continue;
207 : :
208 : 0 : x_info = &npc->prx_dxcfg_cn20k[NIX_INTF_RX][i][lt].xtract;
209 [ # # ]: 0 : if (x_info->enable == 0)
210 : 0 : continue;
211 : :
212 : 0 : hdr_off = x_info->hdr_off * 8;
213 : 0 : keylen = x_info->len * 8;
214 [ # # ]: 0 : for (j = hdr_off; j < (hdr_off + keylen); j++)
215 : 0 : plt_bitmap_set(bmap, j);
216 : : }
217 : 0 : }
218 : :
219 : : static void
220 : 0 : npc_construct_ldata_mask(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid, uint8_t lt,
221 : : uint8_t ld)
222 : : {
223 : : struct npc_xtract_info *x_info, *infoflag;
224 : : int hdr_off, keylen;
225 : : npc_dxcfg_t *p;
226 : : npc_fxcfg_t *q;
227 : : int i, j;
228 : :
229 : : p = &npc->prx_dxcfg;
230 : 0 : x_info = &(*p)[0][lid][lt].xtract[ld];
231 : :
232 [ # # ]: 0 : if (x_info->enable == 0)
233 : : return;
234 : :
235 : 0 : hdr_off = x_info->hdr_off * 8;
236 : 0 : keylen = x_info->len * 8;
237 [ # # ]: 0 : for (i = hdr_off; i < (hdr_off + keylen); i++)
238 : 0 : plt_bitmap_set(bmap, i);
239 : :
240 [ # # ]: 0 : if (x_info->flags_enable == 0)
241 : : return;
242 : :
243 [ # # ]: 0 : if ((npc->prx_lfcfg[0].i & 0x7) != lid)
244 : : return;
245 : :
246 : : q = &npc->prx_fxcfg;
247 [ # # ]: 0 : for (j = 0; j < NPC_MAX_LFL; j++) {
248 : : infoflag = &(*q)[0][ld][j].xtract[0];
249 [ # # ]: 0 : if (infoflag->enable) {
250 : 0 : hdr_off = infoflag->hdr_off * 8;
251 : 0 : keylen = infoflag->len * 8;
252 [ # # ]: 0 : for (i = hdr_off; i < (hdr_off + keylen); i++)
253 : 0 : plt_bitmap_set(bmap, i);
254 : : }
255 : : }
256 : : }
257 : :
258 : : /**
259 : : * Check if given LID+LTYPE combination is present in KEX
260 : : *
261 : : * len is non-zero, this function will return true if KEX extracts len bytes
262 : : * at given offset. Otherwise it'll return true if any bytes are extracted
263 : : * specifically for given LID+LTYPE combination (meaning not LFLAG based).
264 : : * The second case increases flexibility for custom frames whose extracted
265 : : * bits may change depending on KEX profile loaded.
266 : : *
267 : : * @param npc NPC context structure
268 : : * @param lid Layer ID to check for
269 : : * @param lt Layer Type to check for
270 : : * @param offset offset into the layer header to match
271 : : * @param len length of the match
272 : : */
273 : : static bool
274 : 0 : npc_is_kex_enabled(struct npc *npc, uint8_t lid, uint8_t lt, int offset, int len)
275 : : {
276 : : struct plt_bitmap *bmap;
277 : : uint32_t bmap_sz;
278 : : uint8_t *mem;
279 : : int i;
280 : :
281 [ # # ]: 0 : if (!len)
282 : 0 : return npc_lid_lt_in_kex(npc, lid, lt);
283 : :
284 : : bmap_sz = plt_bitmap_get_memory_footprint(300 * 8);
285 : 0 : mem = plt_zmalloc(bmap_sz, 0);
286 [ # # ]: 0 : if (mem == NULL) {
287 : 0 : plt_err("mem alloc failed");
288 : 0 : return false;
289 : : }
290 : 0 : bmap = plt_bitmap_init(300 * 8, mem, bmap_sz);
291 [ # # ]: 0 : if (bmap == NULL) {
292 : 0 : plt_err("mem alloc failed");
293 : 0 : plt_free(mem);
294 : 0 : return false;
295 : : }
296 : :
297 [ # # ]: 0 : if (!roc_model_is_cn20k()) {
298 : 0 : npc_construct_ldata_mask(npc, bmap, lid, lt, 0);
299 : 0 : npc_construct_ldata_mask(npc, bmap, lid, lt, 1);
300 : : } else {
301 : 0 : npc_construct_ldata_mask_cn20k(npc, bmap, lid, lt);
302 : : }
303 : :
304 [ # # ]: 0 : for (i = offset; i < (offset + len); i++) {
305 [ # # ]: 0 : if (plt_bitmap_get(bmap, i) != 0x1) {
306 : 0 : plt_free(mem);
307 : 0 : return false;
308 : : }
309 : : }
310 : :
311 : 0 : plt_free(mem);
312 : 0 : return true;
313 : : }
314 : :
315 : : uint64_t
316 : 0 : npc_get_kex_capability(struct npc *npc)
317 : : {
318 : : npc_kex_cap_terms_t kex_cap;
319 : :
320 : : memset(&kex_cap, 0, sizeof(kex_cap));
321 : :
322 : : /* Ethtype: Offset 12B, len 2B */
323 : 0 : kex_cap.bit.ethtype_0 = npc_is_kex_enabled(npc, NPC_LID_LA, NPC_LT_LA_ETHER, 12 * 8, 2 * 8);
324 : : /* QINQ VLAN Ethtype: offset 8B, len 2B */
325 : 0 : kex_cap.bit.ethtype_x =
326 : 0 : npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 8 * 8, 2 * 8);
327 : : /* VLAN ID0 : Outer VLAN: Offset 2B, len 2B */
328 : 0 : kex_cap.bit.vlan_id_0 = npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_CTAG, 2 * 8, 2 * 8);
329 : : /* VLAN PCP0 : Outer VLAN: Offset 2B, len 1B */
330 : 0 : kex_cap.bit.vlan_pcp_0 = npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_CTAG, 2 * 8, 2 * 1);
331 : : /* VLAN IDX : Inner VLAN: offset 6B, len 2B */
332 : 0 : kex_cap.bit.vlan_id_x =
333 : 0 : npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 6 * 8, 2 * 8);
334 : : /* DMCA: offset 0B, len 6B */
335 : 0 : kex_cap.bit.dmac = npc_is_kex_enabled(npc, NPC_LID_LA, NPC_LT_LA_ETHER, 0 * 8, 6 * 8);
336 : : /* IP proto: offset 9B, len 1B */
337 : 0 : kex_cap.bit.ip_proto = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 9 * 8, 1 * 8);
338 : : /* IPv4 dscp: offset 1B, len 1B, IPv6 dscp: offset 0B, len 2B */
339 [ # # # # ]: 0 : kex_cap.bit.ip_dscp = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 1 * 8, 1 * 8) &&
340 : 0 : npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP6, 0, 2 * 8);
341 : : /* UDP dport: offset 2B, len 2B */
342 : 0 : kex_cap.bit.udp_dport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_UDP, 2 * 8, 2 * 8);
343 : : /* UDP sport: offset 0B, len 2B */
344 : 0 : kex_cap.bit.udp_sport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_UDP, 0 * 8, 2 * 8);
345 : : /* TCP dport: offset 2B, len 2B */
346 : 0 : kex_cap.bit.tcp_dport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_TCP, 2 * 8, 2 * 8);
347 : : /* TCP sport: offset 0B, len 2B */
348 : 0 : kex_cap.bit.tcp_sport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_TCP, 0 * 8, 2 * 8);
349 : : /* IP SIP: offset 12B, len 4B */
350 : 0 : kex_cap.bit.sip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 12 * 8, 4 * 8);
351 : : /* IP DIP: offset 14B, len 4B */
352 : 0 : kex_cap.bit.dip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 14 * 8, 4 * 8);
353 : : /* IP6 SIP: offset 8B, len 16B */
354 : 0 : kex_cap.bit.sip6_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP6, 8 * 8, 16 * 8);
355 : : /* IP6 DIP: offset 24B, len 16B */
356 : 0 : kex_cap.bit.dip6_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP6, 24 * 8, 16 * 8);
357 : : /* ESP SPI: offset 0B, len 4B */
358 : 0 : kex_cap.bit.ipsec_spi = npc_is_kex_enabled(npc, NPC_LID_LE, NPC_LT_LE_ESP, 0 * 8, 4 * 8);
359 : : /* VXLAN VNI: offset 4B, len 3B */
360 : 0 : kex_cap.bit.ld_vni = npc_is_kex_enabled(npc, NPC_LID_LE, NPC_LT_LE_VXLAN, 0 * 8, 3 * 8);
361 : :
362 : : /* Custom L3 frame: varied offset and lengths */
363 : : kex_cap.bit.custom_l3 = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_CUSTOM0, 0, 0);
364 : 0 : kex_cap.bit.custom_l3 |=
365 : : (uint64_t)npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_CUSTOM1, 0, 0);
366 : : /* SCTP sport : offset 0B, len 2B */
367 : 0 : kex_cap.bit.sctp_sport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_SCTP, 0 * 8, 2 * 8);
368 : : /* SCTP dport : offset 2B, len 2B */
369 : 0 : kex_cap.bit.sctp_dport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_SCTP, 2 * 8, 2 * 8);
370 : : /* ICMP type : offset 0B, len 1B */
371 : 0 : kex_cap.bit.icmp_type = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_ICMP, 0 * 8, 1 * 8);
372 : : /* ICMP code : offset 1B, len 1B */
373 : 0 : kex_cap.bit.icmp_code = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_ICMP, 1 * 8, 1 * 8);
374 : : /* ICMP id : offset 4B, len 2B */
375 : 0 : kex_cap.bit.icmp_id = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_ICMP, 4 * 8, 2 * 8);
376 : : /* IGMP grp_addr : offset 4B, len 4B */
377 : 0 : kex_cap.bit.igmp_grp_addr =
378 : 0 : npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_IGMP, 4 * 8, 4 * 8);
379 : : /* GTPU teid : offset 4B, len 4B */
380 : 0 : kex_cap.bit.gtpv1_teid = npc_is_kex_enabled(npc, NPC_LID_LE, NPC_LT_LE_GTPU, 4 * 8, 4 * 8);
381 : 0 : return kex_cap.all_bits;
382 : : }
383 : :
384 : : #define BYTESM1_SHIFT 16
385 : : #define HDR_OFF_SHIFT 8
386 : : static void
387 : : npc_update_kex_info(struct npc_xtract_info *xtract_info, uint64_t val)
388 : : {
389 : 0 : xtract_info->use_hash = ((val >> 20) & 0x1);
390 : 0 : xtract_info->len = ((val >> BYTESM1_SHIFT) & 0xf) + 1;
391 : 0 : xtract_info->hdr_off = (val >> HDR_OFF_SHIFT) & 0xff;
392 : 0 : xtract_info->key_off = val & 0x3f;
393 : 0 : xtract_info->enable = ((val >> 7) & 0x1);
394 : 0 : xtract_info->flags_enable = ((val >> 6) & 0x1);
395 : : }
396 : :
397 : : int
398 : 0 : npc_mcam_alloc_entries(struct mbox *mbox, int ref_mcam, int *alloc_entry, int req_count, int prio,
399 : : int *resp_count, bool is_conti)
400 : : {
401 : : struct npc_mcam_alloc_entry_req *req;
402 : : struct npc_mcam_alloc_entry_rsp *rsp;
403 : : int rc = -ENOSPC;
404 : : int i;
405 : :
406 : 0 : req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox_get(mbox));
407 [ # # ]: 0 : if (req == NULL)
408 : 0 : goto exit;
409 : 0 : req->contig = is_conti;
410 : 0 : req->count = req_count;
411 : 0 : req->ref_priority = prio;
412 : 0 : req->ref_entry = ref_mcam;
413 : :
414 : : rc = mbox_process_msg(mbox, (void *)&rsp);
415 [ # # ]: 0 : if (rc)
416 : 0 : goto exit;
417 [ # # ]: 0 : for (i = 0; i < rsp->count; i++)
418 : 0 : alloc_entry[i] = rsp->entry_list[i];
419 : 0 : *resp_count = rsp->count;
420 [ # # ]: 0 : if (is_conti)
421 : 0 : alloc_entry[0] = rsp->entry;
422 : : rc = 0;
423 : 0 : exit:
424 : : mbox_put(mbox);
425 : 0 : return rc;
426 : : }
427 : :
428 : : int
429 : 0 : npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam, struct roc_npc_flow *ref_mcam,
430 : : uint8_t prio, int *resp_count)
431 : : {
432 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
433 : : struct npc_mcam_alloc_entry_req *req;
434 : : struct npc_mcam_alloc_entry_rsp *rsp;
435 : : int rc = -ENOSPC;
436 : :
437 : 0 : req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
438 [ # # ]: 0 : if (req == NULL)
439 : 0 : goto exit;
440 : 0 : req->contig = 1;
441 : 0 : req->count = 1;
442 : 0 : req->ref_priority = prio;
443 [ # # ]: 0 : req->ref_entry = ref_mcam ? ref_mcam->mcam_id : 0;
444 : 0 : req->kw_type = mcam->key_type;
445 : : rc = mbox_process_msg(mbox, (void *)&rsp);
446 [ # # ]: 0 : if (rc)
447 : 0 : goto exit;
448 : 0 : mcam->mcam_id = rsp->entry;
449 [ # # ]: 0 : mcam->nix_intf = ref_mcam ? ref_mcam->nix_intf : 0;
450 : 0 : *resp_count = rsp->count;
451 : :
452 : : rc = 0;
453 : 0 : exit:
454 : : mbox_put(mbox);
455 : 0 : return rc;
456 : : }
457 : :
458 : : int
459 : 0 : npc_mcam_ena_dis_entry(struct npc *npc, struct roc_npc_flow *mcam, bool enable)
460 : : {
461 : : struct npc_mcam_ena_dis_entry_req *req;
462 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
463 : : int rc = -ENOSPC;
464 : :
465 [ # # ]: 0 : if (enable)
466 : 0 : req = mbox_alloc_msg_npc_mcam_ena_entry(mbox);
467 : : else
468 : 0 : req = mbox_alloc_msg_npc_mcam_dis_entry(mbox);
469 : :
470 [ # # ]: 0 : if (req == NULL)
471 : 0 : goto exit;
472 : 0 : req->entry = mcam->mcam_id;
473 : 0 : mcam->enable = enable;
474 : 0 : rc = mbox_process(mbox);
475 : 0 : exit:
476 : : mbox_put(mbox);
477 : 0 : return rc;
478 : : }
479 : :
480 : : int
481 : 0 : npc_mcam_write_entry(struct mbox *mbox, struct roc_npc_flow *mcam)
482 : : {
483 : : struct npc_mcam_write_entry_req *req;
484 : : struct npc_cn20k_mcam_write_entry_req *cn20k_req;
485 : : struct mbox_msghdr *rsp;
486 : : int rc = -ENOSPC;
487 : 0 : uint16_t ctr = 0;
488 : : int i;
489 : :
490 [ # # # # ]: 0 : if (mcam->use_ctr && mcam->ctr_id == NPC_COUNTER_NONE) {
491 : 0 : rc = npc_mcam_alloc_counter(mbox, &ctr);
492 [ # # ]: 0 : if (rc)
493 : : return rc;
494 : 0 : mcam->ctr_id = ctr;
495 : :
496 : 0 : rc = npc_mcam_clear_counter(mbox, mcam->ctr_id);
497 [ # # ]: 0 : if (rc)
498 : : return rc;
499 : : }
500 : :
501 [ # # ]: 0 : if (roc_model_is_cn20k()) {
502 : 0 : cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox_get(mbox));
503 [ # # ]: 0 : if (cn20k_req == NULL) {
504 : : mbox_put(mbox);
505 [ # # ]: 0 : if (mcam->use_ctr)
506 : 0 : npc_mcam_free_counter(mbox, ctr);
507 : :
508 : 0 : return rc;
509 : : }
510 : 0 : cn20k_req->entry = mcam->mcam_id;
511 : 0 : cn20k_req->intf = mcam->nix_intf;
512 : 0 : cn20k_req->enable_entry = mcam->enable;
513 : 0 : cn20k_req->entry_data.action = mcam->npc_action;
514 : 0 : cn20k_req->entry_data.action2 = mcam->npc_action2;
515 : 0 : cn20k_req->entry_data.vtag_action = mcam->vtag_action;
516 : 0 : cn20k_req->hw_prio = mcam->priority;
517 [ # # ]: 0 : if (mcam->use_ctr)
518 : 0 : cn20k_req->cntr = mcam->ctr_id;
519 : :
520 [ # # ]: 0 : for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
521 : 0 : cn20k_req->entry_data.kw[i] = mcam->mcam_data[i];
522 : 0 : cn20k_req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
523 : : }
524 : : } else {
525 : 0 : req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
526 [ # # ]: 0 : if (req == NULL) {
527 : : mbox_put(mbox);
528 [ # # ]: 0 : if (mcam->use_ctr)
529 : 0 : npc_mcam_free_counter(mbox, ctr);
530 : :
531 : 0 : return rc;
532 : : }
533 : 0 : req->entry = mcam->mcam_id;
534 : 0 : req->intf = mcam->nix_intf;
535 : 0 : req->enable_entry = mcam->enable;
536 : 0 : req->entry_data.action = mcam->npc_action;
537 : 0 : req->entry_data.vtag_action = mcam->vtag_action;
538 [ # # ]: 0 : if (mcam->use_ctr) {
539 : 0 : req->set_cntr = 1;
540 : 0 : req->cntr = mcam->ctr_id;
541 : : }
542 : :
543 [ # # ]: 0 : for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
544 : 0 : req->entry_data.kw[i] = mcam->mcam_data[i];
545 : 0 : req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
546 : : }
547 : : }
548 : : rc = mbox_process_msg(mbox, (void *)&rsp);
549 : : mbox_put(mbox);
550 : 0 : return rc;
551 : : }
552 : :
553 : : static void
554 : 0 : npc_mcam_kex_cfg_dump(struct npc_cn20k_get_kex_cfg_rsp *kex_rsp)
555 : : {
556 [ # # ]: 0 : for (int i = 0; i < NPC_MAX_INTF; i++) {
557 [ # # ]: 0 : for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
558 [ # # ]: 0 : if (kex_rsp->intf_extr[i][j] == 0)
559 : 0 : continue;
560 : 0 : plt_info("Intf %d, Extr %d: 0x%" PRIx64, i, j, kex_rsp->intf_extr[i][j]);
561 : : }
562 : : }
563 : :
564 [ # # ]: 0 : for (int i = 0; i < NPC_MAX_INTF; i++) {
565 [ # # ]: 0 : for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
566 [ # # ]: 0 : for (int k = 0; k < NPC_MAX_LT; k++) {
567 [ # # ]: 0 : if (kex_rsp->intf_extr_lt[i][j][k] == 0)
568 : 0 : continue;
569 : 0 : plt_info("Intf %d, Extr %d, LT %d: 0x%" PRIx64, i, j, k,
570 : : kex_rsp->intf_extr_lt[i][j][k]);
571 : : }
572 : : }
573 : : }
574 : 0 : }
575 : :
576 : : static void
577 : 0 : npc_mcam_process_mkex_cfg_cn20k(struct npc *npc, struct npc_cn20k_get_kex_cfg_rsp *kex_rsp)
578 : : {
579 : : volatile uint64_t(*q)[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT];
580 : : volatile uint64_t(*d)[NPC_MAX_INTF][NPC_MAX_EXTRACTOR];
581 : : struct npc_xtract_info *x_info = NULL;
582 : : union npc_kex_ldata_flags_cfg *ld_info = NULL;
583 : : int ex, lt, ix;
584 : : npc_dxcfg_cn20k_t *p;
585 : : npc_lid_cn20k_t *l;
586 : : uint64_t keyw;
587 : : uint64_t val;
588 : :
589 : 0 : npc->keyx_supp_nmask[NPC_MCAM_RX] = kex_rsp->rx_keyx_cfg & 0x7fffffffULL;
590 : 0 : npc->keyx_supp_nmask[NPC_MCAM_TX] = kex_rsp->tx_keyx_cfg & 0x7fffffffULL;
591 : 0 : npc->keyx_len[NPC_MCAM_RX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_RX]);
592 : 0 : npc->keyx_len[NPC_MCAM_TX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_TX]);
593 : :
594 : 0 : keyw = (kex_rsp->rx_keyx_cfg >> 32) & 0x7ULL;
595 : 0 : npc->keyw[NPC_MCAM_RX] = keyw;
596 : 0 : keyw = (kex_rsp->tx_keyx_cfg >> 32) & 0x7ULL;
597 : 0 : npc->keyw[NPC_MCAM_TX] = keyw;
598 : :
599 : : p = &npc->prx_dxcfg_cn20k;
600 : : l = &npc->lid_cfg;
601 : : q = (volatile uint64_t(*)[][NPC_MAX_EXTRACTOR][NPC_MAX_LT])(&kex_rsp->intf_extr_lt);
602 : : d = (volatile uint64_t(*)[][NPC_MAX_EXTRACTOR])(&kex_rsp->intf_extr);
603 [ # # ]: 0 : for (ix = 0; ix < NPC_MAX_INTF; ix++) {
604 [ # # ]: 0 : for (ex = 0; ex < NPC_MAX_EXTRACTOR; ex++) {
605 : 0 : val = (*d)[ix][ex];
606 : : ld_info = &(*l)[ix][ex];
607 : 0 : ld_info->s.lid = (val & 0x7);
608 [ # # ]: 0 : for (lt = 0; lt < NPC_MAX_LT; lt++) {
609 : : x_info = &(*p)[ix][ex][lt].xtract;
610 : 0 : val = (*q)[ix][ex][lt];
611 : : npc_update_kex_info(x_info, val);
612 : : }
613 : : }
614 : : }
615 : 0 : }
616 : :
617 : : static void
618 : 0 : npc_mcam_process_mkex_cfg(struct npc *npc, struct npc_get_kex_cfg_rsp *kex_rsp)
619 : : {
620 : : volatile uint64_t(*q)[NPC_MAX_INTF][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD];
621 : : struct npc_xtract_info *x_info = NULL;
622 : : int lid, lt, ld, fl, ix;
623 : : npc_dxcfg_t *p;
624 : : uint64_t keyw;
625 : : uint64_t val;
626 : :
627 : 0 : npc->keyx_supp_nmask[NPC_MCAM_RX] = kex_rsp->rx_keyx_cfg & 0x7fffffffULL;
628 : 0 : npc->keyx_supp_nmask[NPC_MCAM_TX] = kex_rsp->tx_keyx_cfg & 0x7fffffffULL;
629 : 0 : npc->keyx_len[NPC_MCAM_RX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_RX]);
630 : 0 : npc->keyx_len[NPC_MCAM_TX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_TX]);
631 : :
632 : 0 : keyw = (kex_rsp->rx_keyx_cfg >> 32) & 0x7ULL;
633 : 0 : npc->keyw[NPC_MCAM_RX] = keyw;
634 : 0 : keyw = (kex_rsp->tx_keyx_cfg >> 32) & 0x7ULL;
635 : 0 : npc->keyw[NPC_MCAM_TX] = keyw;
636 : :
637 : : /* Update KEX_LD_FLAG */
638 [ # # ]: 0 : for (ix = 0; ix < NPC_MAX_INTF; ix++) {
639 [ # # ]: 0 : for (ld = 0; ld < NPC_MAX_LD; ld++) {
640 [ # # ]: 0 : for (fl = 0; fl < NPC_MAX_LFL; fl++) {
641 : : x_info = &npc->prx_fxcfg[ix][ld][fl].xtract[0];
642 : 0 : val = kex_rsp->intf_ld_flags[ix][ld][fl];
643 : : npc_update_kex_info(x_info, val);
644 : : }
645 : : }
646 : : }
647 : :
648 : : /* Update LID, LT and LDATA cfg */
649 : : p = &npc->prx_dxcfg;
650 : : q = (volatile uint64_t(*)[][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD])(&kex_rsp->intf_lid_lt_ld);
651 [ # # ]: 0 : for (ix = 0; ix < NPC_MAX_INTF; ix++) {
652 [ # # ]: 0 : for (lid = 0; lid < NPC_MAX_LID; lid++) {
653 [ # # ]: 0 : for (lt = 0; lt < NPC_MAX_LT; lt++) {
654 [ # # ]: 0 : for (ld = 0; ld < NPC_MAX_LD; ld++) {
655 : : x_info = &(*p)[ix][lid][lt].xtract[ld];
656 : 0 : val = (*q)[ix][lid][lt][ld];
657 : : npc_update_kex_info(x_info, val);
658 : : }
659 : : }
660 : : }
661 : : }
662 : : /* Update LDATA Flags cfg */
663 : 0 : npc->prx_lfcfg[0].i = kex_rsp->kex_ld_flags[0];
664 : 0 : npc->prx_lfcfg[1].i = kex_rsp->kex_ld_flags[1];
665 : 0 : }
666 : :
667 : : int
668 : 0 : npc_mcam_fetch_hw_cap(struct npc *npc, uint8_t *npc_hw_cap)
669 : : {
670 : : struct get_hw_cap_rsp *hw_cap_rsp;
671 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
672 : : int rc = 0;
673 : :
674 : 0 : *npc_hw_cap = 0;
675 : :
676 : 0 : mbox_alloc_msg_get_hw_cap(mbox);
677 : : rc = mbox_process_msg(mbox, (void *)&hw_cap_rsp);
678 [ # # ]: 0 : if (rc) {
679 : 0 : plt_err("Failed to fetch NPC HW capability");
680 : 0 : goto done;
681 : : }
682 : :
683 : 0 : *npc_hw_cap = hw_cap_rsp->npc_hash_extract;
684 : 0 : done:
685 : : mbox_put(mbox);
686 : 0 : return rc;
687 : : }
688 : :
689 : : int
690 : 0 : npc_mcam_fetch_kex_cfg(struct npc *npc)
691 : : {
692 : : struct npc_get_kex_cfg_rsp *kex_rsp;
693 : : struct npc_cn20k_get_kex_cfg_rsp *kex_rsp_20k;
694 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
695 : : int rc = 0;
696 : :
697 : :
698 [ # # ]: 0 : if (!roc_model_is_cn20k()) {
699 : 0 : mbox_alloc_msg_npc_get_kex_cfg(mbox);
700 : : rc = mbox_process_msg(mbox, (void *)&kex_rsp);
701 [ # # ]: 0 : if (rc) {
702 : 0 : plt_err("Failed to fetch NPC KEX config");
703 : 0 : goto done;
704 : : }
705 : :
706 : 0 : mbox_memcpy((char *)npc->profile_name, kex_rsp->mkex_pfl_name, MKEX_NAME_LEN);
707 : :
708 : 0 : npc->exact_match_ena = (kex_rsp->rx_keyx_cfg >> 40) & 0xF;
709 : 0 : npc_mcam_process_mkex_cfg(npc, kex_rsp);
710 : : } else {
711 : 0 : mbox_alloc_msg_npc_cn20k_get_kex_cfg(mbox);
712 : : rc = mbox_process_msg(mbox, (void *)&kex_rsp_20k);
713 [ # # ]: 0 : if (rc) {
714 : 0 : plt_err("Failed to fetch NPC KEX config");
715 : 0 : goto done;
716 : : }
717 : :
718 : 0 : mbox_memcpy((char *)npc->profile_name, kex_rsp_20k->mkex_pfl_name, MKEX_NAME_LEN);
719 : :
720 : 0 : npc->exact_match_ena = (kex_rsp_20k->rx_keyx_cfg >> 40) & 0xF;
721 : 0 : npc_mcam_process_mkex_cfg_cn20k(npc, kex_rsp_20k);
722 [ # # ]: 0 : if (npc->enable_debug)
723 : 0 : npc_mcam_kex_cfg_dump(kex_rsp_20k);
724 : : }
725 : :
726 : 0 : done:
727 : : mbox_put(mbox);
728 : 0 : return rc;
729 : : }
730 : :
731 : : static void
732 : 0 : npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_cn20k_mcam_write_entry_req *req,
733 : : uint16_t channel, uint16_t chan_mask, bool is_second_pass)
734 : : {
735 : : uint16_t chan = 0, mask = 0;
736 : :
737 : 0 : req->entry_data.kw[0] &= ~(GENMASK(11, 0));
738 : 0 : req->entry_data.kw_mask[0] &= ~(GENMASK(11, 0));
739 : 0 : flow->mcam_data[0] &= ~(GENMASK(11, 0));
740 [ # # ]: 0 : flow->mcam_mask[0] &= ~(GENMASK(11, 0));
741 : :
742 : : chan = channel;
743 : : mask = chan_mask;
744 : :
745 [ # # ]: 0 : if (roc_model_runtime_is_cn10k()) {
746 [ # # ]: 0 : if (is_second_pass) {
747 : 0 : chan = (channel | NIX_CHAN_CPT_CH_START);
748 : 0 : mask = (chan_mask | NIX_CHAN_CPT_CH_START);
749 : : } else {
750 [ # # ]: 0 : if (!roc_npc_action_is_rx_inline(flow->npc_action)) {
751 : : /*
752 : : * Clear bits 10 & 11 corresponding to CPT
753 : : * channel. By default, rules should match
754 : : * both first pass packets and second pass
755 : : * packets from CPT.
756 : : */
757 : 0 : chan = (channel & NIX_CHAN_CPT_X2P_MASK);
758 : 0 : mask = (chan_mask & NIX_CHAN_CPT_X2P_MASK);
759 : : }
760 : : }
761 : : }
762 : :
763 : 0 : req->entry_data.kw[0] |= (uint64_t)chan;
764 : 0 : req->entry_data.kw_mask[0] |= (uint64_t)mask;
765 : 0 : flow->mcam_data[0] |= (uint64_t)chan;
766 : 0 : flow->mcam_mask[0] |= (uint64_t)mask;
767 : 0 : }
768 : :
769 : : #define NPC_PF_FUNC_WIDTH 2
770 : : #define NPC_KEX_PF_FUNC_MASK 0xFFFF
771 : :
772 : : static int
773 : 0 : npc_mcam_set_pf_func(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
774 : : {
775 : : uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
776 : : uint8_t *flow_mcam_data, *flow_mcam_mask;
777 : : struct npc_lid_lt_xtract_info *xinfo;
778 : : bool pffunc_found = false;
779 : 0 : uint16_t mask = 0xFFFF;
780 : : int i;
781 : :
782 : 0 : flow_mcam_data = (uint8_t *)flow->mcam_data;
783 : 0 : flow_mcam_mask = (uint8_t *)flow->mcam_mask;
784 : :
785 : : xinfo = &npc->prx_dxcfg[NIX_INTF_TX][NPC_LID_LA][NPC_LT_LA_IH_NIX_ETHER];
786 : :
787 [ # # ]: 0 : for (i = 0; i < NPC_MAX_LD; i++) {
788 : 0 : nr_bytes = xinfo->xtract[i].len;
789 : 0 : hdr_offset = xinfo->xtract[i].hdr_off;
790 : 0 : key_offset = xinfo->xtract[i].key_off;
791 : :
792 [ # # ]: 0 : if (hdr_offset > 0 || nr_bytes < NPC_PF_FUNC_WIDTH)
793 : 0 : continue;
794 : : else
795 : : pffunc_found = true;
796 : :
797 : 0 : pf_func_offset = key_offset + nr_bytes - NPC_PF_FUNC_WIDTH;
798 : 0 : memcpy((void *)&flow_mcam_data[pf_func_offset], (uint8_t *)&pf_func,
799 : : NPC_PF_FUNC_WIDTH);
800 : 0 : memcpy((void *)&flow_mcam_mask[pf_func_offset], (uint8_t *)&mask,
801 : : NPC_PF_FUNC_WIDTH);
802 : : }
803 [ # # ]: 0 : if (!pffunc_found)
804 : 0 : return -EINVAL;
805 : :
806 : : return 0;
807 : : }
808 : :
809 : : static int
810 : 0 : npc_mcam_set_pf_func_cn20k(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
811 : : {
812 : : uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
813 : : struct npc_lid_lt_xtract_info_cn20k *xinfo;
814 : : uint8_t *flow_mcam_data, *flow_mcam_mask;
815 : : bool pffunc_found = false;
816 : 0 : uint16_t mask = 0xFFFF;
817 : : int i;
818 : :
819 : 0 : flow_mcam_data = (uint8_t *)flow->mcam_data;
820 : 0 : flow_mcam_mask = (uint8_t *)flow->mcam_mask;
821 : :
822 : 0 : xinfo = npc->prx_dxcfg_cn20k[NIX_INTF_TX][NPC_LID_LA];
823 : :
824 [ # # ]: 0 : for (i = 0; i < NPC_MAX_LT; i++) {
825 : 0 : nr_bytes = xinfo[i].xtract.len;
826 : 0 : hdr_offset = xinfo[i].xtract.hdr_off;
827 : 0 : key_offset = xinfo[i].xtract.key_off;
828 : :
829 [ # # ]: 0 : if (hdr_offset > 0 || nr_bytes < NPC_PF_FUNC_WIDTH)
830 : 0 : continue;
831 : : else
832 : : pffunc_found = true;
833 : :
834 : 0 : pf_func_offset = key_offset + nr_bytes - NPC_PF_FUNC_WIDTH;
835 : 0 : memcpy((void *)&flow_mcam_data[pf_func_offset], (uint8_t *)&pf_func,
836 : : NPC_PF_FUNC_WIDTH);
837 : 0 : memcpy((void *)&flow_mcam_mask[pf_func_offset], (uint8_t *)&mask,
838 : : NPC_PF_FUNC_WIDTH);
839 : : }
840 [ # # ]: 0 : if (!pffunc_found)
841 : 0 : return -EINVAL;
842 : :
843 : : return 0;
844 : : }
845 : :
846 : : int
847 : 0 : npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_parse_state *pst)
848 : : {
849 : : struct npc_cn20k_mcam_write_entry_req *cn20k_req;
850 : : struct npc_cn20k_mcam_write_entry_req req;
851 : : struct nix_inl_dev *inl_dev = NULL;
852 : 0 : struct mbox *mbox = npc->mbox;
853 : : struct mbox_msghdr *rsp;
854 : : struct idev_cfg *idev;
855 : : uint16_t pf_func = 0;
856 : 0 : uint16_t ctr = ~(0);
857 : : uint32_t la_offset;
858 : : uint64_t mask;
859 : : int rc, idx;
860 : : int entry;
861 : :
862 : : PLT_SET_USED(pst);
863 : :
864 : 0 : idev = idev_get_cfg();
865 [ # # ]: 0 : if (idev)
866 : 0 : inl_dev = idev->nix_inl_dev;
867 : :
868 [ # # # # ]: 0 : if (inl_dev && inl_dev->ipsec_index) {
869 [ # # ]: 0 : if (flow->is_inline_dev)
870 : 0 : mbox = inl_dev->dev.mbox;
871 : : }
872 : :
873 [ # # ]: 0 : if (flow->use_ctr) {
874 : 0 : rc = npc_mcam_alloc_counter(mbox, &ctr);
875 [ # # ]: 0 : if (rc)
876 : : return rc;
877 : :
878 : 0 : flow->ctr_id = ctr;
879 : 0 : rc = npc_mcam_clear_counter(mbox, flow->ctr_id);
880 [ # # ]: 0 : if (rc)
881 : : return rc;
882 : : }
883 : :
884 [ # # ]: 0 : if (roc_model_is_cn20k()) {
885 : 0 : req.hw_prio = flow->priority;
886 : 0 : flow->key_type = npc_get_key_type(npc, flow);
887 : 0 : req.req_kw_type = flow->key_type;
888 : : }
889 : :
890 [ # # # # : 0 : if (flow->nix_intf == NIX_INTF_RX && flow->is_inline_dev && inl_dev &&
# # ]
891 [ # # # # ]: 0 : inl_dev->ipsec_index && inl_dev->is_multi_channel) {
892 [ # # ]: 0 : if (inl_dev->curr_ipsec_idx >= inl_dev->alloc_ipsec_rules)
893 : : return NPC_ERR_MCAM_ALLOC;
894 : 0 : entry = inl_dev->ipsec_index[inl_dev->curr_ipsec_idx];
895 : 0 : inl_dev->curr_ipsec_idx++;
896 : 0 : flow->use_pre_alloc = 1;
897 : : } else {
898 : 0 : entry = npc_get_free_mcam_entry(mbox, flow, npc);
899 [ # # ]: 0 : if (entry < 0) {
900 [ # # ]: 0 : if (flow->use_ctr)
901 : 0 : npc_mcam_free_counter(mbox, ctr);
902 : 0 : return NPC_ERR_MCAM_ALLOC;
903 : : }
904 : : }
905 : :
906 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_TX) {
907 : 0 : uint16_t pffunc = flow->tx_pf_func;
908 : :
909 [ # # ]: 0 : if (flow->has_rep)
910 : 0 : pffunc = flow->rep_pf_func;
911 : :
912 [ # # ]: 0 : pffunc = plt_cpu_to_be_16(pffunc);
913 : :
914 [ # # ]: 0 : if (roc_model_is_cn20k())
915 : 0 : rc = npc_mcam_set_pf_func_cn20k(npc, flow, pffunc);
916 : : else
917 : 0 : rc = npc_mcam_set_pf_func(npc, flow, pffunc);
918 [ # # ]: 0 : if (rc)
919 : : return rc;
920 : : }
921 : :
922 [ # # ]: 0 : if (flow->is_sampling_rule) {
923 : : /* Save and restore any mark value set */
924 : 0 : uint16_t mark = (flow->npc_action >> 40) & 0xffff;
925 : : uint16_t mce_index = 0;
926 : 0 : uint32_t rqs[2] = {};
927 : :
928 : 0 : rqs[1] = flow->recv_queue;
929 : 0 : rc = roc_nix_mcast_list_setup(npc->mbox, flow->nix_intf, 2, flow->mcast_pf_funcs,
930 : 0 : flow->mcast_channels, rqs, &flow->mcast_grp_index,
931 : : &flow->mce_start_index);
932 [ # # ]: 0 : if (rc)
933 : 0 : return rc;
934 : :
935 : : flow->npc_action = NIX_RX_ACTIONOP_MCAST;
936 : 0 : mce_index = flow->mce_start_index;
937 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_TX) {
938 : 0 : flow->npc_action |= (uint64_t)mce_index << 12;
939 : 0 : flow->npc_action |= (uint64_t)mark << 32;
940 : : } else {
941 : 0 : flow->npc_action |= (uint64_t)mce_index << 20;
942 : 0 : flow->npc_action |= (uint64_t)mark << 40;
943 : : }
944 : : }
945 : :
946 : 0 : req.cntr = flow->ctr_id;
947 : 0 : req.entry = entry;
948 : :
949 : 0 : req.intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
950 : 0 : req.enable_entry = 1;
951 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_RX)
952 : 0 : flow->npc_action |= (uint64_t)flow->recv_queue << 20;
953 : 0 : req.entry_data.action = flow->npc_action;
954 : 0 : req.entry_data.action2 = flow->npc_action2;
955 : :
956 : : /*
957 : : * Driver sets vtag action on per interface basis, not
958 : : * per flow basis. It is a matter of how we decide to support
959 : : * this pmd specific behavior. There are two ways:
960 : : * 1. Inherit the vtag action from the one configured
961 : : * for this interface. This can be read from the
962 : : * vtag_action configured for default mcam entry of
963 : : * this pf_func.
964 : : * 2. Do not support vtag action with npc_flow.
965 : : *
966 : : * Second approach is used now.
967 : : */
968 : 0 : req.entry_data.vtag_action = flow->vtag_action;
969 : :
970 [ # # ]: 0 : for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
971 : 0 : req.entry_data.kw[idx] = flow->mcam_data[idx];
972 : 0 : req.entry_data.kw_mask[idx] = flow->mcam_mask[idx];
973 : : }
974 : :
975 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_RX) {
976 [ # # # # : 0 : if (inl_dev && inl_dev->is_multi_channel &&
# # ]
977 : : roc_npc_action_is_rx_inline(flow->npc_action)) {
978 : 0 : pf_func = nix_inl_dev_pffunc_get();
979 : 0 : req.entry_data.action &= ~(GENMASK(19, 4));
980 : 0 : req.entry_data.action |= (uint64_t)pf_func << 4;
981 : 0 : flow->npc_action &= ~(GENMASK(19, 4));
982 : 0 : flow->npc_action |= (uint64_t)pf_func << 4;
983 : :
984 : 0 : npc_mcam_set_channel(flow, &req, inl_dev->channel, inl_dev->chan_mask,
985 : : false);
986 [ # # ]: 0 : } else if (flow->has_rep) {
987 [ # # ]: 0 : pf_func = (flow->rep_act_pf_func == 0) ? flow->rep_pf_func :
988 : : flow->rep_act_pf_func;
989 : 0 : req.entry_data.action &= ~(GENMASK(19, 4));
990 : 0 : req.entry_data.action |= (uint64_t)pf_func << 4;
991 : 0 : flow->npc_action &= ~(GENMASK(19, 4));
992 : 0 : flow->npc_action |= (uint64_t)pf_func << 4;
993 : 0 : npc_mcam_set_channel(flow, &req, flow->rep_channel, (BIT_ULL(12) - 1),
994 : : false);
995 [ # # ]: 0 : } else if (npc->is_sdp_link) {
996 : 0 : npc_mcam_set_channel(flow, &req, npc->sdp_channel, npc->sdp_channel_mask,
997 : 0 : pst->is_second_pass_rule);
998 : : } else {
999 : 0 : npc_mcam_set_channel(flow, &req, npc->channel, (BIT_ULL(12) - 1),
1000 : 0 : pst->is_second_pass_rule);
1001 : : }
1002 : : /*
1003 : : * For second pass rule, set LA LTYPE to CPT_HDR.
1004 : : * For all other rules, set LA LTYPE to match both 1st pass and 2nd pass ltypes.
1005 : : */
1006 [ # # # # ]: 0 : if (pst->is_second_pass_rule || (!pst->is_second_pass_rule && pst->has_eth_type)) {
1007 [ # # ]: 0 : la_offset = plt_popcount32(npc->keyx_supp_nmask[flow->nix_intf] &
1008 : : ((1ULL << 9 /* LA offset */) - 1));
1009 : 0 : la_offset *= 4;
1010 : :
1011 : 0 : mask = ~((0xfULL << la_offset));
1012 : 0 : req.entry_data.kw[0] &= mask;
1013 : 0 : req.entry_data.kw_mask[0] &= mask;
1014 : 0 : flow->mcam_data[0] &= mask;
1015 : 0 : flow->mcam_mask[0] &= mask;
1016 [ # # ]: 0 : if (pst->is_second_pass_rule) {
1017 : 0 : req.entry_data.kw[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
1018 : 0 : req.entry_data.kw_mask[0] |= (0xFULL << la_offset);
1019 : 0 : flow->mcam_data[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
1020 : 0 : flow->mcam_mask[0] |= (0xFULL << la_offset);
1021 : : } else {
1022 : : /* Mask ltype ETHER (0x2) and CPT_HDR (0xa) */
1023 : 0 : req.entry_data.kw[0] |= (0x2ULL << la_offset);
1024 : 0 : req.entry_data.kw_mask[0] |= (0x7ULL << la_offset);
1025 : 0 : flow->mcam_data[0] |= (0x2ULL << la_offset);
1026 : 0 : flow->mcam_mask[0] |= (0x7ULL << la_offset);
1027 : : }
1028 : : }
1029 : : }
1030 : :
1031 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1032 : 0 : cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox_get(mbox));
1033 [ # # ]: 0 : if (cn20k_req == NULL) {
1034 : : mbox_put(mbox);
1035 [ # # ]: 0 : if (flow->use_ctr)
1036 : 0 : npc_mcam_free_counter(mbox, ctr);
1037 : :
1038 : 0 : return rc;
1039 : : }
1040 : 0 : cn20k_req->entry = req.entry;
1041 : 0 : cn20k_req->intf = req.intf;
1042 : 0 : cn20k_req->enable_entry = req.enable_entry;
1043 : 0 : cn20k_req->entry_data.action = req.entry_data.action;
1044 : 0 : cn20k_req->entry_data.vtag_action = req.entry_data.vtag_action;
1045 : 0 : cn20k_req->hw_prio = req.hw_prio;
1046 : 0 : cn20k_req->req_kw_type = req.req_kw_type;
1047 [ # # ]: 0 : if (flow->use_ctr)
1048 : 0 : cn20k_req->cntr = req.cntr;
1049 : :
1050 : 0 : mbox_memcpy(&cn20k_req->entry_data, &req.entry_data,
1051 : : sizeof(struct cn20k_mcam_entry));
1052 : : } else {
1053 : : struct npc_mcam_write_entry_req *req_leg;
1054 : :
1055 : 0 : req_leg = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
1056 [ # # ]: 0 : if (req_leg == NULL) {
1057 : : rc = -ENOSPC;
1058 : 0 : goto exit;
1059 : : }
1060 [ # # ]: 0 : for (idx = 0; idx < NPC_MAX_KWS_IN_KEY; idx++) {
1061 : 0 : req_leg->entry_data.kw[idx] = req.entry_data.kw[idx];
1062 : 0 : req_leg->entry_data.kw_mask[idx] = req.entry_data.kw_mask[idx];
1063 : : }
1064 : 0 : req_leg->entry = req.entry;
1065 : 0 : req_leg->intf = req.intf;
1066 : 0 : req_leg->enable_entry = req.enable_entry;
1067 : 0 : req_leg->cntr = req.cntr;
1068 : 0 : req_leg->entry_data.action = req.entry_data.action;
1069 : 0 : req_leg->entry_data.vtag_action = req.entry_data.vtag_action;
1070 : 0 : req_leg->set_cntr = flow->use_ctr;
1071 : : }
1072 : : rc = mbox_process_msg(mbox, (void *)&rsp);
1073 [ # # ]: 0 : if (rc != 0)
1074 : 0 : goto exit;
1075 : :
1076 : 0 : flow->mcam_id = entry;
1077 : :
1078 [ # # ]: 0 : if (flow->use_ctr)
1079 : 0 : flow->ctr_id = ctr;
1080 : : rc = 0;
1081 : :
1082 : 0 : exit:
1083 : : mbox_put(mbox);
1084 [ # # # # ]: 0 : if (rc && flow->is_sampling_rule)
1085 : 0 : roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
1086 : : return rc;
1087 : : }
1088 : :
1089 : : static void
1090 [ # # ]: 0 : npc_set_vlan_ltype(struct npc_parse_state *pst)
1091 : : {
1092 : : uint64_t val, mask;
1093 : : uint8_t lb_offset;
1094 : :
1095 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1096 : 0 : lb_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1097 : : ((1ULL << NPC_CN20K_LTYPE_LB_OFFSET) - 1));
1098 : :
1099 : : } else {
1100 : 0 : lb_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1101 : : ((1ULL << NPC_LTYPE_LB_OFFSET) - 1));
1102 : : }
1103 : 0 : lb_offset *= 4;
1104 : :
1105 : 0 : mask = ~((0xfULL << lb_offset));
1106 : 0 : pst->flow->mcam_data[0] &= mask;
1107 : 0 : pst->flow->mcam_mask[0] &= mask;
1108 : : /* NPC_LT_LB_CTAG: 0b0010, NPC_LT_LB_STAG_QINQ: 0b0011
1109 : : * Set LB layertype/mask as 0b0010/0b1110 to match both.
1110 : : */
1111 : 0 : val = ((uint64_t)(NPC_LT_LB_CTAG & NPC_LT_LB_STAG_QINQ)) << lb_offset;
1112 : 0 : pst->flow->mcam_data[0] |= val;
1113 : 0 : pst->flow->mcam_mask[0] |= (0xeULL << lb_offset);
1114 : 0 : }
1115 : :
1116 : : static void
1117 [ # # ]: 0 : npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
1118 : : {
1119 : : uint8_t lc_offset, lcflag_offset;
1120 : : uint64_t val, mask;
1121 : :
1122 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1123 : 0 : lc_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1124 : : ((1ULL << NPC_CN20K_LTYPE_LC_OFFSET) - 1));
1125 : :
1126 : : } else {
1127 : 0 : lc_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1128 : : ((1ULL << NPC_LTYPE_LC_OFFSET) - 1));
1129 : : }
1130 : 0 : lc_offset *= 4;
1131 : :
1132 : 0 : mask = ~((0xfULL << lc_offset));
1133 : 0 : pst->flow->mcam_data[0] &= mask;
1134 : 0 : pst->flow->mcam_mask[0] &= mask;
1135 : : /* NPC_LT_LC_IP6: 0b0100, NPC_LT_LC_IP6_EXT: 0b0101
1136 : : * Set LC layertype/mask as 0b0100/0b1110 to match both.
1137 : : */
1138 : 0 : val = ((uint64_t)(NPC_LT_LC_IP6 & NPC_LT_LC_IP6_EXT)) << lc_offset;
1139 : 0 : pst->flow->mcam_data[0] |= val;
1140 : 0 : pst->flow->mcam_mask[0] |= (0xeULL << lc_offset);
1141 : :
1142 : : /* If LC LFLAG is non-zero, set the LC LFLAG mask to 0xF. In general
1143 : : * case flag mask is set same as the value in data. For example, to
1144 : : * match 3 VLANs, flags have to match a range of values. But, for IPv6
1145 : : * extended attributes matching, we need an exact match. Hence, set the
1146 : : * mask as 0xF. This is done only if LC LFLAG value is non-zero,
1147 : : * because for AH and ESP, LC LFLAG is zero and we don't want to match
1148 : : * zero in LFLAG.
1149 : : */
1150 [ # # ]: 0 : if (pst->npc->keyx_supp_nmask[pst->nix_intf] & (1ULL << NPC_LFLAG_LC_OFFSET)) {
1151 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1152 : 0 : lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1153 : : ((1ULL << NPC_CN20K_LFLAG_LC_OFFSET) - 1));
1154 : :
1155 : : } else {
1156 : 0 : lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1157 : : ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
1158 : : }
1159 : 0 : lcflag_offset *= 4;
1160 : :
1161 : 0 : mask = (0xfULL << lcflag_offset);
1162 : 0 : val = pst->flow->mcam_data[0] & mask;
1163 [ # # ]: 0 : if (val)
1164 : 0 : pst->flow->mcam_mask[0] |= mask;
1165 : : }
1166 : 0 : }
1167 : :
1168 : : int
1169 : 0 : npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
1170 : : {
1171 : : /* This is non-LDATA part in search key */
1172 : 0 : uint64_t key_data[2] = {0ULL, 0ULL};
1173 : 0 : uint64_t key_mask[2] = {0ULL, 0ULL};
1174 : : int key_len, bit = 0, index, rc = 0;
1175 : : struct nix_inl_dev *inl_dev = NULL;
1176 : 0 : int intf = pst->flow->nix_intf;
1177 : : bool skip_base_rule = false;
1178 : : int off, idx, data_off = 0;
1179 : : uint8_t lid, mask, data;
1180 : : struct idev_cfg *idev;
1181 : : uint16_t layer_info;
1182 : : uint64_t lt, flags;
1183 : : struct mbox *mbox;
1184 : :
1185 : : /* Skip till Layer A data start */
1186 [ # # ]: 0 : while (bit < NPC_PARSE_KEX_S_LA_OFFSET) {
1187 [ # # ]: 0 : if (npc->keyx_supp_nmask[intf] & (1 << bit))
1188 : 0 : data_off++;
1189 : 0 : bit++;
1190 : : }
1191 : :
1192 : : /* Each bit represents 1 nibble */
1193 [ # # ]: 0 : data_off *= 4;
1194 : :
1195 : : index = 0;
1196 [ # # ]: 0 : if (!roc_model_is_cn20k()) {
1197 [ # # ]: 0 : for (lid = 0; lid < NPC_MAX_LID; lid++) {
1198 : : /* Offset in key */
1199 : 0 : off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
1200 : 0 : lt = pst->lt[lid] & 0xf;
1201 : 0 : flags = pst->flags[lid] & 0xff;
1202 : :
1203 : : /* NPC_LAYER_KEX_S */
1204 : 0 : layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
1205 [ # # ]: 0 : if (!layer_info)
1206 : 0 : continue;
1207 : :
1208 [ # # ]: 0 : for (idx = 0; idx <= 2; idx++) {
1209 [ # # ]: 0 : if (!(layer_info & (1 << idx)))
1210 : 0 : continue;
1211 : :
1212 [ # # ]: 0 : if (idx == 2) {
1213 : : data = lt;
1214 : : mask = 0xf;
1215 [ # # ]: 0 : } else if (idx == 1) {
1216 : 0 : data = ((flags >> 4) & 0xf);
1217 : : mask = ((flags >> 4) & 0xf);
1218 : : } else {
1219 : 0 : data = (flags & 0xf);
1220 : : mask = (flags & 0xf);
1221 : : }
1222 : :
1223 [ # # ]: 0 : if (data_off >= 64) {
1224 : : data_off = 0;
1225 : 0 : index++;
1226 : : }
1227 : 0 : key_data[index] |= ((uint64_t)data << data_off);
1228 : :
1229 [ # # ]: 0 : if (lt == 0)
1230 : : mask = 0;
1231 : 0 : key_mask[index] |= ((uint64_t)mask << data_off);
1232 : 0 : data_off += 4;
1233 : : }
1234 : : }
1235 : : } else {
1236 [ # # ]: 0 : for (lid = 0; lid < NPC_MAX_LID; lid++) {
1237 : : /* Offset in key */
1238 : 0 : off = NPC_PARSE_KEX_S_LID_OFFSET_CN20K(lid);
1239 : 0 : lt = pst->lt[lid] & 0xf;
1240 : 0 : flags = pst->flags[lid] & 0xf;
1241 : :
1242 : : /* NPC_LAYER_KEX_S */
1243 : 0 : layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x3);
1244 [ # # ]: 0 : if (!layer_info)
1245 : 0 : continue;
1246 : :
1247 [ # # ]: 0 : for (idx = 0; idx <= 1; idx++) {
1248 [ # # ]: 0 : if (!(layer_info & (1 << idx)))
1249 : 0 : continue;
1250 : :
1251 [ # # ]: 0 : if (idx == 1) {
1252 : : data = lt;
1253 : : mask = 0xf;
1254 : : } else {
1255 : : data = (flags & 0xf);
1256 : : mask = (flags & 0xf);
1257 : : }
1258 : :
1259 [ # # ]: 0 : if (data_off >= 64) {
1260 : : data_off = 0;
1261 : 0 : index++;
1262 : : }
1263 : 0 : key_data[index] |= ((uint64_t)data << data_off);
1264 : :
1265 [ # # ]: 0 : if (lt == 0)
1266 : : mask = 0;
1267 : 0 : key_mask[index] |= ((uint64_t)mask << data_off);
1268 : 0 : data_off += 4;
1269 : : }
1270 : : }
1271 : : }
1272 : :
1273 : : /* Copy this into mcam string */
1274 : 0 : key_len = (pst->npc->keyx_len[intf] + 7) / 8;
1275 [ # # ]: 0 : memcpy(pst->flow->mcam_data, key_data, key_len);
1276 : 0 : memcpy(pst->flow->mcam_mask, key_mask, key_len);
1277 : :
1278 [ # # ]: 0 : if (pst->set_vlan_ltype_mask)
1279 : 0 : npc_set_vlan_ltype(pst);
1280 : :
1281 [ # # ]: 0 : if (pst->set_ipv6ext_ltype_mask)
1282 : 0 : npc_set_ipv6ext_ltype_mask(pst);
1283 : :
1284 : 0 : idev = idev_get_cfg();
1285 [ # # ]: 0 : if (idev)
1286 : 0 : inl_dev = idev->nix_inl_dev;
1287 [ # # # # : 0 : if (inl_dev && inl_dev->is_multi_channel &&
# # ]
1288 [ # # ]: 0 : roc_npc_action_is_rx_inline(pst->flow->npc_action))
1289 : : skip_base_rule = true;
1290 : :
1291 [ # # # # : 0 : if ((pst->is_vf || pst->flow->is_rep_vf) && pst->flow->nix_intf == NIX_INTF_RX &&
# # # # ]
1292 : : !skip_base_rule) {
1293 [ # # ]: 0 : if (pst->flow->has_rep)
1294 : 0 : mbox = mbox_get(pst->flow->rep_mbox);
1295 : : else
1296 : 0 : mbox = mbox_get(npc->mbox);
1297 : 0 : (void)mbox_alloc_msg_npc_read_base_steer_rule(mbox);
1298 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1299 : : struct npc_cn20k_mcam_read_base_rule_rsp *base_rule_rsp;
1300 : : struct cn20k_mcam_entry *base_entry;
1301 : :
1302 : : rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
1303 [ # # ]: 0 : if (rc) {
1304 : : mbox_put(mbox);
1305 : 0 : plt_err("Failed to fetch VF's base MCAM entry");
1306 : 0 : return rc;
1307 : : }
1308 : : mbox_put(mbox);
1309 : 0 : base_entry = &base_rule_rsp->entry;
1310 [ # # ]: 0 : for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
1311 : 0 : pst->flow->mcam_data[idx] |= base_entry->kw[idx];
1312 : 0 : pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
1313 : : }
1314 : :
1315 : : } else {
1316 : : struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
1317 : : struct mcam_entry *base_entry;
1318 : :
1319 : : rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
1320 [ # # ]: 0 : if (rc) {
1321 : : mbox_put(mbox);
1322 : 0 : plt_err("Failed to fetch VF's base MCAM entry");
1323 : 0 : return rc;
1324 : : }
1325 : : mbox_put(mbox);
1326 : 0 : base_entry = &base_rule_rsp->entry_data;
1327 [ # # ]: 0 : for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
1328 : 0 : pst->flow->mcam_data[idx] |= base_entry->kw[idx];
1329 : 0 : pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
1330 : : }
1331 : : }
1332 : : }
1333 : :
1334 : : /*
1335 : : * Now we have mcam data and mask formatted as
1336 : : * [Key_len/4 nibbles][0 or 1 nibble hole][data]
1337 : : * hole is present if key_len is odd number of nibbles.
1338 : : * mcam data must be split into 64 bits + 48 bits segments
1339 : : * for each back W0, W1.
1340 : : */
1341 : :
1342 [ # # ]: 0 : if (mcam_alloc)
1343 : 0 : return npc_mcam_alloc_and_write(npc, pst->flow, pst);
1344 : : else
1345 : : return 0;
1346 : : }
1347 : :
1348 : : int
1349 : 0 : npc_flow_enable_all_entries(struct npc *npc, bool enable)
1350 : : {
1351 : : struct nix_inl_dev *inl_dev;
1352 : : struct npc_flow_list *list;
1353 : : struct roc_npc_flow *flow;
1354 : : struct idev_cfg *idev;
1355 : : int rc = 0, idx;
1356 : :
1357 : : /* Free any MCAM counters and delete flow list */
1358 [ # # ]: 0 : for (idx = 0; idx < npc->flow_max_priority; idx++) {
1359 : 0 : list = &npc->flow_list[idx];
1360 [ # # ]: 0 : TAILQ_FOREACH(flow, list, next) {
1361 : 0 : flow->enable = enable;
1362 : 0 : rc = npc_mcam_write_entry(npc->mbox, flow);
1363 [ # # ]: 0 : if (rc)
1364 : 0 : return rc;
1365 : : }
1366 : : }
1367 : :
1368 : : list = &npc->ipsec_list;
1369 : 0 : idev = idev_get_cfg();
1370 [ # # ]: 0 : if (!idev)
1371 : : return 0;
1372 : 0 : inl_dev = idev->nix_inl_dev;
1373 : :
1374 [ # # ]: 0 : if (inl_dev) {
1375 [ # # ]: 0 : TAILQ_FOREACH(flow, list, next) {
1376 : 0 : flow->enable = enable;
1377 : 0 : rc = npc_mcam_write_entry(inl_dev->dev.mbox, flow);
1378 [ # # ]: 0 : if (rc)
1379 : 0 : return rc;
1380 : : }
1381 : : }
1382 : : return rc;
1383 : : }
1384 : :
1385 : : int
1386 : 0 : npc_flow_free_all_resources(struct npc *npc)
1387 : : {
1388 : : struct roc_npc_flow *flow;
1389 : : int rc, idx;
1390 : :
1391 : : /* Free all MCAM entries allocated */
1392 : 0 : rc = npc_mcam_free_all_entries(npc);
1393 : :
1394 : : /* Free any MCAM counters and delete flow list */
1395 [ # # ]: 0 : for (idx = 0; idx < npc->flow_max_priority; idx++) {
1396 [ # # ]: 0 : while ((flow = TAILQ_FIRST(&npc->flow_list[idx])) != NULL) {
1397 : 0 : npc_rss_group_free(npc, flow);
1398 [ # # ]: 0 : if (flow->ctr_id != NPC_COUNTER_NONE) {
1399 : 0 : rc |= npc_mcam_clear_counter(npc->mbox, flow->ctr_id);
1400 : 0 : rc |= npc_mcam_free_counter(npc->mbox, flow->ctr_id);
1401 : : }
1402 : :
1403 [ # # ]: 0 : if (flow->is_sampling_rule)
1404 : 0 : roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
1405 : :
1406 : 0 : npc_delete_prio_list_entry(npc, flow);
1407 : :
1408 [ # # ]: 0 : TAILQ_REMOVE(&npc->flow_list[idx], flow, next);
1409 : 0 : plt_free(flow);
1410 : : }
1411 : : }
1412 : 0 : return rc;
1413 : : }
|