Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2025 Yunsilicon Technology Co., Ltd.
3 : : */
4 : :
5 : : #include <rte_io.h>
6 : :
7 : : #include "xsc_log.h"
8 : : #include "xsc_defs.h"
9 : : #include "xsc_dev.h"
10 : : #include "xsc_ethdev.h"
11 : : #include "xsc_cmd.h"
12 : : #include "xsc_rx.h"
13 : :
14 : : #define XSC_MAX_RECV_LEN 9800
15 : :
16 : : static inline void
17 : : xsc_cq_to_mbuf(struct xsc_rxq_data *rxq, struct rte_mbuf *pkt,
18 : : volatile struct xsc_cqe *cqe)
19 : : {
20 : : uint32_t rss_hash_res = 0;
21 : :
22 : 0 : pkt->port = rxq->port_id;
23 : 0 : if (rxq->rss_hash) {
24 : 0 : rss_hash_res = rte_be_to_cpu_32(cqe->vni);
25 [ # # ]: 0 : if (rss_hash_res) {
26 : 0 : pkt->hash.rss = rss_hash_res;
27 : 0 : pkt->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
28 : : }
29 : : }
30 : : }
31 : :
32 : : static inline int
33 : 0 : xsc_rx_poll_len(struct xsc_rxq_data *rxq, volatile struct xsc_cqe *cqe)
34 : : {
35 : : int len;
36 : :
37 : : do {
38 : : len = 0;
39 : : int ret;
40 : :
41 [ # # ]: 0 : ret = xsc_check_cqe_own(cqe, rxq->cqe_n, rxq->cq_ci);
42 [ # # ]: 0 : if (unlikely(ret != XSC_CQE_OWNER_SW)) {
43 [ # # ]: 0 : if (unlikely(ret == XSC_CQE_OWNER_ERR)) {
44 : 0 : ++rxq->stats.rx_errors;
45 : : } else {
46 : : return 0;
47 : : }
48 : : }
49 : :
50 : 0 : rxq->cq_ci += 1;
51 : 0 : len = rte_le_to_cpu_32(cqe->msg_len);
52 : 0 : return len;
53 : : } while (1);
54 : : }
55 : :
56 : : static __rte_always_inline void
57 : : xsc_pkt_info_sync(struct rte_mbuf *rep, struct rte_mbuf *seg)
58 : : {
59 : 0 : if (rep != NULL && seg != NULL) {
60 : 0 : rep->data_len = seg->data_len;
61 : 0 : rep->pkt_len = seg->pkt_len;
62 : 0 : rep->data_off = seg->data_off;
63 : 0 : rep->port = seg->port;
64 : : }
65 : : }
66 : :
67 : : uint16_t
68 : 0 : xsc_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
69 : : {
70 : : struct xsc_rxq_data *rxq = dpdk_rxq;
71 : 0 : const uint32_t wqe_m = rxq->wqe_m;
72 : 0 : const uint32_t cqe_m = rxq->cqe_m;
73 : 0 : const uint32_t sge_n = rxq->sge_n;
74 : : struct rte_mbuf *pkt = NULL;
75 : : struct rte_mbuf *seg = NULL;
76 : 0 : volatile struct xsc_cqe *cqe = &(*rxq->cqes)[rxq->cq_ci & cqe_m];
77 : : uint32_t nb_pkts = 0;
78 : : uint64_t nb_bytes = 0;
79 : 0 : uint32_t rq_ci = rxq->rq_ci;
80 : : int len = 0;
81 : : uint32_t cq_ci_two = 0;
82 : : int valid_cqe_num = 0;
83 : : int cqe_msg_len = 0;
84 : : volatile struct xsc_cqe_u64 *cqe_u64 = NULL;
85 : : struct rte_mbuf *rep;
86 : : uint16_t cq_pi;
87 : : uint16_t cqe_pkts_n = 0;
88 : :
89 [ # # ]: 0 : if (rxq->cq_pi != NULL) {
90 : 0 : cq_pi = (*(volatile uint32_t *)(rxq->cq_pi)) & 0xFFFF;
91 [ # # ]: 0 : if (cq_pi == rxq->cq_ci)
92 : : return 0;
93 : 0 : cqe_pkts_n = (uint16_t)((cq_pi - rxq->cq_ci) & 0xFFFF);
94 : 0 : pkts_n = pkts_n < cqe_pkts_n ? pkts_n : cqe_pkts_n;
95 : : }
96 : :
97 [ # # ]: 0 : while (pkts_n) {
98 : 0 : uint32_t idx = rq_ci & wqe_m;
99 : 0 : volatile struct xsc_wqe_data_seg *wqe =
100 : 0 : &((volatile struct xsc_wqe_data_seg *)rxq->wqes)[idx << sge_n];
101 : :
102 : 0 : seg = (*rxq->elts)[idx];
103 : : rte_prefetch0(cqe);
104 : : rte_prefetch0(wqe);
105 : :
106 : 0 : rep = rte_mbuf_raw_alloc(seg->pool);
107 [ # # ]: 0 : if (unlikely(rep == NULL)) {
108 : 0 : ++rxq->stats.rx_nombuf;
109 : 0 : break;
110 : : }
111 : :
112 : : if (!pkt) {
113 [ # # ]: 0 : if (valid_cqe_num) {
114 : 0 : cqe = cqe + 1;
115 : : len = cqe_msg_len;
116 : : valid_cqe_num = 0;
117 [ # # # # ]: 0 : } else if ((rxq->cq_ci % 2 == 0) && (pkts_n > 1)) {
118 : 0 : cq_ci_two = (rxq->cq_ci & rxq->cqe_m) / 2;
119 : 0 : cqe_u64 = &(*rxq->cqes_u64)[cq_ci_two];
120 : : cqe = (volatile struct xsc_cqe *)cqe_u64;
121 : 0 : len = xsc_rx_poll_len(rxq, cqe);
122 [ # # ]: 0 : if (len > 0) {
123 : 0 : cqe_msg_len = xsc_rx_poll_len(rxq, cqe + 1);
124 [ # # ]: 0 : if (cqe_msg_len > 0)
125 : : valid_cqe_num = 1;
126 : : }
127 : : } else {
128 : 0 : cqe = &(*rxq->cqes)[rxq->cq_ci & rxq->cqe_m];
129 : 0 : len = xsc_rx_poll_len(rxq, cqe);
130 : : }
131 : :
132 [ # # ]: 0 : if (!len) {
133 : : rte_mbuf_raw_free(rep);
134 : : break;
135 : : }
136 : :
137 [ # # ]: 0 : if (len > rte_pktmbuf_data_len(seg)) {
138 : : rte_mbuf_raw_free(rep);
139 : : pkt = NULL;
140 : 0 : ++rq_ci;
141 : 0 : continue;
142 : : }
143 : :
144 : : pkt = seg;
145 [ # # ]: 0 : pkt->ol_flags &= RTE_MBUF_F_EXTERNAL;
146 : : xsc_cq_to_mbuf(rxq, pkt, cqe);
147 : :
148 [ # # ]: 0 : if (rxq->crc_present)
149 : 0 : len -= RTE_ETHER_CRC_LEN;
150 [ # # ]: 0 : rte_pktmbuf_pkt_len(pkt) = len;
151 : : }
152 : :
153 : : xsc_pkt_info_sync(rep, seg);
154 : 0 : (*rxq->elts)[idx] = rep;
155 : :
156 : : /* Fill wqe */
157 : 0 : wqe->va = rte_cpu_to_le_64(rte_pktmbuf_iova(rep));
158 : 0 : rte_pktmbuf_data_len(seg) = len;
159 : 0 : nb_bytes += rte_pktmbuf_pkt_len(pkt);
160 : :
161 : 0 : *(pkts++) = pkt;
162 : : pkt = NULL;
163 : 0 : --pkts_n;
164 : 0 : ++nb_pkts;
165 : 0 : ++rq_ci;
166 : : }
167 : :
168 [ # # # # ]: 0 : if (unlikely(nb_pkts == 0 && rq_ci == rxq->rq_ci))
169 : : return 0;
170 : :
171 : 0 : rxq->rq_ci = rq_ci;
172 : 0 : rxq->nb_rx_hold += nb_pkts;
173 : :
174 [ # # ]: 0 : if (rxq->nb_rx_hold >= rxq->rx_free_thresh) {
175 : 0 : union xsc_cq_doorbell cq_db = {
176 : : .cq_data = 0
177 : : };
178 : 0 : cq_db.next_cid = rxq->cq_ci;
179 : 0 : cq_db.cq_num = rxq->cqn;
180 : :
181 : 0 : union xsc_recv_doorbell rq_db = {
182 : : .recv_data = 0
183 : : };
184 : 0 : rq_db.next_pid = (rxq->rq_ci << sge_n);
185 : 0 : rq_db.qp_num = rxq->qpn;
186 : :
187 : 0 : rte_write32(rte_cpu_to_le_32(cq_db.cq_data), rxq->cq_db);
188 : 0 : rte_write32(rte_cpu_to_le_32(rq_db.recv_data), rxq->rq_db);
189 : 0 : rxq->nb_rx_hold = 0;
190 : : }
191 : :
192 : 0 : rxq->stats.rx_pkts += nb_pkts;
193 : 0 : rxq->stats.rx_bytes += nb_bytes;
194 : :
195 : 0 : return nb_pkts;
196 : : }
197 : :
198 : : static void
199 : 0 : xsc_rxq_initialize(struct xsc_dev *xdev, struct xsc_rxq_data *rxq_data)
200 : : {
201 : 0 : const uint32_t wqe_n = rxq_data->wqe_s;
202 : : uint32_t i;
203 : : uint32_t seg_len = 0;
204 : : struct xsc_hwinfo *hwinfo = &xdev->hwinfo;
205 [ # # ]: 0 : uint32_t rx_ds_num = hwinfo->recv_seg_num;
206 : : uint32_t log2ds = rte_log2_u32(rx_ds_num);
207 : : uintptr_t addr;
208 : : struct rte_mbuf *mbuf;
209 : : void *jumbo_buffer_pa = xdev->jumbo_buffer_pa;
210 : 0 : void *jumbo_buffer_va = xdev->jumbo_buffer_va;
211 : : volatile struct xsc_wqe_data_seg *seg;
212 : : volatile struct xsc_wqe_data_seg *seg_next;
213 : :
214 [ # # ]: 0 : for (i = 0; (i != wqe_n); ++i) {
215 : 0 : mbuf = (*rxq_data->elts)[i];
216 [ # # ]: 0 : seg = &((volatile struct xsc_wqe_data_seg *)rxq_data->wqes)[i * rx_ds_num];
217 : 0 : addr = (uintptr_t)rte_pktmbuf_iova(mbuf);
218 [ # # ]: 0 : if (rx_ds_num == 1)
219 : : seg_len = XSC_MAX_RECV_LEN;
220 : : else
221 : 0 : seg_len = rte_pktmbuf_data_len(mbuf);
222 : 0 : *seg = (struct xsc_wqe_data_seg){
223 : : .va = rte_cpu_to_le_64(addr),
224 : : .seg_len = rte_cpu_to_le_32(seg_len),
225 : : .lkey = 0,
226 : : };
227 : :
228 [ # # ]: 0 : if (rx_ds_num != 1) {
229 : : seg_next = seg + 1;
230 [ # # ]: 0 : if (jumbo_buffer_va == NULL) {
231 : 0 : jumbo_buffer_pa = rte_malloc(NULL, XSC_MAX_RECV_LEN, 0);
232 [ # # ]: 0 : if (jumbo_buffer_pa == NULL) {
233 : : /* Rely on mtu */
234 : 0 : seg->seg_len = XSC_MAX_RECV_LEN;
235 : 0 : PMD_DRV_LOG(ERR, "Failed to malloc jumbo_buffer");
236 : 0 : continue;
237 : : } else {
238 : 0 : jumbo_buffer_va =
239 : 0 : (void *)rte_malloc_virt2iova(jumbo_buffer_pa);
240 [ # # ]: 0 : if ((rte_iova_t)jumbo_buffer_va == RTE_BAD_IOVA) {
241 : 0 : seg->seg_len = XSC_MAX_RECV_LEN;
242 : 0 : PMD_DRV_LOG(ERR, "Failed to turn jumbo_buffer");
243 : 0 : continue;
244 : : }
245 : : }
246 : 0 : xdev->jumbo_buffer_pa = jumbo_buffer_pa;
247 : 0 : xdev->jumbo_buffer_va = jumbo_buffer_va;
248 : : }
249 : 0 : *seg_next = (struct xsc_wqe_data_seg){
250 : 0 : .va = rte_cpu_to_le_64((uint64_t)jumbo_buffer_va),
251 : 0 : .seg_len = rte_cpu_to_le_32(XSC_MAX_RECV_LEN - seg_len),
252 : : .lkey = 0,
253 : : };
254 : : }
255 : : }
256 : :
257 : 0 : rxq_data->rq_ci = wqe_n;
258 : 0 : rxq_data->sge_n = log2ds;
259 : :
260 : 0 : union xsc_recv_doorbell recv_db = {
261 : : .recv_data = 0
262 : : };
263 : :
264 : 0 : recv_db.next_pid = wqe_n << log2ds;
265 : 0 : recv_db.qp_num = rxq_data->qpn;
266 : 0 : rte_write32(rte_cpu_to_le_32(recv_db.recv_data), rxq_data->rq_db);
267 : 0 : }
268 : :
269 : : static int
270 : 0 : xsc_alloc_qpn(struct xsc_dev *xdev, uint16_t *qpn_base, uint16_t qp_cnt)
271 : : {
272 : : int ret;
273 : 0 : struct xsc_cmd_alloc_qpn_mbox_in in = { };
274 : 0 : struct xsc_cmd_alloc_qpn_mbox_out out = { };
275 : :
276 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_ALLOC_QPN);
277 [ # # ]: 0 : in.qp_cnt = rte_cpu_to_be_16(qp_cnt);
278 : 0 : in.qp_type = XSC_QUEUE_TYPE_RAW;
279 : :
280 : 0 : ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
281 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
282 : 0 : PMD_DRV_LOG(ERR,
283 : : "Failed to allocate qpn, port id=%d, qp num=%d, "
284 : : "ret=%d, out.status=%u",
285 : : xdev->port_id, qp_cnt, ret, out.hdr.status);
286 : 0 : rte_errno = ENOEXEC;
287 : 0 : goto error;
288 : : }
289 : :
290 [ # # ]: 0 : *qpn_base = rte_be_to_cpu_16(out.qpn_base);
291 : 0 : return 0;
292 : :
293 : : error:
294 : 0 : return -rte_errno;
295 : : }
296 : :
297 : : static int
298 : 0 : xsc_free_qpn(struct xsc_dev *xdev, uint16_t qpn_base, uint16_t qp_cnt)
299 : : {
300 : : int ret;
301 : 0 : struct xsc_cmd_free_qpn_mbox_in in = { };
302 : 0 : struct xsc_cmd_free_qpn_mbox_out out = { };
303 : :
304 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_FREE_QPN);
305 [ # # ]: 0 : in.qpn_base = rte_cpu_to_be_16(qpn_base);
306 [ # # ]: 0 : in.qp_cnt = rte_cpu_to_be_16(qp_cnt);
307 : 0 : in.qp_type = XSC_QUEUE_TYPE_RAW;
308 : :
309 : 0 : ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
310 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
311 : 0 : PMD_DRV_LOG(ERR,
312 : : "Failed to free qpn, port id=%d, qpn base=%u, qp num=%d, "
313 : : "ret=%d, out.status=%u",
314 : : xdev->port_id, qpn_base, qp_cnt, ret, out.hdr.status);
315 : 0 : rte_errno = ENOEXEC;
316 : 0 : return -rte_errno;
317 : : }
318 : :
319 : : return 0;
320 : : }
321 : :
322 : : static int
323 : 0 : xsc_set_qp_info(struct xsc_dev *xdev, struct xsc_cmd_create_qp_request *qp_info, size_t pas_size)
324 : : {
325 : : int ret;
326 : : size_t in_size;
327 : : struct xsc_cmd_set_qp_info_in *in;
328 : 0 : struct xsc_cmd_set_qp_info_out out = { };
329 : :
330 : 0 : in_size = sizeof(*in) + pas_size;
331 : 0 : in = malloc(in_size);
332 [ # # ]: 0 : if (in == NULL) {
333 : 0 : rte_errno = ENOMEM;
334 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate memory for setting qp info");
335 : 0 : return -rte_errno;
336 : : }
337 : :
338 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_SET_QP_INFO);
339 : 0 : memcpy(&in->qp_info, qp_info, sizeof(*qp_info) + pas_size);
340 : 0 : ret = xsc_dev_mailbox_exec(xdev, in, in_size, &out, sizeof(out));
341 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
342 : 0 : PMD_DRV_LOG(ERR,
343 : : "Failed to set qp info, port id=%d, ret=%d, out.status=%u",
344 : : xdev->port_id, ret, out.hdr.status);
345 : 0 : rte_errno = ENOEXEC;
346 : 0 : goto error;
347 : : }
348 : :
349 : 0 : free(in);
350 : 0 : return 0;
351 : : error:
352 : 0 : free(in);
353 : 0 : return -rte_errno;
354 : : }
355 : :
356 : : static int
357 : 0 : xsc_unset_qp_info(struct xsc_dev *xdev, uint16_t qpn)
358 : : {
359 : : int ret;
360 : 0 : struct xsc_cmd_unset_qp_info_in in = { };
361 : 0 : struct xsc_cmd_unset_qp_info_out out = { };
362 : :
363 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_QP_UNSET_QP_INFO);
364 [ # # ]: 0 : in.qpn = rte_cpu_to_be_16(qpn);
365 : :
366 : 0 : ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
367 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
368 : 0 : PMD_DRV_LOG(ERR,
369 : : "Failed to unset qp info, port id=%d, ret=%d, out.status=%u",
370 : : xdev->port_id, ret, out.hdr.status);
371 : 0 : rte_errno = ENOEXEC;
372 : 0 : return -rte_errno;
373 : : }
374 : :
375 : : return 0;
376 : : }
377 : :
378 : : static int
379 : 0 : xsc_rss_qp_create(struct xsc_ethdev_priv *priv, int port_id)
380 : : {
381 : : int ret;
382 : : int wqe_n;
383 : : int entry_total_len, entry_len;
384 : : uint32_t wqe_total_len;
385 : : uint32_t cq_pi_start;
386 : : uint16_t rqn_base, pa_num;
387 : : uint16_t i, j;
388 : : uint16_t set_last_no = 0;
389 : : uint8_t log_ele, log_rq_sz, log_sq_sz = 0;
390 : : uint64_t iova;
391 : : size_t pas_size;
392 : : struct xsc_rxq_data *rxq_data;
393 : 0 : struct xsc_dev *xdev = priv->xdev;
394 : : struct xsc_cmd_create_qp_request *req, *info;
395 : : struct xsc_hwinfo *hwinfo = &xdev->hwinfo;
396 : 0 : char name[RTE_ETH_NAME_MAX_LEN] = { 0 };
397 [ # # ]: 0 : uint32_t numa_node = priv->eth_dev->device->numa_node;
398 : :
399 : : rxq_data = xsc_rxq_get(priv, 0);
400 : : if (rxq_data == NULL) {
401 : 0 : rte_errno = EINVAL;
402 : 0 : return -rte_errno;
403 : : }
404 : :
405 [ # # ]: 0 : if (numa_node != rxq_data->socket)
406 : 0 : PMD_DRV_LOG(WARNING, "Port %u: rxq numa_node=%u, device numa_node=%u",
407 : : port_id, rxq_data->socket, numa_node);
408 : :
409 : : log_ele = rte_log2_u32(sizeof(struct xsc_wqe_data_seg));
410 : 0 : wqe_n = rxq_data->wqe_s;
411 [ # # ]: 0 : log_rq_sz = rte_log2_u32(wqe_n * hwinfo->recv_seg_num);
412 : 0 : wqe_total_len = 1 << (log_rq_sz + log_sq_sz + log_ele);
413 : :
414 : 0 : pa_num = (wqe_total_len + XSC_PAGE_SIZE - 1) / XSC_PAGE_SIZE;
415 : 0 : entry_len = sizeof(struct xsc_cmd_create_qp_request) + sizeof(uint64_t) * pa_num;
416 : 0 : entry_total_len = entry_len * priv->num_rq;
417 : :
418 : 0 : req = malloc(entry_total_len);
419 [ # # ]: 0 : if (req == NULL) {
420 : 0 : rte_errno = ENOMEM;
421 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc create qp request cmd memory");
422 : 0 : return -rte_errno;
423 : : }
424 : :
425 : 0 : ret = xsc_alloc_qpn(xdev, &rqn_base, priv->num_rq);
426 [ # # ]: 0 : if (ret != 0)
427 : 0 : goto alloc_qpn_fail;
428 : :
429 [ # # ]: 0 : for (i = 0; i < priv->num_rq; i++) {
430 [ # # ]: 0 : rxq_data = xsc_rxq_get(priv, i);
431 : : if (rxq_data == NULL) {
432 : 0 : rte_errno = EINVAL;
433 : 0 : goto set_qp_fail;
434 : : }
435 : :
436 : 0 : info = (struct xsc_cmd_create_qp_request *)((uint8_t *)req + entry_len * i);
437 [ # # ]: 0 : info->input_qpn = rte_cpu_to_be_16(rqn_base + i);
438 [ # # ]: 0 : info->pa_num = rte_cpu_to_be_16(pa_num);
439 : 0 : info->qp_type = XSC_QUEUE_TYPE_RAW;
440 : 0 : info->log_rq_sz = log_rq_sz;
441 [ # # ]: 0 : info->cqn_recv = rte_cpu_to_be_16((uint16_t)rxq_data->cqn);
442 : 0 : info->cqn_send = info->cqn_recv;
443 [ # # ]: 0 : info->glb_funcid = rte_cpu_to_be_16((uint16_t)hwinfo->func_id);
444 : : /* Alloc pas addr */
445 : : snprintf(name, sizeof(name), "wqe_mem_rx_%d_%d", port_id, i);
446 : 0 : rxq_data->rq_pas = rte_memzone_reserve_aligned(name,
447 : 0 : (XSC_PAGE_SIZE * pa_num),
448 : 0 : rxq_data->socket,
449 : : RTE_MEMZONE_IOVA_CONTIG,
450 : : XSC_PAGE_SIZE);
451 [ # # ]: 0 : if (rxq_data->rq_pas == NULL) {
452 : 0 : rte_errno = ENOMEM;
453 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc rxq pas memory");
454 : 0 : goto set_qp_fail;
455 : : }
456 : :
457 : 0 : iova = rxq_data->rq_pas->iova;
458 [ # # ]: 0 : for (j = 0; j < pa_num; j++)
459 [ # # ]: 0 : info->pas[j] = rte_cpu_to_be_64(iova + j * XSC_PAGE_SIZE);
460 : :
461 : 0 : pas_size = pa_num * sizeof(uint64_t);
462 : 0 : ret = xsc_set_qp_info(xdev, info, pas_size);
463 [ # # ]: 0 : if (ret != 0)
464 : 0 : goto set_qp_fail;
465 : :
466 : 0 : set_last_no++;
467 : : }
468 : :
469 : 0 : cq_pi_start = xdev->reg_addr.cq_pi_start;
470 [ # # ]: 0 : for (i = 0; i < priv->num_rq; i++) {
471 [ # # ]: 0 : rxq_data = xsc_rxq_get(priv, i);
472 : : if (rxq_data == NULL) {
473 : 0 : rte_errno = EINVAL;
474 : 0 : goto set_qp_fail;
475 : : }
476 : :
477 : 0 : rxq_data->wqes = rxq_data->rq_pas->addr;
478 : 0 : rxq_data->rq_db = xdev->reg_addr.rxq_db_addr;
479 [ # # ]: 0 : if (!xsc_dev_is_vf(xdev))
480 : 0 : rxq_data->cq_pi = (uint32_t *)((uint8_t *)xdev->bar_addr +
481 : 0 : cq_pi_start + rxq_data->cqn * 4);
482 : : else
483 : 0 : rxq_data->cq_pi = NULL;
484 : :
485 : 0 : rxq_data->qpn = rqn_base + i;
486 : 0 : xsc_dev_modify_qp_status(xdev, rxq_data->qpn, 1, XSC_CMD_OP_RTR2RTS_QP);
487 : 0 : xsc_rxq_initialize(xdev, rxq_data);
488 : 0 : rxq_data->cq_ci = 0;
489 : 0 : PMD_DRV_LOG(INFO, "Port %d create rx qp, wqe_s:%d, wqe_n:%d, qp_db=%p, qpn:%u",
490 : : port_id,
491 : : rxq_data->wqe_s, rxq_data->wqe_n,
492 : : rxq_data->rq_db, rxq_data->qpn);
493 : : }
494 : :
495 : 0 : free(req);
496 : 0 : return 0;
497 : :
498 : 0 : set_qp_fail:
499 : 0 : free(req);
500 [ # # ]: 0 : for (i = 0; i < set_last_no; i++) {
501 : 0 : xsc_unset_qp_info(xdev, rqn_base + i);
502 [ # # ]: 0 : rxq_data = xsc_rxq_get(priv, i);
503 : 0 : if (rxq_data == NULL)
504 : 0 : continue;
505 : 0 : rte_memzone_free(rxq_data->rq_pas);
506 : 0 : rxq_data->rq_pas = NULL;
507 : : }
508 : :
509 : 0 : xsc_free_qpn(xdev, rqn_base, priv->num_rq);
510 : 0 : return -rte_errno;
511 : :
512 : : alloc_qpn_fail:
513 : 0 : free(req);
514 : 0 : return -rte_errno;
515 : : }
516 : :
517 : : int
518 : 0 : xsc_rxq_rss_obj_new(struct xsc_ethdev_priv *priv, uint16_t port_id)
519 : : {
520 : : int ret;
521 : : uint32_t i;
522 : 0 : struct xsc_dev *xdev = priv->xdev;
523 : : struct xsc_rxq_data *rxq_data;
524 : 0 : struct xsc_rx_cq_params cq_params = {0};
525 : 0 : struct xsc_rx_cq_info cq_info = {0};
526 : :
527 : : /* Create CQ */
528 [ # # ]: 0 : for (i = 0; i < priv->num_rq; ++i) {
529 [ # # ]: 0 : rxq_data = xsc_rxq_get(priv, i);
530 : : if (rxq_data == NULL)
531 : : return -EINVAL;
532 : :
533 : : memset(&cq_params, 0, sizeof(cq_params));
534 : : memset(&cq_info, 0, sizeof(cq_info));
535 : 0 : cq_params.port_id = rxq_data->port_id;
536 : 0 : cq_params.qp_id = rxq_data->idx;
537 : 0 : cq_params.wqe_s = rxq_data->wqe_s;
538 : 0 : cq_params.socket_id = rxq_data->socket;
539 : :
540 : 0 : ret = xsc_dev_rx_cq_create(xdev, &cq_params, &cq_info);
541 [ # # ]: 0 : if (ret) {
542 : 0 : PMD_DRV_LOG(ERR, "Port %u rxq %u create cq fail", port_id, i);
543 : 0 : rte_errno = errno;
544 : 0 : goto error;
545 : : }
546 : :
547 : 0 : rxq_data->cq = cq_info.cq;
548 : 0 : rxq_data->cqe_n = cq_info.cqe_n;
549 : 0 : rxq_data->cqe_s = 1 << rxq_data->cqe_n;
550 : 0 : rxq_data->cqe_m = rxq_data->cqe_s - 1;
551 : 0 : rxq_data->cqes = cq_info.cqes;
552 : 0 : rxq_data->cq_db = cq_info.cq_db;
553 : 0 : rxq_data->cqn = cq_info.cqn;
554 : :
555 : 0 : PMD_DRV_LOG(INFO, "Port %u create rx cq, cqe_s:%d, cqe_n:%d, cq_db=%p, cqn:%u",
556 : : port_id,
557 : : rxq_data->cqe_s, rxq_data->cqe_n,
558 : : rxq_data->cq_db, rxq_data->cqn);
559 : : }
560 : :
561 : 0 : ret = xsc_rss_qp_create(priv, port_id);
562 [ # # ]: 0 : if (ret != 0) {
563 : 0 : PMD_DRV_LOG(ERR, "Port %u rss rxq create fail", port_id);
564 : 0 : goto error;
565 : : }
566 : : return 0;
567 : :
568 : 0 : error:
569 : 0 : return -rte_errno;
570 : : }
571 : :
572 : : int
573 : 0 : xsc_rxq_elts_alloc(struct xsc_rxq_data *rxq_data)
574 : : {
575 : 0 : uint32_t elts_s = rxq_data->wqe_s;
576 : : struct rte_mbuf *mbuf;
577 : : uint32_t i;
578 : :
579 [ # # ]: 0 : for (i = 0; (i != elts_s); ++i) {
580 : 0 : mbuf = rte_pktmbuf_alloc(rxq_data->mp);
581 [ # # ]: 0 : if (mbuf == NULL) {
582 : 0 : PMD_DRV_LOG(ERR, "Port %u rxq %u empty mbuf pool",
583 : : rxq_data->port_id, rxq_data->idx);
584 : 0 : rte_errno = ENOMEM;
585 : 0 : goto error;
586 : : }
587 : :
588 : 0 : mbuf->port = rxq_data->port_id;
589 : 0 : mbuf->nb_segs = 1;
590 : 0 : rte_pktmbuf_data_len(mbuf) = mbuf->buf_len - mbuf->data_off;
591 : 0 : rte_pktmbuf_pkt_len(mbuf) = rte_pktmbuf_data_len(mbuf);
592 : 0 : (*rxq_data->elts)[i] = mbuf;
593 : : }
594 : :
595 : : return 0;
596 : : error:
597 : : elts_s = i;
598 [ # # ]: 0 : for (i = 0; (i != elts_s); ++i) {
599 [ # # ]: 0 : if ((*rxq_data->elts)[i] != NULL)
600 : : rte_pktmbuf_free_seg((*rxq_data->elts)[i]);
601 : 0 : (*rxq_data->elts)[i] = NULL;
602 : : }
603 : :
604 : 0 : PMD_DRV_LOG(ERR, "Port %u rxq %u start failed, free elts",
605 : : rxq_data->port_id, rxq_data->idx);
606 : :
607 : 0 : return -rte_errno;
608 : : }
609 : :
610 : : void
611 : 0 : xsc_rxq_elts_free(struct xsc_rxq_data *rxq_data)
612 : : {
613 : : uint16_t i;
614 : :
615 [ # # ]: 0 : if (rxq_data->elts == NULL)
616 : : return;
617 [ # # ]: 0 : for (i = 0; i != rxq_data->wqe_s; ++i) {
618 [ # # ]: 0 : if ((*rxq_data->elts)[i] != NULL)
619 : : rte_pktmbuf_free_seg((*rxq_data->elts)[i]);
620 : 0 : (*rxq_data->elts)[i] = NULL;
621 : : }
622 : :
623 : 0 : PMD_DRV_LOG(DEBUG, "Port %u rxq %u free elts", rxq_data->port_id, rxq_data->idx);
624 : : }
625 : :
626 : : void
627 : 0 : xsc_rxq_rss_obj_release(struct xsc_dev *xdev, struct xsc_rxq_data *rxq_data)
628 : : {
629 : 0 : struct xsc_cmd_destroy_qp_mbox_in in = { .hdr = { 0 } };
630 : 0 : struct xsc_cmd_destroy_qp_mbox_out out = { .hdr = { 0 } };
631 : : int ret, in_len, out_len;
632 : 0 : uint32_t qpn = rxq_data->qpn;
633 : :
634 : 0 : xsc_dev_modify_qp_status(xdev, qpn, 1, XSC_CMD_OP_QP_2RST);
635 : :
636 : : in_len = sizeof(struct xsc_cmd_destroy_qp_mbox_in);
637 : : out_len = sizeof(struct xsc_cmd_destroy_qp_mbox_out);
638 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_DESTROY_QP);
639 [ # # ]: 0 : in.qpn = rte_cpu_to_be_32(rxq_data->qpn);
640 : :
641 : 0 : ret = xsc_dev_mailbox_exec(xdev, &in, in_len, &out, out_len);
642 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
643 : 0 : PMD_DRV_LOG(ERR,
644 : : "Release rss rq failed, port id=%d, qid=%d, err=%d, out.status=%u",
645 : : rxq_data->port_id, rxq_data->idx, ret, out.hdr.status);
646 : 0 : rte_errno = ENOEXEC;
647 : 0 : return;
648 : : }
649 : :
650 : 0 : rte_memzone_free(rxq_data->rq_pas);
651 : :
652 [ # # ]: 0 : if (rxq_data->cq != NULL)
653 : 0 : xsc_dev_destroy_cq(xdev, rxq_data->cq);
654 : 0 : rxq_data->cq = NULL;
655 : : }
|