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