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