Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2014-2020 Broadcom
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include <inttypes.h>
7 : : #include <rte_malloc.h>
8 : : #include <unistd.h>
9 : :
10 : : #include "bnxt.h"
11 : : #include "bnxt_ring.h"
12 : : #include "bnxt_mpc.h"
13 : : #include "bnxt_hwrm.h"
14 : : #include "hsi_struct_def_dpdk.h"
15 : :
16 : : /*#define MPC_DEBUG 1*/
17 : :
18 : : #define BNXT_MPC_BP_SIZE 16
19 : :
20 : 0 : static int bnxt_mpc_chnls_enable(struct bnxt *bp)
21 : : {
22 : 0 : struct bnxt_mpc *mpc = bp->mpc;
23 : : uint8_t mpc_chnl_msk = 0;
24 : : int i, rc;
25 : :
26 [ # # ]: 0 : if (!mpc)
27 : : return -EINVAL;
28 : :
29 [ # # ]: 0 : for (i = 0; i < BNXT_MPC_CHNL_MAX; i++) {
30 [ # # ]: 0 : if (!(mpc->mpc_chnls_cap & (1 << i)))
31 : 0 : continue;
32 : 0 : mpc_chnl_msk |= (1 << i);
33 : : }
34 : 0 : mpc->mpc_chnls_en = mpc_chnl_msk;
35 : :
36 [ # # ]: 0 : if (!BNXT_PF(bp))
37 : : return 0;
38 : :
39 : 0 : rc = bnxt_hwrm_func_cfg_mpc(bp, mpc_chnl_msk, true);
40 [ # # ]: 0 : if (rc != 0) {
41 : 0 : mpc->mpc_chnls_en = 0;
42 : 0 : PMD_DRV_LOG_LINE(ERR, "MPC chnls enabling failed rc:%d", rc);
43 : : }
44 : :
45 : : return rc;
46 : : }
47 : :
48 : 0 : static int bnxt_mpc_chnls_disable(struct bnxt *bp)
49 : : {
50 : 0 : struct bnxt_mpc *mpc = bp->mpc;
51 : : uint8_t mpc_chnl_msk = 0;
52 : : int i, rc;
53 : :
54 [ # # ]: 0 : if (!mpc)
55 : : return -EINVAL;
56 : 0 : mpc->mpc_chnls_en = 0;
57 : :
58 [ # # ]: 0 : if (!BNXT_PF(bp))
59 : : return 0;
60 : :
61 : : for (i = 0; i < BNXT_MPC_CHNL_MAX; i++) {
62 : : if (!(mpc->mpc_chnls_en & (1 << i)))
63 : : continue;
64 : : mpc_chnl_msk |= (1 << i);
65 : : }
66 : 0 : rc = bnxt_hwrm_func_cfg_mpc(bp, mpc_chnl_msk, false);
67 [ # # ]: 0 : if (rc != 0)
68 : 0 : PMD_DRV_LOG_LINE(ERR, "MPC chnls disabling failed rc:%d", rc);
69 : :
70 : : return rc;
71 : : }
72 : :
73 : 0 : static void bnxt_mpc_queue_release_mbufs(struct bnxt_mpc_txq *mpc_queue)
74 : : {
75 : : struct bnxt_sw_mpc_bd *sw_ring;
76 : : uint16_t i;
77 : :
78 [ # # ]: 0 : if (!mpc_queue)
79 : : return;
80 : :
81 : 0 : sw_ring = mpc_queue->mpc_ring->mpc_buf_ring;
82 [ # # ]: 0 : if (!sw_ring)
83 : : return;
84 : :
85 [ # # ]: 0 : for (i = 0; i < mpc_queue->mpc_ring->mpc_ring_struct->ring_size; i++) {
86 [ # # ]: 0 : if (sw_ring[i].mpc_mbuf) {
87 : 0 : rte_free(sw_ring[i].mpc_mbuf);
88 : 0 : sw_ring[i].mpc_mbuf = NULL;
89 : : }
90 : : }
91 : : }
92 : :
93 : 0 : static void bnxt_mpc_queue_release_one(struct bnxt_mpc_txq *mpc_queue)
94 : : {
95 [ # # ]: 0 : if (!mpc_queue)
96 : : return;
97 : :
98 [ # # ]: 0 : if (is_bnxt_in_error(mpc_queue->bp))
99 : : return;
100 : : /* Free MPC ring HW descriptors */
101 : 0 : bnxt_mpc_queue_release_mbufs(mpc_queue);
102 : 0 : bnxt_free_ring(mpc_queue->mpc_ring->mpc_ring_struct);
103 : : /* Free MPC completion ring HW descriptors */
104 : 0 : bnxt_free_ring(mpc_queue->cp_ring->cp_ring_struct);
105 : :
106 : 0 : rte_memzone_free(mpc_queue->mz);
107 : 0 : mpc_queue->mz = NULL;
108 : :
109 : 0 : rte_free(mpc_queue->free);
110 : 0 : rte_free(mpc_queue);
111 : : }
112 : :
113 : 0 : static void bnxt_mpc_ring_free_one(struct bnxt_mpc_txq *mpc_queue)
114 : : {
115 : : struct bnxt_cp_ring_info *cpr;
116 : : struct bnxt_mpc_ring_info *mpr;
117 : : struct bnxt_ring *ring;
118 : :
119 [ # # ]: 0 : if (!mpc_queue)
120 : : return;
121 : :
122 [ # # ]: 0 : if (is_bnxt_in_error(mpc_queue->bp))
123 : : return;
124 : :
125 : 0 : mpr = mpc_queue->mpc_ring;
126 : 0 : ring = mpr->mpc_ring_struct;
127 [ # # ]: 0 : if (ring->fw_ring_id == INVALID_HW_RING_ID)
128 : : return;
129 : :
130 : 0 : cpr = mpc_queue->cp_ring;
131 : 0 : bnxt_hwrm_ring_free(mpc_queue->bp, ring,
132 : : HWRM_RING_FREE_INPUT_RING_TYPE_TX,
133 : 0 : cpr->cp_ring_struct->fw_ring_id);
134 : 0 : ring->fw_ring_id = INVALID_HW_RING_ID;
135 : 0 : memset(mpr->mpc_desc_ring, 0,
136 : 0 : mpr->mpc_ring_struct->ring_size * sizeof(*mpr->mpc_desc_ring));
137 : 0 : memset(mpr->mpc_buf_ring, 0,
138 : 0 : mpr->mpc_ring_struct->ring_size * sizeof(*mpr->mpc_buf_ring));
139 : 0 : mpr->raw_prod = 0;
140 : 0 : mpr->raw_cons = 0;
141 : :
142 : 0 : bnxt_free_cp_ring(mpc_queue->bp, cpr);
143 : 0 : bnxt_hwrm_stat_ctx_free(mpc_queue->bp, cpr);
144 : : }
145 : :
146 : 0 : int bnxt_mpc_close(struct bnxt *bp)
147 : : {
148 : : int i, rc = 0;
149 : : struct bnxt_mpc_txq *mpc_queue;
150 : : struct bnxt_mpc *mpc;
151 : :
152 : 0 : rc = is_bnxt_in_error(bp);
153 [ # # ]: 0 : if (rc)
154 : : return rc;
155 : :
156 [ # # ]: 0 : if (!bp->mpc)
157 : : return 0;
158 : :
159 : : mpc = bp->mpc;
160 : : /* free the MPC TX ring for each channel. */
161 [ # # ]: 0 : for (i = 0; i < BNXT_MPC_CHNL_MAX; i++) {
162 [ # # ]: 0 : if (!(mpc->mpc_chnls_en & (1 << i)))
163 : 0 : continue;
164 : 0 : mpc_queue = mpc->mpc_txq[i];
165 [ # # ]: 0 : if (!mpc_queue)
166 : 0 : continue;
167 : 0 : bnxt_mpc_ring_free_one(mpc_queue);
168 : 0 : bnxt_mpc_queue_release_one(mpc_queue);
169 : 0 : mpc->mpc_txq[i] = NULL;
170 : : }
171 : :
172 : 0 : rc = bnxt_mpc_chnls_disable(bp);
173 [ # # ]: 0 : if (rc)
174 : 0 : PMD_DRV_LOG_LINE(ERR, "MPC channels disable failed rc:%d", rc);
175 : :
176 : : return rc;
177 : : }
178 : :
179 : 0 : static int bnxt_init_mpc_ring_struct(struct bnxt_mpc_txq *mpc_queue,
180 : : unsigned int socket_id)
181 : : {
182 : : struct bnxt_cp_ring_info *cpr;
183 : : struct bnxt_mpc_ring_info *mpr;
184 : : struct bnxt_ring *ring;
185 : : int rc = 0;
186 : :
187 : 0 : mpr = rte_zmalloc_socket("bnxt_mpc_ring",
188 : : sizeof(struct bnxt_mpc_ring_info),
189 : : RTE_CACHE_LINE_SIZE, socket_id);
190 [ # # ]: 0 : if (mpr == NULL)
191 : : return -ENOMEM;
192 : 0 : mpc_queue->mpc_ring = mpr;
193 : :
194 : 0 : ring = rte_zmalloc_socket("bnxt_mpc_ring_struct",
195 : : sizeof(struct bnxt_ring),
196 : : RTE_CACHE_LINE_SIZE, socket_id);
197 [ # # ]: 0 : if (ring == NULL) {
198 : 0 : PMD_DRV_LOG_LINE(ERR, "MPC ring struct alloc failed rc:%d", rc);
199 : : rc = -ENOMEM;
200 : 0 : goto bnxt_init_mpc_ring_struct_err;
201 : : }
202 : :
203 : 0 : mpr->mpc_ring_struct = ring;
204 : 0 : ring->ring_size = rte_align32pow2(mpc_queue->nb_mpc_desc);
205 : 0 : ring->ring_mask = ring->ring_size - 1;
206 : 0 : ring->bd = (void *)mpr->mpc_desc_ring;
207 : 0 : ring->bd_dma = mpr->mpc_desc_mapping;
208 : 0 : ring->vmem_size = ring->ring_size * sizeof(struct bnxt_sw_mpc_bd);
209 : 0 : ring->vmem = (void **)&mpr->mpc_buf_ring;
210 : 0 : ring->fw_ring_id = INVALID_HW_RING_ID;
211 : :
212 : 0 : cpr = rte_zmalloc_socket("bnxt_mpc_ring",
213 : : sizeof(struct bnxt_cp_ring_info),
214 : : RTE_CACHE_LINE_SIZE, socket_id);
215 [ # # ]: 0 : if (cpr == NULL) {
216 : 0 : PMD_DRV_LOG_LINE(ERR, "MPC cp ring alloc failed rc:%d", rc);
217 : : rc = -ENOMEM;
218 : 0 : goto bnxt_init_mpc_ring_struct_err1;
219 : : }
220 : 0 : mpc_queue->cp_ring = cpr;
221 : :
222 : 0 : ring = rte_zmalloc_socket("bnxt_mpc_ring_struct",
223 : : sizeof(struct bnxt_ring),
224 : : RTE_CACHE_LINE_SIZE, socket_id);
225 [ # # ]: 0 : if (ring == NULL) {
226 : 0 : PMD_DRV_LOG_LINE(ERR, "MPC cp ring struct alloc failed rc:%d", rc);
227 : : rc = -ENOMEM;
228 : 0 : goto bnxt_init_mpc_ring_struct_err2;
229 : : }
230 : 0 : cpr->cp_ring_struct = ring;
231 : 0 : ring->ring_size = mpr->mpc_ring_struct->ring_size;
232 : 0 : ring->ring_mask = ring->ring_size - 1;
233 : 0 : ring->bd = (void *)cpr->cp_desc_ring;
234 : 0 : ring->bd_dma = cpr->cp_desc_mapping;
235 : 0 : ring->vmem_size = 0;
236 : 0 : ring->vmem = NULL;
237 : 0 : ring->fw_ring_id = INVALID_HW_RING_ID;
238 : :
239 : 0 : return 0;
240 : :
241 : : bnxt_init_mpc_ring_struct_err2:
242 : 0 : rte_free(cpr);
243 : 0 : bnxt_init_mpc_ring_struct_err1:
244 : 0 : rte_free(ring);
245 : 0 : bnxt_init_mpc_ring_struct_err:
246 : 0 : rte_free(mpr);
247 : 0 : mpc_queue->mpc_ring = NULL;
248 : 0 : return rc;
249 : : }
250 : :
251 : : /*
252 : : * For a MPC queue, allocates a completion ring with vmem and bd ring,
253 : : * stats mem, a TX ring with vmem and bd ring.
254 : : *
255 : : * Order in the allocation is:
256 : : * stats - Always non-zero length
257 : : * cp vmem - Always zero-length, supported for the bnxt_ring abstraction
258 : : * tx vmem - Only non-zero length
259 : : * cp bd ring - Always non-zero length
260 : : * tx bd ring - Only non-zero length
261 : : */
262 : :
263 : 0 : static int bnxt_alloc_mpc_rings(struct bnxt_mpc_txq *mpc_queue,
264 : : const char *suffix)
265 : : {
266 : : struct bnxt_ring *cp_ring;
267 : : struct bnxt_cp_ring_info *cp_ring_info;
268 : : struct bnxt_mpc_ring_info *mpc_ring_info;
269 : : struct bnxt_ring *ring;
270 : : struct rte_pci_device *pdev;
271 : : const struct rte_memzone *mz = NULL;
272 : : char mz_name[RTE_MEMZONE_NAMESIZE];
273 : : rte_iova_t mz_phys_addr;
274 : :
275 [ # # ]: 0 : if (!mpc_queue)
276 : : return -EINVAL;
277 : :
278 : 0 : pdev = mpc_queue->bp->pdev;
279 : 0 : mpc_ring_info = mpc_queue->mpc_ring;
280 : 0 : cp_ring = mpc_queue->cp_ring->cp_ring_struct;
281 : : cp_ring_info = mpc_queue->cp_ring;
282 : :
283 : : int stats_len = BNXT_HWRM_CTX_GET_SIZE(mpc_queue->bp);
284 : : stats_len = RTE_CACHE_LINE_ROUNDUP(stats_len);
285 : : stats_len = RTE_ALIGN(stats_len, 128);
286 : :
287 : : int cp_vmem_start = stats_len;
288 : 0 : int cp_vmem_len = RTE_CACHE_LINE_ROUNDUP(cp_ring->vmem_size);
289 : 0 : cp_vmem_len = RTE_ALIGN(cp_vmem_len, 128);
290 : :
291 : : int nq_vmem_len = RTE_CACHE_LINE_ROUNDUP(cp_ring->vmem_size);
292 : : nq_vmem_len = RTE_ALIGN(nq_vmem_len, 128);
293 : :
294 : 0 : int nq_vmem_start = cp_vmem_start + cp_vmem_len;
295 : :
296 : 0 : int mpc_vmem_start = nq_vmem_start + nq_vmem_len;
297 : 0 : int mpc_vmem_len =
298 : 0 : RTE_CACHE_LINE_ROUNDUP(mpc_ring_info->mpc_ring_struct->vmem_size);
299 : 0 : mpc_vmem_len = RTE_ALIGN(mpc_vmem_len, 128);
300 : :
301 : 0 : int cp_ring_start = mpc_vmem_start + mpc_vmem_len;
302 : 0 : cp_ring_start = RTE_ALIGN(cp_ring_start, 4096);
303 : :
304 : 0 : int cp_ring_len = RTE_CACHE_LINE_ROUNDUP(cp_ring->ring_size *
305 : : sizeof(struct cmpl_base));
306 : 0 : cp_ring_len = RTE_ALIGN(cp_ring_len, 128);
307 : :
308 : 0 : int mpc_ring_start = cp_ring_start + cp_ring_len;
309 : 0 : mpc_ring_start = RTE_ALIGN(mpc_ring_start, 4096);
310 : 0 : int mpc_ring_len =
311 : 0 : RTE_CACHE_LINE_ROUNDUP(mpc_ring_info->mpc_ring_struct->ring_size *
312 : : sizeof(struct tx_bd_mp_cmd));
313 : 0 : mpc_ring_len = RTE_ALIGN(mpc_ring_len, 4096);
314 : :
315 : 0 : int total_alloc_len = mpc_ring_start + mpc_ring_len;
316 : 0 : snprintf(mz_name, RTE_MEMZONE_NAMESIZE,
317 : : "bnxt_" PCI_PRI_FMT "-%04x_%s", pdev->addr.domain,
318 : 0 : pdev->addr.bus, pdev->addr.devid, pdev->addr.function,
319 : 0 : mpc_queue->chnl_id, suffix);
320 : 0 : mz_name[RTE_MEMZONE_NAMESIZE - 1] = 0;
321 : 0 : mz = rte_memzone_lookup(mz_name);
322 [ # # ]: 0 : if (!mz) {
323 : 0 : mz = rte_memzone_reserve_aligned(mz_name, total_alloc_len,
324 : : SOCKET_ID_ANY,
325 : : RTE_MEMZONE_2MB |
326 : : RTE_MEMZONE_SIZE_HINT_ONLY |
327 : : RTE_MEMZONE_IOVA_CONTIG,
328 : 0 : getpagesize());
329 [ # # # # ]: 0 : if (mz == NULL || !mz->addr)
330 : : return -ENOMEM;
331 : : }
332 [ # # ]: 0 : memset(mz->addr, 0, mz->len);
333 : 0 : mz_phys_addr = mz->iova;
334 : :
335 : 0 : mpc_queue->mz = mz;
336 : 0 : ring = mpc_ring_info->mpc_ring_struct;
337 : :
338 : 0 : ring->bd = ((char *)mz->addr + mpc_ring_start);
339 : 0 : mpc_ring_info->mpc_desc_ring = (struct tx_bd_mp_cmd *)ring->bd;
340 : 0 : ring->bd_dma = mz_phys_addr + mpc_ring_start;
341 : 0 : mpc_ring_info->mpc_desc_mapping = ring->bd_dma;
342 : 0 : ring->mem_zone = (const void *)mz;
343 : :
344 [ # # ]: 0 : if (ring->vmem_size) {
345 : 0 : ring->vmem = (void **)((char *)mz->addr + mpc_vmem_start);
346 : 0 : mpc_ring_info->mpc_buf_ring =
347 : : (struct bnxt_sw_mpc_bd *)ring->vmem;
348 : : }
349 : :
350 : 0 : cp_ring->bd = ((char *)mz->addr + cp_ring_start);
351 : 0 : cp_ring->bd_dma = mz_phys_addr + cp_ring_start;
352 : 0 : cp_ring_info->cp_desc_ring = cp_ring->bd;
353 : 0 : cp_ring_info->cp_desc_mapping = cp_ring->bd_dma;
354 : 0 : cp_ring->mem_zone = (const void *)mz;
355 : :
356 [ # # ]: 0 : if (cp_ring->vmem_size)
357 : 0 : *cp_ring->vmem = (char *)mz->addr + stats_len;
358 : :
359 : 0 : cp_ring_info->hw_stats = mz->addr;
360 : 0 : cp_ring_info->hw_stats_map = mz_phys_addr;
361 : 0 : cp_ring_info->hw_stats_ctx_id = HWRM_NA_SIGNATURE;
362 : :
363 : 0 : return 0;
364 : : }
365 : :
366 : : static void bnxt_init_one_mpc_ring(struct bnxt_mpc_txq *mpc_queue)
367 : : {
368 : 0 : struct bnxt_mpc_ring_info *mpr = mpc_queue->mpc_ring;
369 : 0 : struct bnxt_cp_ring_info *cpr = mpc_queue->cp_ring;
370 : 0 : struct bnxt_ring *ring = mpr->mpc_ring_struct;
371 : :
372 : 0 : mpc_queue->wake_thresh = ring->ring_size / 2;
373 : 0 : ring->fw_ring_id = INVALID_HW_RING_ID;
374 : 0 : mpr->epoch = 0;
375 : 0 : cpr->epoch = 0;
376 : : }
377 : :
378 : : static uint16_t get_mpc_ring_logical_id(uint8_t mpc_cap,
379 : : enum bnxt_mpc_chnl chnl_id,
380 : : uint16_t offset)
381 : : {
382 : : unsigned int i;
383 : : uint8_t logical_id = 0;
384 : :
385 [ # # ]: 0 : for (i = 0; i < BNXT_MPC_CHNL_MAX; i++) {
386 [ # # ]: 0 : if (!(mpc_cap & (1 << i)))
387 : 0 : continue;
388 : :
389 [ # # ]: 0 : if (i == chnl_id)
390 : 0 : return logical_id + offset;
391 : :
392 : 0 : logical_id++;
393 : : }
394 : :
395 : : return INVALID_HW_RING_ID;
396 : : }
397 : :
398 : 0 : static int bnxt_mpc_queue_setup_one(struct bnxt *bp, enum bnxt_mpc_chnl chnl_id,
399 : : uint16_t nb_desc, unsigned int socket_id)
400 : : {
401 : : int rc = 0;
402 : : struct bnxt_mpc *mpc;
403 : : struct bnxt_mpc_txq *mpc_queue;
404 : :
405 [ # # # # ]: 0 : if (!bp || !bp->mpc)
406 : : return 0;
407 : :
408 : : mpc = bp->mpc;
409 : 0 : mpc_queue = rte_zmalloc_socket("bnxt_mpc_queue",
410 : : sizeof(struct bnxt_mpc_txq),
411 : : RTE_CACHE_LINE_SIZE, socket_id);
412 [ # # ]: 0 : if (!mpc_queue) {
413 : 0 : PMD_DRV_LOG_LINE(ERR, "bnxt_mpc_queue allocation failed!");
414 : 0 : return -ENOMEM;
415 : : }
416 : :
417 : 0 : mpc_queue->free =
418 : 0 : rte_zmalloc_socket(NULL,
419 : : sizeof(struct bnxt_mpc_mbuf *) * nb_desc,
420 : : RTE_CACHE_LINE_SIZE, socket_id);
421 [ # # ]: 0 : if (!mpc_queue->free) {
422 : 0 : PMD_DRV_LOG_LINE(ERR, "allocation of mpc mbuf free array failed!");
423 : : rc = -ENOMEM;
424 : 0 : goto bnxt_mpc_queue_setup_one_err;
425 : : }
426 : 0 : mpc_queue->bp = bp;
427 : 0 : mpc_queue->nb_mpc_desc = nb_desc;
428 : : /* TBD: hardcoded to 1 for now and should be tuned later for perf */
429 : 0 : mpc_queue->free_thresh = BNXT_MPC_DESC_THRESH;
430 : :
431 : 0 : rc = bnxt_init_mpc_ring_struct(mpc_queue, socket_id);
432 [ # # ]: 0 : if (rc)
433 : 0 : goto bnxt_mpc_queue_setup_one_err1;
434 : :
435 : 0 : mpc_queue->chnl_id = chnl_id;
436 : :
437 : : /* allocate MPC TX ring hardware descriptors */
438 : 0 : rc = bnxt_alloc_mpc_rings(mpc_queue, "mpc");
439 [ # # ]: 0 : if (rc) {
440 : 0 : PMD_DRV_LOG_LINE(ERR, "ring_dma_zone_reserve for mpc_ring failed!");
441 : : rc = -ENOMEM;
442 : 0 : goto bnxt_mpc_queue_setup_one_err1;
443 : : }
444 : : bnxt_init_one_mpc_ring(mpc_queue);
445 : 0 : mpc_queue->queue_idx = get_mpc_ring_logical_id(bp->mpc->mpc_chnls_cap,
446 : : chnl_id,
447 : 0 : bp->tx_cp_nr_rings);
448 : 0 : mpc_queue->started = true;
449 : 0 : mpc->mpc_txq[chnl_id] = mpc_queue;
450 : :
451 : 0 : return 0;
452 : :
453 : 0 : bnxt_mpc_queue_setup_one_err1:
454 : 0 : rte_free(mpc_queue->free);
455 : 0 : bnxt_mpc_queue_setup_one_err:
456 : 0 : rte_free(mpc_queue);
457 : 0 : return rc;
458 : : }
459 : :
460 : 0 : static int bnxt_mpc_ring_alloc_one(struct bnxt *bp, enum bnxt_mpc_chnl chnl_id)
461 : : {
462 : : int rc = 0;
463 : : struct bnxt_mpc_txq *mpc_queue;
464 : : struct bnxt_cp_ring_info *cpr;
465 : : struct bnxt_ring *cp_ring;
466 : : struct bnxt_mpc_ring_info *mpr;
467 : : struct bnxt_ring *ring;
468 : : struct bnxt_coal coal;
469 : : uint32_t map_index;
470 : :
471 [ # # # # ]: 0 : if (!bp || !bp->mpc)
472 : : return 0;
473 : :
474 : 0 : mpc_queue = bp->mpc->mpc_txq[chnl_id];
475 [ # # ]: 0 : if (!mpc_queue)
476 : : return -EINVAL;
477 : :
478 : 0 : bnxt_init_dflt_coal(&coal);
479 : 0 : cpr = mpc_queue->cp_ring;
480 : 0 : cp_ring = cpr->cp_ring_struct;
481 : 0 : map_index = mpc_queue->queue_idx;
482 : :
483 : 0 : rc = bnxt_hwrm_stat_ctx_alloc(bp, cpr);
484 [ # # ]: 0 : if (rc) {
485 : 0 : PMD_DRV_LOG_LINE(ERR, "mpc ring %d stats alloc failed rc:%d!",
486 : : chnl_id, rc);
487 : 0 : return rc;
488 : : }
489 : 0 : rc = bnxt_alloc_cmpl_ring(bp, map_index, cpr);
490 [ # # ]: 0 : if (rc) {
491 : 0 : PMD_DRV_LOG_LINE(ERR, "mpc ring %d cmpl ring alloc failed rc:%d!",
492 : : chnl_id, rc);
493 : 0 : goto bnxt_mpc_ring_alloc_one_err;
494 : : }
495 : 0 : mpr = mpc_queue->mpc_ring;
496 : 0 : ring = mpr->mpc_ring_struct;
497 : 0 : map_index = BNXT_MPC_MAP_INDEX(chnl_id, mpc_queue->queue_idx);
498 : :
499 : 0 : rc = bnxt_hwrm_ring_alloc(bp,
500 : : ring,
501 : : HWRM_RING_ALLOC_INPUT_RING_TYPE_TX,
502 : : map_index,
503 : : cpr->hw_stats_ctx_id,
504 : 0 : cp_ring->fw_ring_id,
505 : : MPC_HW_COS_ID);
506 [ # # ]: 0 : if (rc) {
507 : 0 : PMD_DRV_LOG_LINE(ERR, "mpc ring %d tx ring alloc failed rc:%d!",
508 : : chnl_id, rc);
509 : 0 : goto bnxt_mpc_ring_alloc_one_err1;
510 : : }
511 : :
512 : 0 : bnxt_set_db(bp, &mpr->db, HWRM_RING_ALLOC_INPUT_RING_TYPE_TX, chnl_id,
513 : 0 : ring->fw_ring_id, ring->ring_mask);
514 : :
515 : 0 : bnxt_hwrm_set_ring_coal(bp, &coal, cp_ring->fw_ring_id);
516 : :
517 : 0 : return rc;
518 : :
519 : : bnxt_mpc_ring_alloc_one_err1:
520 : 0 : bnxt_free_cp_ring(bp, cpr);
521 : 0 : bnxt_mpc_ring_alloc_one_err:
522 : 0 : bnxt_hwrm_stat_ctx_free(bp, cpr);
523 : 0 : return rc;
524 : : }
525 : :
526 : 0 : int bnxt_mpc_open(struct bnxt *bp)
527 : : {
528 : : int rc = 0;
529 : : enum bnxt_mpc_chnl i;
530 : : struct bnxt_mpc *mpc;
531 : : unsigned int socket_id;
532 : :
533 : 0 : rc = is_bnxt_in_error(bp);
534 [ # # ]: 0 : if (rc)
535 : : return rc;
536 : :
537 [ # # ]: 0 : if (!bp->mpc)
538 : : return 0;
539 : :
540 : : /* enable the MPC channels first */
541 : 0 : rc = bnxt_mpc_chnls_enable(bp);
542 [ # # ]: 0 : if (rc) {
543 : 0 : PMD_DRV_LOG_LINE(ERR, "MPC channels enable failed rc:%d", rc);
544 : 0 : return rc;
545 : : }
546 : 0 : socket_id = rte_lcore_to_socket_id(rte_get_main_lcore());
547 : 0 : mpc = bp->mpc;
548 : :
549 : : /* Limit to MPC TE_CFA and RE_CFA */
550 : 0 : mpc->mpc_chnls_cap &= (1 << HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_TE_CFA) |
551 : : (1 << HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_RE_CFA);
552 : :
553 : : /* allocate one MPC TX ring for each channel. */
554 [ # # ]: 0 : for (i = 0; i < BNXT_MPC_CHNL_MAX; i++) {
555 [ # # ]: 0 : if (!(mpc->mpc_chnls_cap & (1 << i)))
556 : 0 : continue;
557 : 0 : rc = bnxt_mpc_queue_setup_one(bp, i, BNXT_MPC_NB_DESC, socket_id);
558 [ # # ]: 0 : if (rc) {
559 : 0 : PMD_DRV_LOG_LINE(ERR, "MPC queue %d setup failed rc:%d",
560 : : i, rc);
561 : 0 : goto bnxt_mpc_open_err;
562 : : }
563 : 0 : rc = bnxt_mpc_ring_alloc_one(bp, i);
564 [ # # ]: 0 : if (rc) {
565 : 0 : PMD_DRV_LOG_LINE(ERR, "MPC ring %d alloc failed rc:%d",
566 : : i, rc);
567 : 0 : goto bnxt_mpc_open_err;
568 : : }
569 : : }
570 : :
571 : : return rc;
572 : :
573 : 0 : bnxt_mpc_open_err:
574 : 0 : bnxt_mpc_close(bp);
575 : 0 : return rc;
576 : : }
577 : :
578 : 0 : int bnxt_mpc_cmd_cmpl(struct bnxt_mpc_txq *mpc_queue, struct bnxt_mpc_mbuf *out_msg)
579 : : {
580 : 0 : struct bnxt_cp_ring_info *cpr = mpc_queue->cp_ring;
581 : 0 : uint32_t raw_cons = cpr->cp_raw_cons;
582 : : uint32_t cons;
583 : : struct cmpl_base *mpc_cmpl;
584 : : uint32_t nb_mpc_cmds = 0;
585 : 0 : struct cmpl_base *cp_desc_ring = cpr->cp_desc_ring;
586 : 0 : struct bnxt_ring *cp_ring_struct = cpr->cp_ring_struct;
587 : 0 : uint32_t ring_mask = cp_ring_struct->ring_mask;
588 : : uint32_t idx = raw_cons;
589 : : uint32_t num_bds;
590 : : bool is_long =
591 : 0 : (out_msg->cmp_type == CMPL_BASE_TYPE_MID_PATH_LONG ? true : false);
592 : :
593 : : do {
594 : 0 : cons = RING_CMPL(ring_mask, raw_cons);
595 : 0 : mpc_cmpl = &cpr->cp_desc_ring[cons];
596 : :
597 : 0 : rte_prefetch_non_temporal(&cp_desc_ring[(cons + 2) &
598 : : ring_mask]);
599 : :
600 [ # # ]: 0 : if (!CMPL_VALID(mpc_cmpl, cpr->valid)) {
601 : : break;
602 [ # # ]: 0 : } else if (is_long) {
603 : 0 : uint32_t cons_tmp = cons + 1;
604 : : uint32_t valid;
605 : 0 : struct cmpl_base *tmp_mpc_cmpl = &cp_desc_ring[cons_tmp & ring_mask];
606 : :
607 [ # # ]: 0 : if ((cons_tmp & ring_mask) < (cons & ring_mask))
608 : 0 : valid = !cpr->valid;
609 : : else
610 : 0 : valid = cpr->valid;
611 : :
612 [ # # ]: 0 : if (!CMPL_VALID(tmp_mpc_cmpl, valid))
613 : : break;
614 : : }
615 : :
616 [ # # # # ]: 0 : NEXT_CMPL(cpr,
617 : : cons,
618 : : cpr->valid,
619 : : (is_long ? 2 : 1));
620 : :
621 : 0 : rte_prefetch0(&cp_desc_ring[cons]);
622 : :
623 [ # # ]: 0 : if (likely(CMP_TYPE(mpc_cmpl) == out_msg->cmp_type)) {
624 : : nb_mpc_cmds++;
625 : : idx = raw_cons;
626 : : raw_cons = cons;
627 : : break;
628 : : } else {
629 : 0 : PMD_DRV_LOG_LINE(DEBUG, "Unhandled CMP type %02x",
630 : : CMP_TYPE(mpc_cmpl));
631 : : }
632 : :
633 : : raw_cons = cons;
634 [ # # ]: 0 : } while (nb_mpc_cmds < ring_mask);
635 : :
636 : : if (nb_mpc_cmds) {
637 : 0 : memcpy(out_msg->msg_data,
638 [ # # ]: 0 : &cpr->cp_desc_ring[idx],
639 : : BNXT_MPC_BP_SIZE);
640 : :
641 [ # # ]: 0 : if (is_long) {
642 : 0 : uint32_t tidx = idx + 1;
643 : :
644 [ # # ]: 0 : if (tidx >= BNXT_MPC_NB_DESC)
645 : : tidx = 0;
646 : :
647 : 0 : memcpy(out_msg->msg_data + BNXT_MPC_BP_SIZE,
648 : 0 : &cpr->cp_desc_ring[tidx],
649 : : BNXT_MPC_BP_SIZE);
650 : : }
651 : :
652 [ # # ]: 0 : if (is_long)
653 : : num_bds = 2;
654 : : else
655 : : num_bds = 1;
656 : :
657 : 0 : cpr->cp_raw_cons = idx + num_bds;
658 : :
659 : : /* Handle the wrap */
660 [ # # ]: 0 : if (cpr->cp_raw_cons >= BNXT_MPC_NB_DESC) {
661 : 0 : cpr->epoch = (cpr->epoch == 0 ? 1 : 0);
662 : 0 : cpr->cp_raw_cons -= BNXT_MPC_NB_DESC;
663 : : }
664 : :
665 : 0 : bnxt_db_mpc_cq(cpr);
666 : : }
667 : :
668 : 0 : return nb_mpc_cmds;
669 : : }
670 : :
671 : 0 : static uint16_t bnxt_mpc_xmit(struct bnxt_mpc_mbuf *mpc_cmd,
672 : : struct bnxt_mpc_txq *mpc_queue,
673 : : uint32_t *opaque)
674 : : {
675 : 0 : struct bnxt_mpc_ring_info *mpr = mpc_queue->mpc_ring;
676 : 0 : struct bnxt_ring *ring = mpr->mpc_ring_struct;
677 : : unsigned short nr_bds = 0;
678 : : uint16_t prod;
679 : : struct bnxt_sw_mpc_bd *mpc_buf;
680 : : struct tx_bd_mp_cmd *mpc_bd;
681 : : uint8_t *msg_buf;
682 : : int i;
683 : :
684 [ # # ]: 0 : if (unlikely(is_bnxt_in_error(mpc_queue->bp)))
685 : : return -EIO;
686 : :
687 : 0 : nr_bds = (mpc_cmd->msg_size + sizeof(struct tx_bd_mp_cmd) - 1)
688 : 0 : / sizeof(struct tx_bd_mp_cmd) + 1;
689 : :
690 : 0 : prod = RING_IDX(ring, mpr->raw_prod);
691 : 0 : mpc_buf = &mpr->mpc_buf_ring[prod];
692 : 0 : mpc_buf->mpc_mbuf = mpc_cmd;
693 : 0 : mpc_buf->nr_bds = nr_bds;
694 : :
695 : 0 : mpc_bd = &mpr->mpc_desc_ring[prod];
696 : : memset(mpc_bd, 0, sizeof(struct tx_bd_mp_cmd));
697 : 0 : mpc_bd->opaque = *opaque;
698 : 0 : mpc_bd->flags_type = nr_bds << TX_BD_MP_CMD_FLAGS_BD_CNT_SFT;
699 : 0 : mpc_bd->flags_type |= TX_BD_MP_CMD_TYPE_TX_BD_MP_CMD;
700 : 0 : mpc_bd->len = mpc_cmd->msg_size;
701 : :
702 : : /* copy the messages to the subsequent inline bds */
703 [ # # ]: 0 : for (i = 0; i < nr_bds - 1; i++) {
704 : 0 : mpr->raw_prod = RING_NEXT(mpr->raw_prod) % BNXT_MPC_NB_DESC;
705 : 0 : prod = RING_IDX(ring, mpr->raw_prod);
706 : 0 : mpc_bd = &mpr->mpc_desc_ring[prod];
707 : 0 : msg_buf = mpc_cmd->msg_data + i * sizeof(struct tx_bd_mp_cmd);
708 : : memcpy(mpc_bd, msg_buf, sizeof(struct tx_bd_mp_cmd));
709 : : }
710 : :
711 : 0 : mpr->raw_prod = RING_NEXT(mpr->raw_prod) % BNXT_MPC_NB_DESC;
712 : 0 : return 0;
713 : : }
714 : :
715 : 0 : int bnxt_mpc_send(struct bnxt *bp,
716 : : struct bnxt_mpc_mbuf *in_msg,
717 : : struct bnxt_mpc_mbuf *out_msg,
718 : : uint32_t *opaque,
719 : : bool batch)
720 : : {
721 : : int rc;
722 : 0 : struct bnxt_mpc_txq *mpc_queue = bp->mpc->mpc_txq[in_msg->chnl_id];
723 : : int retry = BNXT_MPC_RX_RETRY;
724 : : uint32_t pi = 0;
725 : :
726 [ # # ]: 0 : if (out_msg->cmp_type != CMPL_BASE_TYPE_MID_PATH_SHORT &&
727 : : out_msg->cmp_type != CMPL_BASE_TYPE_MID_PATH_LONG)
728 : : return -1;
729 : :
730 : : #ifdef MPC_DEBUG
731 : : if (mpc_queue == NULL || mpc_queue->mpc_ring == NULL)
732 : : return -1;
733 : : #endif
734 : :
735 : : /*
736 : : * Save the producer index so that if wrapping occurs
737 : : * it can be detected.
738 : : */
739 : 0 : pi = mpc_queue->mpc_ring->raw_prod;
740 : 0 : rc = bnxt_mpc_xmit(in_msg, mpc_queue, opaque);
741 : :
742 [ # # ]: 0 : if (unlikely(rc))
743 : : return -1;
744 : : /*
745 : : * If the producer index wraps then toggle the epoch.
746 : : */
747 [ # # ]: 0 : if (mpc_queue->mpc_ring->raw_prod < pi)
748 : 0 : mpc_queue->mpc_ring->epoch = (mpc_queue->mpc_ring->epoch == 0 ? 1 : 0);
749 : :
750 : : /*
751 : : * Ring the Tx doorbell.
752 : : */
753 [ # # ]: 0 : bnxt_db_mpc_write(&mpc_queue->mpc_ring->db,
754 : : mpc_queue->mpc_ring->raw_prod,
755 : : mpc_queue->mpc_ring->epoch);
756 : :
757 [ # # ]: 0 : if (batch)
758 : : return 0;
759 : :
760 : : /* Wait for response */
761 : : do {
762 : 0 : rte_delay_us_block(BNXT_MPC_RX_US_DELAY);
763 : :
764 : 0 : rc = bnxt_mpc_cmd_cmpl(mpc_queue, out_msg);
765 : :
766 [ # # ]: 0 : if (rc == 1)
767 : : return 0;
768 : 0 : retry--;
769 [ # # ]: 0 : } while (retry);
770 : :
771 : : return -1;
772 : : }
|