Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2023 Marvell.
3 : : */
4 : :
5 : : #include <rte_mempool.h>
6 : : #include <rte_pmd_cnxk_mempool.h>
7 : :
8 : : #include "roc_api.h"
9 : : #include "cnxk_mempool.h"
10 : :
11 : : #define CN10K_HWPOOL_MEM_SIZE 128
12 : : #define CN10K_NPA_IOVA_RANGE_MIN 0x0
13 : : #define CN10K_NPA_IOVA_RANGE_MAX 0x1fffffffffff80
14 : :
15 : : static int __rte_hot
16 : 0 : cn10k_hwpool_enq(struct rte_mempool *hp, void *const *obj_table, unsigned int n)
17 : : {
18 : : struct rte_mempool *mp;
19 : : unsigned int index;
20 : :
21 : 0 : mp = CNXK_MEMPOOL_CONFIG(hp);
22 : : /* Ensure mbuf init changes are written before the free pointers
23 : : * are enqueued to the stack.
24 : : */
25 : 0 : rte_io_wmb();
26 [ # # ]: 0 : for (index = 0; index < n; index++) {
27 : : struct rte_mempool_objhdr *hdr;
28 : : struct rte_mbuf *m;
29 : :
30 : 0 : m = PLT_PTR_CAST(obj_table[index]);
31 : : /* Update mempool information in the mbuf */
32 : : hdr = rte_mempool_get_header(obj_table[index]);
33 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
34 : : if (hdr->mp != m->pool || hdr->mp != hp)
35 : : plt_err("Pool Header Mismatch");
36 : : #endif
37 : 0 : m->pool = mp;
38 : 0 : hdr->mp = mp;
39 : 0 : roc_npa_aura_op_free(hp->pool_id, 0,
40 : 0 : (uint64_t)obj_table[index]);
41 : : }
42 : :
43 : 0 : return 0;
44 : : }
45 : :
46 : : static int __rte_hot
47 : 0 : cn10k_hwpool_deq(struct rte_mempool *hp, void **obj_table, unsigned int n)
48 : : {
49 : : unsigned int index;
50 : : uint64_t obj;
51 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
52 : : struct rte_mempool *mp;
53 : :
54 : : mp = CNXK_MEMPOOL_CONFIG(hp);
55 : : #endif
56 : :
57 [ # # ]: 0 : for (index = 0; index < n; index++, obj_table++) {
58 : : struct rte_mempool_objhdr *hdr;
59 : : struct rte_mbuf *m;
60 : : int retry = 4;
61 : :
62 : : /* Retry few times before failing */
63 : : do {
64 : : obj = roc_npa_aura_op_alloc(hp->pool_id, 0);
65 : : } while (retry-- && (obj == 0));
66 : :
67 : : if (obj == 0) {
68 : 0 : cn10k_hwpool_enq(hp, obj_table - index, index);
69 : 0 : return -ENOENT;
70 : : }
71 : : /* Update mempool information in the mbuf */
72 : : hdr = rte_mempool_get_header(PLT_PTR_CAST(obj));
73 : : m = PLT_PTR_CAST(obj);
74 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
75 : : if (hdr->mp != m->pool || hdr->mp != mp)
76 : : plt_err("Pool Header Mismatch");
77 : : #endif
78 : : m->pool = hp;
79 : : hdr->mp = hp;
80 : : *obj_table = (void *)obj;
81 : : }
82 : :
83 : : return 0;
84 : : }
85 : :
86 : : static unsigned int
87 : 0 : cn10k_hwpool_get_count(const struct rte_mempool *hp)
88 : : {
89 : 0 : return (unsigned int)roc_npa_aura_op_available(hp->pool_id);
90 : : }
91 : :
92 : : static int
93 : 0 : cn10k_hwpool_alloc(struct rte_mempool *hp)
94 : : {
95 : 0 : uint64_t aura_handle = 0;
96 : : struct rte_mempool *mp;
97 : : uint32_t pool_id;
98 : : int rc;
99 : :
100 [ # # ]: 0 : if (hp->cache_size) {
101 : 0 : plt_err("Hwpool does not support cache");
102 : 0 : return -EINVAL;
103 : : }
104 : :
105 [ # # ]: 0 : if (CNXK_MEMPOOL_FLAGS(hp)) {
106 : 0 : plt_err("Flags must not be passed to hwpool ops");
107 : 0 : return -EINVAL;
108 : : }
109 : :
110 : 0 : mp = CNXK_MEMPOOL_CONFIG(hp);
111 [ # # ]: 0 : if (!mp) {
112 : 0 : plt_err("Invalid rte_mempool passed as pool_config");
113 : 0 : return -EINVAL;
114 : : }
115 [ # # ]: 0 : if (mp->cache_size) {
116 : 0 : plt_err("Hwpool does not support attaching to pool with cache");
117 : 0 : return -EINVAL;
118 : : }
119 : :
120 [ # # ]: 0 : if (hp->elt_size != mp->elt_size ||
121 : 0 : hp->header_size != mp->header_size ||
122 [ # # # # ]: 0 : hp->trailer_size != mp->trailer_size || hp->size != mp->size) {
123 : 0 : plt_err("Hwpool parameters matching with master pool");
124 : 0 : return -EINVAL;
125 : : }
126 : :
127 : : /* Create the NPA aura */
128 : 0 : pool_id = roc_npa_aura_handle_to_aura(mp->pool_id);
129 : 0 : rc = roc_npa_aura_create(&aura_handle, hp->size, NULL, (int)pool_id, 0);
130 [ # # ]: 0 : if (rc) {
131 : 0 : plt_err("Failed to create aura rc=%d", rc);
132 : 0 : return rc;
133 : : }
134 : :
135 : : /* Set the flags for the hardware pool */
136 : 0 : CNXK_MEMPOOL_SET_FLAGS(hp, CNXK_MEMPOOL_F_IS_HWPOOL);
137 : 0 : hp->pool_id = aura_handle;
138 : 0 : plt_npa_dbg("aura_handle=0x%" PRIx64, aura_handle);
139 : :
140 : 0 : return 0;
141 : : }
142 : :
143 : : static void
144 : 0 : cn10k_hwpool_free(struct rte_mempool *hp)
145 : : {
146 : : int rc = 0;
147 : :
148 : 0 : plt_npa_dbg("aura_handle=0x%" PRIx64, hp->pool_id);
149 : : /* It can happen that rte_mempool_free() is called immediately after
150 : : * rte_mempool_create_empty(). In such cases the NPA pool will not be
151 : : * allocated.
152 : : */
153 [ # # ]: 0 : if (roc_npa_aura_handle_to_base(hp->pool_id) == 0)
154 : : return;
155 : :
156 : 0 : rc = roc_npa_aura_destroy(hp->pool_id);
157 [ # # ]: 0 : if (rc)
158 : 0 : plt_err("Failed to destroy aura rc=%d", rc);
159 : : }
160 : :
161 : : static ssize_t
162 : 0 : cn10k_hwpool_calc_mem_size(const struct rte_mempool *hp, uint32_t obj_num,
163 : : uint32_t pg_shift, size_t *min_chunk_size,
164 : : size_t *align)
165 : : {
166 : : RTE_SET_USED(hp);
167 : : RTE_SET_USED(obj_num);
168 : : RTE_SET_USED(pg_shift);
169 : 0 : *min_chunk_size = CN10K_HWPOOL_MEM_SIZE;
170 : 0 : *align = CN10K_HWPOOL_MEM_SIZE;
171 : : /* Return a minimum mem size so that hwpool can also be initialized just
172 : : * like a regular pool. This memzone will not be used anywhere.
173 : : */
174 : 0 : return CN10K_HWPOOL_MEM_SIZE;
175 : : }
176 : :
177 : : static int
178 : 0 : cn10k_hwpool_populate(struct rte_mempool *hp, unsigned int max_objs,
179 : : void *vaddr, rte_iova_t iova, size_t len,
180 : : rte_mempool_populate_obj_cb_t *obj_cb, void *obj_cb_arg)
181 : : {
182 : : uint64_t start_iova, end_iova;
183 : : struct rte_mempool *mp;
184 : :
185 : : RTE_SET_USED(max_objs);
186 : : RTE_SET_USED(vaddr);
187 : : RTE_SET_USED(iova);
188 : : RTE_SET_USED(len);
189 : : RTE_SET_USED(obj_cb);
190 : : RTE_SET_USED(obj_cb_arg);
191 : : /* HW pools does not require populating anything as these pools are
192 : : * only associated with NPA aura. The NPA pool being used is that of
193 : : * another rte_mempool. Only copy the iova range from the aura of
194 : : * the other rte_mempool to this pool's aura.
195 : : */
196 : 0 : mp = CNXK_MEMPOOL_CONFIG(hp);
197 : 0 : roc_npa_aura_op_range_get(mp->pool_id, &start_iova, &end_iova);
198 : 0 : roc_npa_aura_op_range_set(hp->pool_id, start_iova, end_iova);
199 : :
200 : 0 : return hp->size;
201 : : }
202 : :
203 : : int
204 : 0 : rte_pmd_cnxk_mempool_mbuf_exchange(struct rte_mbuf *m1, struct rte_mbuf *m2)
205 : : {
206 : : struct rte_mempool_objhdr *hdr;
207 : :
208 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
209 : : if (!(CNXK_MEMPOOL_FLAGS(m1->pool) & CNXK_MEMPOOL_F_NO_RANGE_CHECK) ||
210 : : !(CNXK_MEMPOOL_FLAGS(m2->pool) & CNXK_MEMPOOL_F_NO_RANGE_CHECK)) {
211 : : plt_err("Pools must have range check disabled");
212 : : return -EINVAL;
213 : : }
214 : : if (m1->pool->elt_size != m2->pool->elt_size ||
215 : : m1->pool->header_size != m2->pool->header_size ||
216 : : m1->pool->trailer_size != m2->pool->trailer_size ||
217 : : m1->pool->size != m2->pool->size) {
218 : : plt_err("Parameters of pools involved in exchange does not match");
219 : : return -EINVAL;
220 : : }
221 : : #endif
222 : 0 : RTE_SWAP(m1->pool, m2->pool);
223 : : hdr = rte_mempool_get_header(m1);
224 : 0 : hdr->mp = m1->pool;
225 : : hdr = rte_mempool_get_header(m2);
226 : 0 : hdr->mp = m2->pool;
227 : 0 : return 0;
228 : : }
229 : :
230 : : int
231 : 0 : rte_pmd_cnxk_mempool_is_hwpool(struct rte_mempool *mp)
232 : : {
233 : 0 : return !!(CNXK_MEMPOOL_FLAGS(mp) & CNXK_MEMPOOL_F_IS_HWPOOL);
234 : : }
235 : :
236 : : int
237 : 0 : rte_pmd_cnxk_mempool_range_check_disable(struct rte_mempool *mp)
238 : : {
239 [ # # ]: 0 : if (rte_pmd_cnxk_mempool_is_hwpool(mp)) {
240 : : /* Disable only aura range check for hardware pools */
241 : 0 : roc_npa_aura_op_range_set(mp->pool_id, CN10K_NPA_IOVA_RANGE_MIN,
242 : : CN10K_NPA_IOVA_RANGE_MAX);
243 : 0 : CNXK_MEMPOOL_SET_FLAGS(mp, CNXK_MEMPOOL_F_NO_RANGE_CHECK);
244 : 0 : mp = CNXK_MEMPOOL_CONFIG(mp);
245 : : }
246 : :
247 : : /* No need to disable again if already disabled */
248 [ # # ]: 0 : if (CNXK_MEMPOOL_FLAGS(mp) & CNXK_MEMPOOL_F_NO_RANGE_CHECK)
249 : : return 0;
250 : :
251 : : /* Disable aura/pool range check */
252 : 0 : roc_npa_pool_op_range_set(mp->pool_id, CN10K_NPA_IOVA_RANGE_MIN,
253 : : CN10K_NPA_IOVA_RANGE_MAX);
254 [ # # ]: 0 : if (roc_npa_pool_range_update_check(mp->pool_id) < 0)
255 : : return -EBUSY;
256 : :
257 : 0 : CNXK_MEMPOOL_SET_FLAGS(mp, CNXK_MEMPOOL_F_NO_RANGE_CHECK);
258 : 0 : return 0;
259 : : }
260 : :
261 : : static struct rte_mempool_ops cn10k_hwpool_ops = {
262 : : .name = "cn10k_hwpool_ops",
263 : : .alloc = cn10k_hwpool_alloc,
264 : : .free = cn10k_hwpool_free,
265 : : .enqueue = cn10k_hwpool_enq,
266 : : .dequeue = cn10k_hwpool_deq,
267 : : .get_count = cn10k_hwpool_get_count,
268 : : .calc_mem_size = cn10k_hwpool_calc_mem_size,
269 : : .populate = cn10k_hwpool_populate,
270 : : };
271 : :
272 : 252 : RTE_MEMPOOL_REGISTER_OPS(cn10k_hwpool_ops);
|