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 : : #include "gve_ethdev.h"
7 : : #include "base/gve_adminq.h"
8 : :
9 : : static inline void
10 : 0 : gve_tx_clean_dqo(struct gve_tx_queue *txq)
11 : : {
12 : : struct gve_tx_compl_desc *compl_ring;
13 : : struct gve_tx_compl_desc *compl_desc;
14 : : struct gve_tx_queue *aim_txq;
15 : : uint16_t nb_desc_clean;
16 : : struct rte_mbuf *txe;
17 : : uint16_t compl_tag;
18 : : uint16_t next;
19 : :
20 : 0 : next = txq->complq_tail;
21 : 0 : compl_ring = txq->compl_ring;
22 : 0 : compl_desc = &compl_ring[next];
23 : :
24 [ # # ]: 0 : if (compl_desc->generation != txq->cur_gen_bit)
25 : : return;
26 : :
27 : 0 : compl_tag = rte_le_to_cpu_16(compl_desc->completion_tag);
28 : :
29 : 0 : aim_txq = txq->txqs[compl_desc->id];
30 : :
31 [ # # # # : 0 : switch (compl_desc->type) {
# ]
32 : 0 : case GVE_COMPL_TYPE_DQO_DESC:
33 : : /* need to clean Descs from last_cleaned to compl_tag */
34 [ # # ]: 0 : if (aim_txq->last_desc_cleaned > compl_tag)
35 : 0 : nb_desc_clean = aim_txq->nb_tx_desc - aim_txq->last_desc_cleaned +
36 : : compl_tag;
37 : : else
38 : 0 : nb_desc_clean = compl_tag - aim_txq->last_desc_cleaned;
39 : 0 : aim_txq->nb_free += nb_desc_clean;
40 : 0 : aim_txq->last_desc_cleaned = compl_tag;
41 : 0 : break;
42 : 0 : case GVE_COMPL_TYPE_DQO_REINJECTION:
43 : 0 : PMD_DRV_LOG(DEBUG, "GVE_COMPL_TYPE_DQO_REINJECTION !!!");
44 : : /* FALLTHROUGH */
45 : 0 : case GVE_COMPL_TYPE_DQO_PKT:
46 : 0 : txe = aim_txq->sw_ring[compl_tag];
47 [ # # ]: 0 : if (txe != NULL) {
48 : : rte_pktmbuf_free_seg(txe);
49 : : txe = NULL;
50 : : }
51 : : break;
52 : 0 : case GVE_COMPL_TYPE_DQO_MISS:
53 : 0 : rte_delay_us_sleep(1);
54 : 0 : PMD_DRV_LOG(DEBUG, "GVE_COMPL_TYPE_DQO_MISS ignored !!!");
55 : 0 : break;
56 : 0 : default:
57 : 0 : PMD_DRV_LOG(ERR, "unknown completion type.");
58 : 0 : return;
59 : : }
60 : :
61 : 0 : next++;
62 [ # # ]: 0 : if (next == txq->nb_tx_desc * DQO_TX_MULTIPLIER) {
63 : : next = 0;
64 : 0 : txq->cur_gen_bit ^= 1;
65 : : }
66 : :
67 : 0 : txq->complq_tail = next;
68 : : }
69 : :
70 : : uint16_t
71 : 0 : gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
72 : : {
73 : : struct gve_tx_queue *txq = tx_queue;
74 : : volatile union gve_tx_desc_dqo *txr;
75 : : volatile union gve_tx_desc_dqo *txd;
76 : : struct rte_mbuf **sw_ring;
77 : : struct rte_mbuf *tx_pkt;
78 : : uint16_t mask, sw_mask;
79 : : uint16_t nb_to_clean;
80 : : uint16_t nb_tx = 0;
81 : : uint64_t ol_flags;
82 : : uint16_t nb_used;
83 : : uint16_t tx_id;
84 : : uint16_t sw_id;
85 : : uint64_t bytes;
86 : :
87 : 0 : sw_ring = txq->sw_ring;
88 : 0 : txr = txq->tx_ring;
89 : :
90 : : bytes = 0;
91 : 0 : mask = txq->nb_tx_desc - 1;
92 : 0 : sw_mask = txq->sw_size - 1;
93 : 0 : tx_id = txq->tx_tail;
94 : 0 : sw_id = txq->sw_tail;
95 : :
96 [ # # ]: 0 : for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
97 : 0 : tx_pkt = tx_pkts[nb_tx];
98 : :
99 [ # # ]: 0 : if (txq->nb_free <= txq->free_thresh) {
100 : 0 : nb_to_clean = DQO_TX_MULTIPLIER * txq->rs_thresh;
101 [ # # ]: 0 : while (nb_to_clean--)
102 : 0 : gve_tx_clean_dqo(txq);
103 : : }
104 : :
105 [ # # ]: 0 : if (txq->nb_free < tx_pkt->nb_segs)
106 : : break;
107 : :
108 : 0 : ol_flags = tx_pkt->ol_flags;
109 : : nb_used = tx_pkt->nb_segs;
110 : :
111 : : do {
112 : 0 : txd = &txr[tx_id];
113 : :
114 [ # # ]: 0 : sw_ring[sw_id] = tx_pkt;
115 : :
116 : : /* fill Tx descriptor */
117 : 0 : txd->pkt.buf_addr = rte_cpu_to_le_64(rte_mbuf_data_iova(tx_pkt));
118 : 0 : txd->pkt.dtype = GVE_TX_PKT_DESC_DTYPE_DQO;
119 : 0 : txd->pkt.compl_tag = rte_cpu_to_le_16(sw_id);
120 : 0 : txd->pkt.buf_size = RTE_MIN(tx_pkt->data_len, GVE_TX_MAX_BUF_SIZE_DQO);
121 : :
122 : : /* size of desc_ring and sw_ring could be different */
123 : 0 : tx_id = (tx_id + 1) & mask;
124 : 0 : sw_id = (sw_id + 1) & sw_mask;
125 : :
126 : 0 : bytes += tx_pkt->pkt_len;
127 : 0 : tx_pkt = tx_pkt->next;
128 [ # # ]: 0 : } while (tx_pkt);
129 : :
130 : : /* fill the last descriptor with End of Packet (EOP) bit */
131 : 0 : txd->pkt.end_of_packet = 1;
132 : :
133 [ # # ]: 0 : if (ol_flags & GVE_TX_CKSUM_OFFLOAD_MASK)
134 : 0 : txd->pkt.checksum_offload_enable = 1;
135 : :
136 : 0 : txq->nb_free -= nb_used;
137 : 0 : txq->nb_used += nb_used;
138 : : }
139 : :
140 : : /* update the tail pointer if any packets were processed */
141 [ # # ]: 0 : if (nb_tx > 0) {
142 : : /* Request a descriptor completion on the last descriptor */
143 : 0 : txq->re_cnt += nb_tx;
144 [ # # ]: 0 : if (txq->re_cnt >= GVE_TX_MIN_RE_INTERVAL) {
145 : 0 : txd = &txr[(tx_id - 1) & mask];
146 : 0 : txd->pkt.report_event = true;
147 : 0 : txq->re_cnt = 0;
148 : : }
149 : :
150 : 0 : rte_write32(tx_id, txq->qtx_tail);
151 : 0 : txq->tx_tail = tx_id;
152 : 0 : txq->sw_tail = sw_id;
153 : :
154 : 0 : txq->stats.packets += nb_tx;
155 : 0 : txq->stats.bytes += bytes;
156 : 0 : txq->stats.errors += nb_pkts - nb_tx;
157 : : }
158 : :
159 : 0 : return nb_tx;
160 : : }
161 : :
162 : : static inline void
163 : 0 : gve_release_txq_mbufs_dqo(struct gve_tx_queue *txq)
164 : : {
165 : : uint16_t i;
166 : :
167 [ # # ]: 0 : for (i = 0; i < txq->sw_size; i++) {
168 [ # # ]: 0 : if (txq->sw_ring[i]) {
169 : : rte_pktmbuf_free_seg(txq->sw_ring[i]);
170 : 0 : txq->sw_ring[i] = NULL;
171 : : }
172 : : }
173 : 0 : }
174 : :
175 : : void
176 : 0 : gve_tx_queue_release_dqo(struct rte_eth_dev *dev, uint16_t qid)
177 : : {
178 : 0 : struct gve_tx_queue *q = dev->data->tx_queues[qid];
179 : :
180 [ # # ]: 0 : if (q == NULL)
181 : : return;
182 : :
183 : 0 : gve_release_txq_mbufs_dqo(q);
184 : 0 : rte_free(q->sw_ring);
185 : 0 : rte_memzone_free(q->mz);
186 : 0 : rte_memzone_free(q->compl_ring_mz);
187 : 0 : rte_memzone_free(q->qres_mz);
188 : 0 : q->qres = NULL;
189 : 0 : rte_free(q);
190 : : }
191 : :
192 : : static int
193 : 0 : check_tx_thresh_dqo(uint16_t nb_desc, uint16_t tx_rs_thresh,
194 : : uint16_t tx_free_thresh)
195 : : {
196 [ # # ]: 0 : if (tx_rs_thresh >= (nb_desc - 2)) {
197 : 0 : PMD_DRV_LOG(ERR, "tx_rs_thresh (%u) must be less than the "
198 : : "number of TX descriptors (%u) minus 2",
199 : : tx_rs_thresh, nb_desc);
200 : 0 : return -EINVAL;
201 : : }
202 [ # # ]: 0 : if (tx_free_thresh >= (nb_desc - 3)) {
203 : 0 : PMD_DRV_LOG(ERR, "tx_free_thresh (%u) must be less than the "
204 : : "number of TX descriptors (%u) minus 3.",
205 : : tx_free_thresh, nb_desc);
206 : 0 : return -EINVAL;
207 : : }
208 [ # # ]: 0 : if (tx_rs_thresh > tx_free_thresh) {
209 : 0 : PMD_DRV_LOG(ERR, "tx_rs_thresh (%u) must be less than or "
210 : : "equal to tx_free_thresh (%u).",
211 : : tx_rs_thresh, tx_free_thresh);
212 : 0 : return -EINVAL;
213 : : }
214 [ # # ]: 0 : if ((nb_desc % tx_rs_thresh) != 0) {
215 : 0 : PMD_DRV_LOG(ERR, "tx_rs_thresh (%u) must be a divisor of the "
216 : : "number of TX descriptors (%u).",
217 : : tx_rs_thresh, nb_desc);
218 : 0 : return -EINVAL;
219 : : }
220 : :
221 : : return 0;
222 : : }
223 : :
224 : : static void
225 : 0 : gve_reset_txq_dqo(struct gve_tx_queue *txq)
226 : : {
227 : : struct rte_mbuf **sw_ring;
228 : : uint32_t size, i;
229 : :
230 [ # # ]: 0 : if (txq == NULL) {
231 : 0 : PMD_DRV_LOG(DEBUG, "Pointer to txq is NULL");
232 : 0 : return;
233 : : }
234 : :
235 : 0 : size = txq->nb_tx_desc * sizeof(union gve_tx_desc_dqo);
236 [ # # ]: 0 : for (i = 0; i < size; i++)
237 : 0 : ((volatile char *)txq->tx_ring)[i] = 0;
238 : :
239 : 0 : size = txq->sw_size * sizeof(struct gve_tx_compl_desc);
240 [ # # ]: 0 : for (i = 0; i < size; i++)
241 : 0 : ((volatile char *)txq->compl_ring)[i] = 0;
242 : :
243 : 0 : sw_ring = txq->sw_ring;
244 [ # # ]: 0 : for (i = 0; i < txq->sw_size; i++)
245 : 0 : sw_ring[i] = NULL;
246 : :
247 : 0 : txq->tx_tail = 0;
248 : 0 : txq->nb_used = 0;
249 : :
250 : 0 : txq->last_desc_cleaned = 0;
251 : 0 : txq->sw_tail = 0;
252 : 0 : txq->nb_free = txq->nb_tx_desc - 1;
253 : :
254 : 0 : txq->complq_tail = 0;
255 : 0 : txq->cur_gen_bit = 1;
256 : : }
257 : :
258 : : int
259 : 0 : gve_tx_queue_setup_dqo(struct rte_eth_dev *dev, uint16_t queue_id,
260 : : uint16_t nb_desc, unsigned int socket_id,
261 : : const struct rte_eth_txconf *conf)
262 : : {
263 : 0 : struct gve_priv *hw = dev->data->dev_private;
264 : : const struct rte_memzone *mz;
265 : : struct gve_tx_queue *txq;
266 : : uint16_t free_thresh;
267 : : uint16_t rs_thresh;
268 : : uint16_t sw_size;
269 : : int err = 0;
270 : :
271 : : /* Free memory if needed. */
272 [ # # ]: 0 : if (dev->data->tx_queues[queue_id]) {
273 : 0 : gve_tx_queue_release_dqo(dev, queue_id);
274 : 0 : dev->data->tx_queues[queue_id] = NULL;
275 : : }
276 : :
277 : : /* Allocate the TX queue data structure. */
278 : 0 : txq = rte_zmalloc_socket("gve txq",
279 : : sizeof(struct gve_tx_queue),
280 : : RTE_CACHE_LINE_SIZE, socket_id);
281 [ # # ]: 0 : if (txq == NULL) {
282 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate memory for tx queue structure");
283 : 0 : return -ENOMEM;
284 : : }
285 : :
286 : : /* need to check free_thresh here */
287 [ # # ]: 0 : free_thresh = conf->tx_free_thresh ?
288 : : conf->tx_free_thresh : GVE_DEFAULT_TX_FREE_THRESH;
289 [ # # ]: 0 : rs_thresh = conf->tx_rs_thresh ?
290 : : conf->tx_rs_thresh : GVE_DEFAULT_TX_RS_THRESH;
291 [ # # ]: 0 : if (check_tx_thresh_dqo(nb_desc, rs_thresh, free_thresh))
292 : : return -EINVAL;
293 : :
294 : 0 : txq->nb_tx_desc = nb_desc;
295 : 0 : txq->free_thresh = free_thresh;
296 : 0 : txq->rs_thresh = rs_thresh;
297 : 0 : txq->queue_id = queue_id;
298 : 0 : txq->port_id = dev->data->port_id;
299 : 0 : txq->ntfy_id = queue_id;
300 : 0 : txq->hw = hw;
301 [ # # ]: 0 : txq->ntfy_addr = &hw->db_bar2[rte_be_to_cpu_32(hw->irq_dbs[txq->ntfy_id].id)];
302 : :
303 : : /* Allocate software ring */
304 : 0 : sw_size = nb_desc * DQO_TX_MULTIPLIER;
305 : 0 : txq->sw_ring = rte_zmalloc_socket("gve tx sw ring",
306 : : sw_size * sizeof(struct rte_mbuf *),
307 : : RTE_CACHE_LINE_SIZE, socket_id);
308 [ # # ]: 0 : if (txq->sw_ring == NULL) {
309 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate memory for SW TX ring");
310 : : err = -ENOMEM;
311 : 0 : goto free_txq;
312 : : }
313 : 0 : txq->sw_size = sw_size;
314 : :
315 : : /* Allocate TX hardware ring descriptors. */
316 : 0 : mz = rte_eth_dma_zone_reserve(dev, "tx_ring", queue_id,
317 : : nb_desc * sizeof(union gve_tx_desc_dqo),
318 : : PAGE_SIZE, socket_id);
319 [ # # ]: 0 : if (mz == NULL) {
320 : 0 : PMD_DRV_LOG(ERR, "Failed to reserve DMA memory for TX");
321 : : err = -ENOMEM;
322 : 0 : goto free_txq_sw_ring;
323 : : }
324 : 0 : txq->tx_ring = (union gve_tx_desc_dqo *)mz->addr;
325 : 0 : txq->tx_ring_phys_addr = mz->iova;
326 : 0 : txq->mz = mz;
327 : :
328 : : /* Allocate TX completion ring descriptors. */
329 : 0 : mz = rte_eth_dma_zone_reserve(dev, "tx_compl_ring", queue_id,
330 : : sw_size * sizeof(struct gve_tx_compl_desc),
331 : : PAGE_SIZE, socket_id);
332 [ # # ]: 0 : if (mz == NULL) {
333 : 0 : PMD_DRV_LOG(ERR, "Failed to reserve DMA memory for TX completion queue");
334 : : err = -ENOMEM;
335 : 0 : goto free_txq_mz;
336 : : }
337 : 0 : txq->compl_ring = (struct gve_tx_compl_desc *)mz->addr;
338 : 0 : txq->compl_ring_phys_addr = mz->iova;
339 : 0 : txq->compl_ring_mz = mz;
340 : 0 : txq->txqs = dev->data->tx_queues;
341 : :
342 : 0 : mz = rte_eth_dma_zone_reserve(dev, "txq_res", queue_id,
343 : : sizeof(struct gve_queue_resources),
344 : : PAGE_SIZE, socket_id);
345 [ # # ]: 0 : if (mz == NULL) {
346 : 0 : PMD_DRV_LOG(ERR, "Failed to reserve DMA memory for TX resource");
347 : : err = -ENOMEM;
348 : 0 : goto free_txq_cq_mz;
349 : : }
350 : 0 : txq->qres = (struct gve_queue_resources *)mz->addr;
351 : 0 : txq->qres_mz = mz;
352 : :
353 : 0 : gve_reset_txq_dqo(txq);
354 : :
355 : 0 : dev->data->tx_queues[queue_id] = txq;
356 : :
357 : 0 : return 0;
358 : :
359 : : free_txq_cq_mz:
360 : 0 : rte_memzone_free(txq->compl_ring_mz);
361 : 0 : free_txq_mz:
362 : 0 : rte_memzone_free(txq->mz);
363 : 0 : free_txq_sw_ring:
364 : 0 : rte_free(txq->sw_ring);
365 : 0 : free_txq:
366 : 0 : rte_free(txq);
367 : 0 : return err;
368 : : }
369 : :
370 : : int
371 : 0 : gve_tx_queue_start_dqo(struct rte_eth_dev *dev, uint16_t tx_queue_id)
372 : : {
373 : 0 : struct gve_priv *hw = dev->data->dev_private;
374 : : struct gve_tx_queue *txq;
375 : :
376 [ # # ]: 0 : if (tx_queue_id >= dev->data->nb_tx_queues)
377 : : return -EINVAL;
378 : :
379 : 0 : txq = dev->data->tx_queues[tx_queue_id];
380 : :
381 [ # # ]: 0 : txq->qtx_tail = &hw->db_bar2[rte_be_to_cpu_32(txq->qres->db_index)];
382 : 0 : txq->qtx_head =
383 [ # # ]: 0 : &hw->cnt_array[rte_be_to_cpu_32(txq->qres->counter_index)];
384 : :
385 : 0 : rte_write32(rte_cpu_to_be_32(GVE_IRQ_MASK), txq->ntfy_addr);
386 : :
387 : 0 : dev->data->rx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
388 : :
389 : 0 : return 0;
390 : : }
391 : :
392 : : int
393 : 0 : gve_tx_queue_stop_dqo(struct rte_eth_dev *dev, uint16_t tx_queue_id)
394 : : {
395 : : struct gve_tx_queue *txq;
396 : :
397 [ # # ]: 0 : if (tx_queue_id >= dev->data->nb_tx_queues)
398 : : return -EINVAL;
399 : :
400 : 0 : txq = dev->data->tx_queues[tx_queue_id];
401 : 0 : gve_release_txq_mbufs_dqo(txq);
402 : 0 : gve_reset_txq_dqo(txq);
403 : :
404 : 0 : dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
405 : :
406 : 0 : return 0;
407 : : }
408 : :
409 : : void
410 : 0 : gve_stop_tx_queues_dqo(struct rte_eth_dev *dev)
411 : : {
412 : 0 : struct gve_priv *hw = dev->data->dev_private;
413 : : uint16_t i;
414 : : int err;
415 : :
416 : 0 : err = gve_adminq_destroy_tx_queues(hw, dev->data->nb_tx_queues);
417 [ # # ]: 0 : if (err != 0)
418 : 0 : PMD_DRV_LOG(WARNING, "failed to destroy txqs");
419 : :
420 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
421 [ # # ]: 0 : if (gve_tx_queue_stop_dqo(dev, i) != 0)
422 : 0 : PMD_DRV_LOG(WARNING, "Fail to stop Tx queue %d", i);
423 : 0 : }
424 : :
425 : : void
426 : 0 : gve_set_tx_function_dqo(struct rte_eth_dev *dev)
427 : : {
428 : 0 : dev->tx_pkt_burst = gve_tx_burst_dqo;
429 : 0 : }
|