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 : : gve_set_device_rings_ok(priv);
387 : :
388 : 0 : return 0;
389 : :
390 : : err_rx:
391 [ # # ]: 0 : if (gve_is_gqi(priv))
392 : 0 : gve_stop_rx_queues(dev);
393 : : else
394 : 0 : gve_stop_rx_queues_dqo(dev);
395 [ # # ]: 0 : err_tx:
396 [ # # ]: 0 : if (gve_is_gqi(priv))
397 : 0 : gve_stop_tx_queues(dev);
398 : : else
399 : 0 : gve_stop_tx_queues_dqo(dev);
400 : :
401 : : gve_clear_device_rings_ok(priv);
402 : 0 : return ret;
403 : : }
404 : :
405 : : static int
406 : 0 : gve_dev_start(struct rte_eth_dev *dev)
407 : : {
408 : : struct gve_priv *priv;
409 : : int ret;
410 : :
411 : 0 : ret = gve_start_queues(dev);
412 [ # # ]: 0 : if (ret != 0) {
413 : 0 : PMD_DRV_LOG(ERR, "Failed to start queues");
414 : 0 : return ret;
415 : : }
416 : :
417 : 0 : dev->data->dev_started = 1;
418 : 0 : gve_link_update(dev, 0);
419 : :
420 [ # # ]: 0 : priv = dev->data->dev_private;
421 : : /* No stats available yet for Dqo. */
422 [ # # ]: 0 : if (gve_is_gqi(priv)) {
423 : 0 : ret = gve_alloc_stats_report(priv,
424 : 0 : dev->data->nb_tx_queues,
425 : 0 : dev->data->nb_rx_queues);
426 [ # # ]: 0 : if (ret != 0) {
427 : 0 : PMD_DRV_LOG(ERR,
428 : : "Failed to allocate region for stats reporting.");
429 : 0 : return ret;
430 : : }
431 : 0 : ret = gve_adminq_report_stats(priv, priv->stats_report_len,
432 : 0 : priv->stats_report_mem->iova,
433 : : GVE_STATS_REPORT_TIMER_PERIOD);
434 [ # # ]: 0 : if (ret != 0) {
435 : 0 : PMD_DRV_LOG(ERR, "gve_adminq_report_stats command failed.");
436 : 0 : return ret;
437 : : }
438 : : }
439 : :
440 : : return 0;
441 : : }
442 : :
443 : : static int
444 : 0 : gve_dev_stop(struct rte_eth_dev *dev)
445 : : {
446 : 0 : struct gve_priv *priv = dev->data->dev_private;
447 : :
448 : 0 : dev->data->dev_started = 0;
449 [ # # ]: 0 : dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
450 : :
451 : : gve_clear_device_rings_ok(priv);
452 [ # # ]: 0 : if (gve_is_gqi(priv)) {
453 : 0 : gve_stop_tx_queues(dev);
454 : 0 : gve_stop_rx_queues(dev);
455 : : } else {
456 : 0 : gve_stop_tx_queues_dqo(dev);
457 : 0 : gve_stop_rx_queues_dqo(dev);
458 : : }
459 : :
460 [ # # ]: 0 : if (gve_is_gqi(dev->data->dev_private))
461 : : gve_free_stats_report(dev);
462 : :
463 : 0 : return 0;
464 : : }
465 : :
466 : : static void
467 : 0 : gve_free_queues(struct rte_eth_dev *dev)
468 : : {
469 [ # # ]: 0 : struct gve_priv *priv = dev->data->dev_private;
470 : : uint16_t i;
471 : :
472 [ # # ]: 0 : if (gve_is_gqi(priv)) {
473 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
474 : 0 : gve_tx_queue_release(dev, i);
475 : :
476 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
477 : 0 : gve_rx_queue_release(dev, i);
478 : : } else {
479 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
480 : 0 : gve_tx_queue_release_dqo(dev, i);
481 : :
482 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
483 : 0 : gve_rx_queue_release_dqo(dev, i);
484 : : }
485 : 0 : }
486 : :
487 : : static void
488 : : gve_free_counter_array(struct gve_priv *priv)
489 : : {
490 : 0 : rte_memzone_free(priv->cnt_array_mz);
491 : 0 : priv->cnt_array = NULL;
492 : : }
493 : :
494 : : static void
495 : : gve_free_irq_db(struct gve_priv *priv)
496 : : {
497 : 0 : rte_memzone_free(priv->irq_dbs_mz);
498 : 0 : priv->irq_dbs = NULL;
499 : 0 : }
500 : :
501 : : static void
502 : : gve_free_ptype_lut_dqo(struct gve_priv *priv)
503 : : {
504 [ # # ]: 0 : if (!gve_is_gqi(priv)) {
505 : 0 : rte_free(priv->ptype_lut_dqo);
506 : 0 : priv->ptype_lut_dqo = NULL;
507 : : }
508 : : }
509 : :
510 : : static void
511 [ # # ]: 0 : gve_teardown_device_resources(struct gve_priv *priv)
512 : : {
513 : : int err;
514 : :
515 : : /* Tell device its resources are being freed */
516 [ # # ]: 0 : if (gve_get_device_resources_ok(priv)) {
517 : 0 : err = gve_adminq_deconfigure_device_resources(priv);
518 [ # # ]: 0 : if (err)
519 : 0 : PMD_DRV_LOG(ERR, "Could not deconfigure device resources: err=%d", err);
520 : : }
521 : :
522 : : gve_free_ptype_lut_dqo(priv);
523 : : gve_free_counter_array(priv);
524 : : gve_free_irq_db(priv);
525 : : gve_clear_device_resources_ok(priv);
526 : 0 : }
527 : :
528 : : static int
529 : 0 : gve_dev_close(struct rte_eth_dev *dev)
530 : : {
531 : 0 : struct gve_priv *priv = dev->data->dev_private;
532 : : int err = 0;
533 : :
534 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
535 : : return 0;
536 : :
537 [ # # ]: 0 : if (dev->data->dev_started) {
538 : 0 : err = gve_dev_stop(dev);
539 [ # # ]: 0 : if (err != 0)
540 : 0 : PMD_DRV_LOG(ERR, "Failed to stop dev.");
541 : : }
542 : :
543 : 0 : gve_free_queues(dev);
544 : 0 : gve_teardown_device_resources(priv);
545 : 0 : gve_adminq_free(priv);
546 : :
547 : 0 : dev->data->mac_addrs = NULL;
548 : :
549 : 0 : return err;
550 : : }
551 : :
552 : : static int
553 : 0 : gve_verify_driver_compatibility(struct gve_priv *priv)
554 : : {
555 : : const struct rte_memzone *driver_info_mem;
556 : : struct gve_driver_info *driver_info;
557 : : int err;
558 : :
559 : 0 : driver_info_mem = rte_memzone_reserve_aligned("verify_driver_compatibility",
560 : : sizeof(struct gve_driver_info),
561 : 0 : rte_socket_id(),
562 : : RTE_MEMZONE_IOVA_CONTIG, PAGE_SIZE);
563 : :
564 [ # # ]: 0 : if (driver_info_mem == NULL) {
565 : 0 : PMD_DRV_LOG(ERR,
566 : : "Could not alloc memzone for driver compatibility");
567 : 0 : return -ENOMEM;
568 : : }
569 : 0 : driver_info = (struct gve_driver_info *)driver_info_mem->addr;
570 : :
571 : 0 : *driver_info = (struct gve_driver_info) {
572 : : .os_type = 5, /* DPDK */
573 : : .driver_major = GVE_VERSION_MAJOR,
574 : : .driver_minor = GVE_VERSION_MINOR,
575 : : .driver_sub = GVE_VERSION_SUB,
576 : : .os_version_major = cpu_to_be32(DPDK_VERSION_MAJOR),
577 : : .os_version_minor = cpu_to_be32(DPDK_VERSION_MINOR),
578 : : .os_version_sub = cpu_to_be32(DPDK_VERSION_SUB),
579 : : .driver_capability_flags = {
580 : : cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS1),
581 : : cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS2),
582 : : cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS3),
583 : : cpu_to_be64(GVE_DRIVER_CAPABILITY_FLAGS4),
584 : : },
585 : : };
586 : :
587 : 0 : populate_driver_version_strings((char *)driver_info->os_version_str1,
588 : 0 : (char *)driver_info->os_version_str2);
589 : :
590 : 0 : err = gve_adminq_verify_driver_compatibility(priv,
591 : : sizeof(struct gve_driver_info),
592 : 0 : (dma_addr_t)driver_info_mem->iova);
593 : : /* It's ok if the device doesn't support this */
594 [ # # ]: 0 : if (err == -EOPNOTSUPP)
595 : : err = 0;
596 : :
597 : 0 : rte_memzone_free(driver_info_mem);
598 : 0 : return err;
599 : : }
600 : :
601 : : static int
602 : 0 : gve_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
603 : : {
604 : 0 : struct gve_priv *priv = dev->data->dev_private;
605 : :
606 : 0 : dev_info->device = dev->device;
607 : 0 : dev_info->max_mac_addrs = 1;
608 : 0 : dev_info->max_rx_queues = priv->max_nb_rxq;
609 [ # # ]: 0 : dev_info->max_tx_queues = priv->max_nb_txq;
610 [ # # ]: 0 : if (gve_is_gqi(priv)) {
611 : 0 : dev_info->min_rx_bufsize = GVE_RX_MIN_BUF_SIZE_GQI;
612 : 0 : dev_info->max_rx_bufsize = GVE_RX_MAX_BUF_SIZE_GQI;
613 : : } else {
614 : 0 : dev_info->min_rx_bufsize = GVE_RX_MIN_BUF_SIZE_DQO;
615 : 0 : dev_info->max_rx_bufsize = GVE_RX_MAX_BUF_SIZE_DQO;
616 : : }
617 : :
618 : 0 : dev_info->max_rx_pktlen = priv->max_mtu + RTE_ETHER_HDR_LEN;
619 : 0 : dev_info->max_mtu = priv->max_mtu;
620 : 0 : dev_info->min_mtu = RTE_ETHER_MIN_MTU;
621 : :
622 : 0 : dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_RSS_HASH;
623 : 0 : dev_info->tx_offload_capa =
624 : : RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
625 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
626 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
627 : : RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
628 : : RTE_ETH_TX_OFFLOAD_TCP_TSO;
629 : :
630 [ # # ]: 0 : if (!gve_is_gqi(priv)) {
631 : 0 : dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM;
632 : 0 : dev_info->rx_offload_capa |=
633 : : RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
634 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
635 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
636 : : RTE_ETH_RX_OFFLOAD_TCP_LRO;
637 : : }
638 : :
639 : 0 : dev_info->default_rxconf = (struct rte_eth_rxconf) {
640 : : .rx_free_thresh = GVE_DEFAULT_RX_FREE_THRESH,
641 : : .rx_drop_en = 0,
642 : : .offloads = 0,
643 : : };
644 : :
645 : 0 : dev_info->default_txconf = (struct rte_eth_txconf) {
646 : : .tx_free_thresh = GVE_DEFAULT_TX_FREE_THRESH,
647 : : .tx_rs_thresh = GVE_DEFAULT_TX_RS_THRESH,
648 : : .offloads = 0,
649 : : };
650 : :
651 : 0 : dev_info->default_rxportconf.ring_size = priv->default_rx_desc_cnt;
652 : 0 : dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
653 : 0 : .nb_max = priv->max_rx_desc_cnt,
654 : 0 : .nb_min = priv->min_rx_desc_cnt,
655 : : .nb_align = 1,
656 : : };
657 : :
658 : 0 : dev_info->default_txportconf.ring_size = priv->default_tx_desc_cnt;
659 : 0 : dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
660 : 0 : .nb_max = priv->max_tx_desc_cnt,
661 : 0 : .nb_min = priv->min_tx_desc_cnt,
662 : : .nb_align = 1,
663 : : .nb_mtu_seg_max = GVE_TX_MAX_DATA_DESCS - 1,
664 : : };
665 : :
666 : 0 : dev_info->flow_type_rss_offloads = GVE_RTE_RSS_OFFLOAD_ALL;
667 : 0 : dev_info->hash_key_size = GVE_RSS_HASH_KEY_SIZE;
668 : 0 : dev_info->reta_size = GVE_RSS_INDIR_SIZE;
669 : :
670 : 0 : return 0;
671 : : }
672 : :
673 : : static int
674 : 0 : gve_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
675 : : {
676 : : uint16_t i;
677 [ # # ]: 0 : if (gve_is_gqi(dev->data->dev_private))
678 : 0 : gve_get_imissed_from_nic(dev);
679 : :
680 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
681 : 0 : struct gve_tx_queue *txq = dev->data->tx_queues[i];
682 [ # # ]: 0 : if (txq == NULL)
683 : 0 : continue;
684 : :
685 : 0 : stats->opackets += txq->stats.packets;
686 : 0 : stats->obytes += txq->stats.bytes;
687 : 0 : stats->oerrors += txq->stats.errors;
688 : : }
689 : :
690 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
691 : 0 : struct gve_rx_queue *rxq = dev->data->rx_queues[i];
692 [ # # ]: 0 : if (rxq == NULL)
693 : 0 : continue;
694 : :
695 : 0 : stats->ipackets += rxq->stats.packets;
696 : 0 : stats->ibytes += rxq->stats.bytes;
697 : 0 : stats->ierrors += rxq->stats.errors;
698 : 0 : stats->rx_nombuf += rxq->stats.no_mbufs;
699 : 0 : stats->imissed += rxq->stats.imissed;
700 : : }
701 : :
702 : 0 : return 0;
703 : : }
704 : :
705 : : static int
706 : 0 : gve_dev_stats_reset(struct rte_eth_dev *dev)
707 : : {
708 : : uint16_t i;
709 : :
710 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
711 : 0 : struct gve_tx_queue *txq = dev->data->tx_queues[i];
712 [ # # ]: 0 : if (txq == NULL)
713 : 0 : continue;
714 : :
715 : 0 : memset(&txq->stats, 0, sizeof(txq->stats));
716 : : }
717 : :
718 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
719 : 0 : struct gve_rx_queue *rxq = dev->data->rx_queues[i];
720 [ # # ]: 0 : if (rxq == NULL)
721 : 0 : continue;
722 : :
723 : 0 : memset(&rxq->stats, 0, sizeof(rxq->stats));
724 : : }
725 : :
726 : 0 : return 0;
727 : : }
728 : :
729 : : static int
730 : 0 : gve_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
731 : : {
732 : 0 : struct gve_priv *priv = dev->data->dev_private;
733 : : int err;
734 : :
735 [ # # # # ]: 0 : if (mtu < RTE_ETHER_MIN_MTU || mtu > priv->max_mtu) {
736 : 0 : PMD_DRV_LOG(ERR, "MIN MTU is %u, MAX MTU is %u",
737 : : RTE_ETHER_MIN_MTU, priv->max_mtu);
738 : 0 : return -EINVAL;
739 : : }
740 : :
741 : : /* mtu setting is forbidden if port is start */
742 [ # # ]: 0 : if (dev->data->dev_started) {
743 : 0 : PMD_DRV_LOG(ERR, "Port must be stopped before configuration");
744 : 0 : return -EBUSY;
745 : : }
746 : :
747 : 0 : err = gve_adminq_set_mtu(priv, mtu);
748 [ # # ]: 0 : if (err) {
749 : 0 : PMD_DRV_LOG(ERR, "Failed to set mtu as %u err = %d", mtu, err);
750 : 0 : return err;
751 : : }
752 : :
753 : : return 0;
754 : : }
755 : :
756 : : #define TX_QUEUE_STATS_OFFSET(x) offsetof(struct gve_tx_stats, x)
757 : : #define RX_QUEUE_STATS_OFFSET(x) offsetof(struct gve_rx_stats, x)
758 : :
759 : : static const struct gve_xstats_name_offset tx_xstats_name_offset[] = {
760 : : { "packets", TX_QUEUE_STATS_OFFSET(packets) },
761 : : { "bytes", TX_QUEUE_STATS_OFFSET(bytes) },
762 : : { "errors", TX_QUEUE_STATS_OFFSET(errors) },
763 : : };
764 : :
765 : : static const struct gve_xstats_name_offset rx_xstats_name_offset[] = {
766 : : { "packets", RX_QUEUE_STATS_OFFSET(packets) },
767 : : { "bytes", RX_QUEUE_STATS_OFFSET(bytes) },
768 : : { "errors", RX_QUEUE_STATS_OFFSET(errors) },
769 : : { "mbuf_alloc_errors", RX_QUEUE_STATS_OFFSET(no_mbufs) },
770 : : { "mbuf_alloc_errors_bulk", RX_QUEUE_STATS_OFFSET(no_mbufs_bulk) },
771 : : { "imissed", RX_QUEUE_STATS_OFFSET(imissed) },
772 : : };
773 : :
774 : : static int
775 : 0 : gve_xstats_count(struct rte_eth_dev *dev)
776 : : {
777 : : uint16_t i, count = 0;
778 : :
779 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
780 [ # # ]: 0 : if (dev->data->tx_queues[i])
781 : 0 : count += RTE_DIM(tx_xstats_name_offset);
782 : : }
783 : :
784 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
785 [ # # ]: 0 : if (dev->data->rx_queues[i])
786 : 0 : count += RTE_DIM(rx_xstats_name_offset);
787 : : }
788 : :
789 : 0 : return count;
790 : : }
791 : :
792 : : static int
793 : 0 : gve_xstats_get(struct rte_eth_dev *dev,
794 : : struct rte_eth_xstat *xstats,
795 : : unsigned int size)
796 : : {
797 : 0 : uint16_t i, j, count = gve_xstats_count(dev);
798 : : const char *stats;
799 : :
800 [ # # ]: 0 : if (gve_is_gqi(dev->data->dev_private))
801 : 0 : gve_get_imissed_from_nic(dev);
802 : :
803 [ # # # # ]: 0 : if (xstats == NULL || size < count)
804 : 0 : return count;
805 : :
806 : : count = 0;
807 : :
808 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
809 : 0 : const struct gve_tx_queue *txq = dev->data->tx_queues[i];
810 [ # # ]: 0 : if (txq == NULL)
811 : 0 : continue;
812 : :
813 : 0 : stats = (const char *)&txq->stats;
814 [ # # ]: 0 : for (j = 0; j < RTE_DIM(tx_xstats_name_offset); j++, count++) {
815 : 0 : xstats[count].id = count;
816 : 0 : xstats[count].value = *(const uint64_t *)
817 : 0 : (stats + tx_xstats_name_offset[j].offset);
818 : : }
819 : : }
820 : :
821 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
822 : 0 : const struct gve_rx_queue *rxq = dev->data->rx_queues[i];
823 [ # # ]: 0 : if (rxq == NULL)
824 : 0 : continue;
825 : :
826 : 0 : stats = (const char *)&rxq->stats;
827 [ # # ]: 0 : for (j = 0; j < RTE_DIM(rx_xstats_name_offset); j++, count++) {
828 : 0 : xstats[count].id = count;
829 : 0 : xstats[count].value = *(const uint64_t *)
830 : 0 : (stats + rx_xstats_name_offset[j].offset);
831 : : }
832 : : }
833 : :
834 : 0 : return count;
835 : : }
836 : :
837 : : static int
838 : 0 : gve_xstats_get_names(struct rte_eth_dev *dev,
839 : : struct rte_eth_xstat_name *xstats_names,
840 : : unsigned int size)
841 : : {
842 : 0 : uint16_t i, j, count = gve_xstats_count(dev);
843 : :
844 [ # # # # ]: 0 : if (xstats_names == NULL || size < count)
845 : 0 : return count;
846 : :
847 : : count = 0;
848 : :
849 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
850 [ # # ]: 0 : if (dev->data->tx_queues[i] == NULL)
851 : 0 : continue;
852 : :
853 [ # # ]: 0 : for (j = 0; j < RTE_DIM(tx_xstats_name_offset); j++)
854 : 0 : snprintf(xstats_names[count++].name,
855 : : RTE_ETH_XSTATS_NAME_SIZE,
856 : 0 : "tx_q%u_%s", i, tx_xstats_name_offset[j].name);
857 : : }
858 : :
859 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
860 [ # # ]: 0 : if (dev->data->rx_queues[i] == NULL)
861 : 0 : continue;
862 : :
863 [ # # ]: 0 : for (j = 0; j < RTE_DIM(rx_xstats_name_offset); j++)
864 : 0 : snprintf(xstats_names[count++].name,
865 : : RTE_ETH_XSTATS_NAME_SIZE,
866 : 0 : "rx_q%u_%s", i, rx_xstats_name_offset[j].name);
867 : : }
868 : :
869 : 0 : return count;
870 : : }
871 : :
872 : :
873 : : static int
874 : 0 : gve_rss_hash_update(struct rte_eth_dev *dev,
875 : : struct rte_eth_rss_conf *rss_conf)
876 : : {
877 : 0 : struct gve_priv *priv = dev->data->dev_private;
878 : : struct gve_rss_config gve_rss_conf;
879 : : int rss_reta_size;
880 : : int err;
881 : :
882 [ # # ]: 0 : if (gve_validate_rss_hf(rss_conf->rss_hf)) {
883 : 0 : PMD_DRV_LOG(ERR, "Unsupported hash function.");
884 : 0 : return -EINVAL;
885 : : }
886 : :
887 [ # # ]: 0 : if (rss_conf->algorithm != RTE_ETH_HASH_FUNCTION_TOEPLITZ &&
888 : : rss_conf->algorithm != RTE_ETH_HASH_FUNCTION_DEFAULT) {
889 : 0 : PMD_DRV_LOG(ERR, "Device only supports Toeplitz algorithm.");
890 : 0 : return -EINVAL;
891 : : }
892 : :
893 [ # # ]: 0 : if (rss_conf->rss_key_len) {
894 [ # # ]: 0 : if (rss_conf->rss_key_len != GVE_RSS_HASH_KEY_SIZE) {
895 : 0 : PMD_DRV_LOG(ERR,
896 : : "Invalid hash key size. Only RSS hash key size "
897 : : "of %u supported", GVE_RSS_HASH_KEY_SIZE);
898 : 0 : return -EINVAL;
899 : : }
900 : :
901 [ # # ]: 0 : if (!rss_conf->rss_key) {
902 : 0 : PMD_DRV_LOG(ERR, "RSS key must be non-null.");
903 : 0 : return -EINVAL;
904 : : }
905 : : } else {
906 [ # # ]: 0 : if (!priv->rss_config.key_size) {
907 : 0 : PMD_DRV_LOG(ERR, "RSS key must be initialized before "
908 : : "any other configuration.");
909 : 0 : return -EINVAL;
910 : : }
911 : 0 : rss_conf->rss_key_len = priv->rss_config.key_size;
912 : : }
913 : :
914 : 0 : rss_reta_size = priv->rss_config.indir ?
915 [ # # ]: 0 : priv->rss_config.indir_size :
916 : : GVE_RSS_INDIR_SIZE;
917 : 0 : err = gve_init_rss_config(&gve_rss_conf, rss_conf->rss_key_len,
918 : : rss_reta_size);
919 [ # # ]: 0 : if (err)
920 : : return err;
921 : :
922 : 0 : gve_rss_conf.alg = GVE_RSS_HASH_TOEPLITZ;
923 : 0 : err = gve_update_rss_hash_types(priv, &gve_rss_conf, rss_conf);
924 [ # # ]: 0 : if (err)
925 : 0 : goto err;
926 : 0 : err = gve_update_rss_key(priv, &gve_rss_conf, rss_conf);
927 [ # # ]: 0 : if (err)
928 : 0 : goto err;
929 : :
930 : : /* Set redirection table to default or preexisting. */
931 [ # # ]: 0 : if (!priv->rss_config.indir)
932 : 0 : gve_generate_rss_reta(dev, &gve_rss_conf);
933 : : else
934 : 0 : memcpy(gve_rss_conf.indir, priv->rss_config.indir,
935 : 0 : gve_rss_conf.indir_size * sizeof(*priv->rss_config.indir));
936 : :
937 : 0 : err = gve_adminq_configure_rss(priv, &gve_rss_conf);
938 [ # # ]: 0 : if (!err)
939 : 0 : gve_update_priv_rss_config(priv, &gve_rss_conf);
940 : :
941 : 0 : err:
942 : 0 : gve_free_rss_config(&gve_rss_conf);
943 : 0 : return err;
944 : : }
945 : :
946 : : static int
947 : 0 : gve_rss_hash_conf_get(struct rte_eth_dev *dev,
948 : : struct rte_eth_rss_conf *rss_conf)
949 : : {
950 : 0 : struct gve_priv *priv = dev->data->dev_private;
951 : :
952 [ # # ]: 0 : if (!(dev->data->dev_conf.rxmode.offloads &
953 : : RTE_ETH_RX_OFFLOAD_RSS_HASH)) {
954 : 0 : PMD_DRV_LOG(ERR, "RSS not configured.");
955 : 0 : return -ENOTSUP;
956 : : }
957 : :
958 : :
959 : 0 : gve_to_rte_rss_hf(priv->rss_config.hash_types, rss_conf);
960 : 0 : rss_conf->rss_key_len = priv->rss_config.key_size;
961 [ # # ]: 0 : if (rss_conf->rss_key) {
962 [ # # ]: 0 : if (!priv->rss_config.key) {
963 : 0 : PMD_DRV_LOG(ERR, "Unable to retrieve default RSS hash key.");
964 : 0 : return -ENOTSUP;
965 : : }
966 : 0 : memcpy(rss_conf->rss_key, priv->rss_config.key,
967 : : rss_conf->rss_key_len * sizeof(*rss_conf->rss_key));
968 : : }
969 : :
970 : : return 0;
971 : : }
972 : :
973 : : static int
974 : 0 : gve_rss_reta_update(struct rte_eth_dev *dev,
975 : : struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
976 : : {
977 : 0 : struct gve_priv *priv = dev->data->dev_private;
978 : : struct gve_rss_config gve_rss_conf;
979 : : int table_id;
980 : : int err;
981 : : int i;
982 : :
983 : : /* RSS key must be set before the redirection table can be set. */
984 [ # # # # ]: 0 : if (!priv->rss_config.key || priv->rss_config.key_size == 0) {
985 : 0 : PMD_DRV_LOG(ERR, "RSS hash key msut be set before the "
986 : : "redirection table can be updated.");
987 : 0 : return -ENOTSUP;
988 : : }
989 : :
990 [ # # ]: 0 : if (reta_size != GVE_RSS_INDIR_SIZE) {
991 : 0 : PMD_DRV_LOG(ERR, "Redirection table must have %hu elements",
992 : : (uint16_t)GVE_RSS_INDIR_SIZE);
993 : 0 : return -EINVAL;
994 : : }
995 : :
996 : 0 : err = gve_init_rss_config_from_priv(priv, &gve_rss_conf);
997 [ # # ]: 0 : if (err) {
998 : 0 : PMD_DRV_LOG(ERR, "Error allocating new RSS config.");
999 : 0 : return err;
1000 : : }
1001 : :
1002 : : table_id = 0;
1003 [ # # ]: 0 : for (i = 0; i < priv->rss_config.indir_size; i++) {
1004 : 0 : int table_entry = i % RTE_ETH_RETA_GROUP_SIZE;
1005 [ # # ]: 0 : if (reta_conf[table_id].mask & (1ULL << table_entry))
1006 : 0 : gve_rss_conf.indir[i] =
1007 : 0 : reta_conf[table_id].reta[table_entry];
1008 : :
1009 [ # # ]: 0 : if (table_entry == RTE_ETH_RETA_GROUP_SIZE - 1)
1010 : 0 : table_id++;
1011 : : }
1012 : :
1013 : 0 : err = gve_adminq_configure_rss(priv, &gve_rss_conf);
1014 [ # # ]: 0 : if (err)
1015 : 0 : PMD_DRV_LOG(ERR, "Problem configuring RSS with device.");
1016 : : else
1017 : 0 : gve_update_priv_rss_config(priv, &gve_rss_conf);
1018 : :
1019 : 0 : gve_free_rss_config(&gve_rss_conf);
1020 : 0 : return err;
1021 : : }
1022 : :
1023 : : static int
1024 : 0 : gve_rss_reta_query(struct rte_eth_dev *dev,
1025 : : struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
1026 : : {
1027 : 0 : struct gve_priv *priv = dev->data->dev_private;
1028 : : int table_id;
1029 : : int i;
1030 : :
1031 [ # # ]: 0 : if (!(dev->data->dev_conf.rxmode.offloads &
1032 : : RTE_ETH_RX_OFFLOAD_RSS_HASH)) {
1033 : 0 : PMD_DRV_LOG(ERR, "RSS not configured.");
1034 : 0 : return -ENOTSUP;
1035 : : }
1036 : :
1037 : : /* RSS key must be set before the redirection table can be queried. */
1038 [ # # ]: 0 : if (!priv->rss_config.key) {
1039 : 0 : PMD_DRV_LOG(ERR, "RSS hash key must be set before the "
1040 : : "redirection table can be initialized.");
1041 : 0 : return -ENOTSUP;
1042 : : }
1043 : :
1044 [ # # ]: 0 : if (reta_size != priv->rss_config.indir_size) {
1045 : 0 : PMD_DRV_LOG(ERR, "RSS redirection table must have %d entries.",
1046 : : priv->rss_config.indir_size);
1047 : 0 : return -EINVAL;
1048 : : }
1049 : :
1050 : : table_id = 0;
1051 [ # # ]: 0 : for (i = 0; i < priv->rss_config.indir_size; i++) {
1052 : 0 : int table_entry = i % RTE_ETH_RETA_GROUP_SIZE;
1053 [ # # ]: 0 : if (reta_conf[table_id].mask & (1ULL << table_entry))
1054 : 0 : reta_conf[table_id].reta[table_entry] =
1055 : 0 : priv->rss_config.indir[i];
1056 : :
1057 [ # # ]: 0 : if (table_entry == RTE_ETH_RETA_GROUP_SIZE - 1)
1058 : 0 : table_id++;
1059 : : }
1060 : :
1061 : : return 0;
1062 : : }
1063 : :
1064 : : static const struct eth_dev_ops gve_eth_dev_ops = {
1065 : : .dev_configure = gve_dev_configure,
1066 : : .dev_start = gve_dev_start,
1067 : : .dev_stop = gve_dev_stop,
1068 : : .dev_close = gve_dev_close,
1069 : : .dev_infos_get = gve_dev_info_get,
1070 : : .rx_queue_setup = gve_rx_queue_setup,
1071 : : .tx_queue_setup = gve_tx_queue_setup,
1072 : : .rx_queue_release = gve_rx_queue_release,
1073 : : .tx_queue_release = gve_tx_queue_release,
1074 : : .rx_queue_start = gve_rx_queue_start,
1075 : : .tx_queue_start = gve_tx_queue_start,
1076 : : .rx_queue_stop = gve_rx_queue_stop,
1077 : : .tx_queue_stop = gve_tx_queue_stop,
1078 : : .link_update = gve_link_update,
1079 : : .stats_get = gve_dev_stats_get,
1080 : : .stats_reset = gve_dev_stats_reset,
1081 : : .mtu_set = gve_dev_mtu_set,
1082 : : .xstats_get = gve_xstats_get,
1083 : : .xstats_get_names = gve_xstats_get_names,
1084 : : .rss_hash_update = gve_rss_hash_update,
1085 : : .rss_hash_conf_get = gve_rss_hash_conf_get,
1086 : : .reta_update = gve_rss_reta_update,
1087 : : .reta_query = gve_rss_reta_query,
1088 : : };
1089 : :
1090 : : static const struct eth_dev_ops gve_eth_dev_ops_dqo = {
1091 : : .dev_configure = gve_dev_configure,
1092 : : .dev_start = gve_dev_start,
1093 : : .dev_stop = gve_dev_stop,
1094 : : .dev_close = gve_dev_close,
1095 : : .dev_infos_get = gve_dev_info_get,
1096 : : .rx_queue_setup = gve_rx_queue_setup_dqo,
1097 : : .tx_queue_setup = gve_tx_queue_setup_dqo,
1098 : : .rx_queue_release = gve_rx_queue_release_dqo,
1099 : : .tx_queue_release = gve_tx_queue_release_dqo,
1100 : : .rx_queue_start = gve_rx_queue_start_dqo,
1101 : : .tx_queue_start = gve_tx_queue_start_dqo,
1102 : : .rx_queue_stop = gve_rx_queue_stop_dqo,
1103 : : .tx_queue_stop = gve_tx_queue_stop_dqo,
1104 : : .link_update = gve_link_update,
1105 : : .stats_get = gve_dev_stats_get,
1106 : : .stats_reset = gve_dev_stats_reset,
1107 : : .mtu_set = gve_dev_mtu_set,
1108 : : .xstats_get = gve_xstats_get,
1109 : : .xstats_get_names = gve_xstats_get_names,
1110 : : .rss_hash_update = gve_rss_hash_update,
1111 : : .rss_hash_conf_get = gve_rss_hash_conf_get,
1112 : : .reta_update = gve_rss_reta_update,
1113 : : .reta_query = gve_rss_reta_query,
1114 : : };
1115 : :
1116 : : static int
1117 : 0 : pci_dev_msix_vec_count(struct rte_pci_device *pdev)
1118 : : {
1119 : 0 : off_t msix_pos = rte_pci_find_capability(pdev, RTE_PCI_CAP_ID_MSIX);
1120 : : uint16_t control;
1121 : :
1122 [ # # # # ]: 0 : if (msix_pos > 0 && rte_pci_read_config(pdev, &control, sizeof(control),
1123 : : msix_pos + RTE_PCI_MSIX_FLAGS) == sizeof(control))
1124 : 0 : return (control & RTE_PCI_MSIX_FLAGS_QSIZE) + 1;
1125 : :
1126 : : return 0;
1127 : : }
1128 : :
1129 : : static int
1130 : 0 : gve_setup_device_resources(struct gve_priv *priv)
1131 : : {
1132 : : char z_name[RTE_MEMZONE_NAMESIZE];
1133 : : const struct rte_memzone *mz;
1134 : : int err = 0;
1135 : :
1136 : 0 : snprintf(z_name, sizeof(z_name), "gve_%s_cnt_arr", priv->pci_dev->device.name);
1137 : 0 : mz = rte_memzone_reserve_aligned(z_name,
1138 : 0 : priv->num_event_counters * sizeof(*priv->cnt_array),
1139 : 0 : rte_socket_id(), RTE_MEMZONE_IOVA_CONTIG,
1140 : : PAGE_SIZE);
1141 [ # # ]: 0 : if (mz == NULL) {
1142 : 0 : PMD_DRV_LOG(ERR, "Could not alloc memzone for count array");
1143 : 0 : return -ENOMEM;
1144 : : }
1145 : 0 : priv->cnt_array = (rte_be32_t *)mz->addr;
1146 : 0 : priv->cnt_array_mz = mz;
1147 : :
1148 : 0 : snprintf(z_name, sizeof(z_name), "gve_%s_irqmz", priv->pci_dev->device.name);
1149 : 0 : mz = rte_memzone_reserve_aligned(z_name,
1150 : 0 : sizeof(*priv->irq_dbs) * (priv->num_ntfy_blks),
1151 : 0 : rte_socket_id(), RTE_MEMZONE_IOVA_CONTIG,
1152 : : PAGE_SIZE);
1153 [ # # ]: 0 : if (mz == NULL) {
1154 : 0 : PMD_DRV_LOG(ERR, "Could not alloc memzone for irq_dbs");
1155 : : err = -ENOMEM;
1156 : 0 : goto free_cnt_array;
1157 : : }
1158 : 0 : priv->irq_dbs = (struct gve_irq_db *)mz->addr;
1159 : 0 : priv->irq_dbs_mz = mz;
1160 : :
1161 : 0 : err = gve_adminq_configure_device_resources(priv,
1162 : 0 : priv->cnt_array_mz->iova,
1163 : 0 : priv->num_event_counters,
1164 : 0 : priv->irq_dbs_mz->iova,
1165 : : priv->num_ntfy_blks);
1166 [ # # ]: 0 : if (unlikely(err)) {
1167 : 0 : PMD_DRV_LOG(ERR, "Could not config device resources: err=%d", err);
1168 : 0 : goto free_irq_dbs;
1169 : : }
1170 [ # # ]: 0 : if (!gve_is_gqi(priv)) {
1171 : 0 : priv->ptype_lut_dqo = rte_zmalloc("gve_ptype_lut_dqo",
1172 : : sizeof(struct gve_ptype_lut), 0);
1173 [ # # ]: 0 : if (priv->ptype_lut_dqo == NULL) {
1174 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc ptype lut.");
1175 : : err = -ENOMEM;
1176 : 0 : goto free_irq_dbs;
1177 : : }
1178 : 0 : err = gve_adminq_get_ptype_map_dqo(priv, priv->ptype_lut_dqo);
1179 [ # # ]: 0 : if (unlikely(err)) {
1180 : 0 : PMD_DRV_LOG(ERR, "Failed to get ptype map: err=%d", err);
1181 : 0 : goto free_ptype_lut;
1182 : : }
1183 : : }
1184 : :
1185 : : gve_set_device_resources_ok(priv);
1186 : :
1187 : 0 : return 0;
1188 : : free_ptype_lut:
1189 : 0 : rte_free(priv->ptype_lut_dqo);
1190 : 0 : priv->ptype_lut_dqo = NULL;
1191 : 0 : free_irq_dbs:
1192 : : gve_free_irq_db(priv);
1193 : 0 : free_cnt_array:
1194 : : gve_free_counter_array(priv);
1195 : :
1196 : 0 : return err;
1197 : : }
1198 : :
1199 : : static void
1200 : : gve_set_default_ring_size_bounds(struct gve_priv *priv)
1201 : : {
1202 : 0 : priv->max_tx_desc_cnt = GVE_DEFAULT_MAX_RING_SIZE;
1203 : 0 : priv->max_rx_desc_cnt = GVE_DEFAULT_MAX_RING_SIZE;
1204 : 0 : priv->min_tx_desc_cnt = GVE_DEFAULT_MIN_TX_RING_SIZE;
1205 : 0 : priv->min_rx_desc_cnt = GVE_DEFAULT_MIN_RX_RING_SIZE;
1206 : : }
1207 : :
1208 : : static int
1209 : 0 : gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
1210 : : {
1211 : : int num_ntfy;
1212 : : int err;
1213 : :
1214 : : /* Set up the adminq */
1215 : 0 : err = gve_adminq_alloc(priv);
1216 [ # # ]: 0 : if (err) {
1217 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc admin queue: err=%d", err);
1218 : 0 : return err;
1219 : : }
1220 : 0 : err = gve_verify_driver_compatibility(priv);
1221 [ # # ]: 0 : if (err) {
1222 : 0 : PMD_DRV_LOG(ERR, "Could not verify driver compatibility: err=%d", err);
1223 : 0 : goto free_adminq;
1224 : : }
1225 : :
1226 : : /* Set default descriptor counts */
1227 : : gve_set_default_ring_size_bounds(priv);
1228 : :
1229 [ # # ]: 0 : if (skip_describe_device)
1230 : 0 : goto setup_device;
1231 : :
1232 : : /* Get the initial information we need from the device */
1233 : 0 : err = gve_adminq_describe_device(priv);
1234 [ # # ]: 0 : if (err) {
1235 : 0 : PMD_DRV_LOG(ERR, "Could not get device information: err=%d", err);
1236 : 0 : goto free_adminq;
1237 : : }
1238 : :
1239 : 0 : num_ntfy = pci_dev_msix_vec_count(priv->pci_dev);
1240 [ # # ]: 0 : if (num_ntfy <= 0) {
1241 : 0 : PMD_DRV_LOG(ERR, "Could not count MSI-x vectors");
1242 : : err = -EIO;
1243 : 0 : goto free_adminq;
1244 [ # # ]: 0 : } else if (num_ntfy < GVE_MIN_MSIX) {
1245 : 0 : PMD_DRV_LOG(ERR, "GVE needs at least %d MSI-x vectors, but only has %d",
1246 : : GVE_MIN_MSIX, num_ntfy);
1247 : : err = -EINVAL;
1248 : 0 : goto free_adminq;
1249 : : }
1250 : :
1251 : 0 : priv->num_registered_pages = 0;
1252 : :
1253 : : /* gvnic has one Notification Block per MSI-x vector, except for the
1254 : : * management vector
1255 : : */
1256 : 0 : priv->num_ntfy_blks = (num_ntfy - 1) & ~0x1;
1257 : 0 : priv->mgmt_msix_idx = priv->num_ntfy_blks;
1258 : :
1259 : 0 : priv->max_nb_txq = RTE_MIN(priv->max_nb_txq, priv->num_ntfy_blks / 2);
1260 : 0 : priv->max_nb_rxq = RTE_MIN(priv->max_nb_rxq, priv->num_ntfy_blks / 2);
1261 : :
1262 [ # # ]: 0 : if (priv->default_num_queues > 0) {
1263 : 0 : priv->max_nb_txq = RTE_MIN(priv->default_num_queues, priv->max_nb_txq);
1264 : 0 : priv->max_nb_rxq = RTE_MIN(priv->default_num_queues, priv->max_nb_rxq);
1265 : : }
1266 : :
1267 : 0 : PMD_DRV_LOG(INFO, "Max TX queues %d, Max RX queues %d",
1268 : : priv->max_nb_txq, priv->max_nb_rxq);
1269 : :
1270 : 0 : setup_device:
1271 : 0 : err = gve_setup_device_resources(priv);
1272 [ # # ]: 0 : if (!err)
1273 : : return 0;
1274 : 0 : free_adminq:
1275 : 0 : gve_adminq_free(priv);
1276 : 0 : return err;
1277 : : }
1278 : :
1279 : : static int
1280 : 0 : gve_dev_init(struct rte_eth_dev *eth_dev)
1281 : : {
1282 : 0 : struct gve_priv *priv = eth_dev->data->dev_private;
1283 : : int max_tx_queues, max_rx_queues;
1284 : : struct rte_pci_device *pci_dev;
1285 : : struct gve_registers *reg_bar;
1286 : : rte_be32_t *db_bar;
1287 : : int err;
1288 : :
1289 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
1290 [ # # ]: 0 : if (gve_is_gqi(priv)) {
1291 : 0 : gve_set_rx_function(eth_dev);
1292 : 0 : gve_set_tx_function(eth_dev);
1293 : 0 : eth_dev->dev_ops = &gve_eth_dev_ops;
1294 : : } else {
1295 : 0 : gve_set_rx_function_dqo(eth_dev);
1296 : 0 : gve_set_tx_function_dqo(eth_dev);
1297 : 0 : eth_dev->dev_ops = &gve_eth_dev_ops_dqo;
1298 : : }
1299 : 0 : return 0;
1300 : : }
1301 : :
1302 : 0 : pci_dev = RTE_DEV_TO_PCI(eth_dev->device);
1303 : :
1304 : 0 : reg_bar = pci_dev->mem_resource[GVE_REG_BAR].addr;
1305 [ # # ]: 0 : if (!reg_bar) {
1306 : 0 : PMD_DRV_LOG(ERR, "Failed to map pci bar!");
1307 : 0 : return -ENOMEM;
1308 : : }
1309 : :
1310 : 0 : db_bar = pci_dev->mem_resource[GVE_DB_BAR].addr;
1311 [ # # ]: 0 : if (!db_bar) {
1312 : 0 : PMD_DRV_LOG(ERR, "Failed to map doorbell bar!");
1313 : 0 : return -ENOMEM;
1314 : : }
1315 : :
1316 : : gve_write_version(®_bar->driver_version);
1317 : : /* Get max queues to alloc etherdev */
1318 : : max_tx_queues = ioread32be(®_bar->max_tx_queues);
1319 : : max_rx_queues = ioread32be(®_bar->max_rx_queues);
1320 : :
1321 : 0 : priv->reg_bar0 = reg_bar;
1322 : 0 : priv->db_bar2 = db_bar;
1323 : 0 : priv->pci_dev = pci_dev;
1324 : 0 : priv->state_flags = 0x0;
1325 : :
1326 : 0 : priv->max_nb_txq = max_tx_queues;
1327 : 0 : priv->max_nb_rxq = max_rx_queues;
1328 : :
1329 : 0 : err = gve_init_priv(priv, false);
1330 [ # # ]: 0 : if (err)
1331 : : return err;
1332 : :
1333 [ # # ]: 0 : if (gve_is_gqi(priv)) {
1334 : 0 : eth_dev->dev_ops = &gve_eth_dev_ops;
1335 : 0 : gve_set_rx_function(eth_dev);
1336 : 0 : gve_set_tx_function(eth_dev);
1337 : : } else {
1338 : 0 : eth_dev->dev_ops = &gve_eth_dev_ops_dqo;
1339 : 0 : gve_set_rx_function_dqo(eth_dev);
1340 : 0 : gve_set_tx_function_dqo(eth_dev);
1341 : : }
1342 : :
1343 : 0 : eth_dev->data->mac_addrs = &priv->dev_addr;
1344 : :
1345 : 0 : return 0;
1346 : : }
1347 : :
1348 : : static int
1349 : 0 : gve_pci_probe(__rte_unused struct rte_pci_driver *pci_drv,
1350 : : struct rte_pci_device *pci_dev)
1351 : : {
1352 : 0 : return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct gve_priv), gve_dev_init);
1353 : : }
1354 : :
1355 : : static int
1356 : 0 : gve_pci_remove(struct rte_pci_device *pci_dev)
1357 : : {
1358 : 0 : return rte_eth_dev_pci_generic_remove(pci_dev, gve_dev_close);
1359 : : }
1360 : :
1361 : : static const struct rte_pci_id pci_id_gve_map[] = {
1362 : : { RTE_PCI_DEVICE(GOOGLE_VENDOR_ID, GVE_DEV_ID) },
1363 : : { .device_id = 0 },
1364 : : };
1365 : :
1366 : : static struct rte_pci_driver rte_gve_pmd = {
1367 : : .id_table = pci_id_gve_map,
1368 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
1369 : : .probe = gve_pci_probe,
1370 : : .remove = gve_pci_remove,
1371 : : };
1372 : :
1373 : 253 : RTE_PMD_REGISTER_PCI(net_gve, rte_gve_pmd);
1374 : : RTE_PMD_REGISTER_PCI_TABLE(net_gve, pci_id_gve_map);
1375 : : RTE_PMD_REGISTER_KMOD_DEP(net_gve, "* igb_uio | vfio-pci | nic_uio");
1376 [ - + ]: 253 : RTE_LOG_REGISTER_SUFFIX(gve_logtype_driver, driver, NOTICE);
|