Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include <rte_pmd_cnxk.h>
6 : :
7 : : #include <cnxk_ethdev.h>
8 : : #include <cnxk_mempool.h>
9 : :
10 : : #define CNXK_NIX_INL_META_POOL_NAME "NIX_INL_META_POOL"
11 : : #define CN10K_HW_POOL_OPS_NAME "cn10k_hwpool_ops"
12 : :
13 : : #define CNXK_NIX_INL_SELFTEST "selftest"
14 : : #define CNXK_NIX_INL_IPSEC_IN_MIN_SPI "ipsec_in_min_spi"
15 : : #define CNXK_NIX_INL_IPSEC_IN_MAX_SPI "ipsec_in_max_spi"
16 : : #define CNXK_INL_CPT_CHANNEL "inl_cpt_channel"
17 : : #define CNXK_NIX_INL_NB_META_BUFS "nb_meta_bufs"
18 : : #define CNXK_NIX_INL_META_BUF_SZ "meta_buf_sz"
19 : : #define CNXK_NIX_SOFT_EXP_POLL_FREQ "soft_exp_poll_freq"
20 : : #define CNXK_MAX_IPSEC_RULES "max_ipsec_rules"
21 : : #define CNXK_NIX_INL_RX_INJ_ENABLE "rx_inj_ena"
22 : : #define CNXK_NIX_CUSTOM_INB_SA "custom_inb_sa"
23 : : #define CNXK_NIX_NB_INL_INB_QS "nb_inl_inb_qs"
24 : :
25 : : /* Default soft expiry poll freq in usec */
26 : : #define CNXK_NIX_SOFT_EXP_POLL_FREQ_DFLT 100
27 : :
28 : : struct inl_cpt_channel {
29 : : bool is_multi_channel;
30 : : uint16_t channel;
31 : : uint16_t mask;
32 : : };
33 : :
34 : : #define CNXK_NIX_INL_DEV_NAME RTE_STR(cnxk_nix_inl_dev_)
35 : : #define CNXK_NIX_INL_DEV_NAME_LEN \
36 : : (sizeof(CNXK_NIX_INL_DEV_NAME) + PCI_PRI_STR_SIZE)
37 : :
38 : : struct cnxk_ethdev_pmd_ops cnxk_pmd_ops;
39 : :
40 : : static inline int
41 : : bitmap_ctzll(uint64_t slab)
42 : : {
43 : 0 : if (slab == 0)
44 : : return 0;
45 : :
46 : 0 : return rte_ctz64(slab);
47 : : }
48 : :
49 : : int
50 : 0 : cnxk_nix_inl_meta_pool_cb(uint64_t *aura_handle, uintptr_t *mpool, uint32_t buf_sz,
51 : : uint32_t nb_bufs, bool destroy, const char *mempool_name)
52 : : {
53 : : const char *mp_name = NULL;
54 : : struct rte_pktmbuf_pool_private mbp_priv;
55 : : struct rte_mempool *mp;
56 : : uint16_t first_skip;
57 : : int rc;
58 : :
59 : : /* Null Mempool name indicates to allocate Zero aura. */
60 [ # # ]: 0 : if (!mempool_name)
61 : : mp_name = CNXK_NIX_INL_META_POOL_NAME;
62 : : else
63 : : mp_name = mempool_name;
64 : :
65 : : /* Destroy the mempool if requested */
66 [ # # ]: 0 : if (destroy) {
67 : 0 : mp = rte_mempool_lookup(mp_name);
68 [ # # ]: 0 : if (!mp)
69 : : return -ENOENT;
70 : :
71 [ # # ]: 0 : if (mp->pool_id != *aura_handle) {
72 : 0 : plt_err("Meta pool aura mismatch");
73 : 0 : return -EINVAL;
74 : : }
75 : :
76 : 0 : rte_mempool_free(mp);
77 : :
78 : 0 : *aura_handle = 0;
79 : 0 : *mpool = 0;
80 : 0 : return 0;
81 : : }
82 : :
83 : : /* Need to make it similar to rte_pktmbuf_pool() for sake of OOP
84 : : * support.
85 : : */
86 : 0 : mp = rte_mempool_create_empty(mp_name, nb_bufs, buf_sz, 0,
87 : : sizeof(struct rte_pktmbuf_pool_private),
88 : : SOCKET_ID_ANY, 0);
89 [ # # ]: 0 : if (!mp) {
90 : 0 : plt_err("Failed to create inline meta pool");
91 : 0 : return -EIO;
92 : : }
93 : :
94 [ # # ]: 0 : rc = rte_mempool_set_ops_byname(mp, rte_mbuf_platform_mempool_ops(),
95 : : mempool_name ?
96 : : NULL : PLT_PTR_CAST(CNXK_MEMPOOL_F_ZERO_AURA));
97 [ # # ]: 0 : if (rc) {
98 : 0 : plt_err("Failed to setup mempool ops for meta, rc=%d", rc);
99 : 0 : goto free_mp;
100 : : }
101 : :
102 : : /* Init mempool private area */
103 : : first_skip = sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM;
104 : : memset(&mbp_priv, 0, sizeof(mbp_priv));
105 : 0 : mbp_priv.mbuf_data_room_size = (buf_sz - first_skip +
106 : : RTE_PKTMBUF_HEADROOM);
107 : 0 : rte_pktmbuf_pool_init(mp, &mbp_priv);
108 : :
109 : : /* Populate buffer */
110 : 0 : rc = rte_mempool_populate_default(mp);
111 [ # # ]: 0 : if (rc < 0) {
112 : 0 : plt_err("Failed to create inline meta pool, rc=%d", rc);
113 : 0 : goto free_mp;
114 : : }
115 : :
116 : 0 : rte_mempool_obj_iter(mp, rte_pktmbuf_init, NULL);
117 : 0 : *aura_handle = mp->pool_id;
118 : 0 : *mpool = (uintptr_t)mp;
119 : 0 : return 0;
120 : 0 : free_mp:
121 : 0 : rte_mempool_free(mp);
122 : 0 : return rc;
123 : : }
124 : :
125 : : /* Create Aura and link with Global mempool for 1:N Pool:Aura case */
126 : : int
127 : 0 : cnxk_nix_inl_custom_meta_pool_cb(uintptr_t pmpool, uintptr_t *mpool, const char *mempool_name,
128 : : uint64_t *aura_handle, uint32_t buf_sz, uint32_t nb_bufs,
129 : : bool destroy)
130 : : {
131 : : struct rte_mempool *hp;
132 : : int rc;
133 : :
134 : : /* Destroy the mempool if requested */
135 [ # # ]: 0 : if (destroy) {
136 : 0 : hp = rte_mempool_lookup(mempool_name);
137 [ # # ]: 0 : if (!hp)
138 : : return -ENOENT;
139 : :
140 [ # # ]: 0 : if (hp->pool_id != *aura_handle) {
141 : 0 : plt_err("Meta pool aura mismatch");
142 : 0 : return -EINVAL;
143 : : }
144 : :
145 : 0 : plt_free(hp->pool_config);
146 : 0 : rte_mempool_free(hp);
147 : :
148 : 0 : *aura_handle = 0;
149 : 0 : *mpool = 0;
150 : 0 : return 0;
151 : : }
152 : :
153 : : /* Need to make it similar to rte_pktmbuf_pool() for sake of OOP
154 : : * support.
155 : : */
156 : 0 : hp = rte_mempool_create_empty(mempool_name, nb_bufs, buf_sz, 0,
157 : : sizeof(struct rte_pktmbuf_pool_private),
158 : : SOCKET_ID_ANY, 0);
159 [ # # ]: 0 : if (!hp) {
160 : 0 : plt_err("Failed to create inline meta pool");
161 : 0 : return -EIO;
162 : : }
163 : :
164 : 0 : rc = rte_mempool_set_ops_byname(hp, CN10K_HW_POOL_OPS_NAME, (void *)pmpool);
165 : :
166 [ # # ]: 0 : if (rc) {
167 : 0 : plt_err("Failed to setup ops, rc=%d", rc);
168 : 0 : goto free_hp;
169 : : }
170 : :
171 : : /* Populate buffer */
172 : 0 : rc = rte_mempool_populate_default(hp);
173 [ # # ]: 0 : if (rc < 0) {
174 : 0 : plt_err("Failed to populate pool, rc=%d", rc);
175 : 0 : goto free_hp;
176 : : }
177 : :
178 : 0 : *aura_handle = hp->pool_id;
179 : 0 : *mpool = (uintptr_t)hp;
180 : 0 : return 0;
181 : 0 : free_hp:
182 : 0 : rte_mempool_free(hp);
183 : 0 : return rc;
184 : : }
185 : :
186 : : static int
187 : 0 : parse_max_ipsec_rules(const char *key, const char *value, void *extra_args)
188 : : {
189 : : RTE_SET_USED(key);
190 : : uint32_t val;
191 : :
192 : 0 : val = atoi(value);
193 : :
194 [ # # ]: 0 : if (val < 1 || val > 4095)
195 : : return -EINVAL;
196 : :
197 : 0 : *(uint32_t *)extra_args = val;
198 : :
199 : 0 : return 0;
200 : : }
201 : :
202 : : static int
203 : 0 : parse_val_u8(const char *key, const char *value, void *extra_args)
204 : : {
205 : : RTE_SET_USED(key);
206 : : uint32_t val;
207 : :
208 : 0 : val = atoi(value);
209 : :
210 : 0 : *(uint8_t *)extra_args = !!(val == 1);
211 : :
212 : 0 : return 0;
213 : : }
214 : :
215 : : int
216 : 0 : cnxk_eth_outb_sa_idx_get(struct cnxk_eth_dev *dev, uint32_t *idx_p,
217 : : uint32_t spi)
218 : : {
219 : : uint32_t pos, idx;
220 : : uint64_t slab;
221 : : int rc;
222 : :
223 [ # # ]: 0 : if (!dev->outb.sa_bmap)
224 : : return -ENOTSUP;
225 : :
226 : 0 : pos = 0;
227 [ # # ]: 0 : slab = 0;
228 : : /* Scan from the beginning */
229 : : plt_bitmap_scan_init(dev->outb.sa_bmap);
230 : :
231 [ # # ]: 0 : if (dev->nix.custom_sa_action) {
232 [ # # ]: 0 : if (spi > dev->outb.max_sa)
233 : : return -ENOTSUP;
234 : : idx = spi;
235 [ # # ]: 0 : if (!plt_bitmap_get(dev->outb.sa_bmap, idx)) {
236 : 0 : plt_err("Outbound SA index %u already in use", idx);
237 : 0 : return -EEXIST;
238 : : }
239 : : } else {
240 : : /* Scan bitmap to get the free sa index */
241 : 0 : rc = plt_bitmap_scan(dev->outb.sa_bmap, &pos, &slab);
242 : : /* Empty bitmap */
243 [ # # ]: 0 : if (rc == 0) {
244 : 0 : plt_err("Outbound SA' exhausted, use 'ipsec_out_max_sa' "
245 : : "devargs to increase");
246 : 0 : return -ERANGE;
247 : : }
248 : :
249 : : /* Get free SA index */
250 [ # # ]: 0 : idx = pos + bitmap_ctzll(slab);
251 : : }
252 : 0 : plt_bitmap_clear(dev->outb.sa_bmap, idx);
253 : 0 : *idx_p = idx;
254 : 0 : return 0;
255 : : }
256 : :
257 : : int
258 : 0 : cnxk_eth_outb_sa_idx_put(struct cnxk_eth_dev *dev, uint32_t idx)
259 : : {
260 [ # # ]: 0 : if (idx >= dev->outb.max_sa)
261 : : return -EINVAL;
262 : :
263 : : /* Check if it is already free */
264 [ # # ]: 0 : if (plt_bitmap_get(dev->outb.sa_bmap, idx))
265 : : return -EINVAL;
266 : :
267 : : /* Mark index as free */
268 : 0 : plt_bitmap_set(dev->outb.sa_bmap, idx);
269 : 0 : return 0;
270 : : }
271 : :
272 : : struct cnxk_eth_sec_sess *
273 : 0 : cnxk_eth_sec_sess_get_by_sa_idx(struct cnxk_eth_dev *dev, uint32_t sa_idx, bool inb)
274 : : {
275 : : struct cnxk_eth_sec_sess_list *list;
276 : : struct cnxk_eth_sec_sess *eth_sec;
277 : :
278 [ # # ]: 0 : list = inb ? &dev->inb.list : &dev->outb.list;
279 [ # # ]: 0 : TAILQ_FOREACH(eth_sec, list, entry) {
280 [ # # ]: 0 : if (eth_sec->sa_idx == sa_idx)
281 : 0 : return eth_sec;
282 : : }
283 : :
284 : : return NULL;
285 : : }
286 : :
287 : : struct cnxk_eth_sec_sess *
288 : 0 : cnxk_eth_sec_sess_get_by_sess(struct cnxk_eth_dev *dev,
289 : : struct rte_security_session *sess)
290 : : {
291 : : struct cnxk_eth_sec_sess *eth_sec = NULL;
292 : :
293 : : /* Search in inbound list */
294 [ # # ]: 0 : TAILQ_FOREACH(eth_sec, &dev->inb.list, entry) {
295 [ # # ]: 0 : if (eth_sec->sess == sess)
296 : 0 : return eth_sec;
297 : : }
298 : :
299 : : /* Search in outbound list */
300 [ # # ]: 0 : TAILQ_FOREACH(eth_sec, &dev->outb.list, entry) {
301 [ # # ]: 0 : if (eth_sec->sess == sess)
302 : 0 : return eth_sec;
303 : : }
304 : :
305 : : return NULL;
306 : : }
307 : :
308 : : uint16_t
309 : 0 : rte_pmd_cnxk_inl_dev_submit(struct rte_pmd_cnxk_inl_dev_q *qptr, void *inst, uint16_t nb_inst)
310 : : {
311 : 0 : return cnxk_pmd_ops.inl_dev_submit((struct roc_nix_inl_dev_q *)qptr, inst, nb_inst);
312 : : }
313 : :
314 : : struct rte_pmd_cnxk_inl_dev_q *
315 : 0 : rte_pmd_cnxk_inl_dev_qptr_get(void)
316 : : {
317 : 0 : return roc_nix_inl_dev_qptr_get(0);
318 : : }
319 : :
320 : : int
321 : 0 : rte_pmd_cnxk_cpt_q_stats_get(uint16_t portid, enum rte_pmd_cnxk_cpt_q_stats_type type,
322 : : struct rte_pmd_cnxk_cpt_q_stats *stats, uint16_t idx)
323 : : {
324 : 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
325 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
326 : :
327 : 0 : return roc_nix_inl_cpt_lf_stats_get(&dev->nix, (enum roc_nix_cpt_lf_stats_type)type,
328 : : (struct roc_nix_cpt_lf_stats *)stats, idx);
329 : : }
330 : :
331 : : union rte_pmd_cnxk_ipsec_hw_sa *
332 : 0 : rte_pmd_cnxk_hw_session_base_get(uint16_t portid, bool inb)
333 : : {
334 [ # # ]: 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
335 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
336 : : uintptr_t sa_base;
337 : :
338 [ # # ]: 0 : if (inb)
339 : 0 : sa_base = roc_nix_inl_inb_sa_base_get(&dev->nix, dev->inb.inl_dev);
340 : : else
341 : 0 : sa_base = roc_nix_inl_outb_sa_base_get(&dev->nix);
342 : :
343 : 0 : return (union rte_pmd_cnxk_ipsec_hw_sa *)sa_base;
344 : : }
345 : :
346 : : int
347 : 0 : rte_pmd_cnxk_sa_flush(uint16_t portid, union rte_pmd_cnxk_ipsec_hw_sa *sess, bool inb)
348 : : {
349 : 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
350 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
351 : :
352 : 0 : return roc_nix_inl_sa_sync(&dev->nix, sess, inb, ROC_NIX_INL_SA_OP_FLUSH);
353 : : }
354 : :
355 : : int
356 : 0 : rte_pmd_cnxk_hw_sa_read(uint16_t portid, void *sess, union rte_pmd_cnxk_ipsec_hw_sa *data,
357 : : uint32_t len, bool inb)
358 : : {
359 : 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
360 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
361 : : struct cnxk_eth_sec_sess *eth_sec;
362 : : void *sa;
363 : : int rc;
364 : :
365 : 0 : eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
366 [ # # ]: 0 : if (eth_sec)
367 : 0 : sa = eth_sec->sa;
368 : : else
369 : : sa = sess;
370 : :
371 : 0 : rc = roc_nix_inl_sa_sync(&dev->nix, sa, inb, ROC_NIX_INL_SA_OP_FLUSH);
372 [ # # ]: 0 : if (rc)
373 : : return -EINVAL;
374 : :
375 : 0 : memcpy(data, sa, len);
376 : :
377 : 0 : return 0;
378 : : }
379 : :
380 : : int
381 : 0 : rte_pmd_cnxk_hw_sa_write(uint16_t portid, void *sess, union rte_pmd_cnxk_ipsec_hw_sa *data,
382 : : uint32_t len, bool inb)
383 : : {
384 : 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
385 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
386 : : struct cnxk_eth_sec_sess *eth_sec;
387 : : struct roc_nix_inl_dev_q *q;
388 : : void *sa;
389 : :
390 : 0 : eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
391 [ # # ]: 0 : if (eth_sec)
392 : 0 : sa = eth_sec->sa;
393 : : else
394 : : sa = sess;
395 : :
396 : 0 : q = dev->inb.inl_dev_q;
397 [ # # # # ]: 0 : if (q && cnxk_nix_inl_fc_check(q->fc_addr, &q->fc_addr_sw, q->nb_desc, 1))
398 : : return -EAGAIN;
399 : :
400 : 0 : return roc_nix_inl_ctx_write(&dev->nix, data, sa, inb, len);
401 : : }
402 : :
403 : : union rte_pmd_cnxk_cpt_res_s *
404 : 0 : rte_pmd_cnxk_inl_ipsec_res(struct rte_mbuf *mbuf)
405 : : {
406 : : const union nix_rx_parse_u *rx;
407 : : uint16_t desc_size;
408 : : uintptr_t wqe;
409 : :
410 [ # # # # ]: 0 : if (!mbuf || !(mbuf->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD))
411 : : return NULL;
412 : :
413 : 0 : wqe = (uintptr_t)(mbuf + 1);
414 : 0 : rx = (const union nix_rx_parse_u *)(wqe + 8);
415 : 0 : desc_size = (rx->desc_sizem1 + 1) * 16;
416 : :
417 : : /* rte_pmd_cnxk_cpt_res_s sits after SG list at 16B aligned address */
418 : 0 : return (void *)(wqe + 64 + desc_size);
419 : : }
420 : :
421 : : void
422 : 0 : rte_pmd_cnxk_hw_inline_inb_cfg_set(uint16_t portid, struct rte_pmd_cnxk_ipsec_inb_cfg *cfg)
423 : : {
424 : 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
425 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
426 : :
427 : 0 : dev->nix.inb_cfg_param1 = cfg->param1;
428 : 0 : dev->nix.inb_cfg_param2 = cfg->param2;
429 : 0 : }
430 : :
431 : : static unsigned int
432 : 0 : cnxk_eth_sec_session_get_size(void *device __rte_unused)
433 : : {
434 : 0 : return RTE_MAX(sizeof(struct cnxk_macsec_sess), sizeof(struct cnxk_eth_sec_sess));
435 : : }
436 : :
437 : : struct rte_security_ops cnxk_eth_sec_ops = {
438 : : .session_get_size = cnxk_eth_sec_session_get_size
439 : : };
440 : :
441 : : static int
442 : 0 : parse_val_u32(const char *key, const char *value, void *extra_args)
443 : : {
444 : : RTE_SET_USED(key);
445 : : uint32_t val;
446 : :
447 : 0 : errno = 0;
448 : 0 : val = strtoul(value, NULL, 0);
449 [ # # ]: 0 : if (errno)
450 : : val = 0;
451 : :
452 : 0 : *(uint32_t *)extra_args = val;
453 : :
454 : 0 : return 0;
455 : : }
456 : :
457 : : static int
458 : 0 : parse_selftest(const char *key, const char *value, void *extra_args)
459 : : {
460 : : RTE_SET_USED(key);
461 : : uint32_t val;
462 : :
463 : 0 : val = atoi(value);
464 : :
465 : 0 : *(uint8_t *)extra_args = !!(val == 1);
466 : 0 : return 0;
467 : : }
468 : :
469 : : static int
470 : 0 : parse_inl_cpt_channel(const char *key, const char *value, void *extra_args)
471 : : {
472 : : RTE_SET_USED(key);
473 : : uint16_t chan = 0, mask = 0;
474 : 0 : char *next = 0;
475 : :
476 : : /* next will point to the separator '/' */
477 : 0 : chan = strtol(value, &next, 16);
478 : 0 : mask = strtol(++next, 0, 16);
479 : :
480 [ # # ]: 0 : if (chan > GENMASK(12, 0) || mask > GENMASK(12, 0))
481 : : return -EINVAL;
482 : :
483 : 0 : ((struct inl_cpt_channel *)extra_args)->channel = chan;
484 : 0 : ((struct inl_cpt_channel *)extra_args)->mask = mask;
485 : 0 : ((struct inl_cpt_channel *)extra_args)->is_multi_channel = true;
486 : :
487 : 0 : return 0;
488 : : }
489 : :
490 : : static int
491 : 0 : nix_inl_parse_devargs(struct rte_devargs *devargs,
492 : : struct roc_nix_inl_dev *inl_dev)
493 : : {
494 : 0 : uint32_t soft_exp_poll_freq = CNXK_NIX_SOFT_EXP_POLL_FREQ_DFLT;
495 : 0 : uint32_t ipsec_in_max_spi = BIT(8) - 1;
496 : 0 : uint32_t ipsec_in_min_spi = 0;
497 : : struct inl_cpt_channel cpt_channel;
498 : 0 : uint32_t max_ipsec_rules = 0;
499 : : struct rte_kvargs *kvlist;
500 : 0 : uint8_t custom_inb_sa = 0;
501 : 0 : uint8_t nb_inl_inb_qs = 1;
502 : 0 : uint32_t nb_meta_bufs = 0;
503 : 0 : uint32_t meta_buf_sz = 0;
504 : 0 : uint8_t rx_inj_ena = 0;
505 [ # # ]: 0 : uint8_t selftest = 0;
506 : :
507 : : memset(&cpt_channel, 0, sizeof(cpt_channel));
508 : :
509 [ # # ]: 0 : if (devargs == NULL)
510 : 0 : goto null_devargs;
511 : :
512 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
513 [ # # ]: 0 : if (kvlist == NULL)
514 : 0 : goto exit;
515 : :
516 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_SELFTEST, &parse_selftest,
517 : : &selftest);
518 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_IPSEC_IN_MIN_SPI,
519 : : &parse_val_u32, &ipsec_in_min_spi);
520 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_IPSEC_IN_MAX_SPI,
521 : : &parse_val_u32, &ipsec_in_max_spi);
522 : 0 : rte_kvargs_process(kvlist, CNXK_INL_CPT_CHANNEL, &parse_inl_cpt_channel,
523 : : &cpt_channel);
524 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_NB_META_BUFS, &parse_val_u32,
525 : : &nb_meta_bufs);
526 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_META_BUF_SZ, &parse_val_u32,
527 : : &meta_buf_sz);
528 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_SOFT_EXP_POLL_FREQ,
529 : : &parse_val_u32, &soft_exp_poll_freq);
530 : 0 : rte_kvargs_process(kvlist, CNXK_MAX_IPSEC_RULES, &parse_max_ipsec_rules, &max_ipsec_rules);
531 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_RX_INJ_ENABLE, &parse_val_u8, &rx_inj_ena);
532 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_CUSTOM_INB_SA, &parse_val_u8, &custom_inb_sa);
533 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_NB_INL_INB_QS, &parse_val_u8, &nb_inl_inb_qs);
534 : 0 : rte_kvargs_free(kvlist);
535 : :
536 : 0 : null_devargs:
537 : 0 : inl_dev->ipsec_in_min_spi = ipsec_in_min_spi;
538 : 0 : inl_dev->ipsec_in_max_spi = ipsec_in_max_spi;
539 : 0 : inl_dev->selftest = selftest;
540 : 0 : inl_dev->channel = cpt_channel.channel;
541 : 0 : inl_dev->chan_mask = cpt_channel.mask;
542 : 0 : inl_dev->is_multi_channel = cpt_channel.is_multi_channel;
543 : 0 : inl_dev->nb_meta_bufs = nb_meta_bufs;
544 : 0 : inl_dev->meta_buf_sz = meta_buf_sz;
545 : 0 : inl_dev->soft_exp_poll_freq = soft_exp_poll_freq;
546 [ # # ]: 0 : inl_dev->max_ipsec_rules = max_ipsec_rules;
547 [ # # ]: 0 : if (roc_feature_nix_has_rx_inject())
548 : 0 : inl_dev->rx_inj_ena = rx_inj_ena;
549 [ # # ]: 0 : if (roc_feature_nix_has_inl_multi_queue())
550 : 0 : inl_dev->nb_inb_cptlfs = nb_inl_inb_qs;
551 : 0 : inl_dev->custom_inb_sa = custom_inb_sa;
552 : 0 : return 0;
553 : : exit:
554 : 0 : return -EINVAL;
555 : : }
556 : :
557 : : static inline char *
558 : 0 : nix_inl_dev_to_name(struct rte_pci_device *pci_dev, char *name)
559 : : {
560 : 0 : snprintf(name, CNXK_NIX_INL_DEV_NAME_LEN,
561 : : CNXK_NIX_INL_DEV_NAME PCI_PRI_FMT, pci_dev->addr.domain,
562 : 0 : pci_dev->addr.bus, pci_dev->addr.devid,
563 : 0 : pci_dev->addr.function);
564 : :
565 : 0 : return name;
566 : : }
567 : :
568 : : static int
569 : 0 : cnxk_nix_inl_dev_remove(struct rte_pci_device *pci_dev)
570 : : {
571 : : char name[CNXK_NIX_INL_DEV_NAME_LEN];
572 : : const struct rte_memzone *mz;
573 : : struct roc_nix_inl_dev *dev;
574 : : int rc;
575 : :
576 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
577 : : return 0;
578 : :
579 : 0 : mz = rte_memzone_lookup(nix_inl_dev_to_name(pci_dev, name));
580 [ # # ]: 0 : if (!mz)
581 : : return 0;
582 : :
583 : 0 : dev = mz->addr;
584 : :
585 : : /* Cleanup inline dev */
586 : 0 : rc = roc_nix_inl_dev_fini(dev);
587 [ # # ]: 0 : if (rc) {
588 : 0 : plt_err("Failed to cleanup inl dev, rc=%d(%s)", rc,
589 : : roc_error_msg_get(rc));
590 : 0 : return rc;
591 : : }
592 : :
593 : 0 : rte_memzone_free(mz);
594 : 0 : return 0;
595 : : }
596 : :
597 : : static int
598 : 0 : cnxk_nix_inl_dev_probe(struct rte_pci_driver *pci_drv,
599 : : struct rte_pci_device *pci_dev)
600 : : {
601 : : char name[CNXK_NIX_INL_DEV_NAME_LEN];
602 : : struct roc_nix_inl_dev *inl_dev;
603 : : const struct rte_memzone *mz;
604 : : uint16_t wqe_skip;
605 : : int rc = -ENOMEM;
606 : :
607 : : RTE_SET_USED(pci_drv);
608 : :
609 : 0 : rc = roc_plt_init();
610 [ # # ]: 0 : if (rc) {
611 : 0 : plt_err("Failed to initialize platform model, rc=%d", rc);
612 : 0 : return rc;
613 : : }
614 : :
615 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
616 : : return 0;
617 : :
618 : 0 : mz = rte_memzone_reserve_aligned(nix_inl_dev_to_name(pci_dev, name),
619 : : sizeof(*inl_dev), SOCKET_ID_ANY, 0,
620 : : RTE_CACHE_LINE_SIZE);
621 [ # # ]: 0 : if (mz == NULL)
622 : : return rc;
623 : :
624 : 0 : inl_dev = mz->addr;
625 : 0 : inl_dev->pci_dev = pci_dev;
626 : :
627 : : /* Parse devargs string */
628 : 0 : rc = nix_inl_parse_devargs(pci_dev->device.devargs, inl_dev);
629 [ # # ]: 0 : if (rc) {
630 : 0 : plt_err("Failed to parse devargs rc=%d", rc);
631 : 0 : goto free_mem;
632 : : }
633 : :
634 : : /* WQE skip is one for DPDK */
635 : : wqe_skip = RTE_ALIGN_CEIL(sizeof(struct rte_mbuf), ROC_CACHE_LINE_SZ);
636 : : wqe_skip = wqe_skip / ROC_CACHE_LINE_SZ;
637 : 0 : inl_dev->wqe_skip = wqe_skip;
638 : 0 : rc = roc_nix_inl_dev_init(inl_dev);
639 [ # # ]: 0 : if (rc) {
640 : 0 : plt_err("Failed to init nix inl device, rc=%d(%s)", rc,
641 : : roc_error_msg_get(rc));
642 : 0 : goto free_mem;
643 : : }
644 : :
645 : : return 0;
646 : 0 : free_mem:
647 : 0 : rte_memzone_free(mz);
648 : 0 : return rc;
649 : : }
650 : :
651 : : static const struct rte_pci_id cnxk_nix_inl_pci_map[] = {
652 : : {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_RVU_NIX_INL_PF)},
653 : : {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_RVU_NIX_INL_VF)},
654 : : {
655 : : .vendor_id = 0,
656 : : },
657 : : };
658 : :
659 : : static struct rte_pci_driver cnxk_nix_inl_pci = {
660 : : .id_table = cnxk_nix_inl_pci_map,
661 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_NEED_IOVA_AS_VA,
662 : : .probe = cnxk_nix_inl_dev_probe,
663 : : .remove = cnxk_nix_inl_dev_remove,
664 : : };
665 : :
666 : 252 : RTE_PMD_REGISTER_PCI(cnxk_nix_inl, cnxk_nix_inl_pci);
667 : : RTE_PMD_REGISTER_PCI_TABLE(cnxk_nix_inl, cnxk_nix_inl_pci_map);
668 : : RTE_PMD_REGISTER_KMOD_DEP(cnxk_nix_inl, "vfio-pci");
669 : :
670 : : RTE_PMD_REGISTER_PARAM_STRING(cnxk_nix_inl,
671 : : CNXK_NIX_INL_SELFTEST "=1"
672 : : CNXK_NIX_INL_IPSEC_IN_MIN_SPI "=<1-U32_MAX>"
673 : : CNXK_NIX_INL_IPSEC_IN_MAX_SPI "=<1-U32_MAX>"
674 : : CNXK_INL_CPT_CHANNEL "=<1-4095>/<1-4095>"
675 : : CNXK_NIX_INL_NB_META_BUFS "=<1-U32_MAX>"
676 : : CNXK_NIX_INL_META_BUF_SZ "=<1-U32_MAX>"
677 : : CNXK_NIX_SOFT_EXP_POLL_FREQ "=<0-U32_MAX>"
678 : : CNXK_MAX_IPSEC_RULES "=<1-4095>"
679 : : CNXK_NIX_INL_RX_INJ_ENABLE "=1"
680 : : CNXK_NIX_CUSTOM_INB_SA "=1"
681 : : CNXK_NIX_NB_INL_INB_QS "=[0-16]");
|