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