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,
291 : : struct rte_security_session *sess)
292 : : {
293 : : struct cnxk_eth_sec_sess *eth_sec = NULL;
294 : :
295 : : /* Search in inbound list */
296 [ # # ]: 0 : TAILQ_FOREACH(eth_sec, &dev->inb.list, entry) {
297 [ # # ]: 0 : if (eth_sec->sess == sess)
298 : 0 : return eth_sec;
299 : : }
300 : :
301 : : /* Search in outbound list */
302 [ # # ]: 0 : TAILQ_FOREACH(eth_sec, &dev->outb.list, entry) {
303 [ # # ]: 0 : if (eth_sec->sess == sess)
304 : 0 : return eth_sec;
305 : : }
306 : :
307 : : return NULL;
308 : : }
309 : :
310 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_inl_dev_submit, 23.11)
311 : : uint16_t
312 : 0 : rte_pmd_cnxk_inl_dev_submit(struct rte_pmd_cnxk_inl_dev_q *qptr, void *inst, uint16_t nb_inst)
313 : : {
314 : 0 : return cnxk_pmd_ops.inl_dev_submit((struct roc_nix_inl_dev_q *)qptr, inst, nb_inst);
315 : : }
316 : :
317 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_inl_dev_qptr_get, 23.11)
318 : : struct rte_pmd_cnxk_inl_dev_q *
319 : 0 : rte_pmd_cnxk_inl_dev_qptr_get(void)
320 : : {
321 : 0 : return roc_nix_inl_dev_qptr_get(0);
322 : : }
323 : :
324 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_cpt_q_stats_get, 23.11)
325 : : int
326 : 0 : rte_pmd_cnxk_cpt_q_stats_get(uint16_t portid, enum rte_pmd_cnxk_cpt_q_stats_type type,
327 : : struct rte_pmd_cnxk_cpt_q_stats *stats, uint16_t idx)
328 : : {
329 : 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
330 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
331 : :
332 : 0 : return roc_nix_inl_cpt_lf_stats_get(&dev->nix, (enum roc_nix_cpt_lf_stats_type)type,
333 : : (struct roc_nix_cpt_lf_stats *)stats, idx);
334 : : }
335 : :
336 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_hw_session_base_get, 23.11)
337 : : union rte_pmd_cnxk_ipsec_hw_sa *
338 : 0 : rte_pmd_cnxk_hw_session_base_get(uint16_t portid, bool inb)
339 : : {
340 [ # # ]: 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
341 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
342 : : uintptr_t sa_base;
343 : :
344 [ # # ]: 0 : if (inb)
345 : 0 : sa_base = roc_nix_inl_inb_sa_base_get(&dev->nix, dev->inb.inl_dev);
346 : : else
347 : 0 : sa_base = roc_nix_inl_outb_sa_base_get(&dev->nix);
348 : :
349 : 0 : return (union rte_pmd_cnxk_ipsec_hw_sa *)sa_base;
350 : : }
351 : :
352 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_sa_flush, 23.11)
353 : : int
354 : 0 : rte_pmd_cnxk_sa_flush(uint16_t portid, union rte_pmd_cnxk_ipsec_hw_sa *sess, bool inb)
355 : : {
356 [ # # ]: 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
357 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
358 : : rte_spinlock_t *lock;
359 : : bool inl_dev;
360 : : int rc;
361 : :
362 : 0 : inl_dev = !!dev->inb.inl_dev;
363 [ # # ]: 0 : lock = inb ? &dev->inb.lock : &dev->outb.lock;
364 : : rte_spinlock_lock(lock);
365 : :
366 : : /* Acquire lock on inline dev for inbound */
367 [ # # ]: 0 : if (inb && inl_dev)
368 : 0 : roc_nix_inl_dev_lock();
369 : :
370 : 0 : rc = roc_nix_inl_sa_sync(&dev->nix, sess, inb, ROC_NIX_INL_SA_OP_FLUSH);
371 : :
372 [ # # ]: 0 : if (inb && inl_dev)
373 : 0 : roc_nix_inl_dev_unlock();
374 : : rte_spinlock_unlock(lock);
375 : :
376 : 0 : return rc;
377 : : }
378 : :
379 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_hw_sa_read, 22.07)
380 : : int
381 : 0 : rte_pmd_cnxk_hw_sa_read(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 : : rte_spinlock_t *lock;
388 : : bool inl_dev;
389 : : void *sa;
390 : : int rc;
391 : :
392 : 0 : eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
393 [ # # ]: 0 : if (eth_sec)
394 : 0 : sa = eth_sec->sa;
395 : : else
396 : : sa = sess;
397 : :
398 : 0 : inl_dev = !!dev->inb.inl_dev;
399 [ # # ]: 0 : lock = inb ? &dev->inb.lock : &dev->outb.lock;
400 : : rte_spinlock_lock(lock);
401 : :
402 : : /* Acquire lock on inline dev for inbound */
403 [ # # ]: 0 : if (inb && inl_dev)
404 : 0 : roc_nix_inl_dev_lock();
405 : :
406 : 0 : rc = roc_nix_inl_sa_sync(&dev->nix, sa, inb, ROC_NIX_INL_SA_OP_FLUSH);
407 [ # # ]: 0 : if (rc)
408 : 0 : goto err;
409 : :
410 [ # # ]: 0 : if (inb && inl_dev)
411 : 0 : roc_nix_inl_dev_unlock();
412 : : rte_spinlock_unlock(lock);
413 : :
414 : 0 : memcpy(data, sa, len);
415 : :
416 : 0 : return 0;
417 : : err:
418 [ # # ]: 0 : if (inb && inl_dev)
419 : 0 : roc_nix_inl_dev_unlock();
420 : : rte_spinlock_unlock(lock);
421 : :
422 : 0 : return rc;
423 : : }
424 : :
425 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_hw_sa_write, 22.07)
426 : : int
427 : 0 : rte_pmd_cnxk_hw_sa_write(uint16_t portid, void *sess, union rte_pmd_cnxk_ipsec_hw_sa *data,
428 : : uint32_t len, bool inb)
429 : : {
430 : 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
431 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
432 : : struct cnxk_eth_sec_sess *eth_sec;
433 : : struct roc_nix_inl_dev_q *q;
434 : : rte_spinlock_t *lock;
435 : : bool inl_dev;
436 : : void *sa;
437 : : int rc;
438 : :
439 : 0 : eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
440 [ # # ]: 0 : if (eth_sec)
441 : 0 : sa = eth_sec->sa;
442 : : else
443 : : sa = sess;
444 : :
445 : 0 : q = dev->inb.inl_dev_q;
446 [ # # # # ]: 0 : if (q && cnxk_nix_inl_fc_check(q->fc_addr, &q->fc_addr_sw, q->nb_desc, 1))
447 : : return -EAGAIN;
448 : :
449 : 0 : inl_dev = !!dev->inb.inl_dev;
450 [ # # ]: 0 : lock = inb ? &dev->inb.lock : &dev->outb.lock;
451 : : rte_spinlock_lock(lock);
452 : :
453 : : /* Acquire lock on inline dev for inbound */
454 [ # # ]: 0 : if (inb && inl_dev)
455 : 0 : roc_nix_inl_dev_lock();
456 : :
457 : 0 : rc = roc_nix_inl_ctx_write(&dev->nix, data, sa, inb, len);
458 : :
459 [ # # ]: 0 : if (inb && inl_dev)
460 : 0 : roc_nix_inl_dev_unlock();
461 : : rte_spinlock_unlock(lock);
462 : :
463 : 0 : return rc;
464 : : }
465 : :
466 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_inl_ipsec_res, 23.11)
467 : : union rte_pmd_cnxk_cpt_res_s *
468 : 0 : rte_pmd_cnxk_inl_ipsec_res(struct rte_mbuf *mbuf)
469 : : {
470 : : const union nix_rx_parse_u *rx;
471 : : uint16_t desc_size;
472 : : uintptr_t wqe;
473 : :
474 [ # # # # ]: 0 : if (!mbuf || !(mbuf->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD))
475 : : return NULL;
476 : :
477 : 0 : wqe = (uintptr_t)(mbuf + 1);
478 : 0 : rx = (const union nix_rx_parse_u *)(wqe + 8);
479 : 0 : desc_size = (rx->desc_sizem1 + 1) * 16;
480 : :
481 : : /* rte_pmd_cnxk_cpt_res_s sits after SG list at 16B aligned address */
482 : 0 : return (void *)(wqe + 64 + desc_size);
483 : : }
484 : :
485 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_hw_inline_inb_cfg_set, 23.11)
486 : : void
487 : 0 : rte_pmd_cnxk_hw_inline_inb_cfg_set(uint16_t portid, struct rte_pmd_cnxk_ipsec_inb_cfg *cfg)
488 : : {
489 : 0 : struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
490 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
491 : :
492 : 0 : dev->nix.inb_cfg_param1 = cfg->param1;
493 : 0 : dev->nix.inb_cfg_param2 = cfg->param2;
494 : 0 : }
495 : :
496 : : static unsigned int
497 : 0 : cnxk_eth_sec_session_get_size(void *device __rte_unused)
498 : : {
499 : 0 : return RTE_MAX(sizeof(struct cnxk_macsec_sess), sizeof(struct cnxk_eth_sec_sess));
500 : : }
501 : :
502 : : struct rte_security_ops cnxk_eth_sec_ops = {
503 : : .session_get_size = cnxk_eth_sec_session_get_size
504 : : };
505 : :
506 : : static int
507 : 0 : parse_val_u32(const char *key, const char *value, void *extra_args)
508 : : {
509 : : RTE_SET_USED(key);
510 : : uint32_t val;
511 : :
512 : 0 : errno = 0;
513 : 0 : val = strtoul(value, NULL, 0);
514 [ # # ]: 0 : if (errno)
515 : : val = 0;
516 : :
517 : 0 : *(uint32_t *)extra_args = val;
518 : :
519 : 0 : return 0;
520 : : }
521 : :
522 : : static int
523 : 0 : parse_selftest(const char *key, const char *value, void *extra_args)
524 : : {
525 : : RTE_SET_USED(key);
526 : : uint32_t val;
527 : :
528 : 0 : val = atoi(value);
529 : :
530 : 0 : *(uint8_t *)extra_args = !!(val == 1);
531 : 0 : return 0;
532 : : }
533 : :
534 : : static int
535 : 0 : parse_inl_cpt_channel(const char *key, const char *value, void *extra_args)
536 : : {
537 : : RTE_SET_USED(key);
538 : : uint16_t chan = 0, mask = 0;
539 : 0 : char *next = 0;
540 : :
541 : : /* next will point to the separator '/' */
542 : 0 : chan = strtol(value, &next, 16);
543 : 0 : mask = strtol(++next, 0, 16);
544 : :
545 [ # # ]: 0 : if (chan > GENMASK(12, 0) || mask > GENMASK(12, 0))
546 : : return -EINVAL;
547 : :
548 : 0 : ((struct inl_cpt_channel *)extra_args)->channel = chan;
549 : 0 : ((struct inl_cpt_channel *)extra_args)->mask = mask;
550 : 0 : ((struct inl_cpt_channel *)extra_args)->is_multi_channel = true;
551 : :
552 : 0 : return 0;
553 : : }
554 : :
555 : : static int
556 : 0 : nix_inl_parse_devargs(struct rte_devargs *devargs,
557 : : struct roc_nix_inl_dev *inl_dev)
558 : : {
559 : 0 : uint32_t soft_exp_poll_freq = CNXK_NIX_SOFT_EXP_POLL_FREQ_DFLT;
560 : 0 : uint32_t ipsec_in_max_spi = BIT(8) - 1;
561 : 0 : uint32_t ipsec_in_min_spi = 0;
562 : : struct inl_cpt_channel cpt_channel;
563 : 0 : uint32_t max_ipsec_rules = 0;
564 : : struct rte_kvargs *kvlist;
565 : 0 : uint8_t custom_inb_sa = 0;
566 : 0 : uint8_t nb_inl_inb_qs = 1;
567 : 0 : uint32_t nb_meta_bufs = 0;
568 : 0 : uint32_t meta_buf_sz = 0;
569 : 0 : uint8_t rx_inj_ena = 0;
570 : 0 : uint8_t selftest = 0;
571 [ # # ]: 0 : uint8_t cpt_cq_enable = 0;
572 : :
573 : : memset(&cpt_channel, 0, sizeof(cpt_channel));
574 : :
575 [ # # ]: 0 : if (devargs == NULL)
576 : 0 : goto null_devargs;
577 : :
578 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
579 [ # # ]: 0 : if (kvlist == NULL)
580 : 0 : goto exit;
581 : :
582 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_SELFTEST, &parse_selftest,
583 : : &selftest);
584 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_IPSEC_IN_MIN_SPI,
585 : : &parse_val_u32, &ipsec_in_min_spi);
586 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_IPSEC_IN_MAX_SPI,
587 : : &parse_val_u32, &ipsec_in_max_spi);
588 : 0 : rte_kvargs_process(kvlist, CNXK_INL_CPT_CHANNEL, &parse_inl_cpt_channel,
589 : : &cpt_channel);
590 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_NB_META_BUFS, &parse_val_u32,
591 : : &nb_meta_bufs);
592 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_META_BUF_SZ, &parse_val_u32,
593 : : &meta_buf_sz);
594 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_SOFT_EXP_POLL_FREQ,
595 : : &parse_val_u32, &soft_exp_poll_freq);
596 : 0 : rte_kvargs_process(kvlist, CNXK_MAX_IPSEC_RULES, &parse_max_ipsec_rules, &max_ipsec_rules);
597 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_RX_INJ_ENABLE, &parse_val_u8, &rx_inj_ena);
598 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_CUSTOM_INB_SA, &parse_val_u8, &custom_inb_sa);
599 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_NB_INL_INB_QS, &parse_val_u8, &nb_inl_inb_qs);
600 : 0 : rte_kvargs_process(kvlist, CNXK_NIX_INL_CPT_CQ_ENABLE, &parse_val_u8, &cpt_cq_enable);
601 : 0 : rte_kvargs_free(kvlist);
602 : :
603 : 0 : null_devargs:
604 : 0 : inl_dev->ipsec_in_min_spi = ipsec_in_min_spi;
605 : 0 : inl_dev->ipsec_in_max_spi = ipsec_in_max_spi;
606 : 0 : inl_dev->selftest = selftest;
607 : 0 : inl_dev->channel = cpt_channel.channel;
608 : 0 : inl_dev->chan_mask = cpt_channel.mask;
609 : 0 : inl_dev->is_multi_channel = cpt_channel.is_multi_channel;
610 : 0 : inl_dev->nb_meta_bufs = nb_meta_bufs;
611 : 0 : inl_dev->meta_buf_sz = meta_buf_sz;
612 : 0 : inl_dev->soft_exp_poll_freq = soft_exp_poll_freq;
613 : 0 : inl_dev->cpt_cq_enable = cpt_cq_enable;
614 [ # # ]: 0 : inl_dev->max_ipsec_rules = max_ipsec_rules;
615 [ # # ]: 0 : if (roc_feature_nix_has_rx_inject())
616 : 0 : inl_dev->rx_inj_ena = rx_inj_ena;
617 [ # # ]: 0 : if (roc_feature_nix_has_inl_multi_queue())
618 : 0 : inl_dev->nb_inb_cptlfs = nb_inl_inb_qs;
619 : 0 : inl_dev->custom_inb_sa = custom_inb_sa;
620 : 0 : return 0;
621 : : exit:
622 : 0 : return -EINVAL;
623 : : }
624 : :
625 : : static inline char *
626 : 0 : nix_inl_dev_to_name(struct rte_pci_device *pci_dev, char *name)
627 : : {
628 : 0 : snprintf(name, CNXK_NIX_INL_DEV_NAME_LEN,
629 : : CNXK_NIX_INL_DEV_NAME PCI_PRI_FMT, pci_dev->addr.domain,
630 : 0 : pci_dev->addr.bus, pci_dev->addr.devid,
631 : 0 : pci_dev->addr.function);
632 : :
633 : 0 : return name;
634 : : }
635 : :
636 : : static int
637 : 0 : cnxk_nix_inl_dev_remove(struct rte_pci_device *pci_dev)
638 : : {
639 : : char name[CNXK_NIX_INL_DEV_NAME_LEN];
640 : : const struct rte_memzone *mz;
641 : : struct roc_nix_inl_dev *dev;
642 : : int rc;
643 : :
644 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
645 : : return 0;
646 : :
647 : 0 : mz = rte_memzone_lookup(nix_inl_dev_to_name(pci_dev, name));
648 [ # # ]: 0 : if (!mz)
649 : : return 0;
650 : :
651 : 0 : dev = mz->addr;
652 : :
653 : : /* Cleanup inline dev */
654 : 0 : rc = roc_nix_inl_dev_fini(dev);
655 [ # # ]: 0 : if (rc) {
656 : 0 : plt_err("Failed to cleanup inl dev, rc=%d(%s)", rc,
657 : : roc_error_msg_get(rc));
658 : 0 : return rc;
659 : : }
660 : :
661 : 0 : rte_memzone_free(mz);
662 : 0 : return 0;
663 : : }
664 : :
665 : : static int
666 : 0 : cnxk_nix_inl_dev_probe(struct rte_pci_driver *pci_drv,
667 : : struct rte_pci_device *pci_dev)
668 : : {
669 : : char name[CNXK_NIX_INL_DEV_NAME_LEN];
670 : : struct roc_nix_inl_dev *inl_dev;
671 : : const struct rte_memzone *mz;
672 : : uint16_t wqe_skip;
673 : : int rc = -ENOMEM;
674 : :
675 : : RTE_SET_USED(pci_drv);
676 : :
677 : 0 : rc = roc_plt_init();
678 [ # # ]: 0 : if (rc) {
679 : 0 : plt_err("Failed to initialize platform model, rc=%d", rc);
680 : 0 : return rc;
681 : : }
682 : :
683 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
684 : : return 0;
685 : :
686 : 0 : mz = rte_memzone_reserve_aligned(nix_inl_dev_to_name(pci_dev, name),
687 : : sizeof(*inl_dev), SOCKET_ID_ANY, 0,
688 : : RTE_CACHE_LINE_SIZE);
689 [ # # ]: 0 : if (mz == NULL)
690 : : return rc;
691 : :
692 : 0 : inl_dev = mz->addr;
693 : 0 : inl_dev->pci_dev = pci_dev;
694 : :
695 : : /* Parse devargs string */
696 : 0 : rc = nix_inl_parse_devargs(pci_dev->device.devargs, inl_dev);
697 [ # # ]: 0 : if (rc) {
698 : 0 : plt_err("Failed to parse devargs rc=%d", rc);
699 : 0 : goto free_mem;
700 : : }
701 : :
702 : : /* WQE skip is one for DPDK */
703 : : wqe_skip = RTE_ALIGN_CEIL(sizeof(struct rte_mbuf), ROC_CACHE_LINE_SZ);
704 : : wqe_skip = wqe_skip / ROC_CACHE_LINE_SZ;
705 : 0 : inl_dev->wqe_skip = wqe_skip;
706 : 0 : rc = roc_nix_inl_dev_init(inl_dev);
707 [ # # ]: 0 : if (rc) {
708 : 0 : plt_err("Failed to init nix inl device, rc=%d(%s)", rc,
709 : : roc_error_msg_get(rc));
710 : 0 : goto free_mem;
711 : : }
712 : :
713 : : return 0;
714 : 0 : free_mem:
715 : 0 : rte_memzone_free(mz);
716 : 0 : return rc;
717 : : }
718 : :
719 : : static const struct rte_pci_id cnxk_nix_inl_pci_map[] = {
720 : : {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_RVU_NIX_INL_PF)},
721 : : {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_RVU_NIX_INL_VF)},
722 : : {
723 : : .vendor_id = 0,
724 : : },
725 : : };
726 : :
727 : : static struct rte_pci_driver cnxk_nix_inl_pci = {
728 : : .id_table = cnxk_nix_inl_pci_map,
729 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_NEED_IOVA_AS_VA,
730 : : .probe = cnxk_nix_inl_dev_probe,
731 : : .remove = cnxk_nix_inl_dev_remove,
732 : : };
733 : :
734 : 254 : RTE_PMD_REGISTER_PCI(cnxk_nix_inl, cnxk_nix_inl_pci);
735 : : RTE_PMD_REGISTER_PCI_TABLE(cnxk_nix_inl, cnxk_nix_inl_pci_map);
736 : : RTE_PMD_REGISTER_KMOD_DEP(cnxk_nix_inl, "vfio-pci");
737 : :
738 : : RTE_PMD_REGISTER_PARAM_STRING(cnxk_nix_inl,
739 : : CNXK_NIX_INL_SELFTEST "=1"
740 : : CNXK_NIX_INL_IPSEC_IN_MIN_SPI "=<1-U32_MAX>"
741 : : CNXK_NIX_INL_IPSEC_IN_MAX_SPI "=<1-U32_MAX>"
742 : : CNXK_INL_CPT_CHANNEL "=<1-4095>/<1-4095>"
743 : : CNXK_NIX_INL_NB_META_BUFS "=<1-U32_MAX>"
744 : : CNXK_NIX_INL_META_BUF_SZ "=<1-U32_MAX>"
745 : : CNXK_NIX_SOFT_EXP_POLL_FREQ "=<0-U32_MAX>"
746 : : CNXK_MAX_IPSEC_RULES "=<1-4095>"
747 : : CNXK_NIX_INL_RX_INJ_ENABLE "=1"
748 : : CNXK_NIX_CUSTOM_INB_SA "=1"
749 : : CNXK_NIX_NB_INL_INB_QS "=[0-16]");
|