Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include <eal_export.h>
6 : : #include <rte_pmd_cnxk.h>
7 : :
8 : : #include <cnxk_ethdev.h>
9 : : #include <cnxk_mempool.h>
10 : :
11 : : #define CNXK_NIX_INL_META_POOL_NAME "NIX_INL_META_POOL"
12 : : #define CN10K_HW_POOL_OPS_NAME "cn10k_hwpool_ops"
13 : :
14 : : #define CNXK_NIX_INL_SELFTEST "selftest"
15 : : #define CNXK_NIX_INL_IPSEC_IN_MIN_SPI "ipsec_in_min_spi"
16 : : #define CNXK_NIX_INL_IPSEC_IN_MAX_SPI "ipsec_in_max_spi"
17 : : #define CNXK_INL_CPT_CHANNEL "inl_cpt_channel"
18 : : #define CNXK_NIX_INL_NB_META_BUFS "nb_meta_bufs"
19 : : #define CNXK_NIX_INL_META_BUF_SZ "meta_buf_sz"
20 : : #define CNXK_NIX_SOFT_EXP_POLL_FREQ "soft_exp_poll_freq"
21 : : #define CNXK_MAX_IPSEC_RULES "max_ipsec_rules"
22 : : #define CNXK_NIX_INL_RX_INJ_ENABLE "rx_inj_ena"
23 : : #define CNXK_NIX_CUSTOM_INB_SA "custom_inb_sa"
24 : : #define CNXK_NIX_NB_INL_INB_QS "nb_inl_inb_qs"
25 : : #define CNXK_NIX_INL_CPT_CQ_ENABLE "cpt_cq_enable"
26 : :
27 : : /* Default soft expiry poll freq in usec */
28 : : #define CNXK_NIX_SOFT_EXP_POLL_FREQ_DFLT 100
29 : :
30 : : struct inl_cpt_channel {
31 : : bool is_multi_channel;
32 : : uint16_t channel;
33 : : uint16_t mask;
34 : : };
35 : :
36 : : #define CNXK_NIX_INL_DEV_NAME RTE_STR(cnxk_nix_inl_dev_)
37 : : #define CNXK_NIX_INL_DEV_NAME_LEN \
38 : : (sizeof(CNXK_NIX_INL_DEV_NAME) + PCI_PRI_STR_SIZE)
39 : :
40 : : struct cnxk_ethdev_pmd_ops cnxk_pmd_ops;
41 : :
42 : : static inline int
43 : : bitmap_ctzll(uint64_t slab)
44 : : {
45 : 0 : if (slab == 0)
46 : : return 0;
47 : :
48 : 0 : return rte_ctz64(slab);
49 : : }
50 : :
51 : : int
52 : 0 : cnxk_nix_inl_meta_pool_cb(uint64_t *aura_handle, uintptr_t *mpool, uint32_t buf_sz,
53 : : uint32_t nb_bufs, bool destroy, const char *mempool_name)
54 : : {
55 : : const char *mp_name = NULL;
56 : : struct rte_pktmbuf_pool_private mbp_priv;
57 : : struct rte_mempool *mp;
58 : : uint16_t first_skip;
59 : : int rc;
60 : :
61 : : /* Null Mempool name indicates to allocate Zero aura. */
62 [ # # ]: 0 : if (!mempool_name)
63 : : mp_name = CNXK_NIX_INL_META_POOL_NAME;
64 : : else
65 : : mp_name = mempool_name;
66 : :
67 : : /* Destroy the mempool if requested */
68 [ # # ]: 0 : if (destroy) {
69 : 0 : mp = rte_mempool_lookup(mp_name);
70 [ # # ]: 0 : if (!mp)
71 : : return -ENOENT;
72 : :
73 [ # # ]: 0 : if (mp->pool_id != *aura_handle) {
74 : 0 : plt_err("Meta pool aura mismatch");
75 : 0 : return -EINVAL;
76 : : }
77 : :
78 : 0 : rte_mempool_free(mp);
79 : :
80 : 0 : *aura_handle = 0;
81 : 0 : *mpool = 0;
82 : 0 : return 0;
83 : : }
84 : :
85 : : /* Need to make it similar to rte_pktmbuf_pool() for sake of OOP
86 : : * support.
87 : : */
88 : 0 : mp = rte_mempool_create_empty(mp_name, nb_bufs, buf_sz, 0,
89 : : sizeof(struct rte_pktmbuf_pool_private),
90 : : SOCKET_ID_ANY, 0);
91 [ # # ]: 0 : if (!mp) {
92 : 0 : plt_err("Failed to create inline meta pool");
93 : 0 : return -EIO;
94 : : }
95 : :
96 [ # # ]: 0 : rc = rte_mempool_set_ops_byname(mp, rte_mbuf_platform_mempool_ops(),
97 : : mempool_name ?
98 : : NULL : PLT_PTR_CAST(CNXK_MEMPOOL_F_ZERO_AURA));
99 [ # # ]: 0 : if (rc) {
100 : 0 : plt_err("Failed to setup mempool ops for meta, rc=%d", rc);
101 : 0 : goto free_mp;
102 : : }
103 : :
104 : : /* Init mempool private area */
105 : : first_skip = sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM;
106 : : memset(&mbp_priv, 0, sizeof(mbp_priv));
107 : 0 : mbp_priv.mbuf_data_room_size = (buf_sz - first_skip +
108 : : RTE_PKTMBUF_HEADROOM);
109 : 0 : rte_pktmbuf_pool_init(mp, &mbp_priv);
110 : :
111 : : /* Populate buffer */
112 : 0 : rc = rte_mempool_populate_default(mp);
113 [ # # ]: 0 : if (rc < 0) {
114 : 0 : plt_err("Failed to create inline meta pool, rc=%d", rc);
115 : 0 : goto free_mp;
116 : : }
117 : :
118 : 0 : rte_mempool_obj_iter(mp, rte_pktmbuf_init, NULL);
119 : 0 : *aura_handle = mp->pool_id;
120 : 0 : *mpool = (uintptr_t)mp;
121 : 0 : return 0;
122 : 0 : free_mp:
123 : 0 : rte_mempool_free(mp);
124 : 0 : return rc;
125 : : }
126 : :
127 : : /* Create Aura and link with Global mempool for 1:N Pool:Aura case */
128 : : int
129 : 0 : cnxk_nix_inl_custom_meta_pool_cb(uintptr_t pmpool, uintptr_t *mpool, const char *mempool_name,
130 : : uint64_t *aura_handle, uint32_t buf_sz, uint32_t nb_bufs,
131 : : bool destroy)
132 : : {
133 : : struct rte_mempool *hp;
134 : : int rc;
135 : :
136 : : /* Destroy the mempool if requested */
137 [ # # ]: 0 : if (destroy) {
138 : 0 : hp = rte_mempool_lookup(mempool_name);
139 [ # # ]: 0 : if (!hp)
140 : : return -ENOENT;
141 : :
142 [ # # ]: 0 : if (hp->pool_id != *aura_handle) {
143 : 0 : plt_err("Meta pool aura mismatch");
144 : 0 : return -EINVAL;
145 : : }
146 : :
147 : 0 : plt_free(hp->pool_config);
148 : 0 : rte_mempool_free(hp);
149 : :
150 : 0 : *aura_handle = 0;
151 : 0 : *mpool = 0;
152 : 0 : return 0;
153 : : }
154 : :
155 : : /* Need to make it similar to rte_pktmbuf_pool() for sake of OOP
156 : : * support.
157 : : */
158 : 0 : hp = rte_mempool_create_empty(mempool_name, nb_bufs, buf_sz, 0,
159 : : sizeof(struct rte_pktmbuf_pool_private),
160 : : SOCKET_ID_ANY, 0);
161 [ # # ]: 0 : if (!hp) {
162 : 0 : plt_err("Failed to create inline meta pool");
163 : 0 : return -EIO;
164 : : }
165 : :
166 : 0 : rc = rte_mempool_set_ops_byname(hp, CN10K_HW_POOL_OPS_NAME, (void *)pmpool);
167 : :
168 [ # # ]: 0 : if (rc) {
169 : 0 : plt_err("Failed to setup ops, rc=%d", rc);
170 : 0 : goto free_hp;
171 : : }
172 : :
173 : : /* Populate buffer */
174 : 0 : rc = rte_mempool_populate_default(hp);
175 [ # # ]: 0 : if (rc < 0) {
176 : 0 : plt_err("Failed to populate pool, rc=%d", rc);
177 : 0 : goto free_hp;
178 : : }
179 : :
180 : 0 : *aura_handle = hp->pool_id;
181 : 0 : *mpool = (uintptr_t)hp;
182 : 0 : return 0;
183 : 0 : free_hp:
184 : 0 : rte_mempool_free(hp);
185 : 0 : return rc;
186 : : }
187 : :
188 : : static int
189 : 0 : parse_max_ipsec_rules(const char *key, const char *value, void *extra_args)
190 : : {
191 : : RTE_SET_USED(key);
192 : : uint32_t val;
193 : :
194 : 0 : val = atoi(value);
195 : :
196 [ # # ]: 0 : if (val < 1 || val > 4095)
197 : : return -EINVAL;
198 : :
199 : 0 : *(uint32_t *)extra_args = val;
200 : :
201 : 0 : return 0;
202 : : }
203 : :
204 : : static int
205 : 0 : parse_val_u8(const char *key, const char *value, void *extra_args)
206 : : {
207 : : RTE_SET_USED(key);
208 : : uint32_t val;
209 : :
210 : 0 : val = atoi(value);
211 : :
212 : 0 : *(uint8_t *)extra_args = !!(val == 1);
213 : :
214 : 0 : return 0;
215 : : }
216 : :
217 : : int
218 : 0 : cnxk_eth_outb_sa_idx_get(struct cnxk_eth_dev *dev, uint32_t *idx_p,
219 : : uint32_t spi)
220 : : {
221 : : uint32_t pos, idx;
222 : : uint64_t slab;
223 : : int rc;
224 : :
225 [ # # ]: 0 : if (!dev->outb.sa_bmap)
226 : : return -ENOTSUP;
227 : :
228 : 0 : pos = 0;
229 [ # # ]: 0 : slab = 0;
230 : : /* Scan from the beginning */
231 : : plt_bitmap_scan_init(dev->outb.sa_bmap);
232 : :
233 [ # # ]: 0 : if (dev->nix.custom_sa_action) {
234 [ # # ]: 0 : if (spi > dev->outb.max_sa)
235 : : return -ENOTSUP;
236 : : idx = spi;
237 [ # # ]: 0 : if (!plt_bitmap_get(dev->outb.sa_bmap, idx)) {
238 : 0 : plt_err("Outbound SA index %u already in use", idx);
239 : 0 : return -EEXIST;
240 : : }
241 : : } else {
242 : : /* Scan bitmap to get the free sa index */
243 : 0 : rc = plt_bitmap_scan(dev->outb.sa_bmap, &pos, &slab);
244 : : /* Empty bitmap */
245 [ # # ]: 0 : if (rc == 0) {
246 : 0 : plt_err("Outbound SA' exhausted, use 'ipsec_out_max_sa' "
247 : : "devargs to increase");
248 : 0 : return -ERANGE;
249 : : }
250 : :
251 : : /* Get free SA index */
252 [ # # ]: 0 : idx = pos + bitmap_ctzll(slab);
253 : : }
254 : 0 : plt_bitmap_clear(dev->outb.sa_bmap, idx);
255 : 0 : *idx_p = idx;
256 : 0 : return 0;
257 : : }
258 : :
259 : : int
260 : 0 : cnxk_eth_outb_sa_idx_put(struct cnxk_eth_dev *dev, uint32_t idx)
261 : : {
262 [ # # ]: 0 : if (idx >= dev->outb.max_sa)
263 : : return -EINVAL;
264 : :
265 : : /* Check if it is already free */
266 [ # # ]: 0 : if (plt_bitmap_get(dev->outb.sa_bmap, idx))
267 : : return -EINVAL;
268 : :
269 : : /* Mark index as free */
270 : 0 : plt_bitmap_set(dev->outb.sa_bmap, idx);
271 : 0 : return 0;
272 : : }
273 : :
274 : : struct cnxk_eth_sec_sess *
275 : 0 : cnxk_eth_sec_sess_get_by_sa_idx(struct cnxk_eth_dev *dev, uint32_t sa_idx, bool inb)
276 : : {
277 : : struct cnxk_eth_sec_sess_list *list;
278 : : struct cnxk_eth_sec_sess *eth_sec;
279 : :
280 [ # # ]: 0 : list = inb ? &dev->inb.list : &dev->outb.list;
281 [ # # ]: 0 : TAILQ_FOREACH(eth_sec, list, entry) {
282 [ # # ]: 0 : if (eth_sec->sa_idx == sa_idx)
283 : 0 : return eth_sec;
284 : : }
285 : :
286 : : return NULL;
287 : : }
288 : :
289 : : struct cnxk_eth_sec_sess *
290 : 0 : cnxk_eth_sec_sess_get_by_sess(struct cnxk_eth_dev *dev, const struct rte_security_session *sess)
291 : : {
292 : : struct cnxk_eth_sec_sess *eth_sec = NULL;
293 : :
294 : : /* Search in inbound list */
295 [ # # ]: 0 : TAILQ_FOREACH(eth_sec, &dev->inb.list, entry) {
296 [ # # ]: 0 : if (eth_sec->sess == sess)
297 : 0 : return eth_sec;
298 : : }
299 : :
300 : : /* Search in outbound list */
301 [ # # ]: 0 : TAILQ_FOREACH(eth_sec, &dev->outb.list, entry) {
302 [ # # ]: 0 : if (eth_sec->sess == sess)
303 : 0 : return eth_sec;
304 : : }
305 : :
306 : : return NULL;
307 : : }
308 : :
309 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_inl_dev_submit, 23.11)
310 : : uint16_t
311 : 0 : rte_pmd_cnxk_inl_dev_submit(struct rte_pmd_cnxk_inl_dev_q *qptr, void *inst, uint16_t nb_inst)
312 : : {
313 : 0 : return cnxk_pmd_ops.inl_dev_submit((struct roc_nix_inl_dev_q *)qptr, inst, nb_inst);
314 : : }
315 : :
316 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_inl_dev_qptr_get, 23.11)
317 : : struct rte_pmd_cnxk_inl_dev_q *
318 : 0 : rte_pmd_cnxk_inl_dev_qptr_get(void)
319 : : {
320 : 0 : return roc_nix_inl_dev_qptr_get(0);
321 : : }
322 : :
323 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_cpt_q_stats_get, 23.11)
324 : : int
325 : 0 : rte_pmd_cnxk_cpt_q_stats_get(uint16_t portid, enum rte_pmd_cnxk_cpt_q_stats_type type,
326 : : struct rte_pmd_cnxk_cpt_q_stats *stats, uint16_t idx)
327 : : {
328 : 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
329 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
330 : :
331 : 0 : return roc_nix_inl_cpt_lf_stats_get(&dev->nix, (enum roc_nix_cpt_lf_stats_type)type,
332 : : (struct roc_nix_cpt_lf_stats *)stats, idx);
333 : : }
334 : :
335 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_hw_session_base_get, 23.11)
336 : : union rte_pmd_cnxk_ipsec_hw_sa *
337 : 0 : rte_pmd_cnxk_hw_session_base_get(uint16_t portid, bool inb)
338 : : {
339 [ # # ]: 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
340 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
341 : : uintptr_t sa_base;
342 : :
343 [ # # ]: 0 : if (inb)
344 : 0 : sa_base = roc_nix_inl_inb_sa_base_get(&dev->nix, dev->inb.inl_dev);
345 : : else
346 : 0 : sa_base = roc_nix_inl_outb_sa_base_get(&dev->nix);
347 : :
348 : 0 : return (union rte_pmd_cnxk_ipsec_hw_sa *)sa_base;
349 : : }
350 : :
351 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_inl_inb_prof_sa_base_get, 25.11)
352 : : union rte_pmd_cnxk_ipsec_hw_sa *
353 : 0 : rte_pmd_cnxk_inl_inb_prof_sa_base_get(uint16_t portid, uint16_t profile_id)
354 : : {
355 : : struct rte_eth_dev *eth_dev;
356 : : struct cnxk_eth_dev *dev;
357 : : uintptr_t sa_base;
358 : :
359 [ # # ]: 0 : if (!rte_eth_dev_is_valid_port(portid))
360 : : return NULL;
361 : :
362 : : eth_dev = &rte_eth_devices[portid];
363 : : dev = cnxk_eth_pmd_priv(eth_dev);
364 : :
365 : 0 : sa_base = roc_nix_inl_inb_prof_sa_base_get(&dev->nix, !dev->inb.no_inl_dev, profile_id);
366 : :
367 [ # # ]: 0 : if (!sa_base)
368 : : return NULL;
369 : :
370 : 0 : return (union rte_pmd_cnxk_ipsec_hw_sa *)sa_base;
371 : : }
372 : :
373 : : static uint64_t
374 : 0 : cnxk_rx_def_inl_cfg_pack(const struct rte_pmd_cnxk_rx_def_inl_cfg *cfg)
375 : : {
376 : : uint64_t val = 0;
377 : :
378 : 0 : val |= PACK(cfg->ltype_mask, NIX_LTYPE_MASK_SHIFT, 4);
379 : 0 : val |= PACK(cfg->ltype_match, NIX_LTYPE_MATCH_SHIFT, 4);
380 : 0 : val |= PACK(cfg->lid, NIX_LID_SHIFT, 3);
381 : 0 : val |= PACK(cfg->gen_offset_ng, NIX_GEN_OFFSET_NG_SHIFT, 1);
382 : 0 : val |= PACK(cfg->gen_offset, NIX_GEN_OFFSET_SHIFT, 4);
383 : 0 : val |= PACK(cfg->gen_nz, NIX_GEN_NZ_SHIFT, 1);
384 : 0 : val |= PACK(cfg->cpt_l3_lid, NIX_CPT_L3_LID_SHIFT, 3);
385 : 0 : val |= PACK(cfg->flags_mask, NIX_FLAGS_MASK_SHIFT, 4);
386 : 0 : val |= PACK(cfg->flags_match, NIX_FLAGS_MATCH_SHIFT, 4);
387 : 0 : val |= PACK(cfg->match_oipv4, NIX_MATCH_OIPV4_SHIFT, 1);
388 : 0 : val |= PACK(cfg->match_oipv6, NIX_MATCH_OIPV6_SHIFT, 1);
389 : 0 : val |= PACK(cfg->oiplen_ena, NIX_OIPLEN_ENA_SHIFT, 1);
390 : 0 : val |= PACK(cfg->inline_shift, NIX_INLINE_SHIFT_SHIFT, 2);
391 : :
392 : 0 : return val;
393 : : }
394 : :
395 : : static uint64_t
396 : : cnxk_rx_gen_inl_cfg_pack(const struct rte_pmd_cnxk_rx_gen_inl_cfg *cfg)
397 : : {
398 : : uint64_t val = 0;
399 : :
400 : : /* CPT instruction fields */
401 : 0 : val |= PACK(cfg->param2, NIX_PARAM2_SHIFT, 16);
402 : 0 : val |= PACK(cfg->param1, NIX_PARAM1_SHIFT, 16);
403 : 0 : val |= PACK(cfg->opcode, NIX_OPCODE_SHIFT, 16);
404 : 0 : val |= PACK(cfg->egrp, NIX_EGRP_SHIFT, 3);
405 : 0 : val |= PACK(cfg->ctx_val, NIX_CTX_VAL_SHIFT, 1);
406 : :
407 : : return val;
408 : : }
409 : :
410 : : static uint64_t
411 : 0 : cnxk_rx_extract_inl_cfg_pack(const struct rte_pmd_cnxk_rx_extract_inl_cfg *cfg)
412 : : {
413 : : uint64_t val = 0;
414 : :
415 : 0 : val |= PACK(cfg->len_l, NIX_LEN_L_SHIFT, 6);
416 : 0 : val |= PACK(cfg->bitpos_l, NIX_BITPOS_L_SHIFT, 6);
417 : 0 : val |= PACK(cfg->len_m, NIX_LEN_M_SHIFT, 6);
418 : 0 : val |= PACK(cfg->bitpos_m, NIX_BITPOS_M_SHIFT, 6);
419 : 0 : val |= PACK(cfg->len_h, NIX_LEN_H_SHIFT, 6);
420 : 0 : val |= PACK(cfg->bitpos_h, NIX_BITPOS_H_SHIFT, 6);
421 : :
422 : 0 : return val;
423 : : }
424 : :
425 : : static uint64_t
426 : : cnxk_rx_prot_field_inline_cfg_pack(const struct rte_pmd_cnxk_rx_prot_field_inl_cfg *cfg)
427 : : {
428 : : uint64_t val = 0;
429 : :
430 : 0 : val |= PACK(cfg->valid, NIX_VALID_SHIFT, 1);
431 : 0 : val |= PACK(cfg->offset, NIX_OFFSET_SHIFT, 6);
432 : 0 : val |= PACK(cfg->sizem1, NIX_SIZEM1_SHIFT, 4);
433 : 0 : val |= PACK(cfg->logmult, NIX_LOGMULT_SHIFT, 2);
434 : :
435 : : return val;
436 : : }
437 : :
438 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_nix_inl_custom_profile_setup, 25.11)
439 : : int
440 : 0 : rte_pmd_cnxk_nix_inl_custom_profile_setup(uint16_t portid,
441 : : const struct rte_pmd_cnxk_profile_cfg_params *cfg,
442 : : uint16_t *profile_id)
443 : : {
444 : 0 : uint64_t prot_field_cfg_val[RTE_PMD_CNXK_MAX_PROT_FIELDS] = {0};
445 : : struct rte_eth_dev *eth_dev;
446 : : struct cnxk_eth_dev *dev;
447 : : uint64_t extract_cfg_val = 0;
448 : : uint64_t def_cfg_val = 0;
449 : : uint64_t gen_cfg_val = 0;
450 : : uint32_t sa_size = 0;
451 : : uint32_t max_sa = 0;
452 [ # # ]: 0 : uint16_t prof_id = 0;
453 : : int rc = 0;
454 : : int i;
455 : :
456 [ # # ]: 0 : if (!roc_feature_nix_has_inl_profile())
457 : : return -ENOTSUP;
458 : :
459 [ # # ]: 0 : if (!rte_eth_dev_is_valid_port(portid))
460 : : return -EINVAL;
461 : :
462 [ # # ]: 0 : if (!cfg || !profile_id)
463 : : return -EINVAL;
464 : :
465 : : eth_dev = &rte_eth_devices[portid];
466 : : dev = cnxk_eth_pmd_priv(eth_dev);
467 : :
468 : : /* Pack default inline configuration */
469 : 0 : def_cfg_val = cnxk_rx_def_inl_cfg_pack(&cfg->def_cfg);
470 : :
471 : : /* Pack generic inline configuration */
472 : : gen_cfg_val = cnxk_rx_gen_inl_cfg_pack(&cfg->gen_cfg);
473 : :
474 : : /* Pack extract inline configuration */
475 : 0 : extract_cfg_val = cnxk_rx_extract_inl_cfg_pack(&cfg->extract_cfg);
476 : :
477 : : /* Pack protocol field inline configurations */
478 [ # # ]: 0 : for (i = 0; i < RTE_PMD_CNXK_MAX_PROT_FIELDS; i++)
479 : 0 : prot_field_cfg_val[i] = cnxk_rx_prot_field_inline_cfg_pack(&cfg->prot_field_cfg[i]);
480 : :
481 : : /* Get SA size and max SA count */
482 : 0 : sa_size = cfg->sa_size;
483 : 0 : max_sa = cfg->max_sa;
484 : :
485 : : /* Call ROC API to configure the custom profile */
486 : 0 : rc = roc_nix_inl_custom_profile_setup(&dev->nix, def_cfg_val, gen_cfg_val, extract_cfg_val,
487 : : prot_field_cfg_val, sa_size, max_sa,
488 : 0 : !dev->inb.no_inl_dev, &prof_id);
489 [ # # ]: 0 : if (rc) {
490 : 0 : plt_err("Failed to setup custom profile: rc=%d", rc);
491 : 0 : return rc;
492 : : }
493 : :
494 : 0 : *profile_id = prof_id;
495 : :
496 : 0 : plt_nix_dbg("Custom profile setup: port=%u, sa_size=%u, max_sa=%u, profile_id=%u", portid,
497 : : sa_size, max_sa, *profile_id);
498 : :
499 : 0 : return 0;
500 : : }
501 : :
502 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_nix_inl_custom_profile_release, 25.11)
503 : : int
504 : 0 : rte_pmd_cnxk_nix_inl_custom_profile_release(uint16_t portid, uint16_t profile_id)
505 : : {
506 : : struct rte_eth_dev *eth_dev;
507 : : struct cnxk_eth_dev *dev;
508 : : int rc;
509 : :
510 [ # # ]: 0 : if (!rte_eth_dev_is_valid_port(portid))
511 : : return -EINVAL;
512 : :
513 : : eth_dev = &rte_eth_devices[portid];
514 : : dev = cnxk_eth_pmd_priv(eth_dev);
515 : :
516 : : /* Call ROC API to release the custom profile */
517 : 0 : rc = roc_nix_inl_custom_profile_release(&dev->nix, profile_id, !dev->inb.no_inl_dev);
518 [ # # ]: 0 : if (rc) {
519 : 0 : plt_err("Failed to release custom profile %u: rc=%d", profile_id, rc);
520 : 0 : return rc;
521 : : }
522 : :
523 : : return 0;
524 : : }
525 : :
526 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_sa_flush, 23.11)
527 : : int
528 : 0 : rte_pmd_cnxk_sa_flush(uint16_t portid, union rte_pmd_cnxk_ipsec_hw_sa *sess, bool inb)
529 : : {
530 [ # # ]: 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
531 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
532 : : rte_spinlock_t *lock;
533 : : bool inl_dev;
534 : : int rc;
535 : :
536 : 0 : inl_dev = !!dev->inb.inl_dev;
537 [ # # ]: 0 : lock = inb ? &dev->inb.lock : &dev->outb.lock;
538 : : rte_spinlock_lock(lock);
539 : :
540 : : /* Acquire lock on inline dev for inbound */
541 [ # # ]: 0 : if (inb && inl_dev)
542 : 0 : roc_nix_inl_dev_lock();
543 : :
544 : 0 : rc = roc_nix_inl_sa_sync(&dev->nix, sess, inb, ROC_NIX_INL_SA_OP_FLUSH);
545 : :
546 [ # # ]: 0 : if (inb && inl_dev)
547 : 0 : roc_nix_inl_dev_unlock();
548 : : rte_spinlock_unlock(lock);
549 : :
550 : 0 : return rc;
551 : : }
552 : :
553 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_hw_sa_read, 22.07)
554 : : int
555 : 0 : rte_pmd_cnxk_hw_sa_read(uint16_t portid, void *sess, union rte_pmd_cnxk_ipsec_hw_sa *data,
556 : : uint32_t len, bool inb)
557 : : {
558 : 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
559 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
560 : : struct cnxk_eth_sec_sess *eth_sec;
561 : : rte_spinlock_t *lock;
562 : : bool inl_dev;
563 : : void *sa;
564 : : int rc;
565 : :
566 : 0 : eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
567 [ # # ]: 0 : if (eth_sec)
568 : 0 : sa = eth_sec->sa;
569 : : else
570 : : sa = sess;
571 : :
572 : 0 : inl_dev = !!dev->inb.inl_dev;
573 [ # # ]: 0 : lock = inb ? &dev->inb.lock : &dev->outb.lock;
574 : : rte_spinlock_lock(lock);
575 : :
576 : : /* Acquire lock on inline dev for inbound */
577 [ # # ]: 0 : if (inb && inl_dev)
578 : 0 : roc_nix_inl_dev_lock();
579 : :
580 : 0 : rc = roc_nix_inl_sa_sync(&dev->nix, sa, inb, ROC_NIX_INL_SA_OP_FLUSH);
581 [ # # ]: 0 : if (rc)
582 : 0 : goto err;
583 : :
584 [ # # ]: 0 : if (inb && inl_dev)
585 : 0 : roc_nix_inl_dev_unlock();
586 : : rte_spinlock_unlock(lock);
587 : :
588 : 0 : memcpy(data, sa, len);
589 : :
590 : 0 : return 0;
591 : : err:
592 [ # # ]: 0 : if (inb && inl_dev)
593 : 0 : roc_nix_inl_dev_unlock();
594 : : rte_spinlock_unlock(lock);
595 : :
596 : 0 : return rc;
597 : : }
598 : :
599 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_hw_sa_write, 22.07)
600 : : int
601 : 0 : rte_pmd_cnxk_hw_sa_write(uint16_t portid, void *sess, union rte_pmd_cnxk_ipsec_hw_sa *data,
602 : : uint32_t len, bool inb)
603 : : {
604 : 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
605 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
606 : : struct cnxk_eth_sec_sess *eth_sec;
607 : : struct roc_nix_inl_dev_q *q;
608 : : rte_spinlock_t *lock;
609 : : bool inl_dev;
610 : : void *sa;
611 : : int rc;
612 : :
613 : 0 : eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
614 [ # # ]: 0 : if (eth_sec)
615 : 0 : sa = eth_sec->sa;
616 : : else
617 : : sa = sess;
618 : :
619 : 0 : q = dev->inb.inl_dev_q;
620 [ # # # # ]: 0 : if (q && cnxk_nix_inl_fc_check(q->fc_addr, &q->fc_addr_sw, q->nb_desc, 1))
621 : : return -EAGAIN;
622 : :
623 : 0 : inl_dev = !!dev->inb.inl_dev;
624 [ # # ]: 0 : lock = inb ? &dev->inb.lock : &dev->outb.lock;
625 : : rte_spinlock_lock(lock);
626 : :
627 : : /* Acquire lock on inline dev for inbound */
628 [ # # ]: 0 : if (inb && inl_dev)
629 : 0 : roc_nix_inl_dev_lock();
630 : :
631 : 0 : rc = roc_nix_inl_ctx_write(&dev->nix, data, sa, inb, len);
632 : :
633 [ # # ]: 0 : if (inb && inl_dev)
634 : 0 : roc_nix_inl_dev_unlock();
635 : : rte_spinlock_unlock(lock);
636 : :
637 : 0 : return rc;
638 : : }
639 : :
640 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_inl_ipsec_res, 23.11)
641 : : union rte_pmd_cnxk_cpt_res_s *
642 : 0 : rte_pmd_cnxk_inl_ipsec_res(struct rte_mbuf *mbuf)
643 : : {
644 : : const union nix_rx_parse_u *rx;
645 : : uint16_t desc_size;
646 : : uintptr_t wqe;
647 : :
648 [ # # # # ]: 0 : if (!mbuf || !(mbuf->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD))
649 : : return NULL;
650 : :
651 : 0 : wqe = (uintptr_t)(mbuf + 1);
652 : 0 : rx = (const union nix_rx_parse_u *)(wqe + 8);
653 : 0 : desc_size = (rx->desc_sizem1 + 1) * 16;
654 : :
655 : : /* rte_pmd_cnxk_cpt_res_s sits after SG list at 16B aligned address */
656 : 0 : return (void *)(wqe + 64 + desc_size);
657 : : }
658 : :
659 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_hw_inline_inb_cfg_set, 23.11)
660 : : void
661 : 0 : rte_pmd_cnxk_hw_inline_inb_cfg_set(uint16_t portid, struct rte_pmd_cnxk_ipsec_inb_cfg *cfg)
662 : : {
663 : 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
664 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
665 : :
666 : 0 : dev->nix.inb_cfg_param1 = cfg->param1;
667 : 0 : dev->nix.inb_cfg_param2 = cfg->param2;
668 : 0 : }
669 : :
670 : : static unsigned int
671 : 0 : cnxk_eth_sec_session_get_size(void *device __rte_unused)
672 : : {
673 : 0 : return RTE_MAX(sizeof(struct cnxk_macsec_sess), sizeof(struct cnxk_eth_sec_sess));
674 : : }
675 : :
676 : : struct rte_security_ops cnxk_eth_sec_ops = {
677 : : .session_get_size = cnxk_eth_sec_session_get_size
678 : : };
679 : :
680 : : static int
681 : 0 : parse_val_u32(const char *key, const char *value, void *extra_args)
682 : : {
683 : : RTE_SET_USED(key);
684 : : uint32_t val;
685 : :
686 : 0 : errno = 0;
687 : 0 : val = strtoul(value, NULL, 0);
688 [ # # ]: 0 : if (errno)
689 : : val = 0;
690 : :
691 : 0 : *(uint32_t *)extra_args = val;
692 : :
693 : 0 : return 0;
694 : : }
695 : :
696 : : static int
697 : 0 : parse_selftest(const char *key, const char *value, void *extra_args)
698 : : {
699 : : RTE_SET_USED(key);
700 : : uint32_t val;
701 : :
702 : 0 : val = atoi(value);
703 : :
704 : 0 : *(uint8_t *)extra_args = !!(val == 1);
705 : 0 : return 0;
706 : : }
707 : :
708 : : static int
709 : 0 : parse_inl_cpt_channel(const char *key, const char *value, void *extra_args)
710 : : {
711 : : RTE_SET_USED(key);
712 : : uint16_t chan = 0, mask = 0;
713 : 0 : char *next = 0;
714 : :
715 : : /* next will point to the separator '/' */
716 : 0 : chan = strtol(value, &next, 16);
717 : 0 : mask = strtol(++next, 0, 16);
718 : :
719 [ # # ]: 0 : if (chan > GENMASK(12, 0) || mask > GENMASK(12, 0))
720 : : return -EINVAL;
721 : :
722 : 0 : ((struct inl_cpt_channel *)extra_args)->channel = chan;
723 : 0 : ((struct inl_cpt_channel *)extra_args)->mask = mask;
724 : 0 : ((struct inl_cpt_channel *)extra_args)->is_multi_channel = true;
725 : :
726 : 0 : return 0;
727 : : }
728 : :
729 : : static int
730 : 0 : nix_inl_parse_devargs(struct rte_devargs *devargs,
731 : : struct roc_nix_inl_dev *inl_dev)
732 : : {
733 : 0 : uint32_t soft_exp_poll_freq = CNXK_NIX_SOFT_EXP_POLL_FREQ_DFLT;
734 : 0 : uint32_t ipsec_in_max_spi = BIT(8) - 1;
735 : 0 : uint32_t ipsec_in_min_spi = 0;
736 : : struct inl_cpt_channel cpt_channel;
737 : 0 : uint32_t max_ipsec_rules = 0;
738 : : struct rte_kvargs *kvlist;
739 : 0 : uint8_t custom_inb_sa = 0;
740 : 0 : uint8_t nb_inl_inb_qs = 1;
741 : 0 : uint32_t nb_meta_bufs = 0;
742 : 0 : uint32_t meta_buf_sz = 0;
743 : 0 : uint8_t rx_inj_ena = 0;
744 : 0 : uint8_t selftest = 0;
745 [ # # ]: 0 : uint8_t cpt_cq_enable = 0;
746 : :
747 : : memset(&cpt_channel, 0, sizeof(cpt_channel));
748 : :
749 [ # # ]: 0 : if (devargs == NULL)
750 : 0 : goto null_devargs;
751 : :
752 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
753 [ # # ]: 0 : if (kvlist == NULL)
754 : 0 : goto exit;
755 : :
756 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_SELFTEST, &parse_selftest,
757 : : &selftest);
758 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_IPSEC_IN_MIN_SPI,
759 : : &parse_val_u32, &ipsec_in_min_spi);
760 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_IPSEC_IN_MAX_SPI,
761 : : &parse_val_u32, &ipsec_in_max_spi);
762 : 0 : rte_kvargs_process(kvlist, CNXK_INL_CPT_CHANNEL, &parse_inl_cpt_channel,
763 : : &cpt_channel);
764 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_NB_META_BUFS, &parse_val_u32,
765 : : &nb_meta_bufs);
766 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_META_BUF_SZ, &parse_val_u32,
767 : : &meta_buf_sz);
768 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_SOFT_EXP_POLL_FREQ,
769 : : &parse_val_u32, &soft_exp_poll_freq);
770 : 0 : rte_kvargs_process(kvlist, CNXK_MAX_IPSEC_RULES, &parse_max_ipsec_rules, &max_ipsec_rules);
771 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_RX_INJ_ENABLE, &parse_val_u8, &rx_inj_ena);
772 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_CUSTOM_INB_SA, &parse_val_u8, &custom_inb_sa);
773 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_NB_INL_INB_QS, &parse_val_u8, &nb_inl_inb_qs);
774 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_CPT_CQ_ENABLE, &parse_val_u8, &cpt_cq_enable);
775 : 0 : rte_kvargs_free(kvlist);
776 : :
777 : 0 : null_devargs:
778 : 0 : inl_dev->ipsec_in_min_spi = ipsec_in_min_spi;
779 : 0 : inl_dev->ipsec_in_max_spi = ipsec_in_max_spi;
780 : 0 : inl_dev->selftest = selftest;
781 : 0 : inl_dev->channel = cpt_channel.channel;
782 : 0 : inl_dev->chan_mask = cpt_channel.mask;
783 : 0 : inl_dev->is_multi_channel = cpt_channel.is_multi_channel;
784 : 0 : inl_dev->nb_meta_bufs = nb_meta_bufs;
785 : 0 : inl_dev->meta_buf_sz = meta_buf_sz;
786 : 0 : inl_dev->soft_exp_poll_freq = soft_exp_poll_freq;
787 : 0 : inl_dev->cpt_cq_enable = cpt_cq_enable;
788 [ # # ]: 0 : inl_dev->max_ipsec_rules = max_ipsec_rules;
789 [ # # ]: 0 : if (roc_feature_nix_has_rx_inject())
790 : 0 : inl_dev->rx_inj_ena = rx_inj_ena;
791 [ # # ]: 0 : if (roc_feature_nix_has_inl_multi_queue())
792 : 0 : inl_dev->nb_inb_cptlfs = nb_inl_inb_qs;
793 : 0 : inl_dev->custom_inb_sa = custom_inb_sa;
794 : 0 : return 0;
795 : : exit:
796 : 0 : return -EINVAL;
797 : : }
798 : :
799 : : static inline char *
800 : 0 : nix_inl_dev_to_name(struct rte_pci_device *pci_dev, char *name)
801 : : {
802 : 0 : snprintf(name, CNXK_NIX_INL_DEV_NAME_LEN,
803 : : CNXK_NIX_INL_DEV_NAME PCI_PRI_FMT, pci_dev->addr.domain,
804 : 0 : pci_dev->addr.bus, pci_dev->addr.devid,
805 : 0 : pci_dev->addr.function);
806 : :
807 : 0 : return name;
808 : : }
809 : :
810 : : static int
811 : 0 : cnxk_nix_inl_dev_remove(struct rte_pci_device *pci_dev)
812 : : {
813 : : char name[CNXK_NIX_INL_DEV_NAME_LEN];
814 : : const struct rte_memzone *mz;
815 : : struct roc_nix_inl_dev *dev;
816 : : int rc;
817 : :
818 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
819 : : return 0;
820 : :
821 : 0 : mz = rte_memzone_lookup(nix_inl_dev_to_name(pci_dev, name));
822 [ # # ]: 0 : if (!mz)
823 : : return 0;
824 : :
825 : 0 : dev = mz->addr;
826 : :
827 : : /* Cleanup inline dev */
828 : 0 : rc = roc_nix_inl_dev_fini(dev);
829 [ # # ]: 0 : if (rc) {
830 : 0 : plt_err("Failed to cleanup inl dev, rc=%d(%s)", rc,
831 : : roc_error_msg_get(rc));
832 : 0 : return rc;
833 : : }
834 : :
835 : 0 : rte_memzone_free(mz);
836 : 0 : return 0;
837 : : }
838 : :
839 : : static int
840 : 0 : cnxk_nix_inl_dev_probe(struct rte_pci_driver *pci_drv,
841 : : struct rte_pci_device *pci_dev)
842 : : {
843 : : char name[CNXK_NIX_INL_DEV_NAME_LEN];
844 : : struct roc_nix_inl_dev *inl_dev;
845 : : const struct rte_memzone *mz;
846 : : uint16_t wqe_skip;
847 : : int rc = -ENOMEM;
848 : :
849 : : RTE_SET_USED(pci_drv);
850 : :
851 : 0 : rc = roc_plt_init();
852 [ # # ]: 0 : if (rc) {
853 : 0 : plt_err("Failed to initialize platform model, rc=%d", rc);
854 : 0 : return rc;
855 : : }
856 : :
857 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
858 : : return 0;
859 : :
860 : 0 : mz = rte_memzone_reserve_aligned(nix_inl_dev_to_name(pci_dev, name),
861 : : sizeof(*inl_dev), SOCKET_ID_ANY, 0,
862 : : RTE_CACHE_LINE_SIZE);
863 [ # # ]: 0 : if (mz == NULL)
864 : : return rc;
865 : :
866 : 0 : inl_dev = mz->addr;
867 : 0 : inl_dev->pci_dev = pci_dev;
868 : :
869 : : /* Parse devargs string */
870 : 0 : rc = nix_inl_parse_devargs(pci_dev->device.devargs, inl_dev);
871 [ # # ]: 0 : if (rc) {
872 : 0 : plt_err("Failed to parse devargs rc=%d", rc);
873 : 0 : goto free_mem;
874 : : }
875 : :
876 : : /* WQE skip is one for DPDK */
877 : : wqe_skip = RTE_ALIGN_CEIL(sizeof(struct rte_mbuf), ROC_CACHE_LINE_SZ);
878 : : wqe_skip = wqe_skip / ROC_CACHE_LINE_SZ;
879 : 0 : inl_dev->wqe_skip = wqe_skip;
880 : 0 : rc = roc_nix_inl_dev_init(inl_dev);
881 [ # # ]: 0 : if (rc) {
882 : 0 : plt_err("Failed to init nix inl device, rc=%d(%s)", rc,
883 : : roc_error_msg_get(rc));
884 : 0 : goto free_mem;
885 : : }
886 : :
887 : : return 0;
888 : 0 : free_mem:
889 : 0 : rte_memzone_free(mz);
890 : 0 : return rc;
891 : : }
892 : :
893 : : static const struct rte_pci_id cnxk_nix_inl_pci_map[] = {
894 : : {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_RVU_NIX_INL_PF)},
895 : : {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_RVU_NIX_INL_VF)},
896 : : {
897 : : .vendor_id = 0,
898 : : },
899 : : };
900 : :
901 : : static struct rte_pci_driver cnxk_nix_inl_pci = {
902 : : .id_table = cnxk_nix_inl_pci_map,
903 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_NEED_IOVA_AS_VA,
904 : : .probe = cnxk_nix_inl_dev_probe,
905 : : .remove = cnxk_nix_inl_dev_remove,
906 : : };
907 : :
908 : 301 : RTE_PMD_REGISTER_PCI(cnxk_nix_inl, cnxk_nix_inl_pci);
909 : : RTE_PMD_REGISTER_PCI_TABLE(cnxk_nix_inl, cnxk_nix_inl_pci_map);
910 : : RTE_PMD_REGISTER_KMOD_DEP(cnxk_nix_inl, "vfio-pci");
911 : :
912 : : RTE_PMD_REGISTER_PARAM_STRING(cnxk_nix_inl,
913 : : CNXK_NIX_INL_SELFTEST "=1"
914 : : CNXK_NIX_INL_IPSEC_IN_MIN_SPI "=<1-U32_MAX>"
915 : : CNXK_NIX_INL_IPSEC_IN_MAX_SPI "=<1-U32_MAX>"
916 : : CNXK_INL_CPT_CHANNEL "=<1-4095>/<1-4095>"
917 : : CNXK_NIX_INL_NB_META_BUFS "=<1-U32_MAX>"
918 : : CNXK_NIX_INL_META_BUF_SZ "=<1-U32_MAX>"
919 : : CNXK_NIX_SOFT_EXP_POLL_FREQ "=<0-U32_MAX>"
920 : : CNXK_MAX_IPSEC_RULES "=<1-4095>"
921 : : CNXK_NIX_INL_RX_INJ_ENABLE "=1"
922 : : CNXK_NIX_CUSTOM_INB_SA "=1"
923 : : CNXK_NIX_NB_INL_INB_QS "=[0-16]");
|