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