Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2022-2023 Intel Corporation
3 : : * Copyright(C) 2023 Google LLC
4 : : */
5 : :
6 : : #include "gve_ethdev.h"
7 : : #include "base/gve_adminq.h"
8 : : #include "base/gve_register.h"
9 : : #include "base/gve_osdep.h"
10 : : #include "gve_version.h"
11 : : #include "rte_ether.h"
12 : : #include "gve_rss.h"
13 : :
14 : : static void
15 : : gve_write_version(uint8_t *driver_version_register)
16 : : {
17 : 0 : const char *c = gve_version_string();
18 [ # # ]: 0 : while (*c) {
19 : 0 : writeb(*c, driver_version_register);
20 : 0 : c++;
21 : : }
22 : : writeb('\n', driver_version_register);
23 : : }
24 : :
25 : : static const struct rte_memzone *
26 : 0 : gve_alloc_using_mz(const char *name, uint32_t num_pages)
27 : : {
28 : : const struct rte_memzone *mz;
29 : 0 : mz = rte_memzone_reserve_aligned(name, num_pages * PAGE_SIZE,
30 : 0 : rte_socket_id(),
31 : : RTE_MEMZONE_IOVA_CONTIG, PAGE_SIZE);
32 [ # # ]: 0 : if (mz == NULL)
33 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memzone %s.", name);
34 : 0 : return mz;
35 : : }
36 : :
37 : : static int
38 : 0 : gve_alloc_using_malloc(void **bufs, uint32_t num_entries)
39 : : {
40 : : uint32_t i;
41 : :
42 [ # # ]: 0 : for (i = 0; i < num_entries; i++) {
43 : 0 : bufs[i] = rte_malloc_socket(NULL, PAGE_SIZE, PAGE_SIZE, rte_socket_id());
44 [ # # ]: 0 : if (bufs[i] == NULL) {
45 : 0 : PMD_DRV_LOG(ERR, "Failed to malloc");
46 : 0 : goto free_bufs;
47 : : }
48 : : }
49 : : return 0;
50 : :
51 : : free_bufs:
52 [ # # ]: 0 : while (i > 0)
53 : 0 : rte_free(bufs[--i]);
54 : :
55 : : return -ENOMEM;
56 : : }
57 : :
58 : : static struct gve_queue_page_list *
59 : 0 : gve_alloc_queue_page_list(const char *name, uint32_t num_pages, bool is_rx)
60 : : {
61 : : struct gve_queue_page_list *qpl;
62 : : const struct rte_memzone *mz;
63 : : uint32_t i;
64 : :
65 : 0 : qpl = rte_zmalloc("qpl struct", sizeof(struct gve_queue_page_list), 0);
66 [ # # ]: 0 : if (!qpl)
67 : : return NULL;
68 : :
69 : 0 : qpl->page_buses = rte_zmalloc("qpl page buses",
70 : : num_pages * sizeof(dma_addr_t), 0);
71 [ # # ]: 0 : if (qpl->page_buses == NULL) {
72 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc qpl page buses");
73 : 0 : goto free_qpl_struct;
74 : : }
75 : :
76 [ # # ]: 0 : if (is_rx) {
77 : : /* RX QPL need not be IOVA contiguous.
78 : : * Allocate 4K size buffers using malloc
79 : : */
80 : 0 : qpl->qpl_bufs = rte_zmalloc("qpl bufs",
81 : : num_pages * sizeof(void *), 0);
82 [ # # ]: 0 : if (qpl->qpl_bufs == NULL) {
83 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc qpl bufs");
84 : 0 : goto free_qpl_page_buses;
85 : : }
86 : :
87 [ # # ]: 0 : if (gve_alloc_using_malloc(qpl->qpl_bufs, num_pages))
88 : 0 : goto free_qpl_page_bufs;
89 : :
90 : : /* Populate the IOVA addresses */
91 [ # # ]: 0 : for (i = 0; i < num_pages; i++)
92 : 0 : qpl->page_buses[i] =
93 : 0 : rte_malloc_virt2iova(qpl->qpl_bufs[i]);
94 : : } else {
95 : : /* TX QPL needs to be IOVA contiguous
96 : : * Allocate QPL using memzone
97 : : */
98 : 0 : mz = gve_alloc_using_mz(name, num_pages);
99 [ # # ]: 0 : if (!mz)
100 : 0 : goto free_qpl_page_buses;
101 : :
102 : 0 : qpl->mz = mz;
103 : :
104 : : /* Populate the IOVA addresses */
105 [ # # ]: 0 : for (i = 0; i < num_pages; i++)
106 : 0 : qpl->page_buses[i] = mz->iova + i * PAGE_SIZE;
107 : : }
108 : :
109 : 0 : qpl->num_entries = num_pages;
110 : 0 : return qpl;
111 : :
112 : : free_qpl_page_bufs:
113 : 0 : rte_free(qpl->qpl_bufs);
114 : 0 : free_qpl_page_buses:
115 : 0 : rte_free(qpl->page_buses);
116 : 0 : free_qpl_struct:
117 : 0 : rte_free(qpl);
118 : 0 : return NULL;
119 : : }
120 : :
121 : : static void
122 : 0 : gve_free_queue_page_list(struct gve_queue_page_list *qpl)
123 : : {
124 [ # # ]: 0 : if (qpl->mz) {
125 : 0 : rte_memzone_free(qpl->mz);
126 : 0 : qpl->mz = NULL;
127 : : } else if (qpl->qpl_bufs) {
128 : : uint32_t i;
129 : :
130 : : for (i = 0; i < qpl->num_entries; i++)
131 : : rte_free(qpl->qpl_bufs[i]);
132 : : }
133 : :
134 [ # # ]: 0 : if (qpl->qpl_bufs) {
135 : 0 : rte_free(qpl->qpl_bufs);
136 : 0 : qpl->qpl_bufs = NULL;
137 : : }
138 : :
139 [ # # ]: 0 : if (qpl->page_buses) {
140 : 0 : rte_free(qpl->page_buses);
141 : 0 : qpl->page_buses = NULL;
142 : : }
143 : 0 : rte_free(qpl);
144 : 0 : }
145 : :
146 : : struct gve_queue_page_list *
147 : 0 : gve_setup_queue_page_list(struct gve_priv *priv, uint16_t queue_id, bool is_rx,
148 : : uint32_t num_pages)
149 : : {
150 [ # # ]: 0 : const char *queue_type_string = is_rx ? "rx" : "tx";
151 : : char qpl_name[RTE_MEMZONE_NAMESIZE];
152 : : struct gve_queue_page_list *qpl;
153 : : int err;
154 : :
155 : : /* Allocate a new QPL. */
156 : 0 : snprintf(qpl_name, sizeof(qpl_name), "gve_%s_%s_qpl%d",
157 : 0 : priv->pci_dev->device.name, queue_type_string, queue_id);
158 : 0 : qpl = gve_alloc_queue_page_list(qpl_name, num_pages, is_rx);
159 [ # # ]: 0 : if (!qpl) {
160 : 0 : PMD_DRV_LOG(ERR,
161 : : "Failed to alloc %s qpl for queue %hu.",
162 : : queue_type_string, queue_id);
163 : 0 : return NULL;
164 : : }
165 : :
166 : : /* Assign the QPL an ID. */
167 : 0 : qpl->id = queue_id;
168 [ # # ]: 0 : if (is_rx)
169 : 0 : qpl->id += priv->max_nb_txq;
170 : :
171 : : /* Validate page registration limit and register QPLs. */
172 : 0 : if (priv->num_registered_pages + qpl->num_entries >
173 [ # # ]: 0 : priv->max_registered_pages) {
174 : 0 : PMD_DRV_LOG(ERR, "Pages %" PRIu64 " > max registered pages %" PRIu64,
175 : : priv->num_registered_pages + qpl->num_entries,
176 : : priv->max_registered_pages);
177 : 0 : goto cleanup_qpl;
178 : : }
179 : 0 : err = gve_adminq_register_page_list(priv, qpl);
180 [ # # ]: 0 : if (err) {
181 : 0 : PMD_DRV_LOG(ERR,
182 : : "Failed to register %s qpl for queue %hu.",
183 : : queue_type_string, queue_id);
184 : 0 : goto cleanup_qpl;
185 : : }
186 : 0 : priv->num_registered_pages += qpl->num_entries;
187 : 0 : return qpl;
188 : :
189 : 0 : cleanup_qpl:
190 : 0 : gve_free_queue_page_list(qpl);
191 : 0 : return NULL;
192 : : }
193 : :
194 : : int
195 : 0 : gve_teardown_queue_page_list(struct gve_priv *priv,
196 : : struct gve_queue_page_list *qpl)
197 : : {
198 : 0 : int err = gve_adminq_unregister_page_list(priv, qpl->id);
199 [ # # ]: 0 : if (err) {
200 : 0 : PMD_DRV_LOG(CRIT, "Unable to unregister qpl %d!", qpl->id);
201 : 0 : return err;
202 : : }
203 : 0 : priv->num_registered_pages -= qpl->num_entries;
204 : 0 : gve_free_queue_page_list(qpl);
205 : 0 : return 0;
206 : : }
207 : :
208 : : static int
209 : 0 : gve_dev_configure(struct rte_eth_dev *dev)
210 : : {
211 : 0 : struct gve_priv *priv = dev->data->dev_private;
212 : :
213 [ # # ]: 0 : if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) {
214 : 0 : dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
215 : 0 : priv->rss_config.alg = GVE_RSS_HASH_TOEPLITZ;
216 : : }
217 : :
218 [ # # ]: 0 : if (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO)
219 : 0 : priv->enable_rsc = 1;
220 : :
221 : : /* Reset RSS RETA in case number of queues changed. */
222 [ # # ]: 0 : if (priv->rss_config.indir) {
223 : : struct gve_rss_config update_reta_config;
224 : 0 : gve_init_rss_config_from_priv(priv, &update_reta_config);
225 : 0 : gve_generate_rss_reta(dev, &update_reta_config);
226 : :
227 : 0 : int err = gve_adminq_configure_rss(priv, &update_reta_config);
228 [ # # ]: 0 : if (err)
229 : 0 : PMD_DRV_LOG(ERR,
230 : : "Could not reconfigure RSS redirection table.");
231 : : else
232 : 0 : gve_update_priv_rss_config(priv, &update_reta_config);
233 : :
234 : 0 : gve_free_rss_config(&update_reta_config);
235 : : return err;
236 : : }
237 : :
238 : : return 0;
239 : : }
240 : :
241 : : static int
242 : 0 : gve_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete)
243 : : {
244 [ # # ]: 0 : struct gve_priv *priv = dev->data->dev_private;
245 : : struct rte_eth_link link;
246 : : int err;
247 : :
248 : : memset(&link, 0, sizeof(link));
249 : 0 : link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
250 : 0 : link.link_autoneg = RTE_ETH_LINK_AUTONEG;
251 : :
252 [ # # ]: 0 : if (!dev->data->dev_started) {
253 : : link.link_status = RTE_ETH_LINK_DOWN;
254 : : link.link_speed = RTE_ETH_SPEED_NUM_NONE;
255 : : } else {
256 : 0 : link.link_status = RTE_ETH_LINK_UP;
257 : 0 : PMD_DRV_LOG(DEBUG, "Get link status from hw");
258 : 0 : err = gve_adminq_report_link_speed(priv);
259 [ # # ]: 0 : if (err) {
260 : 0 : PMD_DRV_LOG(ERR, "Failed to get link speed.");
261 : 0 : priv->link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
262 : : }
263 : 0 : link.link_speed = priv->link_speed;
264 : : }
265 : :
266 : 0 : return rte_eth_linkstatus_set(dev, &link);
267 : : }
268 : :
269 : : static int
270 : 0 : gve_alloc_stats_report(struct gve_priv *priv,
271 : : uint16_t nb_tx_queues, uint16_t nb_rx_queues)
272 : : {
273 : : char z_name[RTE_MEMZONE_NAMESIZE];
274 : : int tx_stats_cnt;
275 : : int rx_stats_cnt;
276 : :
277 : 0 : tx_stats_cnt = (GVE_TX_STATS_REPORT_NUM + NIC_TX_STATS_REPORT_NUM) *
278 : : nb_tx_queues;
279 : 0 : rx_stats_cnt = (GVE_RX_STATS_REPORT_NUM + NIC_RX_STATS_REPORT_NUM) *
280 : : nb_rx_queues;
281 : 0 : priv->stats_report_len = sizeof(struct gve_stats_report) +
282 : 0 : sizeof(struct stats) * (tx_stats_cnt + rx_stats_cnt);
283 : :
284 : 0 : snprintf(z_name, sizeof(z_name), "gve_stats_report_%s",
285 : 0 : priv->pci_dev->device.name);
286 : 0 : priv->stats_report_mem = rte_memzone_reserve_aligned(z_name,
287 : 0 : priv->stats_report_len,
288 : 0 : rte_socket_id(),
289 : : RTE_MEMZONE_IOVA_CONTIG, PAGE_SIZE);
290 : :
291 [ # # ]: 0 : if (!priv->stats_report_mem)
292 : : return -ENOMEM;
293 : :
294 : : /* offset by skipping stats written by gve. */
295 : 0 : priv->stats_start_idx = (GVE_TX_STATS_REPORT_NUM * nb_tx_queues) +
296 : : (GVE_RX_STATS_REPORT_NUM * nb_rx_queues);
297 : 0 : priv->stats_end_idx = priv->stats_start_idx +
298 : 0 : (NIC_TX_STATS_REPORT_NUM * nb_tx_queues) +
299 : 0 : (NIC_RX_STATS_REPORT_NUM * nb_rx_queues) - 1;
300 : :
301 : 0 : return 0;
302 : : }
303 : :
304 : : static void
305 : : gve_free_stats_report(struct rte_eth_dev *dev)
306 : : {
307 : : struct gve_priv *priv = dev->data->dev_private;
308 : 0 : rte_memzone_free(priv->stats_report_mem);
309 : 0 : priv->stats_report_mem = NULL;
310 : 0 : }
311 : :
312 : : /* Read Rx NIC stats from shared region */
313 : : static void
314 : 0 : gve_get_imissed_from_nic(struct rte_eth_dev *dev)
315 : : {
316 : : struct gve_stats_report *stats_report;
317 : : struct gve_rx_queue *rxq;
318 : : struct gve_priv *priv;
319 : : struct stats stat;
320 : : int queue_id;
321 : : int stat_id;
322 : : int i;
323 : :
324 : 0 : priv = dev->data->dev_private;
325 [ # # ]: 0 : if (!priv->stats_report_mem)
326 : : return;
327 : 0 : stats_report = (struct gve_stats_report *)
328 : : priv->stats_report_mem->addr;
329 [ # # ]: 0 : for (i = priv->stats_start_idx; i <= priv->stats_end_idx; i++) {
330 : 0 : stat = stats_report->stats[i];
331 [ # # ]: 0 : queue_id = cpu_to_be32(stat.queue_id);
332 : 0 : rxq = dev->data->rx_queues[queue_id];
333 [ # # ]: 0 : if (rxq == NULL)
334 : 0 : continue;
335 [ # # ]: 0 : stat_id = cpu_to_be32(stat.stat_name);
336 : : /* Update imissed. */
337 [ # # ]: 0 : if (stat_id == RX_NO_BUFFERS_POSTED)
338 [ # # ]: 0 : rxq->stats.imissed = cpu_to_be64(stat.value);
339 : : }
340 : : }
341 : :
342 : : static int
343 : 0 : gve_start_queues(struct rte_eth_dev *dev)
344 : : {
345 : 0 : struct gve_priv *priv = dev->data->dev_private;
346 : : uint16_t num_queues;
347 : : uint16_t i;
348 : : int ret;
349 : :
350 : 0 : num_queues = dev->data->nb_tx_queues;
351 : 0 : priv->txqs = (struct gve_tx_queue **)dev->data->tx_queues;
352 : 0 : ret = gve_adminq_create_tx_queues(priv, num_queues);
353 [ # # ]: 0 : if (ret != 0) {
354 : 0 : PMD_DRV_LOG(ERR, "Failed to create %u tx queues.", num_queues);
355 : 0 : return ret;
356 : : }
357 [ # # ]: 0 : for (i = 0; i < num_queues; i++) {
358 [ # # ]: 0 : if (gve_is_gqi(priv))
359 : 0 : ret = gve_tx_queue_start(dev, i);
360 : : else
361 : 0 : ret = gve_tx_queue_start_dqo(dev, i);
362 [ # # ]: 0 : if (ret != 0) {
363 : 0 : PMD_DRV_LOG(ERR, "Fail to start Tx queue %d", i);
364 : 0 : goto err_tx;
365 : : }
366 : : }
367 : :
368 : 0 : num_queues = dev->data->nb_rx_queues;
369 : 0 : priv->rxqs = (struct gve_rx_queue **)dev->data->rx_queues;
370 : 0 : ret = gve_adminq_create_rx_queues(priv, num_queues);
371 [ # # ]: 0 : if (ret != 0) {
372 : 0 : PMD_DRV_LOG(ERR, "Failed to create %u rx queues.", num_queues);
373 : 0 : goto err_tx;
374 : : }
375 [ # # ]: 0 : for (i = 0; i < num_queues; i++) {
376 [ # # ]: 0 : if (gve_is_gqi(priv))
377 : 0 : ret = gve_rx_queue_start(dev, i);
378 : : else
379 : 0 : ret = gve_rx_queue_start_dqo(dev, i);
380 [ # # ]: 0 : if (ret != 0) {
381 : 0 : PMD_DRV_LOG(ERR, "Fail to start Rx queue %d", i);
382 [ # # ]: 0 : goto err_rx;
383 : : }
384 : : }
385 : :
386 : : return 0;
387 : :
388 : : err_rx:
389 [ # # ]: 0 : if (gve_is_gqi(priv))
390 : 0 : gve_stop_rx_queues(dev);
391 : : else
392 : 0 : gve_stop_rx_queues_dqo(dev);
393 [ # # ]: 0 : err_tx:
394 [ # # ]: 0 : if (gve_is_gqi(priv))
395 : 0 : gve_stop_tx_queues(dev);
396 : : else
397 : 0 : gve_stop_tx_queues_dqo(dev);
398 : : return ret;
399 : : }
400 : :
401 : : static int
402 : 0 : gve_dev_start(struct rte_eth_dev *dev)
403 : : {
404 : : struct gve_priv *priv;
405 : : int ret;
406 : :
407 : 0 : ret = gve_start_queues(dev);
408 [ # # ]: 0 : if (ret != 0) {
409 : 0 : PMD_DRV_LOG(ERR, "Failed to start queues");
410 : 0 : return ret;
411 : : }
412 : :
413 : 0 : dev->data->dev_started = 1;
414 : 0 : gve_link_update(dev, 0);
415 : :
416 [ # # ]: 0 : priv = dev->data->dev_private;
417 : : /* No stats available yet for Dqo. */
418 [ # # ]: 0 : if (gve_is_gqi(priv)) {
419 : 0 : ret = gve_alloc_stats_report(priv,
420 : 0 : dev->data->nb_tx_queues,
421 : 0 : dev->data->nb_rx_queues);
422 [ # # ]: 0 : if (ret != 0) {
423 : 0 : PMD_DRV_LOG(ERR,
424 : : "Failed to allocate region for stats reporting.");
425 : 0 : return ret;
426 : : }
427 : 0 : ret = gve_adminq_report_stats(priv, priv->stats_report_len,
428 : 0 : priv->stats_report_mem->iova,
429 : : GVE_STATS_REPORT_TIMER_PERIOD);
430 [ # # ]: 0 : if (ret != 0) {
431 : 0 : PMD_DRV_LOG(ERR, "gve_adminq_report_stats command failed.");
432 : 0 : return ret;
433 : : }
434 : : }
435 : :
436 : : return 0;
437 : : }
438 : :
439 : : static int
440 : 0 : gve_dev_stop(struct rte_eth_dev *dev)
441 : : {
442 : 0 : struct gve_priv *priv = dev->data->dev_private;
443 [ # # ]: 0 : dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
444 : :
445 [ # # ]: 0 : if (gve_is_gqi(priv)) {
446 : 0 : gve_stop_tx_queues(dev);
447 : 0 : gve_stop_rx_queues(dev);
448 : : } else {
449 : 0 : gve_stop_tx_queues_dqo(dev);
450 : 0 : gve_stop_rx_queues_dqo(dev);
451 : : }
452 : :
453 : 0 : dev->data->dev_started = 0;
454 : :
455 [ # # ]: 0 : if (gve_is_gqi(dev->data->dev_private))
456 : : gve_free_stats_report(dev);
457 : :
458 : 0 : return 0;
459 : : }
460 : :
461 : : static int
462 : 0 : gve_dev_close(struct rte_eth_dev *dev)
463 : : {
464 : 0 : struct gve_priv *priv = dev->data->dev_private;
465 : : int err = 0;
466 : : uint16_t i;
467 : :
468 [ # # ]: 0 : if (dev->data->dev_started) {
469 : 0 : err = gve_dev_stop(dev);
470 [ # # ]: 0 : if (err != 0)
471 : 0 : PMD_DRV_LOG(ERR, "Failed to stop dev.");
472 : : }
473 : :
474 [ # # ]: 0 : if (gve_is_gqi(priv)) {
475 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
476 : 0 : gve_tx_queue_release(dev, i);
477 : :
478 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
479 : 0 : gve_rx_queue_release(dev, i);
480 : : } else {
481 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
482 : 0 : gve_tx_queue_release_dqo(dev, i);
483 : :
484 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
485 : 0 : gve_rx_queue_release_dqo(dev, i);
486 : : }
487 : :
488 : 0 : rte_free(priv->adminq);
489 : :
490 : 0 : dev->data->mac_addrs = NULL;
491 : :
492 : 0 : return err;
493 : : }
494 : :
495 : : static int
496 : 0 : gve_verify_driver_compatibility(struct gve_priv *priv)
497 : : {
498 : : const struct rte_memzone *driver_info_mem;
499 : : struct gve_driver_info *driver_info;
500 : : int err;
501 : :
502 : 0 : driver_info_mem = rte_memzone_reserve_aligned("verify_driver_compatibility",
503 : : sizeof(struct gve_driver_info),
504 : 0 : rte_socket_id(),
505 : : RTE_MEMZONE_IOVA_CONTIG, PAGE_SIZE);
506 : :
507 [ # # ]: 0 : if (driver_info_mem == NULL) {
508 : 0 : PMD_DRV_LOG(ERR,
509 : : "Could not alloc memzone for driver compatibility");
510 : 0 : return -ENOMEM;
511 : : }
512 : 0 : driver_info = (struct gve_driver_info *)driver_info_mem->addr;
513 : :
514 : 0 : *driver_info = (struct gve_driver_info) {
515 : : .os_type = 5, /* DPDK */
516 : : .driver_major = GVE_VERSION_MAJOR,
517 : : .driver_minor = GVE_VERSION_MINOR,
518 : : .driver_sub = GVE_VERSION_SUB,
519 : : .os_version_major = cpu_to_be32(DPDK_VERSION_MAJOR),
520 : : .os_version_minor = cpu_to_be32(DPDK_VERSION_MINOR),
521 : : .os_version_sub = cpu_to_be32(DPDK_VERSION_SUB),
522 : : .driver_capability_flags = {
523 : : cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS1),
524 : : cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS2),
525 : : cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS3),
526 : : cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS4),
527 : : },
528 : : };
529 : :
530 : 0 : populate_driver_version_strings((char *)driver_info->os_version_str1,
531 : 0 : (char *)driver_info->os_version_str2);
532 : :
533 : 0 : err = gve_adminq_verify_driver_compatibility(priv,
534 : : sizeof(struct gve_driver_info),
535 : 0 : (dma_addr_t)driver_info_mem->iova);
536 : : /* It's ok if the device doesn't support this */
537 [ # # ]: 0 : if (err == -EOPNOTSUPP)
538 : : err = 0;
539 : :
540 : 0 : rte_memzone_free(driver_info_mem);
541 : 0 : return err;
542 : : }
543 : :
544 : : static int
545 : 0 : gve_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
546 : : {
547 : 0 : struct gve_priv *priv = dev->data->dev_private;
548 : :
549 : 0 : dev_info->device = dev->device;
550 : 0 : dev_info->max_mac_addrs = 1;
551 : 0 : dev_info->max_rx_queues = priv->max_nb_rxq;
552 [ # # ]: 0 : dev_info->max_tx_queues = priv->max_nb_txq;
553 [ # # ]: 0 : if (gve_is_gqi(priv)) {
554 : 0 : dev_info->min_rx_bufsize = GVE_RX_MIN_BUF_SIZE_GQI;
555 : 0 : dev_info->max_rx_bufsize = GVE_RX_MAX_BUF_SIZE_GQI;
556 : : } else {
557 : 0 : dev_info->min_rx_bufsize = GVE_RX_MIN_BUF_SIZE_DQO;
558 : 0 : dev_info->max_rx_bufsize = GVE_RX_MAX_BUF_SIZE_DQO;
559 : : }
560 : :
561 : 0 : dev_info->max_rx_pktlen = priv->max_mtu + RTE_ETHER_HDR_LEN;
562 : 0 : dev_info->max_mtu = priv->max_mtu;
563 : 0 : dev_info->min_mtu = RTE_ETHER_MIN_MTU;
564 : :
565 : 0 : dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_RSS_HASH;
566 : 0 : dev_info->tx_offload_capa =
567 : : RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
568 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
569 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
570 : : RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
571 : : RTE_ETH_TX_OFFLOAD_TCP_TSO;
572 : :
573 [ # # ]: 0 : if (!gve_is_gqi(priv)) {
574 : 0 : dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM;
575 : 0 : dev_info->rx_offload_capa |=
576 : : RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
577 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
578 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
579 : : RTE_ETH_RX_OFFLOAD_TCP_LRO;
580 : : }
581 : :
582 : 0 : dev_info->default_rxconf = (struct rte_eth_rxconf) {
583 : : .rx_free_thresh = GVE_DEFAULT_RX_FREE_THRESH,
584 : : .rx_drop_en = 0,
585 : : .offloads = 0,
586 : : };
587 : :
588 : 0 : dev_info->default_txconf = (struct rte_eth_txconf) {
589 : : .tx_free_thresh = GVE_DEFAULT_TX_FREE_THRESH,
590 : : .tx_rs_thresh = GVE_DEFAULT_TX_RS_THRESH,
591 : : .offloads = 0,
592 : : };
593 : :
594 : 0 : dev_info->default_rxportconf.ring_size = priv->default_rx_desc_cnt;
595 : 0 : dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
596 : 0 : .nb_max = priv->max_rx_desc_cnt,
597 : 0 : .nb_min = priv->min_rx_desc_cnt,
598 : : .nb_align = 1,
599 : : };
600 : :
601 : 0 : dev_info->default_txportconf.ring_size = priv->default_tx_desc_cnt;
602 : 0 : dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
603 : 0 : .nb_max = priv->max_tx_desc_cnt,
604 : 0 : .nb_min = priv->min_tx_desc_cnt,
605 : : .nb_align = 1,
606 : : };
607 : :
608 : 0 : dev_info->flow_type_rss_offloads = GVE_RTE_RSS_OFFLOAD_ALL;
609 : 0 : dev_info->hash_key_size = GVE_RSS_HASH_KEY_SIZE;
610 : 0 : dev_info->reta_size = GVE_RSS_INDIR_SIZE;
611 : :
612 : 0 : return 0;
613 : : }
614 : :
615 : : static int
616 : 0 : gve_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
617 : : {
618 : : uint16_t i;
619 [ # # ]: 0 : if (gve_is_gqi(dev->data->dev_private))
620 : 0 : gve_get_imissed_from_nic(dev);
621 : :
622 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
623 : 0 : struct gve_tx_queue *txq = dev->data->tx_queues[i];
624 [ # # ]: 0 : if (txq == NULL)
625 : 0 : continue;
626 : :
627 : 0 : stats->opackets += txq->stats.packets;
628 : 0 : stats->obytes += txq->stats.bytes;
629 : 0 : stats->oerrors += txq->stats.errors;
630 : : }
631 : :
632 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
633 : 0 : struct gve_rx_queue *rxq = dev->data->rx_queues[i];
634 [ # # ]: 0 : if (rxq == NULL)
635 : 0 : continue;
636 : :
637 : 0 : stats->ipackets += rxq->stats.packets;
638 : 0 : stats->ibytes += rxq->stats.bytes;
639 : 0 : stats->ierrors += rxq->stats.errors;
640 : 0 : stats->rx_nombuf += rxq->stats.no_mbufs;
641 : 0 : stats->imissed += rxq->stats.imissed;
642 : : }
643 : :
644 : 0 : return 0;
645 : : }
646 : :
647 : : static int
648 : 0 : gve_dev_stats_reset(struct rte_eth_dev *dev)
649 : : {
650 : : uint16_t i;
651 : :
652 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
653 : 0 : struct gve_tx_queue *txq = dev->data->tx_queues[i];
654 [ # # ]: 0 : if (txq == NULL)
655 : 0 : continue;
656 : :
657 : 0 : memset(&txq->stats, 0, sizeof(txq->stats));
658 : : }
659 : :
660 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
661 : 0 : struct gve_rx_queue *rxq = dev->data->rx_queues[i];
662 [ # # ]: 0 : if (rxq == NULL)
663 : 0 : continue;
664 : :
665 : 0 : memset(&rxq->stats, 0, sizeof(rxq->stats));
666 : : }
667 : :
668 : 0 : return 0;
669 : : }
670 : :
671 : : static int
672 : 0 : gve_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
673 : : {
674 : 0 : struct gve_priv *priv = dev->data->dev_private;
675 : : int err;
676 : :
677 [ # # # # ]: 0 : if (mtu < RTE_ETHER_MIN_MTU || mtu > priv->max_mtu) {
678 : 0 : PMD_DRV_LOG(ERR, "MIN MTU is %u, MAX MTU is %u",
679 : : RTE_ETHER_MIN_MTU, priv->max_mtu);
680 : 0 : return -EINVAL;
681 : : }
682 : :
683 : : /* mtu setting is forbidden if port is start */
684 [ # # ]: 0 : if (dev->data->dev_started) {
685 : 0 : PMD_DRV_LOG(ERR, "Port must be stopped before configuration");
686 : 0 : return -EBUSY;
687 : : }
688 : :
689 : 0 : err = gve_adminq_set_mtu(priv, mtu);
690 [ # # ]: 0 : if (err) {
691 : 0 : PMD_DRV_LOG(ERR, "Failed to set mtu as %u err = %d", mtu, err);
692 : 0 : return err;
693 : : }
694 : :
695 : : return 0;
696 : : }
697 : :
698 : : #define TX_QUEUE_STATS_OFFSET(x) offsetof(struct gve_tx_stats, x)
699 : : #define RX_QUEUE_STATS_OFFSET(x) offsetof(struct gve_rx_stats, x)
700 : :
701 : : static const struct gve_xstats_name_offset tx_xstats_name_offset[] = {
702 : : { "packets", TX_QUEUE_STATS_OFFSET(packets) },
703 : : { "bytes", TX_QUEUE_STATS_OFFSET(bytes) },
704 : : { "errors", TX_QUEUE_STATS_OFFSET(errors) },
705 : : };
706 : :
707 : : static const struct gve_xstats_name_offset rx_xstats_name_offset[] = {
708 : : { "packets", RX_QUEUE_STATS_OFFSET(packets) },
709 : : { "bytes", RX_QUEUE_STATS_OFFSET(bytes) },
710 : : { "errors", RX_QUEUE_STATS_OFFSET(errors) },
711 : : { "mbuf_alloc_errors", RX_QUEUE_STATS_OFFSET(no_mbufs) },
712 : : { "mbuf_alloc_errors_bulk", RX_QUEUE_STATS_OFFSET(no_mbufs_bulk) },
713 : : { "imissed", RX_QUEUE_STATS_OFFSET(imissed) },
714 : : };
715 : :
716 : : static int
717 : 0 : gve_xstats_count(struct rte_eth_dev *dev)
718 : : {
719 : : uint16_t i, count = 0;
720 : :
721 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
722 [ # # ]: 0 : if (dev->data->tx_queues[i])
723 : 0 : count += RTE_DIM(tx_xstats_name_offset);
724 : : }
725 : :
726 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
727 [ # # ]: 0 : if (dev->data->rx_queues[i])
728 : 0 : count += RTE_DIM(rx_xstats_name_offset);
729 : : }
730 : :
731 : 0 : return count;
732 : : }
733 : :
734 : : static int
735 : 0 : gve_xstats_get(struct rte_eth_dev *dev,
736 : : struct rte_eth_xstat *xstats,
737 : : unsigned int size)
738 : : {
739 : 0 : uint16_t i, j, count = gve_xstats_count(dev);
740 : : const char *stats;
741 : :
742 [ # # ]: 0 : if (gve_is_gqi(dev->data->dev_private))
743 : 0 : gve_get_imissed_from_nic(dev);
744 : :
745 [ # # # # ]: 0 : if (xstats == NULL || size < count)
746 : 0 : return count;
747 : :
748 : : count = 0;
749 : :
750 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
751 : 0 : const struct gve_tx_queue *txq = dev->data->tx_queues[i];
752 [ # # ]: 0 : if (txq == NULL)
753 : 0 : continue;
754 : :
755 : 0 : stats = (const char *)&txq->stats;
756 [ # # ]: 0 : for (j = 0; j < RTE_DIM(tx_xstats_name_offset); j++, count++) {
757 : 0 : xstats[count].id = count;
758 : 0 : xstats[count].value = *(const uint64_t *)
759 : 0 : (stats + tx_xstats_name_offset[j].offset);
760 : : }
761 : : }
762 : :
763 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
764 : 0 : const struct gve_rx_queue *rxq = dev->data->rx_queues[i];
765 [ # # ]: 0 : if (rxq == NULL)
766 : 0 : continue;
767 : :
768 : 0 : stats = (const char *)&rxq->stats;
769 [ # # ]: 0 : for (j = 0; j < RTE_DIM(rx_xstats_name_offset); j++, count++) {
770 : 0 : xstats[count].id = count;
771 : 0 : xstats[count].value = *(const uint64_t *)
772 : 0 : (stats + rx_xstats_name_offset[j].offset);
773 : : }
774 : : }
775 : :
776 : 0 : return count;
777 : : }
778 : :
779 : : static int
780 : 0 : gve_xstats_get_names(struct rte_eth_dev *dev,
781 : : struct rte_eth_xstat_name *xstats_names,
782 : : unsigned int size)
783 : : {
784 : 0 : uint16_t i, j, count = gve_xstats_count(dev);
785 : :
786 [ # # # # ]: 0 : if (xstats_names == NULL || size < count)
787 : 0 : return count;
788 : :
789 : : count = 0;
790 : :
791 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
792 [ # # ]: 0 : if (dev->data->tx_queues[i] == NULL)
793 : 0 : continue;
794 : :
795 [ # # ]: 0 : for (j = 0; j < RTE_DIM(tx_xstats_name_offset); j++)
796 : 0 : snprintf(xstats_names[count++].name,
797 : : RTE_ETH_XSTATS_NAME_SIZE,
798 : 0 : "tx_q%u_%s", i, tx_xstats_name_offset[j].name);
799 : : }
800 : :
801 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
802 [ # # ]: 0 : if (dev->data->rx_queues[i] == NULL)
803 : 0 : continue;
804 : :
805 [ # # ]: 0 : for (j = 0; j < RTE_DIM(rx_xstats_name_offset); j++)
806 : 0 : snprintf(xstats_names[count++].name,
807 : : RTE_ETH_XSTATS_NAME_SIZE,
808 : 0 : "rx_q%u_%s", i, rx_xstats_name_offset[j].name);
809 : : }
810 : :
811 : 0 : return count;
812 : : }
813 : :
814 : :
815 : : static int
816 : 0 : gve_rss_hash_update(struct rte_eth_dev *dev,
817 : : struct rte_eth_rss_conf *rss_conf)
818 : : {
819 : 0 : struct gve_priv *priv = dev->data->dev_private;
820 : : struct gve_rss_config gve_rss_conf;
821 : : int rss_reta_size;
822 : : int err;
823 : :
824 [ # # ]: 0 : if (gve_validate_rss_hf(rss_conf->rss_hf)) {
825 : 0 : PMD_DRV_LOG(ERR, "Unsupported hash function.");
826 : 0 : return -EINVAL;
827 : : }
828 : :
829 [ # # ]: 0 : if (rss_conf->algorithm != RTE_ETH_HASH_FUNCTION_TOEPLITZ &&
830 : : rss_conf->algorithm != RTE_ETH_HASH_FUNCTION_DEFAULT) {
831 : 0 : PMD_DRV_LOG(ERR, "Device only supports Toeplitz algorithm.");
832 : 0 : return -EINVAL;
833 : : }
834 : :
835 [ # # ]: 0 : if (rss_conf->rss_key_len) {
836 [ # # ]: 0 : if (rss_conf->rss_key_len != GVE_RSS_HASH_KEY_SIZE) {
837 : 0 : PMD_DRV_LOG(ERR,
838 : : "Invalid hash key size. Only RSS hash key size "
839 : : "of %u supported", GVE_RSS_HASH_KEY_SIZE);
840 : 0 : return -EINVAL;
841 : : }
842 : :
843 [ # # ]: 0 : if (!rss_conf->rss_key) {
844 : 0 : PMD_DRV_LOG(ERR, "RSS key must be non-null.");
845 : 0 : return -EINVAL;
846 : : }
847 : : } else {
848 [ # # ]: 0 : if (!priv->rss_config.key_size) {
849 : 0 : PMD_DRV_LOG(ERR, "RSS key must be initialized before "
850 : : "any other configuration.");
851 : 0 : return -EINVAL;
852 : : }
853 : 0 : rss_conf->rss_key_len = priv->rss_config.key_size;
854 : : }
855 : :
856 : 0 : rss_reta_size = priv->rss_config.indir ?
857 [ # # ]: 0 : priv->rss_config.indir_size :
858 : : GVE_RSS_INDIR_SIZE;
859 : 0 : err = gve_init_rss_config(&gve_rss_conf, rss_conf->rss_key_len,
860 : : rss_reta_size);
861 [ # # ]: 0 : if (err)
862 : : return err;
863 : :
864 : 0 : gve_rss_conf.alg = GVE_RSS_HASH_TOEPLITZ;
865 : 0 : err = gve_update_rss_hash_types(priv, &gve_rss_conf, rss_conf);
866 [ # # ]: 0 : if (err)
867 : 0 : goto err;
868 : 0 : err = gve_update_rss_key(priv, &gve_rss_conf, rss_conf);
869 [ # # ]: 0 : if (err)
870 : 0 : goto err;
871 : :
872 : : /* Set redirection table to default or preexisting. */
873 [ # # ]: 0 : if (!priv->rss_config.indir)
874 : 0 : gve_generate_rss_reta(dev, &gve_rss_conf);
875 : : else
876 : 0 : memcpy(gve_rss_conf.indir, priv->rss_config.indir,
877 : 0 : gve_rss_conf.indir_size * sizeof(*priv->rss_config.indir));
878 : :
879 : 0 : err = gve_adminq_configure_rss(priv, &gve_rss_conf);
880 [ # # ]: 0 : if (!err)
881 : 0 : gve_update_priv_rss_config(priv, &gve_rss_conf);
882 : :
883 : 0 : err:
884 : 0 : gve_free_rss_config(&gve_rss_conf);
885 : 0 : return err;
886 : : }
887 : :
888 : : static int
889 : 0 : gve_rss_hash_conf_get(struct rte_eth_dev *dev,
890 : : struct rte_eth_rss_conf *rss_conf)
891 : : {
892 : 0 : struct gve_priv *priv = dev->data->dev_private;
893 : :
894 [ # # ]: 0 : if (!(dev->data->dev_conf.rxmode.offloads &
895 : : RTE_ETH_RX_OFFLOAD_RSS_HASH)) {
896 : 0 : PMD_DRV_LOG(ERR, "RSS not configured.");
897 : 0 : return -ENOTSUP;
898 : : }
899 : :
900 : :
901 : 0 : gve_to_rte_rss_hf(priv->rss_config.hash_types, rss_conf);
902 : 0 : rss_conf->rss_key_len = priv->rss_config.key_size;
903 [ # # ]: 0 : if (rss_conf->rss_key) {
904 [ # # ]: 0 : if (!priv->rss_config.key) {
905 : 0 : PMD_DRV_LOG(ERR, "Unable to retrieve default RSS hash key.");
906 : 0 : return -ENOTSUP;
907 : : }
908 : 0 : memcpy(rss_conf->rss_key, priv->rss_config.key,
909 : : rss_conf->rss_key_len * sizeof(*rss_conf->rss_key));
910 : : }
911 : :
912 : : return 0;
913 : : }
914 : :
915 : : static int
916 : 0 : gve_rss_reta_update(struct rte_eth_dev *dev,
917 : : struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
918 : : {
919 : 0 : struct gve_priv *priv = dev->data->dev_private;
920 : : struct gve_rss_config gve_rss_conf;
921 : : int table_id;
922 : : int err;
923 : : int i;
924 : :
925 : : /* RSS key must be set before the redirection table can be set. */
926 [ # # # # ]: 0 : if (!priv->rss_config.key || priv->rss_config.key_size == 0) {
927 : 0 : PMD_DRV_LOG(ERR, "RSS hash key msut be set before the "
928 : : "redirection table can be updated.");
929 : 0 : return -ENOTSUP;
930 : : }
931 : :
932 [ # # ]: 0 : if (reta_size != GVE_RSS_INDIR_SIZE) {
933 : 0 : PMD_DRV_LOG(ERR, "Redirection table must have %hu elements",
934 : : (uint16_t)GVE_RSS_INDIR_SIZE);
935 : 0 : return -EINVAL;
936 : : }
937 : :
938 : 0 : err = gve_init_rss_config_from_priv(priv, &gve_rss_conf);
939 [ # # ]: 0 : if (err) {
940 : 0 : PMD_DRV_LOG(ERR, "Error allocating new RSS config.");
941 : 0 : return err;
942 : : }
943 : :
944 : : table_id = 0;
945 [ # # ]: 0 : for (i = 0; i < priv->rss_config.indir_size; i++) {
946 : 0 : int table_entry = i % RTE_ETH_RETA_GROUP_SIZE;
947 [ # # ]: 0 : if (reta_conf[table_id].mask & (1ULL << table_entry))
948 : 0 : gve_rss_conf.indir[i] =
949 : 0 : reta_conf[table_id].reta[table_entry];
950 : :
951 [ # # ]: 0 : if (table_entry == RTE_ETH_RETA_GROUP_SIZE - 1)
952 : 0 : table_id++;
953 : : }
954 : :
955 : 0 : err = gve_adminq_configure_rss(priv, &gve_rss_conf);
956 [ # # ]: 0 : if (err)
957 : 0 : PMD_DRV_LOG(ERR, "Problem configuring RSS with device.");
958 : : else
959 : 0 : gve_update_priv_rss_config(priv, &gve_rss_conf);
960 : :
961 : 0 : gve_free_rss_config(&gve_rss_conf);
962 : 0 : return err;
963 : : }
964 : :
965 : : static int
966 : 0 : gve_rss_reta_query(struct rte_eth_dev *dev,
967 : : struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
968 : : {
969 : 0 : struct gve_priv *priv = dev->data->dev_private;
970 : : int table_id;
971 : : int i;
972 : :
973 [ # # ]: 0 : if (!(dev->data->dev_conf.rxmode.offloads &
974 : : RTE_ETH_RX_OFFLOAD_RSS_HASH)) {
975 : 0 : PMD_DRV_LOG(ERR, "RSS not configured.");
976 : 0 : return -ENOTSUP;
977 : : }
978 : :
979 : : /* RSS key must be set before the redirection table can be queried. */
980 [ # # ]: 0 : if (!priv->rss_config.key) {
981 : 0 : PMD_DRV_LOG(ERR, "RSS hash key must be set before the "
982 : : "redirection table can be initialized.");
983 : 0 : return -ENOTSUP;
984 : : }
985 : :
986 [ # # ]: 0 : if (reta_size != priv->rss_config.indir_size) {
987 : 0 : PMD_DRV_LOG(ERR, "RSS redirection table must have %d entries.",
988 : : priv->rss_config.indir_size);
989 : 0 : return -EINVAL;
990 : : }
991 : :
992 : : table_id = 0;
993 [ # # ]: 0 : for (i = 0; i < priv->rss_config.indir_size; i++) {
994 : 0 : int table_entry = i % RTE_ETH_RETA_GROUP_SIZE;
995 [ # # ]: 0 : if (reta_conf[table_id].mask & (1ULL << table_entry))
996 : 0 : reta_conf[table_id].reta[table_entry] =
997 : 0 : priv->rss_config.indir[i];
998 : :
999 [ # # ]: 0 : if (table_entry == RTE_ETH_RETA_GROUP_SIZE - 1)
1000 : 0 : table_id++;
1001 : : }
1002 : :
1003 : : return 0;
1004 : : }
1005 : :
1006 : : static const struct eth_dev_ops gve_eth_dev_ops = {
1007 : : .dev_configure = gve_dev_configure,
1008 : : .dev_start = gve_dev_start,
1009 : : .dev_stop = gve_dev_stop,
1010 : : .dev_close = gve_dev_close,
1011 : : .dev_infos_get = gve_dev_info_get,
1012 : : .rx_queue_setup = gve_rx_queue_setup,
1013 : : .tx_queue_setup = gve_tx_queue_setup,
1014 : : .rx_queue_release = gve_rx_queue_release,
1015 : : .tx_queue_release = gve_tx_queue_release,
1016 : : .rx_queue_start = gve_rx_queue_start,
1017 : : .tx_queue_start = gve_tx_queue_start,
1018 : : .rx_queue_stop = gve_rx_queue_stop,
1019 : : .tx_queue_stop = gve_tx_queue_stop,
1020 : : .link_update = gve_link_update,
1021 : : .stats_get = gve_dev_stats_get,
1022 : : .stats_reset = gve_dev_stats_reset,
1023 : : .mtu_set = gve_dev_mtu_set,
1024 : : .xstats_get = gve_xstats_get,
1025 : : .xstats_get_names = gve_xstats_get_names,
1026 : : .rss_hash_update = gve_rss_hash_update,
1027 : : .rss_hash_conf_get = gve_rss_hash_conf_get,
1028 : : .reta_update = gve_rss_reta_update,
1029 : : .reta_query = gve_rss_reta_query,
1030 : : };
1031 : :
1032 : : static const struct eth_dev_ops gve_eth_dev_ops_dqo = {
1033 : : .dev_configure = gve_dev_configure,
1034 : : .dev_start = gve_dev_start,
1035 : : .dev_stop = gve_dev_stop,
1036 : : .dev_close = gve_dev_close,
1037 : : .dev_infos_get = gve_dev_info_get,
1038 : : .rx_queue_setup = gve_rx_queue_setup_dqo,
1039 : : .tx_queue_setup = gve_tx_queue_setup_dqo,
1040 : : .rx_queue_release = gve_rx_queue_release_dqo,
1041 : : .tx_queue_release = gve_tx_queue_release_dqo,
1042 : : .rx_queue_start = gve_rx_queue_start_dqo,
1043 : : .tx_queue_start = gve_tx_queue_start_dqo,
1044 : : .rx_queue_stop = gve_rx_queue_stop_dqo,
1045 : : .tx_queue_stop = gve_tx_queue_stop_dqo,
1046 : : .link_update = gve_link_update,
1047 : : .stats_get = gve_dev_stats_get,
1048 : : .stats_reset = gve_dev_stats_reset,
1049 : : .mtu_set = gve_dev_mtu_set,
1050 : : .xstats_get = gve_xstats_get,
1051 : : .xstats_get_names = gve_xstats_get_names,
1052 : : .rss_hash_update = gve_rss_hash_update,
1053 : : .rss_hash_conf_get = gve_rss_hash_conf_get,
1054 : : .reta_update = gve_rss_reta_update,
1055 : : .reta_query = gve_rss_reta_query,
1056 : : };
1057 : :
1058 : : static void
1059 : : gve_free_counter_array(struct gve_priv *priv)
1060 : : {
1061 : 0 : rte_memzone_free(priv->cnt_array_mz);
1062 : 0 : priv->cnt_array = NULL;
1063 : : }
1064 : :
1065 : : static void
1066 : : gve_free_irq_db(struct gve_priv *priv)
1067 : : {
1068 : 0 : rte_memzone_free(priv->irq_dbs_mz);
1069 : 0 : priv->irq_dbs = NULL;
1070 : 0 : }
1071 : :
1072 : : static void
1073 [ # # ]: 0 : gve_teardown_device_resources(struct gve_priv *priv)
1074 : : {
1075 : : int err;
1076 : :
1077 : : /* Tell device its resources are being freed */
1078 [ # # ]: 0 : if (gve_get_device_resources_ok(priv)) {
1079 : 0 : err = gve_adminq_deconfigure_device_resources(priv);
1080 [ # # ]: 0 : if (err)
1081 : 0 : PMD_DRV_LOG(ERR, "Could not deconfigure device resources: err=%d", err);
1082 : : }
1083 : :
1084 [ # # ]: 0 : if (!gve_is_gqi(priv)) {
1085 : 0 : rte_free(priv->ptype_lut_dqo);
1086 : 0 : priv->ptype_lut_dqo = NULL;
1087 : : }
1088 : : gve_free_counter_array(priv);
1089 : : gve_free_irq_db(priv);
1090 : : gve_clear_device_resources_ok(priv);
1091 : 0 : }
1092 : :
1093 : : static int
1094 : 0 : pci_dev_msix_vec_count(struct rte_pci_device *pdev)
1095 : : {
1096 : 0 : off_t msix_pos = rte_pci_find_capability(pdev, RTE_PCI_CAP_ID_MSIX);
1097 : : uint16_t control;
1098 : :
1099 [ # # # # ]: 0 : if (msix_pos > 0 && rte_pci_read_config(pdev, &control, sizeof(control),
1100 : : msix_pos + RTE_PCI_MSIX_FLAGS) == sizeof(control))
1101 : 0 : return (control & RTE_PCI_MSIX_FLAGS_QSIZE) + 1;
1102 : :
1103 : : return 0;
1104 : : }
1105 : :
1106 : : static int
1107 : 0 : gve_setup_device_resources(struct gve_priv *priv)
1108 : : {
1109 : : char z_name[RTE_MEMZONE_NAMESIZE];
1110 : : const struct rte_memzone *mz;
1111 : : int err = 0;
1112 : :
1113 : 0 : snprintf(z_name, sizeof(z_name), "gve_%s_cnt_arr", priv->pci_dev->device.name);
1114 : 0 : mz = rte_memzone_reserve_aligned(z_name,
1115 : 0 : priv->num_event_counters * sizeof(*priv->cnt_array),
1116 : 0 : rte_socket_id(), RTE_MEMZONE_IOVA_CONTIG,
1117 : : PAGE_SIZE);
1118 [ # # ]: 0 : if (mz == NULL) {
1119 : 0 : PMD_DRV_LOG(ERR, "Could not alloc memzone for count array");
1120 : 0 : return -ENOMEM;
1121 : : }
1122 : 0 : priv->cnt_array = (rte_be32_t *)mz->addr;
1123 : 0 : priv->cnt_array_mz = mz;
1124 : :
1125 : 0 : snprintf(z_name, sizeof(z_name), "gve_%s_irqmz", priv->pci_dev->device.name);
1126 : 0 : mz = rte_memzone_reserve_aligned(z_name,
1127 : 0 : sizeof(*priv->irq_dbs) * (priv->num_ntfy_blks),
1128 : 0 : rte_socket_id(), RTE_MEMZONE_IOVA_CONTIG,
1129 : : PAGE_SIZE);
1130 [ # # ]: 0 : if (mz == NULL) {
1131 : 0 : PMD_DRV_LOG(ERR, "Could not alloc memzone for irq_dbs");
1132 : : err = -ENOMEM;
1133 : 0 : goto free_cnt_array;
1134 : : }
1135 : 0 : priv->irq_dbs = (struct gve_irq_db *)mz->addr;
1136 : 0 : priv->irq_dbs_mz = mz;
1137 : :
1138 : 0 : err = gve_adminq_configure_device_resources(priv,
1139 : 0 : priv->cnt_array_mz->iova,
1140 : 0 : priv->num_event_counters,
1141 : 0 : priv->irq_dbs_mz->iova,
1142 : : priv->num_ntfy_blks);
1143 [ # # ]: 0 : if (unlikely(err)) {
1144 : 0 : PMD_DRV_LOG(ERR, "Could not config device resources: err=%d", err);
1145 : 0 : goto free_irq_dbs;
1146 : : }
1147 [ # # ]: 0 : if (!gve_is_gqi(priv)) {
1148 : 0 : priv->ptype_lut_dqo = rte_zmalloc("gve_ptype_lut_dqo",
1149 : : sizeof(struct gve_ptype_lut), 0);
1150 [ # # ]: 0 : if (priv->ptype_lut_dqo == NULL) {
1151 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc ptype lut.");
1152 : : err = -ENOMEM;
1153 : 0 : goto free_irq_dbs;
1154 : : }
1155 : 0 : err = gve_adminq_get_ptype_map_dqo(priv, priv->ptype_lut_dqo);
1156 [ # # ]: 0 : if (unlikely(err)) {
1157 : 0 : PMD_DRV_LOG(ERR, "Failed to get ptype map: err=%d", err);
1158 : 0 : goto free_ptype_lut;
1159 : : }
1160 : : }
1161 : :
1162 : : return 0;
1163 : : free_ptype_lut:
1164 : 0 : rte_free(priv->ptype_lut_dqo);
1165 : 0 : priv->ptype_lut_dqo = NULL;
1166 : 0 : free_irq_dbs:
1167 : : gve_free_irq_db(priv);
1168 : 0 : free_cnt_array:
1169 : : gve_free_counter_array(priv);
1170 : :
1171 : 0 : return err;
1172 : : }
1173 : :
1174 : : static void
1175 : : gve_set_default_ring_size_bounds(struct gve_priv *priv)
1176 : : {
1177 : 0 : priv->max_tx_desc_cnt = GVE_DEFAULT_MAX_RING_SIZE;
1178 : 0 : priv->max_rx_desc_cnt = GVE_DEFAULT_MAX_RING_SIZE;
1179 : 0 : priv->min_tx_desc_cnt = GVE_DEFAULT_MIN_TX_RING_SIZE;
1180 : 0 : priv->min_rx_desc_cnt = GVE_DEFAULT_MIN_RX_RING_SIZE;
1181 : : }
1182 : :
1183 : : static int
1184 : 0 : gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
1185 : : {
1186 : : int num_ntfy;
1187 : : int err;
1188 : :
1189 : : /* Set up the adminq */
1190 : 0 : err = gve_adminq_alloc(priv);
1191 [ # # ]: 0 : if (err) {
1192 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc admin queue: err=%d", err);
1193 : 0 : return err;
1194 : : }
1195 : 0 : err = gve_verify_driver_compatibility(priv);
1196 [ # # ]: 0 : if (err) {
1197 : 0 : PMD_DRV_LOG(ERR, "Could not verify driver compatibility: err=%d", err);
1198 : 0 : goto free_adminq;
1199 : : }
1200 : :
1201 : : /* Set default descriptor counts */
1202 : : gve_set_default_ring_size_bounds(priv);
1203 : :
1204 [ # # ]: 0 : if (skip_describe_device)
1205 : 0 : goto setup_device;
1206 : :
1207 : : /* Get the initial information we need from the device */
1208 : 0 : err = gve_adminq_describe_device(priv);
1209 [ # # ]: 0 : if (err) {
1210 : 0 : PMD_DRV_LOG(ERR, "Could not get device information: err=%d", err);
1211 : 0 : goto free_adminq;
1212 : : }
1213 : :
1214 : 0 : num_ntfy = pci_dev_msix_vec_count(priv->pci_dev);
1215 [ # # ]: 0 : if (num_ntfy <= 0) {
1216 : 0 : PMD_DRV_LOG(ERR, "Could not count MSI-x vectors");
1217 : : err = -EIO;
1218 : 0 : goto free_adminq;
1219 [ # # ]: 0 : } else if (num_ntfy < GVE_MIN_MSIX) {
1220 : 0 : PMD_DRV_LOG(ERR, "GVE needs at least %d MSI-x vectors, but only has %d",
1221 : : GVE_MIN_MSIX, num_ntfy);
1222 : : err = -EINVAL;
1223 : 0 : goto free_adminq;
1224 : : }
1225 : :
1226 : 0 : priv->num_registered_pages = 0;
1227 : :
1228 : : /* gvnic has one Notification Block per MSI-x vector, except for the
1229 : : * management vector
1230 : : */
1231 : 0 : priv->num_ntfy_blks = (num_ntfy - 1) & ~0x1;
1232 : 0 : priv->mgmt_msix_idx = priv->num_ntfy_blks;
1233 : :
1234 : 0 : priv->max_nb_txq = RTE_MIN(priv->max_nb_txq, priv->num_ntfy_blks / 2);
1235 : 0 : priv->max_nb_rxq = RTE_MIN(priv->max_nb_rxq, priv->num_ntfy_blks / 2);
1236 : :
1237 [ # # ]: 0 : if (priv->default_num_queues > 0) {
1238 : 0 : priv->max_nb_txq = RTE_MIN(priv->default_num_queues, priv->max_nb_txq);
1239 : 0 : priv->max_nb_rxq = RTE_MIN(priv->default_num_queues, priv->max_nb_rxq);
1240 : : }
1241 : :
1242 : 0 : PMD_DRV_LOG(INFO, "Max TX queues %d, Max RX queues %d",
1243 : : priv->max_nb_txq, priv->max_nb_rxq);
1244 : :
1245 : 0 : setup_device:
1246 : 0 : err = gve_setup_device_resources(priv);
1247 [ # # ]: 0 : if (!err)
1248 : : return 0;
1249 : 0 : free_adminq:
1250 : 0 : gve_adminq_free(priv);
1251 : 0 : return err;
1252 : : }
1253 : :
1254 : : static void
1255 : : gve_teardown_priv_resources(struct gve_priv *priv)
1256 : : {
1257 : 0 : gve_teardown_device_resources(priv);
1258 : 0 : gve_adminq_free(priv);
1259 : : }
1260 : :
1261 : : static int
1262 : 0 : gve_dev_init(struct rte_eth_dev *eth_dev)
1263 : : {
1264 : 0 : struct gve_priv *priv = eth_dev->data->dev_private;
1265 : : int max_tx_queues, max_rx_queues;
1266 : : struct rte_pci_device *pci_dev;
1267 : : struct gve_registers *reg_bar;
1268 : : rte_be32_t *db_bar;
1269 : : int err;
1270 : :
1271 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
1272 [ # # ]: 0 : if (gve_is_gqi(priv)) {
1273 : 0 : gve_set_rx_function(eth_dev);
1274 : 0 : gve_set_tx_function(eth_dev);
1275 : 0 : eth_dev->dev_ops = &gve_eth_dev_ops;
1276 : : } else {
1277 : 0 : gve_set_rx_function_dqo(eth_dev);
1278 : 0 : gve_set_tx_function_dqo(eth_dev);
1279 : 0 : eth_dev->dev_ops = &gve_eth_dev_ops_dqo;
1280 : : }
1281 : 0 : return 0;
1282 : : }
1283 : :
1284 : 0 : pci_dev = RTE_DEV_TO_PCI(eth_dev->device);
1285 : :
1286 : 0 : reg_bar = pci_dev->mem_resource[GVE_REG_BAR].addr;
1287 [ # # ]: 0 : if (!reg_bar) {
1288 : 0 : PMD_DRV_LOG(ERR, "Failed to map pci bar!");
1289 : 0 : return -ENOMEM;
1290 : : }
1291 : :
1292 : 0 : db_bar = pci_dev->mem_resource[GVE_DB_BAR].addr;
1293 [ # # ]: 0 : if (!db_bar) {
1294 : 0 : PMD_DRV_LOG(ERR, "Failed to map doorbell bar!");
1295 : 0 : return -ENOMEM;
1296 : : }
1297 : :
1298 : : gve_write_version(®_bar->driver_version);
1299 : : /* Get max queues to alloc etherdev */
1300 : : max_tx_queues = ioread32be(®_bar->max_tx_queues);
1301 : : max_rx_queues = ioread32be(®_bar->max_rx_queues);
1302 : :
1303 : 0 : priv->reg_bar0 = reg_bar;
1304 : 0 : priv->db_bar2 = db_bar;
1305 : 0 : priv->pci_dev = pci_dev;
1306 : 0 : priv->state_flags = 0x0;
1307 : :
1308 : 0 : priv->max_nb_txq = max_tx_queues;
1309 : 0 : priv->max_nb_rxq = max_rx_queues;
1310 : :
1311 : 0 : err = gve_init_priv(priv, false);
1312 [ # # ]: 0 : if (err)
1313 : : return err;
1314 : :
1315 [ # # ]: 0 : if (gve_is_gqi(priv)) {
1316 : 0 : eth_dev->dev_ops = &gve_eth_dev_ops;
1317 : 0 : gve_set_rx_function(eth_dev);
1318 : 0 : gve_set_tx_function(eth_dev);
1319 : : } else {
1320 : 0 : eth_dev->dev_ops = &gve_eth_dev_ops_dqo;
1321 : 0 : gve_set_rx_function_dqo(eth_dev);
1322 : 0 : gve_set_tx_function_dqo(eth_dev);
1323 : : }
1324 : :
1325 : 0 : eth_dev->data->mac_addrs = &priv->dev_addr;
1326 : :
1327 : 0 : return 0;
1328 : : }
1329 : :
1330 : : static int
1331 : 0 : gve_dev_uninit(struct rte_eth_dev *eth_dev)
1332 : : {
1333 : 0 : struct gve_priv *priv = eth_dev->data->dev_private;
1334 : :
1335 : : gve_teardown_priv_resources(priv);
1336 : :
1337 : 0 : eth_dev->data->mac_addrs = NULL;
1338 : :
1339 : 0 : return 0;
1340 : : }
1341 : :
1342 : : static int
1343 : 0 : gve_pci_probe(__rte_unused struct rte_pci_driver *pci_drv,
1344 : : struct rte_pci_device *pci_dev)
1345 : : {
1346 : 0 : return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct gve_priv), gve_dev_init);
1347 : : }
1348 : :
1349 : : static int
1350 : 0 : gve_pci_remove(struct rte_pci_device *pci_dev)
1351 : : {
1352 : 0 : return rte_eth_dev_pci_generic_remove(pci_dev, gve_dev_uninit);
1353 : : }
1354 : :
1355 : : static const struct rte_pci_id pci_id_gve_map[] = {
1356 : : { RTE_PCI_DEVICE(GOOGLE_VENDOR_ID, GVE_DEV_ID) },
1357 : : { .device_id = 0 },
1358 : : };
1359 : :
1360 : : static struct rte_pci_driver rte_gve_pmd = {
1361 : : .id_table = pci_id_gve_map,
1362 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
1363 : : .probe = gve_pci_probe,
1364 : : .remove = gve_pci_remove,
1365 : : };
1366 : :
1367 : 252 : RTE_PMD_REGISTER_PCI(net_gve, rte_gve_pmd);
1368 : : RTE_PMD_REGISTER_PCI_TABLE(net_gve, pci_id_gve_map);
1369 : : RTE_PMD_REGISTER_KMOD_DEP(net_gve, "* igb_uio | vfio-pci");
1370 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(gve_logtype_driver, driver, NOTICE);
|