Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2022-2023 Google LLC
3 : : * Copyright (c) 2022-2023 Intel Corporation
4 : : */
5 : :
6 : :
7 : : #include "gve_ethdev.h"
8 : : #include "base/gve_adminq.h"
9 : :
10 : : static inline void
11 : 0 : gve_rx_refill_dqo(struct gve_rx_queue *rxq)
12 : 0 : {
13 : : volatile struct gve_rx_desc_dqo *rx_buf_ring;
14 : : volatile struct gve_rx_desc_dqo *rx_buf_desc;
15 : 0 : struct rte_mbuf *nmb[rxq->nb_rx_hold];
16 : : uint16_t nb_refill = rxq->nb_rx_hold;
17 : 0 : uint16_t nb_desc = rxq->nb_rx_desc;
18 : 0 : uint16_t next_avail = rxq->bufq_tail;
19 : : struct rte_eth_dev *dev;
20 : : uint64_t dma_addr;
21 : : uint16_t delta;
22 : : int i;
23 : :
24 [ # # ]: 0 : if (rxq->nb_rx_hold < rxq->free_thresh)
25 : 0 : return;
26 : :
27 : 0 : rx_buf_ring = rxq->rx_ring;
28 : 0 : delta = nb_desc - next_avail;
29 [ # # ]: 0 : if (unlikely(delta < nb_refill)) {
30 [ # # ]: 0 : if (likely(rte_pktmbuf_alloc_bulk(rxq->mpool, nmb, delta) == 0)) {
31 [ # # ]: 0 : for (i = 0; i < delta; i++) {
32 : 0 : rx_buf_desc = &rx_buf_ring[next_avail + i];
33 : 0 : rxq->sw_ring[next_avail + i] = nmb[i];
34 : : dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(nmb[i]));
35 : 0 : rx_buf_desc->header_buf_addr = 0;
36 : 0 : rx_buf_desc->buf_addr = dma_addr;
37 : : }
38 : 0 : nb_refill -= delta;
39 : : next_avail = 0;
40 : 0 : rxq->nb_rx_hold -= delta;
41 : : } else {
42 : 0 : rxq->stats.no_mbufs_bulk++;
43 : 0 : rxq->stats.no_mbufs += nb_desc - next_avail;
44 : 0 : dev = &rte_eth_devices[rxq->port_id];
45 : 0 : dev->data->rx_mbuf_alloc_failed += nb_desc - next_avail;
46 : 0 : PMD_DRV_LOG(DEBUG, "RX mbuf alloc failed port_id=%u queue_id=%u",
47 : : rxq->port_id, rxq->queue_id);
48 : 0 : return;
49 : : }
50 : : }
51 : :
52 [ # # ]: 0 : if (nb_desc - next_avail >= nb_refill) {
53 [ # # ]: 0 : if (likely(rte_pktmbuf_alloc_bulk(rxq->mpool, nmb, nb_refill) == 0)) {
54 [ # # ]: 0 : for (i = 0; i < nb_refill; i++) {
55 : 0 : rx_buf_desc = &rx_buf_ring[next_avail + i];
56 : 0 : rxq->sw_ring[next_avail + i] = nmb[i];
57 : : dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(nmb[i]));
58 : 0 : rx_buf_desc->header_buf_addr = 0;
59 : 0 : rx_buf_desc->buf_addr = dma_addr;
60 : : }
61 : 0 : next_avail += nb_refill;
62 : 0 : rxq->nb_rx_hold -= nb_refill;
63 : : } else {
64 : 0 : rxq->stats.no_mbufs_bulk++;
65 : 0 : rxq->stats.no_mbufs += nb_desc - next_avail;
66 : 0 : dev = &rte_eth_devices[rxq->port_id];
67 : 0 : dev->data->rx_mbuf_alloc_failed += nb_desc - next_avail;
68 : 0 : PMD_DRV_LOG(DEBUG, "RX mbuf alloc failed port_id=%u queue_id=%u",
69 : : rxq->port_id, rxq->queue_id);
70 : : }
71 : : }
72 : :
73 : 0 : rte_write32(next_avail, rxq->qrx_tail);
74 : :
75 : 0 : rxq->bufq_tail = next_avail;
76 : : }
77 : :
78 : : uint16_t
79 : 0 : gve_rx_burst_dqo(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
80 : : {
81 : : volatile struct gve_rx_compl_desc_dqo *rx_compl_ring;
82 : : volatile struct gve_rx_compl_desc_dqo *rx_desc;
83 : : struct gve_rx_queue *rxq;
84 : : struct rte_mbuf *rxm;
85 : : uint16_t rx_id_bufq;
86 : : uint16_t pkt_len;
87 : : uint16_t rx_id;
88 : : uint16_t nb_rx;
89 : : uint64_t bytes;
90 : :
91 : : bytes = 0;
92 : : nb_rx = 0;
93 : : rxq = rx_queue;
94 : 0 : rx_id = rxq->rx_tail;
95 : 0 : rx_id_bufq = rxq->next_avail;
96 : 0 : rx_compl_ring = rxq->compl_ring;
97 : :
98 [ # # ]: 0 : while (nb_rx < nb_pkts) {
99 : 0 : rx_desc = &rx_compl_ring[rx_id];
100 : :
101 : : /* check status */
102 [ # # ]: 0 : if (rx_desc->generation != rxq->cur_gen_bit)
103 : : break;
104 : :
105 [ # # ]: 0 : if (unlikely(rx_desc->rx_error)) {
106 : 0 : rxq->stats.errors++;
107 : 0 : continue;
108 : : }
109 : :
110 : 0 : pkt_len = rx_desc->packet_len;
111 : :
112 : 0 : rx_id++;
113 [ # # ]: 0 : if (rx_id == rxq->nb_rx_desc) {
114 : : rx_id = 0;
115 : 0 : rxq->cur_gen_bit ^= 1;
116 : : }
117 : :
118 : 0 : rxm = rxq->sw_ring[rx_id_bufq];
119 : 0 : rx_id_bufq++;
120 [ # # ]: 0 : if (rx_id_bufq == rxq->nb_rx_desc)
121 : : rx_id_bufq = 0;
122 : 0 : rxq->nb_rx_hold++;
123 : :
124 : 0 : rxm->pkt_len = pkt_len;
125 : 0 : rxm->data_len = pkt_len;
126 : 0 : rxm->port = rxq->port_id;
127 : : rxm->ol_flags = 0;
128 : :
129 : 0 : rxm->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
130 : 0 : rxm->hash.rss = rte_be_to_cpu_32(rx_desc->hash);
131 : :
132 : 0 : rx_pkts[nb_rx++] = rxm;
133 : 0 : bytes += pkt_len;
134 : : }
135 : :
136 [ # # ]: 0 : if (nb_rx > 0) {
137 : 0 : rxq->rx_tail = rx_id;
138 [ # # ]: 0 : if (rx_id_bufq != rxq->next_avail)
139 : 0 : rxq->next_avail = rx_id_bufq;
140 : :
141 : 0 : gve_rx_refill_dqo(rxq);
142 : :
143 : 0 : rxq->stats.packets += nb_rx;
144 : 0 : rxq->stats.bytes += bytes;
145 : : }
146 : :
147 : 0 : return nb_rx;
148 : : }
149 : :
150 : : static inline void
151 : 0 : gve_release_rxq_mbufs_dqo(struct gve_rx_queue *rxq)
152 : : {
153 : : uint16_t i;
154 : :
155 [ # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc; i++) {
156 [ # # ]: 0 : if (rxq->sw_ring[i]) {
157 : : rte_pktmbuf_free_seg(rxq->sw_ring[i]);
158 : 0 : rxq->sw_ring[i] = NULL;
159 : : }
160 : : }
161 : :
162 : 0 : rxq->nb_avail = rxq->nb_rx_desc;
163 : 0 : }
164 : :
165 : : void
166 : 0 : gve_rx_queue_release_dqo(struct rte_eth_dev *dev, uint16_t qid)
167 : : {
168 : 0 : struct gve_rx_queue *q = dev->data->rx_queues[qid];
169 : :
170 [ # # ]: 0 : if (q == NULL)
171 : : return;
172 : :
173 : 0 : gve_release_rxq_mbufs_dqo(q);
174 : 0 : rte_free(q->sw_ring);
175 : 0 : rte_memzone_free(q->compl_ring_mz);
176 : 0 : rte_memzone_free(q->mz);
177 : 0 : rte_memzone_free(q->qres_mz);
178 : 0 : q->qres = NULL;
179 : 0 : rte_free(q);
180 : : }
181 : :
182 : : static void
183 : 0 : gve_reset_rxq_dqo(struct gve_rx_queue *rxq)
184 : : {
185 : : struct rte_mbuf **sw_ring;
186 : : uint32_t size, i;
187 : :
188 [ # # ]: 0 : if (rxq == NULL) {
189 : 0 : PMD_DRV_LOG(ERR, "pointer to rxq is NULL");
190 : 0 : return;
191 : : }
192 : :
193 : 0 : size = rxq->nb_rx_desc * sizeof(struct gve_rx_desc_dqo);
194 [ # # ]: 0 : for (i = 0; i < size; i++)
195 : 0 : ((volatile char *)rxq->rx_ring)[i] = 0;
196 : :
197 : 0 : size = rxq->nb_rx_desc * sizeof(struct gve_rx_compl_desc_dqo);
198 [ # # ]: 0 : for (i = 0; i < size; i++)
199 : 0 : ((volatile char *)rxq->compl_ring)[i] = 0;
200 : :
201 : 0 : sw_ring = rxq->sw_ring;
202 [ # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc; i++)
203 : 0 : sw_ring[i] = NULL;
204 : :
205 : 0 : rxq->bufq_tail = 0;
206 : 0 : rxq->next_avail = 0;
207 : 0 : rxq->nb_rx_hold = rxq->nb_rx_desc - 1;
208 : :
209 : 0 : rxq->rx_tail = 0;
210 : 0 : rxq->cur_gen_bit = 1;
211 : : }
212 : :
213 : : int
214 : 0 : gve_rx_queue_setup_dqo(struct rte_eth_dev *dev, uint16_t queue_id,
215 : : uint16_t nb_desc, unsigned int socket_id,
216 : : const struct rte_eth_rxconf *conf,
217 : : struct rte_mempool *pool)
218 : : {
219 : 0 : struct gve_priv *hw = dev->data->dev_private;
220 : : const struct rte_memzone *mz;
221 : : struct gve_rx_queue *rxq;
222 : : uint16_t free_thresh;
223 : : uint32_t mbuf_len;
224 : : int err = 0;
225 : :
226 : : /* Free memory if needed */
227 [ # # ]: 0 : if (dev->data->rx_queues[queue_id]) {
228 : 0 : gve_rx_queue_release_dqo(dev, queue_id);
229 : 0 : dev->data->rx_queues[queue_id] = NULL;
230 : : }
231 : :
232 : : /* Allocate the RX queue data structure. */
233 : 0 : rxq = rte_zmalloc_socket("gve rxq",
234 : : sizeof(struct gve_rx_queue),
235 : : RTE_CACHE_LINE_SIZE,
236 : : socket_id);
237 [ # # ]: 0 : if (rxq == NULL) {
238 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate memory for rx queue structure");
239 : 0 : return -ENOMEM;
240 : : }
241 : :
242 : : /* check free_thresh here */
243 [ # # ]: 0 : free_thresh = conf->rx_free_thresh ?
244 : : conf->rx_free_thresh : GVE_DEFAULT_RX_FREE_THRESH;
245 [ # # ]: 0 : if (free_thresh >= nb_desc) {
246 : 0 : PMD_DRV_LOG(ERR, "rx_free_thresh (%u) must be less than nb_desc (%u).",
247 : : free_thresh, rxq->nb_rx_desc);
248 : : err = -EINVAL;
249 : 0 : goto free_rxq;
250 : : }
251 : :
252 : 0 : rxq->nb_rx_desc = nb_desc;
253 : 0 : rxq->free_thresh = free_thresh;
254 : 0 : rxq->queue_id = queue_id;
255 : 0 : rxq->port_id = dev->data->port_id;
256 : 0 : rxq->ntfy_id = hw->num_ntfy_blks / 2 + queue_id;
257 : :
258 : 0 : rxq->mpool = pool;
259 : 0 : rxq->hw = hw;
260 [ # # # # ]: 0 : rxq->ntfy_addr = &hw->db_bar2[rte_be_to_cpu_32(hw->irq_dbs[rxq->ntfy_id].id)];
261 : :
262 : 0 : mbuf_len =
263 : 0 : rte_pktmbuf_data_room_size(rxq->mpool) - RTE_PKTMBUF_HEADROOM;
264 : 0 : rxq->rx_buf_len =
265 : 0 : RTE_MIN((uint16_t)GVE_RX_MAX_BUF_SIZE_DQO,
266 : : RTE_ALIGN_FLOOR(mbuf_len, GVE_RX_BUF_ALIGN_DQO));
267 : :
268 : : /* Allocate software ring */
269 : 0 : rxq->sw_ring = rte_zmalloc_socket("gve rx sw ring",
270 : : nb_desc * sizeof(struct rte_mbuf *),
271 : : RTE_CACHE_LINE_SIZE, socket_id);
272 [ # # ]: 0 : if (rxq->sw_ring == NULL) {
273 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate memory for SW RX ring");
274 : : err = -ENOMEM;
275 : 0 : goto free_rxq;
276 : : }
277 : :
278 : : /* Allocate RX buffer queue */
279 : 0 : mz = rte_eth_dma_zone_reserve(dev, "rx_ring", queue_id,
280 : : nb_desc * sizeof(struct gve_rx_desc_dqo),
281 : : PAGE_SIZE, socket_id);
282 [ # # ]: 0 : if (mz == NULL) {
283 : 0 : PMD_DRV_LOG(ERR, "Failed to reserve DMA memory for RX buffer queue");
284 : : err = -ENOMEM;
285 : 0 : goto free_rxq_sw_ring;
286 : : }
287 : 0 : rxq->rx_ring = (struct gve_rx_desc_dqo *)mz->addr;
288 : 0 : rxq->rx_ring_phys_addr = mz->iova;
289 : 0 : rxq->mz = mz;
290 : :
291 : : /* Allocate RX completion queue */
292 : 0 : mz = rte_eth_dma_zone_reserve(dev, "compl_ring", queue_id,
293 : : nb_desc * sizeof(struct gve_rx_compl_desc_dqo),
294 : : PAGE_SIZE, socket_id);
295 [ # # ]: 0 : if (mz == NULL) {
296 : 0 : PMD_DRV_LOG(ERR, "Failed to reserve DMA memory for RX completion queue");
297 : : err = -ENOMEM;
298 : 0 : goto free_rxq_mz;
299 : : }
300 : : /* Zero all the descriptors in the ring */
301 : 0 : memset(mz->addr, 0, nb_desc * sizeof(struct gve_rx_compl_desc_dqo));
302 : 0 : rxq->compl_ring = (struct gve_rx_compl_desc_dqo *)mz->addr;
303 : 0 : rxq->compl_ring_phys_addr = mz->iova;
304 : 0 : rxq->compl_ring_mz = mz;
305 : :
306 : 0 : mz = rte_eth_dma_zone_reserve(dev, "rxq_res", queue_id,
307 : : sizeof(struct gve_queue_resources),
308 : : PAGE_SIZE, socket_id);
309 [ # # ]: 0 : if (mz == NULL) {
310 : 0 : PMD_DRV_LOG(ERR, "Failed to reserve DMA memory for RX resource");
311 : : err = -ENOMEM;
312 : 0 : goto free_rxq_cq_mz;
313 : : }
314 : 0 : rxq->qres = (struct gve_queue_resources *)mz->addr;
315 : 0 : rxq->qres_mz = mz;
316 : :
317 : 0 : gve_reset_rxq_dqo(rxq);
318 : :
319 : 0 : dev->data->rx_queues[queue_id] = rxq;
320 : :
321 : 0 : return 0;
322 : :
323 : : free_rxq_cq_mz:
324 : 0 : rte_memzone_free(rxq->compl_ring_mz);
325 : 0 : free_rxq_mz:
326 : 0 : rte_memzone_free(rxq->mz);
327 : 0 : free_rxq_sw_ring:
328 : 0 : rte_free(rxq->sw_ring);
329 : 0 : free_rxq:
330 : 0 : rte_free(rxq);
331 : 0 : return err;
332 : : }
333 : :
334 : : static int
335 : 0 : gve_rxq_mbufs_alloc_dqo(struct gve_rx_queue *rxq)
336 : : {
337 : : struct rte_mbuf *nmb;
338 : : uint16_t i;
339 : : int diag;
340 : :
341 : 0 : diag = rte_pktmbuf_alloc_bulk(rxq->mpool, &rxq->sw_ring[0], rxq->nb_rx_desc);
342 [ # # ]: 0 : if (diag < 0) {
343 : 0 : rxq->stats.no_mbufs_bulk++;
344 [ # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc - 1; i++) {
345 : 0 : nmb = rte_pktmbuf_alloc(rxq->mpool);
346 [ # # ]: 0 : if (!nmb)
347 : : break;
348 : 0 : rxq->sw_ring[i] = nmb;
349 : : }
350 [ # # ]: 0 : if (i < rxq->nb_rx_desc - 1) {
351 : 0 : rxq->stats.no_mbufs += rxq->nb_rx_desc - 1 - i;
352 : 0 : return -ENOMEM;
353 : : }
354 : : }
355 : :
356 [ # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc; i++) {
357 [ # # ]: 0 : if (i == rxq->nb_rx_desc - 1)
358 : : break;
359 : 0 : nmb = rxq->sw_ring[i];
360 : 0 : rxq->rx_ring[i].buf_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(nmb));
361 : 0 : rxq->rx_ring[i].buf_id = rte_cpu_to_le_16(i);
362 : : }
363 : :
364 : 0 : rxq->nb_rx_hold = 0;
365 : 0 : rxq->bufq_tail = rxq->nb_rx_desc - 1;
366 : :
367 : 0 : rte_write32(rxq->bufq_tail, rxq->qrx_tail);
368 : :
369 : 0 : return 0;
370 : : }
371 : :
372 : : int
373 : 0 : gve_rx_queue_start_dqo(struct rte_eth_dev *dev, uint16_t rx_queue_id)
374 : : {
375 : 0 : struct gve_priv *hw = dev->data->dev_private;
376 : : struct gve_rx_queue *rxq;
377 : : int ret;
378 : :
379 [ # # ]: 0 : if (rx_queue_id >= dev->data->nb_rx_queues)
380 : : return -EINVAL;
381 : :
382 : 0 : rxq = dev->data->rx_queues[rx_queue_id];
383 : :
384 [ # # ]: 0 : rxq->qrx_tail = &hw->db_bar2[rte_be_to_cpu_32(rxq->qres->db_index)];
385 : :
386 : 0 : rte_write32(rte_cpu_to_be_32(GVE_IRQ_MASK), rxq->ntfy_addr);
387 : :
388 : 0 : ret = gve_rxq_mbufs_alloc_dqo(rxq);
389 [ # # ]: 0 : if (ret != 0) {
390 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc Rx queue mbuf");
391 : 0 : return ret;
392 : : }
393 : :
394 : 0 : dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
395 : :
396 : 0 : return 0;
397 : : }
398 : :
399 : : int
400 : 0 : gve_rx_queue_stop_dqo(struct rte_eth_dev *dev, uint16_t rx_queue_id)
401 : : {
402 : : struct gve_rx_queue *rxq;
403 : :
404 [ # # ]: 0 : if (rx_queue_id >= dev->data->nb_rx_queues)
405 : : return -EINVAL;
406 : :
407 : 0 : rxq = dev->data->rx_queues[rx_queue_id];
408 : 0 : gve_release_rxq_mbufs_dqo(rxq);
409 : 0 : gve_reset_rxq_dqo(rxq);
410 : :
411 : 0 : dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
412 : :
413 : 0 : return 0;
414 : : }
415 : :
416 : : void
417 : 0 : gve_stop_rx_queues_dqo(struct rte_eth_dev *dev)
418 : : {
419 : 0 : struct gve_priv *hw = dev->data->dev_private;
420 : : uint16_t i;
421 : : int err;
422 : :
423 : 0 : err = gve_adminq_destroy_rx_queues(hw, dev->data->nb_rx_queues);
424 [ # # ]: 0 : if (err != 0)
425 : 0 : PMD_DRV_LOG(WARNING, "failed to destroy rxqs");
426 : :
427 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
428 [ # # ]: 0 : if (gve_rx_queue_stop_dqo(dev, i) != 0)
429 : 0 : PMD_DRV_LOG(WARNING, "Fail to stop Rx queue %d", i);
430 : 0 : }
431 : :
432 : : void
433 : 0 : gve_set_rx_function_dqo(struct rte_eth_dev *dev)
434 : : {
435 : 0 : dev->rx_pkt_burst = gve_rx_burst_dqo;
436 : 0 : }
|