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.vtag_action = mcam->vtag_action;
515 : 0 : cn20k_req->hw_prio = mcam->priority;
516 [ # # ]: 0 : if (mcam->use_ctr)
517 : 0 : cn20k_req->cntr = mcam->ctr_id;
518 : :
519 [ # # ]: 0 : for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
520 : 0 : cn20k_req->entry_data.kw[i] = mcam->mcam_data[i];
521 : 0 : cn20k_req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
522 : : }
523 : : } else {
524 : 0 : req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
525 [ # # ]: 0 : if (req == NULL) {
526 : : mbox_put(mbox);
527 [ # # ]: 0 : if (mcam->use_ctr)
528 : 0 : npc_mcam_free_counter(mbox, ctr);
529 : :
530 : 0 : return rc;
531 : : }
532 : 0 : req->entry = mcam->mcam_id;
533 : 0 : req->intf = mcam->nix_intf;
534 : 0 : req->enable_entry = mcam->enable;
535 : 0 : req->entry_data.action = mcam->npc_action;
536 : 0 : req->entry_data.vtag_action = mcam->vtag_action;
537 [ # # ]: 0 : if (mcam->use_ctr) {
538 : 0 : req->set_cntr = 1;
539 : 0 : req->cntr = mcam->ctr_id;
540 : : }
541 : :
542 [ # # ]: 0 : for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
543 : 0 : req->entry_data.kw[i] = mcam->mcam_data[i];
544 : 0 : req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
545 : : }
546 : : }
547 : : rc = mbox_process_msg(mbox, (void *)&rsp);
548 : : mbox_put(mbox);
549 : 0 : return rc;
550 : : }
551 : :
552 : : static void
553 : 0 : npc_mcam_kex_cfg_dump(struct npc_cn20k_get_kex_cfg_rsp *kex_rsp)
554 : : {
555 [ # # ]: 0 : for (int i = 0; i < NPC_MAX_INTF; i++) {
556 [ # # ]: 0 : for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
557 [ # # ]: 0 : if (kex_rsp->intf_extr[i][j] == 0)
558 : 0 : continue;
559 : 0 : plt_info("Intf %d, Extr %d: 0x%" PRIx64, i, j, kex_rsp->intf_extr[i][j]);
560 : : }
561 : : }
562 : :
563 [ # # ]: 0 : for (int i = 0; i < NPC_MAX_INTF; i++) {
564 [ # # ]: 0 : for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
565 [ # # ]: 0 : for (int k = 0; k < NPC_MAX_LT; k++) {
566 [ # # ]: 0 : if (kex_rsp->intf_extr_lt[i][j][k] == 0)
567 : 0 : continue;
568 : 0 : plt_info("Intf %d, Extr %d, LT %d: 0x%" PRIx64, i, j, k,
569 : : kex_rsp->intf_extr_lt[i][j][k]);
570 : : }
571 : : }
572 : : }
573 : 0 : }
574 : :
575 : : static void
576 : 0 : npc_mcam_process_mkex_cfg_cn20k(struct npc *npc, struct npc_cn20k_get_kex_cfg_rsp *kex_rsp)
577 : : {
578 : : volatile uint64_t(*q)[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT];
579 : : volatile uint64_t(*d)[NPC_MAX_INTF][NPC_MAX_EXTRACTOR];
580 : : struct npc_xtract_info *x_info = NULL;
581 : : union npc_kex_ldata_flags_cfg *ld_info = NULL;
582 : : int ex, lt, ix;
583 : : npc_dxcfg_cn20k_t *p;
584 : : npc_lid_cn20k_t *l;
585 : : uint64_t keyw;
586 : : uint64_t val;
587 : :
588 : 0 : npc->keyx_supp_nmask[NPC_MCAM_RX] = kex_rsp->rx_keyx_cfg & 0x7fffffffULL;
589 : 0 : npc->keyx_supp_nmask[NPC_MCAM_TX] = kex_rsp->tx_keyx_cfg & 0x7fffffffULL;
590 : 0 : npc->keyx_len[NPC_MCAM_RX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_RX]);
591 : 0 : npc->keyx_len[NPC_MCAM_TX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_TX]);
592 : :
593 : 0 : keyw = (kex_rsp->rx_keyx_cfg >> 32) & 0x7ULL;
594 : 0 : npc->keyw[NPC_MCAM_RX] = keyw;
595 : 0 : keyw = (kex_rsp->tx_keyx_cfg >> 32) & 0x7ULL;
596 : 0 : npc->keyw[NPC_MCAM_TX] = keyw;
597 : :
598 : : p = &npc->prx_dxcfg_cn20k;
599 : : l = &npc->lid_cfg;
600 : : q = (volatile uint64_t(*)[][NPC_MAX_EXTRACTOR][NPC_MAX_LT])(&kex_rsp->intf_extr_lt);
601 : : d = (volatile uint64_t(*)[][NPC_MAX_EXTRACTOR])(&kex_rsp->intf_extr);
602 [ # # ]: 0 : for (ix = 0; ix < NPC_MAX_INTF; ix++) {
603 [ # # ]: 0 : for (ex = 0; ex < NPC_MAX_EXTRACTOR; ex++) {
604 : 0 : val = (*d)[ix][ex];
605 : : ld_info = &(*l)[ix][ex];
606 : 0 : ld_info->s.lid = (val & 0x7);
607 [ # # ]: 0 : for (lt = 0; lt < NPC_MAX_LT; lt++) {
608 : : x_info = &(*p)[ix][ex][lt].xtract;
609 : 0 : val = (*q)[ix][ex][lt];
610 : : npc_update_kex_info(x_info, val);
611 : : }
612 : : }
613 : : }
614 : 0 : }
615 : :
616 : : static void
617 : 0 : npc_mcam_process_mkex_cfg(struct npc *npc, struct npc_get_kex_cfg_rsp *kex_rsp)
618 : : {
619 : : volatile uint64_t(*q)[NPC_MAX_INTF][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD];
620 : : struct npc_xtract_info *x_info = NULL;
621 : : int lid, lt, ld, fl, ix;
622 : : npc_dxcfg_t *p;
623 : : uint64_t keyw;
624 : : uint64_t val;
625 : :
626 : 0 : npc->keyx_supp_nmask[NPC_MCAM_RX] = kex_rsp->rx_keyx_cfg & 0x7fffffffULL;
627 : 0 : npc->keyx_supp_nmask[NPC_MCAM_TX] = kex_rsp->tx_keyx_cfg & 0x7fffffffULL;
628 : 0 : npc->keyx_len[NPC_MCAM_RX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_RX]);
629 : 0 : npc->keyx_len[NPC_MCAM_TX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_TX]);
630 : :
631 : 0 : keyw = (kex_rsp->rx_keyx_cfg >> 32) & 0x7ULL;
632 : 0 : npc->keyw[NPC_MCAM_RX] = keyw;
633 : 0 : keyw = (kex_rsp->tx_keyx_cfg >> 32) & 0x7ULL;
634 : 0 : npc->keyw[NPC_MCAM_TX] = keyw;
635 : :
636 : : /* Update KEX_LD_FLAG */
637 [ # # ]: 0 : for (ix = 0; ix < NPC_MAX_INTF; ix++) {
638 [ # # ]: 0 : for (ld = 0; ld < NPC_MAX_LD; ld++) {
639 [ # # ]: 0 : for (fl = 0; fl < NPC_MAX_LFL; fl++) {
640 : : x_info = &npc->prx_fxcfg[ix][ld][fl].xtract[0];
641 : 0 : val = kex_rsp->intf_ld_flags[ix][ld][fl];
642 : : npc_update_kex_info(x_info, val);
643 : : }
644 : : }
645 : : }
646 : :
647 : : /* Update LID, LT and LDATA cfg */
648 : : p = &npc->prx_dxcfg;
649 : : q = (volatile uint64_t(*)[][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD])(&kex_rsp->intf_lid_lt_ld);
650 [ # # ]: 0 : for (ix = 0; ix < NPC_MAX_INTF; ix++) {
651 [ # # ]: 0 : for (lid = 0; lid < NPC_MAX_LID; lid++) {
652 [ # # ]: 0 : for (lt = 0; lt < NPC_MAX_LT; lt++) {
653 [ # # ]: 0 : for (ld = 0; ld < NPC_MAX_LD; ld++) {
654 : : x_info = &(*p)[ix][lid][lt].xtract[ld];
655 : 0 : val = (*q)[ix][lid][lt][ld];
656 : : npc_update_kex_info(x_info, val);
657 : : }
658 : : }
659 : : }
660 : : }
661 : : /* Update LDATA Flags cfg */
662 : 0 : npc->prx_lfcfg[0].i = kex_rsp->kex_ld_flags[0];
663 : 0 : npc->prx_lfcfg[1].i = kex_rsp->kex_ld_flags[1];
664 : 0 : }
665 : :
666 : : int
667 : 0 : npc_mcam_fetch_hw_cap(struct npc *npc, uint8_t *npc_hw_cap)
668 : : {
669 : : struct get_hw_cap_rsp *hw_cap_rsp;
670 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
671 : : int rc = 0;
672 : :
673 : 0 : *npc_hw_cap = 0;
674 : :
675 : 0 : mbox_alloc_msg_get_hw_cap(mbox);
676 : : rc = mbox_process_msg(mbox, (void *)&hw_cap_rsp);
677 [ # # ]: 0 : if (rc) {
678 : 0 : plt_err("Failed to fetch NPC HW capability");
679 : 0 : goto done;
680 : : }
681 : :
682 : 0 : *npc_hw_cap = hw_cap_rsp->npc_hash_extract;
683 : 0 : done:
684 : : mbox_put(mbox);
685 : 0 : return rc;
686 : : }
687 : :
688 : : int
689 : 0 : npc_mcam_fetch_kex_cfg(struct npc *npc)
690 : : {
691 : : struct npc_get_kex_cfg_rsp *kex_rsp;
692 : : struct npc_cn20k_get_kex_cfg_rsp *kex_rsp_20k;
693 : 0 : struct mbox *mbox = mbox_get(npc->mbox);
694 : : int rc = 0;
695 : :
696 : :
697 [ # # ]: 0 : if (!roc_model_is_cn20k()) {
698 : 0 : mbox_alloc_msg_npc_get_kex_cfg(mbox);
699 : : rc = mbox_process_msg(mbox, (void *)&kex_rsp);
700 [ # # ]: 0 : if (rc) {
701 : 0 : plt_err("Failed to fetch NPC KEX config");
702 : 0 : goto done;
703 : : }
704 : :
705 : 0 : mbox_memcpy((char *)npc->profile_name, kex_rsp->mkex_pfl_name, MKEX_NAME_LEN);
706 : :
707 : 0 : npc->exact_match_ena = (kex_rsp->rx_keyx_cfg >> 40) & 0xF;
708 : 0 : npc_mcam_process_mkex_cfg(npc, kex_rsp);
709 : : } else {
710 : 0 : mbox_alloc_msg_npc_cn20k_get_kex_cfg(mbox);
711 : : rc = mbox_process_msg(mbox, (void *)&kex_rsp_20k);
712 [ # # ]: 0 : if (rc) {
713 : 0 : plt_err("Failed to fetch NPC KEX config");
714 : 0 : goto done;
715 : : }
716 : :
717 : 0 : mbox_memcpy((char *)npc->profile_name, kex_rsp_20k->mkex_pfl_name, MKEX_NAME_LEN);
718 : :
719 : 0 : npc->exact_match_ena = (kex_rsp_20k->rx_keyx_cfg >> 40) & 0xF;
720 : 0 : npc_mcam_process_mkex_cfg_cn20k(npc, kex_rsp_20k);
721 [ # # ]: 0 : if (npc->enable_debug)
722 : 0 : npc_mcam_kex_cfg_dump(kex_rsp_20k);
723 : : }
724 : :
725 : 0 : done:
726 : : mbox_put(mbox);
727 : 0 : return rc;
728 : : }
729 : :
730 : : static void
731 : 0 : npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_cn20k_mcam_write_entry_req *req,
732 : : uint16_t channel, uint16_t chan_mask, bool is_second_pass)
733 : : {
734 : : uint16_t chan = 0, mask = 0;
735 : :
736 : 0 : req->entry_data.kw[0] &= ~(GENMASK(11, 0));
737 : 0 : req->entry_data.kw_mask[0] &= ~(GENMASK(11, 0));
738 : 0 : flow->mcam_data[0] &= ~(GENMASK(11, 0));
739 [ # # ]: 0 : flow->mcam_mask[0] &= ~(GENMASK(11, 0));
740 : :
741 : : chan = channel;
742 : : mask = chan_mask;
743 : :
744 [ # # ]: 0 : if (roc_model_runtime_is_cn10k()) {
745 [ # # ]: 0 : if (is_second_pass) {
746 : 0 : chan = (channel | NIX_CHAN_CPT_CH_START);
747 : 0 : mask = (chan_mask | NIX_CHAN_CPT_CH_START);
748 : : } else {
749 [ # # ]: 0 : if (!(flow->npc_action & NIX_RX_ACTIONOP_UCAST_IPSEC)) {
750 : : /*
751 : : * Clear bits 10 & 11 corresponding to CPT
752 : : * channel. By default, rules should match
753 : : * both first pass packets and second pass
754 : : * packets from CPT.
755 : : */
756 : 0 : chan = (channel & NIX_CHAN_CPT_X2P_MASK);
757 : 0 : mask = (chan_mask & NIX_CHAN_CPT_X2P_MASK);
758 : : }
759 : : }
760 : : }
761 : :
762 : 0 : req->entry_data.kw[0] |= (uint64_t)chan;
763 : 0 : req->entry_data.kw_mask[0] |= (uint64_t)mask;
764 : 0 : flow->mcam_data[0] |= (uint64_t)chan;
765 : 0 : flow->mcam_mask[0] |= (uint64_t)mask;
766 : 0 : }
767 : :
768 : : #define NPC_PF_FUNC_WIDTH 2
769 : : #define NPC_KEX_PF_FUNC_MASK 0xFFFF
770 : :
771 : : static int
772 : 0 : npc_mcam_set_pf_func(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
773 : : {
774 : : uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
775 : : uint8_t *flow_mcam_data, *flow_mcam_mask;
776 : : struct npc_lid_lt_xtract_info *xinfo;
777 : : bool pffunc_found = false;
778 : 0 : uint16_t mask = 0xFFFF;
779 : : int i;
780 : :
781 : 0 : flow_mcam_data = (uint8_t *)flow->mcam_data;
782 : 0 : flow_mcam_mask = (uint8_t *)flow->mcam_mask;
783 : :
784 : : xinfo = &npc->prx_dxcfg[NIX_INTF_TX][NPC_LID_LA][NPC_LT_LA_IH_NIX_ETHER];
785 : :
786 [ # # ]: 0 : for (i = 0; i < NPC_MAX_LD; i++) {
787 : 0 : nr_bytes = xinfo->xtract[i].len;
788 : 0 : hdr_offset = xinfo->xtract[i].hdr_off;
789 : 0 : key_offset = xinfo->xtract[i].key_off;
790 : :
791 [ # # ]: 0 : if (hdr_offset > 0 || nr_bytes < NPC_PF_FUNC_WIDTH)
792 : 0 : continue;
793 : : else
794 : : pffunc_found = true;
795 : :
796 : 0 : pf_func_offset = key_offset + nr_bytes - NPC_PF_FUNC_WIDTH;
797 : 0 : memcpy((void *)&flow_mcam_data[pf_func_offset], (uint8_t *)&pf_func,
798 : : NPC_PF_FUNC_WIDTH);
799 : 0 : memcpy((void *)&flow_mcam_mask[pf_func_offset], (uint8_t *)&mask,
800 : : NPC_PF_FUNC_WIDTH);
801 : : }
802 [ # # ]: 0 : if (!pffunc_found)
803 : 0 : return -EINVAL;
804 : :
805 : : return 0;
806 : : }
807 : :
808 : : static int
809 : 0 : npc_mcam_set_pf_func_cn20k(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
810 : : {
811 : : uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
812 : : struct npc_lid_lt_xtract_info_cn20k *xinfo;
813 : : uint8_t *flow_mcam_data, *flow_mcam_mask;
814 : : bool pffunc_found = false;
815 : 0 : uint16_t mask = 0xFFFF;
816 : : int i;
817 : :
818 : 0 : flow_mcam_data = (uint8_t *)flow->mcam_data;
819 : 0 : flow_mcam_mask = (uint8_t *)flow->mcam_mask;
820 : :
821 : 0 : xinfo = npc->prx_dxcfg_cn20k[NIX_INTF_TX][NPC_LID_LA];
822 : :
823 [ # # ]: 0 : for (i = 0; i < NPC_MAX_LT; i++) {
824 : 0 : nr_bytes = xinfo[i].xtract.len;
825 : 0 : hdr_offset = xinfo[i].xtract.hdr_off;
826 : 0 : key_offset = xinfo[i].xtract.key_off;
827 : :
828 [ # # ]: 0 : if (hdr_offset > 0 || nr_bytes < NPC_PF_FUNC_WIDTH)
829 : 0 : continue;
830 : : else
831 : : pffunc_found = true;
832 : :
833 : 0 : pf_func_offset = key_offset + nr_bytes - NPC_PF_FUNC_WIDTH;
834 : 0 : memcpy((void *)&flow_mcam_data[pf_func_offset], (uint8_t *)&pf_func,
835 : : NPC_PF_FUNC_WIDTH);
836 : 0 : memcpy((void *)&flow_mcam_mask[pf_func_offset], (uint8_t *)&mask,
837 : : NPC_PF_FUNC_WIDTH);
838 : : }
839 [ # # ]: 0 : if (!pffunc_found)
840 : 0 : return -EINVAL;
841 : :
842 : : return 0;
843 : : }
844 : :
845 : : int
846 : 0 : npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_parse_state *pst)
847 : : {
848 : : struct npc_cn20k_mcam_write_entry_req *cn20k_req;
849 : : struct npc_cn20k_mcam_write_entry_req req;
850 : : struct nix_inl_dev *inl_dev = NULL;
851 : 0 : struct mbox *mbox = npc->mbox;
852 : : struct mbox_msghdr *rsp;
853 : : struct idev_cfg *idev;
854 : : uint16_t pf_func = 0;
855 : 0 : uint16_t ctr = ~(0);
856 : : uint32_t la_offset;
857 : : uint64_t mask;
858 : : int rc, idx;
859 : : int entry;
860 : :
861 : : PLT_SET_USED(pst);
862 : :
863 : 0 : idev = idev_get_cfg();
864 [ # # ]: 0 : if (idev)
865 : 0 : inl_dev = idev->nix_inl_dev;
866 : :
867 [ # # # # ]: 0 : if (inl_dev && inl_dev->ipsec_index) {
868 [ # # ]: 0 : if (flow->is_inline_dev)
869 : 0 : mbox = inl_dev->dev.mbox;
870 : : }
871 : :
872 [ # # ]: 0 : if (flow->use_ctr) {
873 : 0 : rc = npc_mcam_alloc_counter(mbox, &ctr);
874 [ # # ]: 0 : if (rc)
875 : : return rc;
876 : :
877 : 0 : flow->ctr_id = ctr;
878 : 0 : rc = npc_mcam_clear_counter(mbox, flow->ctr_id);
879 [ # # ]: 0 : if (rc)
880 : : return rc;
881 : : }
882 : :
883 [ # # ]: 0 : if (roc_model_is_cn20k()) {
884 : 0 : req.hw_prio = flow->priority;
885 : 0 : flow->key_type = npc_get_key_type(npc, flow);
886 : 0 : req.req_kw_type = flow->key_type;
887 : : }
888 : :
889 [ # # # # : 0 : if (flow->nix_intf == NIX_INTF_RX && flow->is_inline_dev && inl_dev &&
# # ]
890 [ # # # # ]: 0 : inl_dev->ipsec_index && inl_dev->is_multi_channel) {
891 [ # # ]: 0 : if (inl_dev->curr_ipsec_idx >= inl_dev->alloc_ipsec_rules)
892 : : return NPC_ERR_MCAM_ALLOC;
893 : 0 : entry = inl_dev->ipsec_index[inl_dev->curr_ipsec_idx];
894 : 0 : inl_dev->curr_ipsec_idx++;
895 : 0 : flow->use_pre_alloc = 1;
896 : : } else {
897 : 0 : entry = npc_get_free_mcam_entry(mbox, flow, npc);
898 [ # # ]: 0 : if (entry < 0) {
899 [ # # ]: 0 : if (flow->use_ctr)
900 : 0 : npc_mcam_free_counter(mbox, ctr);
901 : 0 : return NPC_ERR_MCAM_ALLOC;
902 : : }
903 : : }
904 : :
905 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_TX) {
906 : 0 : uint16_t pffunc = flow->tx_pf_func;
907 : :
908 [ # # ]: 0 : if (flow->has_rep)
909 : 0 : pffunc = flow->rep_pf_func;
910 : :
911 [ # # ]: 0 : pffunc = plt_cpu_to_be_16(pffunc);
912 : :
913 [ # # ]: 0 : if (roc_model_is_cn20k())
914 : 0 : rc = npc_mcam_set_pf_func_cn20k(npc, flow, pffunc);
915 : : else
916 : 0 : rc = npc_mcam_set_pf_func(npc, flow, pffunc);
917 [ # # ]: 0 : if (rc)
918 : : return rc;
919 : : }
920 : :
921 [ # # ]: 0 : if (flow->is_sampling_rule) {
922 : : /* Save and restore any mark value set */
923 : 0 : uint16_t mark = (flow->npc_action >> 40) & 0xffff;
924 : : uint16_t mce_index = 0;
925 : 0 : uint32_t rqs[2] = {};
926 : :
927 : 0 : rqs[1] = flow->recv_queue;
928 : 0 : rc = roc_nix_mcast_list_setup(npc->mbox, flow->nix_intf, 2, flow->mcast_pf_funcs,
929 : 0 : flow->mcast_channels, rqs, &flow->mcast_grp_index,
930 : : &flow->mce_start_index);
931 [ # # ]: 0 : if (rc)
932 : 0 : return rc;
933 : :
934 : : flow->npc_action = NIX_RX_ACTIONOP_MCAST;
935 : 0 : mce_index = flow->mce_start_index;
936 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_TX) {
937 : 0 : flow->npc_action |= (uint64_t)mce_index << 12;
938 : 0 : flow->npc_action |= (uint64_t)mark << 32;
939 : : } else {
940 : 0 : flow->npc_action |= (uint64_t)mce_index << 20;
941 : 0 : flow->npc_action |= (uint64_t)mark << 40;
942 : : }
943 : : }
944 : :
945 : 0 : req.cntr = flow->ctr_id;
946 : 0 : req.entry = entry;
947 : :
948 : 0 : req.intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
949 : 0 : req.enable_entry = 1;
950 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_RX)
951 : 0 : flow->npc_action |= (uint64_t)flow->recv_queue << 20;
952 : 0 : req.entry_data.action = flow->npc_action;
953 : :
954 : : /*
955 : : * Driver sets vtag action on per interface basis, not
956 : : * per flow basis. It is a matter of how we decide to support
957 : : * this pmd specific behavior. There are two ways:
958 : : * 1. Inherit the vtag action from the one configured
959 : : * for this interface. This can be read from the
960 : : * vtag_action configured for default mcam entry of
961 : : * this pf_func.
962 : : * 2. Do not support vtag action with npc_flow.
963 : : *
964 : : * Second approach is used now.
965 : : */
966 : 0 : req.entry_data.vtag_action = flow->vtag_action;
967 : :
968 [ # # ]: 0 : for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
969 : 0 : req.entry_data.kw[idx] = flow->mcam_data[idx];
970 : 0 : req.entry_data.kw_mask[idx] = flow->mcam_mask[idx];
971 : : }
972 : :
973 [ # # ]: 0 : if (flow->nix_intf == NIX_INTF_RX) {
974 [ # # # # ]: 0 : if (inl_dev && inl_dev->is_multi_channel &&
975 [ # # ]: 0 : (flow->npc_action & NIX_RX_ACTIONOP_UCAST_IPSEC)) {
976 : 0 : pf_func = nix_inl_dev_pffunc_get();
977 : 0 : req.entry_data.action &= ~(GENMASK(19, 4));
978 : 0 : req.entry_data.action |= (uint64_t)pf_func << 4;
979 : 0 : flow->npc_action &= ~(GENMASK(19, 4));
980 : 0 : flow->npc_action |= (uint64_t)pf_func << 4;
981 : :
982 : 0 : npc_mcam_set_channel(flow, &req, inl_dev->channel, inl_dev->chan_mask,
983 : : false);
984 [ # # ]: 0 : } else if (flow->has_rep) {
985 [ # # ]: 0 : pf_func = (flow->rep_act_pf_func == 0) ? flow->rep_pf_func :
986 : : flow->rep_act_pf_func;
987 : 0 : req.entry_data.action &= ~(GENMASK(19, 4));
988 : 0 : req.entry_data.action |= (uint64_t)pf_func << 4;
989 : 0 : flow->npc_action &= ~(GENMASK(19, 4));
990 : 0 : flow->npc_action |= (uint64_t)pf_func << 4;
991 : 0 : npc_mcam_set_channel(flow, &req, flow->rep_channel, (BIT_ULL(12) - 1),
992 : : false);
993 [ # # ]: 0 : } else if (npc->is_sdp_link) {
994 : 0 : npc_mcam_set_channel(flow, &req, npc->sdp_channel, npc->sdp_channel_mask,
995 : 0 : pst->is_second_pass_rule);
996 : : } else {
997 : 0 : npc_mcam_set_channel(flow, &req, npc->channel, (BIT_ULL(12) - 1),
998 : 0 : pst->is_second_pass_rule);
999 : : }
1000 : : /*
1001 : : * For second pass rule, set LA LTYPE to CPT_HDR.
1002 : : * For all other rules, set LA LTYPE to match both 1st pass and 2nd pass ltypes.
1003 : : */
1004 [ # # # # ]: 0 : if (pst->is_second_pass_rule || (!pst->is_second_pass_rule && pst->has_eth_type)) {
1005 [ # # ]: 0 : la_offset = plt_popcount32(npc->keyx_supp_nmask[flow->nix_intf] &
1006 : : ((1ULL << 9 /* LA offset */) - 1));
1007 : 0 : la_offset *= 4;
1008 : :
1009 : 0 : mask = ~((0xfULL << la_offset));
1010 : 0 : req.entry_data.kw[0] &= mask;
1011 : 0 : req.entry_data.kw_mask[0] &= mask;
1012 : 0 : flow->mcam_data[0] &= mask;
1013 : 0 : flow->mcam_mask[0] &= mask;
1014 [ # # ]: 0 : if (pst->is_second_pass_rule) {
1015 : 0 : req.entry_data.kw[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
1016 : 0 : req.entry_data.kw_mask[0] |= (0xFULL << la_offset);
1017 : 0 : flow->mcam_data[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
1018 : 0 : flow->mcam_mask[0] |= (0xFULL << la_offset);
1019 : : } else {
1020 : : /* Mask ltype ETHER (0x2) and CPT_HDR (0xa) */
1021 : 0 : req.entry_data.kw[0] |= (0x2ULL << la_offset);
1022 : 0 : req.entry_data.kw_mask[0] |= (0x7ULL << la_offset);
1023 : 0 : flow->mcam_data[0] |= (0x2ULL << la_offset);
1024 : 0 : flow->mcam_mask[0] |= (0x7ULL << la_offset);
1025 : : }
1026 : : }
1027 : : }
1028 : :
1029 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1030 : 0 : cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox_get(mbox));
1031 [ # # ]: 0 : if (cn20k_req == NULL) {
1032 : : mbox_put(mbox);
1033 [ # # ]: 0 : if (flow->use_ctr)
1034 : 0 : npc_mcam_free_counter(mbox, ctr);
1035 : :
1036 : 0 : return rc;
1037 : : }
1038 : 0 : cn20k_req->entry = req.entry;
1039 : 0 : cn20k_req->intf = req.intf;
1040 : 0 : cn20k_req->enable_entry = req.enable_entry;
1041 : 0 : cn20k_req->entry_data.action = req.entry_data.action;
1042 : 0 : cn20k_req->entry_data.vtag_action = req.entry_data.vtag_action;
1043 : 0 : cn20k_req->hw_prio = req.hw_prio;
1044 : 0 : cn20k_req->req_kw_type = req.req_kw_type;
1045 [ # # ]: 0 : if (flow->use_ctr)
1046 : 0 : cn20k_req->cntr = req.cntr;
1047 : :
1048 : 0 : mbox_memcpy(&cn20k_req->entry_data, &req.entry_data,
1049 : : sizeof(struct cn20k_mcam_entry));
1050 : : } else {
1051 : : struct npc_mcam_write_entry_req *req_leg;
1052 : :
1053 : 0 : req_leg = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
1054 [ # # ]: 0 : if (req_leg == NULL) {
1055 : : rc = -ENOSPC;
1056 : 0 : goto exit;
1057 : : }
1058 [ # # ]: 0 : for (idx = 0; idx < NPC_MAX_KWS_IN_KEY; idx++) {
1059 : 0 : req_leg->entry_data.kw[idx] = req.entry_data.kw[idx];
1060 : 0 : req_leg->entry_data.kw_mask[idx] = req.entry_data.kw_mask[idx];
1061 : : }
1062 : 0 : req_leg->entry = req.entry;
1063 : 0 : req_leg->intf = req.intf;
1064 : 0 : req_leg->enable_entry = req.enable_entry;
1065 : 0 : req_leg->cntr = req.cntr;
1066 : 0 : req_leg->entry_data.action = req.entry_data.action;
1067 : 0 : req_leg->entry_data.vtag_action = req.entry_data.vtag_action;
1068 : 0 : req_leg->set_cntr = flow->use_ctr;
1069 : : }
1070 : : rc = mbox_process_msg(mbox, (void *)&rsp);
1071 [ # # ]: 0 : if (rc != 0)
1072 : 0 : goto exit;
1073 : :
1074 : 0 : flow->mcam_id = entry;
1075 : :
1076 [ # # ]: 0 : if (flow->use_ctr)
1077 : 0 : flow->ctr_id = ctr;
1078 : : rc = 0;
1079 : :
1080 : 0 : exit:
1081 : : mbox_put(mbox);
1082 [ # # # # ]: 0 : if (rc && flow->is_sampling_rule)
1083 : 0 : roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
1084 : : return rc;
1085 : : }
1086 : :
1087 : : static void
1088 [ # # ]: 0 : npc_set_vlan_ltype(struct npc_parse_state *pst)
1089 : : {
1090 : : uint64_t val, mask;
1091 : : uint8_t lb_offset;
1092 : :
1093 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1094 : 0 : lb_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1095 : : ((1ULL << NPC_CN20K_LTYPE_LB_OFFSET) - 1));
1096 : :
1097 : : } else {
1098 : 0 : lb_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1099 : : ((1ULL << NPC_LTYPE_LB_OFFSET) - 1));
1100 : : }
1101 : 0 : lb_offset *= 4;
1102 : :
1103 : 0 : mask = ~((0xfULL << lb_offset));
1104 : 0 : pst->flow->mcam_data[0] &= mask;
1105 : 0 : pst->flow->mcam_mask[0] &= mask;
1106 : : /* NPC_LT_LB_CTAG: 0b0010, NPC_LT_LB_STAG_QINQ: 0b0011
1107 : : * Set LB layertype/mask as 0b0010/0b1110 to match both.
1108 : : */
1109 : 0 : val = ((uint64_t)(NPC_LT_LB_CTAG & NPC_LT_LB_STAG_QINQ)) << lb_offset;
1110 : 0 : pst->flow->mcam_data[0] |= val;
1111 : 0 : pst->flow->mcam_mask[0] |= (0xeULL << lb_offset);
1112 : 0 : }
1113 : :
1114 : : static void
1115 [ # # ]: 0 : npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
1116 : : {
1117 : : uint8_t lc_offset, lcflag_offset;
1118 : : uint64_t val, mask;
1119 : :
1120 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1121 : 0 : lc_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1122 : : ((1ULL << NPC_CN20K_LTYPE_LC_OFFSET) - 1));
1123 : :
1124 : : } else {
1125 : 0 : lc_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1126 : : ((1ULL << NPC_LTYPE_LC_OFFSET) - 1));
1127 : : }
1128 : 0 : lc_offset *= 4;
1129 : :
1130 : 0 : mask = ~((0xfULL << lc_offset));
1131 : 0 : pst->flow->mcam_data[0] &= mask;
1132 : 0 : pst->flow->mcam_mask[0] &= mask;
1133 : : /* NPC_LT_LC_IP6: 0b0100, NPC_LT_LC_IP6_EXT: 0b0101
1134 : : * Set LC layertype/mask as 0b0100/0b1110 to match both.
1135 : : */
1136 : 0 : val = ((uint64_t)(NPC_LT_LC_IP6 & NPC_LT_LC_IP6_EXT)) << lc_offset;
1137 : 0 : pst->flow->mcam_data[0] |= val;
1138 : 0 : pst->flow->mcam_mask[0] |= (0xeULL << lc_offset);
1139 : :
1140 : : /* If LC LFLAG is non-zero, set the LC LFLAG mask to 0xF. In general
1141 : : * case flag mask is set same as the value in data. For example, to
1142 : : * match 3 VLANs, flags have to match a range of values. But, for IPv6
1143 : : * extended attributes matching, we need an exact match. Hence, set the
1144 : : * mask as 0xF. This is done only if LC LFLAG value is non-zero,
1145 : : * because for AH and ESP, LC LFLAG is zero and we don't want to match
1146 : : * zero in LFLAG.
1147 : : */
1148 [ # # ]: 0 : if (pst->npc->keyx_supp_nmask[pst->nix_intf] & (1ULL << NPC_LFLAG_LC_OFFSET)) {
1149 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1150 : 0 : lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1151 : : ((1ULL << NPC_CN20K_LFLAG_LC_OFFSET) - 1));
1152 : :
1153 : : } else {
1154 : 0 : lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
1155 : : ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
1156 : : }
1157 : 0 : lcflag_offset *= 4;
1158 : :
1159 : 0 : mask = (0xfULL << lcflag_offset);
1160 : 0 : val = pst->flow->mcam_data[0] & mask;
1161 [ # # ]: 0 : if (val)
1162 : 0 : pst->flow->mcam_mask[0] |= mask;
1163 : : }
1164 : 0 : }
1165 : :
1166 : : int
1167 : 0 : npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
1168 : : {
1169 : : /* This is non-LDATA part in search key */
1170 : 0 : uint64_t key_data[2] = {0ULL, 0ULL};
1171 : 0 : uint64_t key_mask[2] = {0ULL, 0ULL};
1172 : : int key_len, bit = 0, index, rc = 0;
1173 : : struct nix_inl_dev *inl_dev = NULL;
1174 : 0 : int intf = pst->flow->nix_intf;
1175 : : bool skip_base_rule = false;
1176 : : int off, idx, data_off = 0;
1177 : : uint8_t lid, mask, data;
1178 : : struct idev_cfg *idev;
1179 : : uint16_t layer_info;
1180 : : uint64_t lt, flags;
1181 : : struct mbox *mbox;
1182 : :
1183 : : /* Skip till Layer A data start */
1184 [ # # ]: 0 : while (bit < NPC_PARSE_KEX_S_LA_OFFSET) {
1185 [ # # ]: 0 : if (npc->keyx_supp_nmask[intf] & (1 << bit))
1186 : 0 : data_off++;
1187 : 0 : bit++;
1188 : : }
1189 : :
1190 : : /* Each bit represents 1 nibble */
1191 [ # # ]: 0 : data_off *= 4;
1192 : :
1193 : : index = 0;
1194 [ # # ]: 0 : if (!roc_model_is_cn20k()) {
1195 [ # # ]: 0 : for (lid = 0; lid < NPC_MAX_LID; lid++) {
1196 : : /* Offset in key */
1197 : 0 : off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
1198 : 0 : lt = pst->lt[lid] & 0xf;
1199 : 0 : flags = pst->flags[lid] & 0xff;
1200 : :
1201 : : /* NPC_LAYER_KEX_S */
1202 : 0 : layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
1203 [ # # ]: 0 : if (!layer_info)
1204 : 0 : continue;
1205 : :
1206 [ # # ]: 0 : for (idx = 0; idx <= 2; idx++) {
1207 [ # # ]: 0 : if (!(layer_info & (1 << idx)))
1208 : 0 : continue;
1209 : :
1210 [ # # ]: 0 : if (idx == 2) {
1211 : : data = lt;
1212 : : mask = 0xf;
1213 [ # # ]: 0 : } else if (idx == 1) {
1214 : 0 : data = ((flags >> 4) & 0xf);
1215 : : mask = ((flags >> 4) & 0xf);
1216 : : } else {
1217 : 0 : data = (flags & 0xf);
1218 : : mask = (flags & 0xf);
1219 : : }
1220 : :
1221 [ # # ]: 0 : if (data_off >= 64) {
1222 : : data_off = 0;
1223 : 0 : index++;
1224 : : }
1225 : 0 : key_data[index] |= ((uint64_t)data << data_off);
1226 : :
1227 [ # # ]: 0 : if (lt == 0)
1228 : : mask = 0;
1229 : 0 : key_mask[index] |= ((uint64_t)mask << data_off);
1230 : 0 : data_off += 4;
1231 : : }
1232 : : }
1233 : : } else {
1234 [ # # ]: 0 : for (lid = 0; lid < NPC_MAX_LID; lid++) {
1235 : : /* Offset in key */
1236 : 0 : off = NPC_PARSE_KEX_S_LID_OFFSET_CN20K(lid);
1237 : 0 : lt = pst->lt[lid] & 0xf;
1238 : 0 : flags = pst->flags[lid] & 0xf;
1239 : :
1240 : : /* NPC_LAYER_KEX_S */
1241 : 0 : layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x3);
1242 [ # # ]: 0 : if (!layer_info)
1243 : 0 : continue;
1244 : :
1245 [ # # ]: 0 : for (idx = 0; idx <= 1; idx++) {
1246 [ # # ]: 0 : if (!(layer_info & (1 << idx)))
1247 : 0 : continue;
1248 : :
1249 [ # # ]: 0 : if (idx == 1) {
1250 : : data = lt;
1251 : : mask = 0xf;
1252 : : } else {
1253 : : data = (flags & 0xf);
1254 : : mask = (flags & 0xf);
1255 : : }
1256 : :
1257 [ # # ]: 0 : if (data_off >= 64) {
1258 : : data_off = 0;
1259 : 0 : index++;
1260 : : }
1261 : 0 : key_data[index] |= ((uint64_t)data << data_off);
1262 : :
1263 [ # # ]: 0 : if (lt == 0)
1264 : : mask = 0;
1265 : 0 : key_mask[index] |= ((uint64_t)mask << data_off);
1266 : 0 : data_off += 4;
1267 : : }
1268 : : }
1269 : : }
1270 : :
1271 : : /* Copy this into mcam string */
1272 : 0 : key_len = (pst->npc->keyx_len[intf] + 7) / 8;
1273 [ # # ]: 0 : memcpy(pst->flow->mcam_data, key_data, key_len);
1274 : 0 : memcpy(pst->flow->mcam_mask, key_mask, key_len);
1275 : :
1276 [ # # ]: 0 : if (pst->set_vlan_ltype_mask)
1277 : 0 : npc_set_vlan_ltype(pst);
1278 : :
1279 [ # # ]: 0 : if (pst->set_ipv6ext_ltype_mask)
1280 : 0 : npc_set_ipv6ext_ltype_mask(pst);
1281 : :
1282 : 0 : idev = idev_get_cfg();
1283 [ # # ]: 0 : if (idev)
1284 : 0 : inl_dev = idev->nix_inl_dev;
1285 [ # # # # ]: 0 : if (inl_dev && inl_dev->is_multi_channel &&
1286 [ # # ]: 0 : (pst->flow->npc_action & NIX_RX_ACTIONOP_UCAST_IPSEC))
1287 : : skip_base_rule = true;
1288 : :
1289 [ # # # # : 0 : if ((pst->is_vf || pst->flow->is_rep_vf) && pst->flow->nix_intf == NIX_INTF_RX &&
# # # # ]
1290 : : !skip_base_rule) {
1291 [ # # ]: 0 : if (pst->flow->has_rep)
1292 : 0 : mbox = mbox_get(pst->flow->rep_mbox);
1293 : : else
1294 : 0 : mbox = mbox_get(npc->mbox);
1295 : 0 : (void)mbox_alloc_msg_npc_read_base_steer_rule(mbox);
1296 [ # # ]: 0 : if (roc_model_is_cn20k()) {
1297 : : struct npc_cn20k_mcam_read_base_rule_rsp *base_rule_rsp;
1298 : : struct cn20k_mcam_entry *base_entry;
1299 : :
1300 : : rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
1301 [ # # ]: 0 : if (rc) {
1302 : : mbox_put(mbox);
1303 : 0 : plt_err("Failed to fetch VF's base MCAM entry");
1304 : 0 : return rc;
1305 : : }
1306 : : mbox_put(mbox);
1307 : 0 : base_entry = &base_rule_rsp->entry;
1308 [ # # ]: 0 : for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
1309 : 0 : pst->flow->mcam_data[idx] |= base_entry->kw[idx];
1310 : 0 : pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
1311 : : }
1312 : :
1313 : : } else {
1314 : : struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
1315 : : struct mcam_entry *base_entry;
1316 : :
1317 : : rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
1318 [ # # ]: 0 : if (rc) {
1319 : : mbox_put(mbox);
1320 : 0 : plt_err("Failed to fetch VF's base MCAM entry");
1321 : 0 : return rc;
1322 : : }
1323 : : mbox_put(mbox);
1324 : 0 : base_entry = &base_rule_rsp->entry_data;
1325 [ # # ]: 0 : for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
1326 : 0 : pst->flow->mcam_data[idx] |= base_entry->kw[idx];
1327 : 0 : pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
1328 : : }
1329 : : }
1330 : : }
1331 : :
1332 : : /*
1333 : : * Now we have mcam data and mask formatted as
1334 : : * [Key_len/4 nibbles][0 or 1 nibble hole][data]
1335 : : * hole is present if key_len is odd number of nibbles.
1336 : : * mcam data must be split into 64 bits + 48 bits segments
1337 : : * for each back W0, W1.
1338 : : */
1339 : :
1340 [ # # ]: 0 : if (mcam_alloc)
1341 : 0 : return npc_mcam_alloc_and_write(npc, pst->flow, pst);
1342 : : else
1343 : : return 0;
1344 : : }
1345 : :
1346 : : int
1347 : 0 : npc_flow_enable_all_entries(struct npc *npc, bool enable)
1348 : : {
1349 : : struct nix_inl_dev *inl_dev;
1350 : : struct npc_flow_list *list;
1351 : : struct roc_npc_flow *flow;
1352 : : struct idev_cfg *idev;
1353 : : int rc = 0, idx;
1354 : :
1355 : : /* Free any MCAM counters and delete flow list */
1356 [ # # ]: 0 : for (idx = 0; idx < npc->flow_max_priority; idx++) {
1357 : 0 : list = &npc->flow_list[idx];
1358 [ # # ]: 0 : TAILQ_FOREACH(flow, list, next) {
1359 : 0 : flow->enable = enable;
1360 : 0 : rc = npc_mcam_write_entry(npc->mbox, flow);
1361 [ # # ]: 0 : if (rc)
1362 : 0 : return rc;
1363 : : }
1364 : : }
1365 : :
1366 : : list = &npc->ipsec_list;
1367 : 0 : idev = idev_get_cfg();
1368 [ # # ]: 0 : if (!idev)
1369 : : return 0;
1370 : 0 : inl_dev = idev->nix_inl_dev;
1371 : :
1372 [ # # ]: 0 : if (inl_dev) {
1373 [ # # ]: 0 : TAILQ_FOREACH(flow, list, next) {
1374 : 0 : flow->enable = enable;
1375 : 0 : rc = npc_mcam_write_entry(inl_dev->dev.mbox, flow);
1376 [ # # ]: 0 : if (rc)
1377 : 0 : return rc;
1378 : : }
1379 : : }
1380 : : return rc;
1381 : : }
1382 : :
1383 : : int
1384 : 0 : npc_flow_free_all_resources(struct npc *npc)
1385 : : {
1386 : : struct roc_npc_flow *flow;
1387 : : int rc, idx;
1388 : :
1389 : : /* Free all MCAM entries allocated */
1390 : 0 : rc = npc_mcam_free_all_entries(npc);
1391 : :
1392 : : /* Free any MCAM counters and delete flow list */
1393 [ # # ]: 0 : for (idx = 0; idx < npc->flow_max_priority; idx++) {
1394 [ # # ]: 0 : while ((flow = TAILQ_FIRST(&npc->flow_list[idx])) != NULL) {
1395 : 0 : npc_rss_group_free(npc, flow);
1396 [ # # ]: 0 : if (flow->ctr_id != NPC_COUNTER_NONE) {
1397 : 0 : rc |= npc_mcam_clear_counter(npc->mbox, flow->ctr_id);
1398 : 0 : rc |= npc_mcam_free_counter(npc->mbox, flow->ctr_id);
1399 : : }
1400 : :
1401 [ # # ]: 0 : if (flow->is_sampling_rule)
1402 : 0 : roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
1403 : :
1404 : 0 : npc_delete_prio_list_entry(npc, flow);
1405 : :
1406 [ # # ]: 0 : TAILQ_REMOVE(&npc->flow_list[idx], flow, next);
1407 : 0 : plt_free(flow);
1408 : : }
1409 : : }
1410 : 0 : return rc;
1411 : : }
|