Branch data Line data Source code
1 : : /* SPDX-License-Identifier: MIT
2 : : * Google Virtual Ethernet (gve) driver
3 : : * Copyright (C) 2015-2022 Google, Inc.
4 : : */
5 : :
6 : : #include "../gve_ethdev.h"
7 : : #include "gve_adminq.h"
8 : : #include "gve_register.h"
9 : :
10 : : #define GVE_MAX_ADMINQ_RELEASE_CHECK 500
11 : : #define GVE_ADMINQ_SLEEP_LEN 20
12 : : #define GVE_MAX_ADMINQ_EVENT_COUNTER_CHECK 100
13 : :
14 : : #define GVE_DEVICE_OPTION_ERROR_FMT "%s option error: Expected: length=%d, feature_mask=%x. Actual: length=%d, feature_mask=%x."
15 : :
16 : : #define GVE_DEVICE_OPTION_TOO_BIG_FMT "Length of %s option larger than expected. Possible older version of guest driver."
17 : :
18 : : static void gve_set_min_desc_cnt(struct gve_priv *priv,
19 : : struct gve_device_option_modify_ring *dev_op_modify_ring);
20 : :
21 : : static
22 : : struct gve_device_option *gve_get_next_option(struct gve_device_descriptor *descriptor,
23 : : struct gve_device_option *option)
24 : : {
25 : : uintptr_t option_end, descriptor_end;
26 : :
27 [ # # ]: 0 : option_end = (uintptr_t)option + sizeof(*option) + be16_to_cpu(option->option_length);
28 [ # # ]: 0 : descriptor_end = (uintptr_t)descriptor + be16_to_cpu(descriptor->total_length);
29 : :
30 [ # # ]: 0 : return option_end > descriptor_end ? NULL : (struct gve_device_option *)option_end;
31 : : }
32 : :
33 : : static
34 : 0 : void gve_parse_device_option(struct gve_priv *priv,
35 : : struct gve_device_option *option,
36 : : struct gve_device_option_gqi_rda **dev_op_gqi_rda,
37 : : struct gve_device_option_gqi_qpl **dev_op_gqi_qpl,
38 : : struct gve_device_option_dqo_rda **dev_op_dqo_rda,
39 : : struct gve_device_option_flow_steering **dev_op_flow_steering,
40 : : struct gve_device_option_modify_ring **dev_op_modify_ring,
41 : : struct gve_device_option_jumbo_frames **dev_op_jumbo_frames,
42 : : struct gve_device_option_nic_timestamp **dev_op_nic_timestamp)
43 : : {
44 [ # # ]: 0 : u32 req_feat_mask = be32_to_cpu(option->required_features_mask);
45 [ # # ]: 0 : u16 option_length = be16_to_cpu(option->option_length);
46 [ # # ]: 0 : u16 option_id = be16_to_cpu(option->option_id);
47 : :
48 : : /* If the length or feature mask doesn't match, continue without
49 : : * enabling the feature.
50 : : */
51 [ # # # # : 0 : switch (option_id) {
# # # #
# ]
52 : 0 : case GVE_DEV_OPT_ID_GQI_RAW_ADDRESSING:
53 : 0 : if (option_length != GVE_DEV_OPT_LEN_GQI_RAW_ADDRESSING ||
54 [ # # ]: 0 : req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_GQI_RAW_ADDRESSING) {
55 : 0 : PMD_DRV_LOG(WARNING, GVE_DEVICE_OPTION_ERROR_FMT,
56 : : "Raw Addressing",
57 : : GVE_DEV_OPT_LEN_GQI_RAW_ADDRESSING,
58 : : GVE_DEV_OPT_REQ_FEAT_MASK_GQI_RAW_ADDRESSING,
59 : : option_length, req_feat_mask);
60 : 0 : break;
61 : : }
62 : :
63 : 0 : PMD_DRV_LOG(INFO, "Gqi raw addressing device option enabled.");
64 : 0 : priv->queue_format = GVE_GQI_RDA_FORMAT;
65 : 0 : break;
66 : 0 : case GVE_DEV_OPT_ID_GQI_RDA:
67 : 0 : if (option_length < sizeof(**dev_op_gqi_rda) ||
68 [ # # ]: 0 : req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_GQI_RDA) {
69 : 0 : PMD_DRV_LOG(WARNING, GVE_DEVICE_OPTION_ERROR_FMT,
70 : : "GQI RDA", (int)sizeof(**dev_op_gqi_rda),
71 : : GVE_DEV_OPT_REQ_FEAT_MASK_GQI_RDA,
72 : : option_length, req_feat_mask);
73 : 0 : break;
74 : : }
75 : :
76 [ # # ]: 0 : if (option_length > sizeof(**dev_op_gqi_rda)) {
77 : 0 : PMD_DRV_LOG(WARNING,
78 : : GVE_DEVICE_OPTION_TOO_BIG_FMT, "GQI RDA");
79 : : }
80 : 0 : *dev_op_gqi_rda = RTE_PTR_ADD(option, sizeof(*option));
81 : 0 : break;
82 : 0 : case GVE_DEV_OPT_ID_GQI_QPL:
83 : 0 : if (option_length < sizeof(**dev_op_gqi_qpl) ||
84 [ # # ]: 0 : req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_GQI_QPL) {
85 : 0 : PMD_DRV_LOG(WARNING, GVE_DEVICE_OPTION_ERROR_FMT,
86 : : "GQI QPL", (int)sizeof(**dev_op_gqi_qpl),
87 : : GVE_DEV_OPT_REQ_FEAT_MASK_GQI_QPL,
88 : : option_length, req_feat_mask);
89 : 0 : break;
90 : : }
91 : :
92 [ # # ]: 0 : if (option_length > sizeof(**dev_op_gqi_qpl)) {
93 : 0 : PMD_DRV_LOG(WARNING,
94 : : GVE_DEVICE_OPTION_TOO_BIG_FMT, "GQI QPL");
95 : : }
96 : 0 : *dev_op_gqi_qpl = RTE_PTR_ADD(option, sizeof(*option));
97 : 0 : break;
98 : 0 : case GVE_DEV_OPT_ID_DQO_RDA:
99 : 0 : if (option_length < sizeof(**dev_op_dqo_rda) ||
100 [ # # ]: 0 : req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_DQO_RDA) {
101 : 0 : PMD_DRV_LOG(WARNING, GVE_DEVICE_OPTION_ERROR_FMT,
102 : : "DQO RDA", (int)sizeof(**dev_op_dqo_rda),
103 : : GVE_DEV_OPT_REQ_FEAT_MASK_DQO_RDA,
104 : : option_length, req_feat_mask);
105 : 0 : break;
106 : : }
107 : :
108 [ # # ]: 0 : if (option_length > sizeof(**dev_op_dqo_rda)) {
109 : 0 : PMD_DRV_LOG(WARNING,
110 : : GVE_DEVICE_OPTION_TOO_BIG_FMT, "DQO RDA");
111 : : }
112 : 0 : *dev_op_dqo_rda = RTE_PTR_ADD(option, sizeof(*option));
113 : 0 : break;
114 : 0 : case GVE_DEV_OPT_ID_FLOW_STEERING:
115 : 0 : if (option_length < sizeof(**dev_op_flow_steering) ||
116 [ # # ]: 0 : req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_FLOW_STEERING) {
117 : 0 : PMD_DRV_LOG(WARNING, GVE_DEVICE_OPTION_ERROR_FMT,
118 : : "Flow Steering", (int)sizeof(**dev_op_flow_steering),
119 : : GVE_DEV_OPT_REQ_FEAT_MASK_FLOW_STEERING,
120 : : option_length, req_feat_mask);
121 : 0 : break;
122 : : }
123 : :
124 [ # # ]: 0 : if (option_length > sizeof(**dev_op_flow_steering)) {
125 : 0 : PMD_DRV_LOG(WARNING,
126 : : GVE_DEVICE_OPTION_TOO_BIG_FMT, "Flow Steering");
127 : : }
128 : 0 : *dev_op_flow_steering = RTE_PTR_ADD(option, sizeof(*option));
129 : 0 : break;
130 : 0 : case GVE_DEV_OPT_ID_MODIFY_RING:
131 : : /* Min ring size bound is optional. */
132 : 0 : if (option_length < (sizeof(**dev_op_modify_ring) -
133 : 0 : sizeof(struct gve_ring_size_bound)) ||
134 [ # # ]: 0 : req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING) {
135 : 0 : PMD_DRV_LOG(WARNING, GVE_DEVICE_OPTION_ERROR_FMT,
136 : : "Modify Ring",
137 : : (int)sizeof(**dev_op_modify_ring),
138 : : GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING,
139 : : option_length, req_feat_mask);
140 : 0 : break;
141 : : }
142 : :
143 [ # # ]: 0 : if (option_length > sizeof(**dev_op_modify_ring)) {
144 : 0 : PMD_DRV_LOG(WARNING,
145 : : GVE_DEVICE_OPTION_TOO_BIG_FMT,
146 : : "Modify Ring");
147 : : }
148 : 0 : *dev_op_modify_ring = RTE_PTR_ADD(option, sizeof(*option));
149 : :
150 : : /* Min ring size included; set the minimum ring size. */
151 [ # # ]: 0 : if (option_length == sizeof(**dev_op_modify_ring))
152 : : gve_set_min_desc_cnt(priv, *dev_op_modify_ring);
153 : : break;
154 : 0 : case GVE_DEV_OPT_ID_JUMBO_FRAMES:
155 : 0 : if (option_length < sizeof(**dev_op_jumbo_frames) ||
156 [ # # ]: 0 : req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES) {
157 : 0 : PMD_DRV_LOG(WARNING, GVE_DEVICE_OPTION_ERROR_FMT,
158 : : "Jumbo Frames",
159 : : (int)sizeof(**dev_op_jumbo_frames),
160 : : GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES,
161 : : option_length, req_feat_mask);
162 : 0 : break;
163 : : }
164 : :
165 [ # # ]: 0 : if (option_length > sizeof(**dev_op_jumbo_frames)) {
166 : 0 : PMD_DRV_LOG(WARNING,
167 : : GVE_DEVICE_OPTION_TOO_BIG_FMT,
168 : : "Jumbo Frames");
169 : : }
170 : 0 : *dev_op_jumbo_frames = RTE_PTR_ADD(option, sizeof(*option));
171 : 0 : break;
172 : 0 : case GVE_DEV_OPT_ID_NIC_TIMESTAMP:
173 : 0 : if (option_length < sizeof(**dev_op_nic_timestamp) ||
174 [ # # ]: 0 : req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_NIC_TIMESTAMP) {
175 : 0 : PMD_DRV_LOG(WARNING, GVE_DEVICE_OPTION_ERROR_FMT,
176 : : "Nic Timestamp",
177 : : (int)sizeof(**dev_op_nic_timestamp),
178 : : GVE_DEV_OPT_REQ_FEAT_MASK_NIC_TIMESTAMP,
179 : : option_length, req_feat_mask);
180 : 0 : break;
181 : : }
182 : :
183 [ # # ]: 0 : if (option_length > sizeof(**dev_op_nic_timestamp)) {
184 : 0 : PMD_DRV_LOG(WARNING,
185 : : GVE_DEVICE_OPTION_TOO_BIG_FMT,
186 : : "Nic Timestamp");
187 : : }
188 : 0 : *dev_op_nic_timestamp = RTE_PTR_ADD(option, sizeof(*option));
189 : 0 : break;
190 : 0 : default:
191 : : /* If we don't recognize the option just continue
192 : : * without doing anything.
193 : : */
194 : 0 : PMD_DRV_LOG(DEBUG, "Unrecognized device option 0x%hx not enabled.",
195 : : option_id);
196 : : }
197 : 0 : }
198 : :
199 : : /* Process all device options for a given describe device call. */
200 : : static int
201 : 0 : gve_process_device_options(struct gve_priv *priv,
202 : : struct gve_device_descriptor *descriptor,
203 : : struct gve_device_option_gqi_rda **dev_op_gqi_rda,
204 : : struct gve_device_option_gqi_qpl **dev_op_gqi_qpl,
205 : : struct gve_device_option_dqo_rda **dev_op_dqo_rda,
206 : : struct gve_device_option_flow_steering **dev_op_flow_steering,
207 : : struct gve_device_option_modify_ring **dev_op_modify_ring,
208 : : struct gve_device_option_jumbo_frames **dev_op_jumbo_frames,
209 : : struct gve_device_option_nic_timestamp **dev_op_nic_timestamp)
210 : : {
211 [ # # ]: 0 : const int num_options = be16_to_cpu(descriptor->num_device_options);
212 : : struct gve_device_option *dev_opt;
213 : : int i;
214 : :
215 : : /* The options struct directly follows the device descriptor. */
216 : 0 : dev_opt = RTE_PTR_ADD(descriptor, sizeof(*descriptor));
217 [ # # ]: 0 : for (i = 0; i < num_options; i++) {
218 : : struct gve_device_option *next_opt;
219 : :
220 : : next_opt = gve_get_next_option(descriptor, dev_opt);
221 [ # # ]: 0 : if (!next_opt) {
222 : 0 : PMD_DRV_LOG(ERR,
223 : : "options exceed device_descriptor's total length.");
224 : 0 : return -EINVAL;
225 : : }
226 : :
227 : 0 : gve_parse_device_option(priv, dev_opt,
228 : : dev_op_gqi_rda, dev_op_gqi_qpl,
229 : : dev_op_dqo_rda, dev_op_flow_steering,
230 : : dev_op_modify_ring, dev_op_jumbo_frames,
231 : : dev_op_nic_timestamp);
232 : : dev_opt = next_opt;
233 : : }
234 : :
235 : : return 0;
236 : : }
237 : :
238 : 0 : int gve_adminq_alloc(struct gve_priv *priv)
239 : : {
240 : : pthread_mutexattr_t mutexattr;
241 : : uint8_t pci_rev_id;
242 : :
243 : 0 : priv->adminq = gve_alloc_dma_mem(&priv->adminq_dma_mem, PAGE_SIZE);
244 [ # # ]: 0 : if (unlikely(!priv->adminq))
245 : : return -ENOMEM;
246 : :
247 : 0 : priv->adminq_mask = (PAGE_SIZE / sizeof(union gve_adminq_command)) - 1;
248 : 0 : priv->adminq_prod_cnt = 0;
249 : 0 : priv->adminq_cmd_fail = 0;
250 : 0 : priv->adminq_timeouts = 0;
251 : 0 : priv->adminq_describe_device_cnt = 0;
252 : 0 : priv->adminq_cfg_device_resources_cnt = 0;
253 : 0 : priv->adminq_register_page_list_cnt = 0;
254 : 0 : priv->adminq_unregister_page_list_cnt = 0;
255 : 0 : priv->adminq_create_tx_queue_cnt = 0;
256 : 0 : priv->adminq_create_rx_queue_cnt = 0;
257 : 0 : priv->adminq_destroy_tx_queue_cnt = 0;
258 : 0 : priv->adminq_destroy_rx_queue_cnt = 0;
259 : 0 : priv->adminq_dcfg_device_resources_cnt = 0;
260 : 0 : priv->adminq_set_driver_parameter_cnt = 0;
261 : 0 : priv->adminq_report_stats_cnt = 0;
262 : 0 : priv->adminq_report_link_speed_cnt = 0;
263 : 0 : priv->adminq_get_ptype_map_cnt = 0;
264 : 0 : priv->adminq_cfg_flow_rule_cnt = 0;
265 : :
266 : 0 : priv->adminq_report_nic_timestamp_cnt = 0;
267 : :
268 : 0 : pthread_mutexattr_init(&mutexattr);
269 : 0 : pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
270 : 0 : pthread_mutex_init(&priv->adminq_lock, &mutexattr);
271 : 0 : pthread_mutexattr_destroy(&mutexattr);
272 : :
273 : : /* Setup Admin queue with the device */
274 : 0 : rte_pci_read_config(priv->pci_dev, &pci_rev_id, sizeof(pci_rev_id),
275 : : RTE_PCI_REVISION_ID);
276 [ # # ]: 0 : if (pci_rev_id < 0x1) { /* Use AQ PFN. */
277 : 0 : iowrite32be(priv->adminq_dma_mem.pa / PAGE_SIZE,
278 [ # # ]: 0 : &priv->reg_bar0->adminq_pfn);
279 : : } else { /* Use full AQ address. */
280 : : iowrite16be(GVE_ADMINQ_BUFFER_SIZE,
281 : 0 : &priv->reg_bar0->adminq_length);
282 : 0 : iowrite32be(priv->adminq_dma_mem.pa >> 32,
283 [ # # ]: 0 : &priv->reg_bar0->adminq_base_address_hi);
284 : 0 : iowrite32be(priv->adminq_dma_mem.pa,
285 [ # # ]: 0 : &priv->reg_bar0->adminq_base_address_lo);
286 : : iowrite32be(GVE_DRIVER_STATUS_RUN_MASK,
287 : 0 : &priv->reg_bar0->driver_status);
288 : : }
289 : :
290 : : gve_set_admin_queue_ok(priv);
291 : 0 : return 0;
292 : : }
293 : :
294 : 0 : void gve_adminq_release(struct gve_priv *priv)
295 : : {
296 : : uint8_t pci_rev_id;
297 : : int i = 0;
298 : :
299 : : /* Tell the device the adminq is leaving */
300 : 0 : rte_pci_read_config(priv->pci_dev, &pci_rev_id, sizeof(pci_rev_id),
301 : : RTE_PCI_REVISION_ID);
302 [ # # ]: 0 : if (pci_rev_id < 0x1) {
303 : 0 : iowrite32be(0x0, &priv->reg_bar0->adminq_pfn);
304 [ # # ]: 0 : while (ioread32be(&priv->reg_bar0->adminq_pfn)) {
305 : : /* If this is reached the device is unrecoverable and still
306 : : * holding memory. Continue looping to avoid memory corruption,
307 : : * but WARN so it is visible what is going on.
308 : : */
309 [ # # ]: 0 : if (i == GVE_MAX_ADMINQ_RELEASE_CHECK)
310 : 0 : PMD_DRV_LOG(WARNING,
311 : : "Unrecoverable platform error!");
312 : 0 : i++;
313 : : msleep(GVE_ADMINQ_SLEEP_LEN);
314 : : }
315 : : } else {
316 : : iowrite32be(GVE_DRIVER_STATUS_RESET_MASK,
317 : 0 : &priv->reg_bar0->driver_status);
318 : 0 : while (!(ioread32be(&priv->reg_bar0->device_status)
319 [ # # ]: 0 : & GVE_DEVICE_STATUS_DEVICE_IS_RESET)) {
320 [ # # ]: 0 : if (i == GVE_MAX_ADMINQ_RELEASE_CHECK)
321 : 0 : PMD_DRV_LOG(WARNING,
322 : : "Unrecoverable platform error!");
323 : 0 : i++;
324 : : msleep(GVE_ADMINQ_SLEEP_LEN);
325 : : }
326 : : }
327 : : gve_clear_admin_queue_ok(priv);
328 : 0 : }
329 : :
330 [ # # ]: 0 : void gve_adminq_free(struct gve_priv *priv)
331 : : {
332 [ # # ]: 0 : if (!gve_get_admin_queue_ok(priv))
333 : : return;
334 : 0 : gve_adminq_release(priv);
335 : 0 : gve_free_dma_mem(&priv->adminq_dma_mem);
336 : 0 : pthread_mutex_destroy(&priv->adminq_lock);
337 : : gve_clear_admin_queue_ok(priv);
338 : : }
339 : :
340 : : static void gve_adminq_kick_cmd(struct gve_priv *priv, u32 prod_cnt)
341 : : {
342 : 0 : iowrite32be(prod_cnt, &priv->reg_bar0->adminq_doorbell);
343 : 0 : }
344 : :
345 : : static bool gve_adminq_wait_for_cmd(struct gve_priv *priv, u32 prod_cnt)
346 : : {
347 : : int i;
348 : :
349 [ # # ]: 0 : for (i = 0; i < GVE_MAX_ADMINQ_EVENT_COUNTER_CHECK; i++) {
350 [ # # ]: 0 : if (ioread32be(&priv->reg_bar0->adminq_event_counter)
351 : : == prod_cnt)
352 : : return true;
353 : : msleep(GVE_ADMINQ_SLEEP_LEN);
354 : : }
355 : :
356 : : return false;
357 : : }
358 : :
359 : 0 : static int gve_adminq_parse_err(struct gve_priv *priv, u32 status)
360 : : {
361 [ # # ]: 0 : if (status != GVE_ADMINQ_COMMAND_PASSED &&
362 : : status != GVE_ADMINQ_COMMAND_UNSET) {
363 : 0 : PMD_DRV_LOG(ERR, "AQ command failed with status %d", status);
364 : 0 : priv->adminq_cmd_fail++;
365 : : }
366 [ # # # # : 0 : switch (status) {
# # # #
# ]
367 : : case GVE_ADMINQ_COMMAND_PASSED:
368 : : return 0;
369 : 0 : case GVE_ADMINQ_COMMAND_UNSET:
370 : 0 : PMD_DRV_LOG(ERR, "parse_aq_err: err and status both unset, this should not be possible.");
371 : 0 : return -EINVAL;
372 : 0 : case GVE_ADMINQ_COMMAND_ERROR_ABORTED:
373 : : case GVE_ADMINQ_COMMAND_ERROR_CANCELLED:
374 : : case GVE_ADMINQ_COMMAND_ERROR_DATALOSS:
375 : : case GVE_ADMINQ_COMMAND_ERROR_FAILED_PRECONDITION:
376 : : case GVE_ADMINQ_COMMAND_ERROR_UNAVAILABLE:
377 : 0 : return -EAGAIN;
378 : 0 : case GVE_ADMINQ_COMMAND_ERROR_ALREADY_EXISTS:
379 : : case GVE_ADMINQ_COMMAND_ERROR_INTERNAL_ERROR:
380 : : case GVE_ADMINQ_COMMAND_ERROR_INVALID_ARGUMENT:
381 : : case GVE_ADMINQ_COMMAND_ERROR_NOT_FOUND:
382 : : case GVE_ADMINQ_COMMAND_ERROR_OUT_OF_RANGE:
383 : : case GVE_ADMINQ_COMMAND_ERROR_UNKNOWN_ERROR:
384 : 0 : return -EINVAL;
385 : 0 : case GVE_ADMINQ_COMMAND_ERROR_DEADLINE_EXCEEDED:
386 : 0 : return -ETIMEDOUT;
387 : 0 : case GVE_ADMINQ_COMMAND_ERROR_PERMISSION_DENIED:
388 : : case GVE_ADMINQ_COMMAND_ERROR_UNAUTHENTICATED:
389 : 0 : return -EACCES;
390 : 0 : case GVE_ADMINQ_COMMAND_ERROR_RESOURCE_EXHAUSTED:
391 : 0 : return -ENOMEM;
392 : 0 : case GVE_ADMINQ_COMMAND_ERROR_UNIMPLEMENTED:
393 : 0 : return -ENOTSUP;
394 : 0 : default:
395 : 0 : PMD_DRV_LOG(ERR, "parse_aq_err: unknown status code %d",
396 : : status);
397 : 0 : return -EINVAL;
398 : : }
399 : : }
400 : :
401 : : /* Flushes all AQ commands currently queued and waits for them to complete.
402 : : * If there are failures, it will return the first error.
403 : : */
404 : 0 : static int gve_adminq_kick_and_wait(struct gve_priv *priv)
405 : : {
406 : : u32 tail, head;
407 : : u32 i;
408 : :
409 : 0 : tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
410 [ # # ]: 0 : head = priv->adminq_prod_cnt;
411 : :
412 : : gve_adminq_kick_cmd(priv, head);
413 [ # # ]: 0 : if (!gve_adminq_wait_for_cmd(priv, head)) {
414 : 0 : PMD_DRV_LOG(ERR, "AQ commands timed out, need to reset AQ");
415 : 0 : priv->adminq_timeouts++;
416 : 0 : return -ENOTRECOVERABLE;
417 : : }
418 : :
419 [ # # ]: 0 : for (i = tail; i < head; i++) {
420 : : union gve_adminq_command *cmd;
421 : : u32 status, err;
422 : :
423 : 0 : cmd = &priv->adminq[i & priv->adminq_mask];
424 : : status = be32_to_cpu(READ_ONCE32(cmd->status));
425 : 0 : err = gve_adminq_parse_err(priv, status);
426 [ # # ]: 0 : if (err)
427 : : /* Return the first error if we failed. */
428 : 0 : return err;
429 : : }
430 : :
431 : : return 0;
432 : : }
433 : :
434 : : /* This function is not threadsafe - the caller is responsible for any
435 : : * necessary locks.
436 : : */
437 : 0 : static int gve_adminq_issue_cmd(struct gve_priv *priv,
438 : : union gve_adminq_command *cmd_orig)
439 : : {
440 : : union gve_adminq_command *cmd;
441 : : u32 opcode;
442 : : u32 tail;
443 : :
444 : 0 : tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
445 : :
446 : : /* Check if next command will overflow the buffer. */
447 [ # # ]: 0 : if (((priv->adminq_prod_cnt + 1) & priv->adminq_mask) ==
448 : : (tail & priv->adminq_mask)) {
449 : : int err;
450 : :
451 : : /* Flush existing commands to make room.
452 : : * Note: This kicks the doorbell for all staged commands.
453 : : * Any failure here means we failed after attempting to kick.
454 : : */
455 : 0 : err = gve_adminq_kick_and_wait(priv);
456 [ # # ]: 0 : if (err)
457 : : return err;
458 : :
459 : : /* Retry. */
460 : 0 : tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
461 [ # # ]: 0 : if (((priv->adminq_prod_cnt + 1) & priv->adminq_mask) ==
462 : : (tail & priv->adminq_mask)) {
463 : : /* This should never happen. We just flushed the
464 : : * command queue so there should be enough space.
465 : : */
466 : : return -ENOMEM;
467 : : }
468 : : }
469 : :
470 : 0 : cmd = &priv->adminq[priv->adminq_prod_cnt & priv->adminq_mask];
471 : 0 : priv->adminq_prod_cnt++;
472 : :
473 : : memcpy(cmd, cmd_orig, sizeof(*cmd_orig));
474 : : opcode = be32_to_cpu(READ_ONCE32(cmd->opcode));
475 [ # # ]: 0 : if (opcode == GVE_ADMINQ_EXTENDED_COMMAND)
476 : : opcode = be32_to_cpu(READ_ONCE32(cmd->extended_command.inner_opcode));
477 : :
478 [ # # # # : 0 : switch (opcode) {
# # # # #
# # # # #
# # # # ]
479 : 0 : case GVE_ADMINQ_DESCRIBE_DEVICE:
480 : 0 : priv->adminq_describe_device_cnt++;
481 : 0 : break;
482 : 0 : case GVE_ADMINQ_CONFIGURE_DEVICE_RESOURCES:
483 : 0 : priv->adminq_cfg_device_resources_cnt++;
484 : 0 : break;
485 : 0 : case GVE_ADMINQ_REGISTER_PAGE_LIST:
486 : 0 : priv->adminq_register_page_list_cnt++;
487 : 0 : break;
488 : 0 : case GVE_ADMINQ_UNREGISTER_PAGE_LIST:
489 : 0 : priv->adminq_unregister_page_list_cnt++;
490 : 0 : break;
491 : 0 : case GVE_ADMINQ_CREATE_TX_QUEUE:
492 : 0 : priv->adminq_create_tx_queue_cnt++;
493 : 0 : break;
494 : 0 : case GVE_ADMINQ_CREATE_RX_QUEUE:
495 : 0 : priv->adminq_create_rx_queue_cnt++;
496 : 0 : break;
497 : 0 : case GVE_ADMINQ_DESTROY_TX_QUEUE:
498 : 0 : priv->adminq_destroy_tx_queue_cnt++;
499 : 0 : break;
500 : 0 : case GVE_ADMINQ_DESTROY_RX_QUEUE:
501 : 0 : priv->adminq_destroy_rx_queue_cnt++;
502 : 0 : break;
503 : 0 : case GVE_ADMINQ_DECONFIGURE_DEVICE_RESOURCES:
504 : 0 : priv->adminq_dcfg_device_resources_cnt++;
505 : 0 : break;
506 : 0 : case GVE_ADMINQ_CONFIGURE_RSS:
507 : 0 : priv->adminq_cfg_rss_cnt++;
508 : 0 : break;
509 : 0 : case GVE_ADMINQ_SET_DRIVER_PARAMETER:
510 : 0 : priv->adminq_set_driver_parameter_cnt++;
511 : 0 : break;
512 : 0 : case GVE_ADMINQ_REPORT_STATS:
513 : 0 : priv->adminq_report_stats_cnt++;
514 : 0 : break;
515 : 0 : case GVE_ADMINQ_REPORT_LINK_SPEED:
516 : 0 : priv->adminq_report_link_speed_cnt++;
517 : 0 : break;
518 : 0 : case GVE_ADMINQ_GET_PTYPE_MAP:
519 : 0 : priv->adminq_get_ptype_map_cnt++;
520 : 0 : break;
521 : 0 : case GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY:
522 : 0 : priv->adminq_verify_driver_compatibility_cnt++;
523 : 0 : break;
524 : 0 : case GVE_ADMINQ_CONFIGURE_FLOW_RULE:
525 : 0 : priv->adminq_cfg_flow_rule_cnt++;
526 : 0 : break;
527 : 0 : case GVE_ADMINQ_REPORT_NIC_TIMESTAMP:
528 : 0 : priv->adminq_report_nic_timestamp_cnt++;
529 : 0 : break;
530 : :
531 : 0 : default:
532 : 0 : PMD_DRV_LOG(ERR, "unknown AQ command opcode %d", opcode);
533 : : }
534 : :
535 : : return 0;
536 : : }
537 : :
538 : : /* This function is not threadsafe - the caller is responsible for any
539 : : * necessary locks.
540 : : * The caller is also responsible for making sure there are no commands
541 : : * waiting to be executed.
542 : : */
543 : 0 : static int gve_adminq_execute_cmd(struct gve_priv *priv,
544 : : union gve_adminq_command *cmd_orig)
545 : : {
546 : : u32 tail, head;
547 : : int err;
548 : :
549 : 0 : pthread_mutex_lock(&priv->adminq_lock);
550 : 0 : tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
551 : 0 : head = priv->adminq_prod_cnt;
552 [ # # ]: 0 : if (tail != head) {
553 : : /* This is not a valid path */
554 : : err = -EINVAL;
555 : 0 : goto unlock_and_return;
556 : : }
557 : :
558 : 0 : err = gve_adminq_issue_cmd(priv, cmd_orig);
559 [ # # ]: 0 : if (err)
560 : 0 : goto unlock_and_return;
561 : :
562 : 0 : err = gve_adminq_kick_and_wait(priv);
563 : :
564 : 0 : unlock_and_return:
565 : 0 : pthread_mutex_unlock(&priv->adminq_lock);
566 : 0 : return err;
567 : : }
568 : :
569 : 0 : static int gve_adminq_execute_extended_cmd(struct gve_priv *priv, u32 opcode,
570 : : size_t cmd_size, void *cmd_orig)
571 : : {
572 : : union gve_adminq_command cmd;
573 : : struct gve_dma_mem inner_cmd_dma_mem;
574 : : void *inner_cmd;
575 : : int err;
576 : :
577 : 0 : inner_cmd = gve_alloc_dma_mem(&inner_cmd_dma_mem, cmd_size);
578 [ # # ]: 0 : if (!inner_cmd)
579 : : return -ENOMEM;
580 : :
581 : : memcpy(inner_cmd, cmd_orig, cmd_size);
582 : :
583 : : memset(&cmd, 0, sizeof(cmd));
584 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_EXTENDED_COMMAND);
585 : 0 : cmd.extended_command = (struct gve_adminq_extended_command) {
586 [ # # ]: 0 : .inner_opcode = cpu_to_be32(opcode),
587 [ # # ]: 0 : .inner_length = cpu_to_be32(cmd_size),
588 [ # # ]: 0 : .inner_command_addr = cpu_to_be64(inner_cmd_dma_mem.pa),
589 : : };
590 : :
591 : 0 : err = gve_adminq_execute_cmd(priv, &cmd);
592 : :
593 : 0 : gve_free_dma_mem(&inner_cmd_dma_mem);
594 : 0 : return err;
595 : : }
596 : :
597 : : static int
598 : : gve_adminq_configure_flow_rule(struct gve_priv *priv,
599 : : struct gve_adminq_configure_flow_rule *flow_rule_cmd)
600 : : {
601 : 0 : int err = gve_adminq_execute_extended_cmd(priv,
602 : : GVE_ADMINQ_CONFIGURE_FLOW_RULE,
603 : : sizeof(struct gve_adminq_configure_flow_rule),
604 : : flow_rule_cmd);
605 : :
606 : : return err;
607 : : }
608 : :
609 : 0 : int gve_adminq_add_flow_rule(struct gve_priv *priv,
610 : : struct gve_flow_rule_params *rule, u32 loc)
611 : : {
612 : 0 : struct gve_adminq_configure_flow_rule flow_rule_cmd = {
613 : : .opcode = cpu_to_be16(GVE_FLOW_RULE_CFG_ADD),
614 [ # # ]: 0 : .location = cpu_to_be32(loc),
615 : : .rule = {
616 [ # # ]: 0 : .flow_type = cpu_to_be16(rule->flow_type),
617 [ # # ]: 0 : .action = cpu_to_be16(rule->action),
618 : : .key = rule->key,
619 : : .mask = rule->mask,
620 : : },
621 : : };
622 : :
623 : 0 : return gve_adminq_configure_flow_rule(priv, &flow_rule_cmd);
624 : : }
625 : :
626 : 0 : int gve_adminq_del_flow_rule(struct gve_priv *priv, u32 loc)
627 : : {
628 : 0 : struct gve_adminq_configure_flow_rule flow_rule_cmd = {
629 : : .opcode = cpu_to_be16(GVE_FLOW_RULE_CFG_DEL),
630 [ # # ]: 0 : .location = cpu_to_be32(loc),
631 : : };
632 : :
633 : 0 : return gve_adminq_configure_flow_rule(priv, &flow_rule_cmd);
634 : : }
635 : :
636 : 0 : int gve_adminq_reset_flow_rules(struct gve_priv *priv)
637 : : {
638 : 0 : struct gve_adminq_configure_flow_rule flow_rule_cmd = {
639 : : .opcode = cpu_to_be16(GVE_FLOW_RULE_CFG_RESET),
640 : : };
641 : :
642 : 0 : return gve_adminq_configure_flow_rule(priv, &flow_rule_cmd);
643 : : }
644 : :
645 [ # # ]: 0 : int gve_adminq_report_nic_timestamp(struct gve_priv *priv, dma_addr_t nic_ts_report_addr)
646 : : {
647 : : union gve_adminq_command cmd;
648 : :
649 : : memset(&cmd, 0, sizeof(cmd));
650 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_REPORT_NIC_TIMESTAMP);
651 : 0 : cmd.report_nic_timestamp = (struct gve_adminq_report_nic_timestamp) {
652 : : .nic_ts_report_len = cpu_to_be64(sizeof(struct gve_nic_ts_report)),
653 [ # # ]: 0 : .nic_timestamp_addr = cpu_to_be64(nic_ts_report_addr),
654 : : };
655 : :
656 : 0 : return gve_adminq_execute_cmd(priv, &cmd);
657 : : }
658 : :
659 : : /* The device specifies that the management vector can either be the first irq
660 : : * or the last irq. ntfy_blk_msix_base_idx indicates the first irq assigned to
661 : : * the ntfy blks. It if is 0 then the management vector is last, if it is 1 then
662 : : * the management vector is first.
663 : : *
664 : : * gve arranges the msix vectors so that the management vector is last.
665 : : */
666 : : #define GVE_NTFY_BLK_BASE_MSIX_IDX 0
667 [ # # ]: 0 : int gve_adminq_configure_device_resources(struct gve_priv *priv,
668 : : dma_addr_t counter_array_bus_addr,
669 : : u32 num_counters,
670 : : dma_addr_t db_array_bus_addr,
671 : : u32 num_ntfy_blks)
672 : : {
673 : : union gve_adminq_command cmd;
674 : :
675 : : memset(&cmd, 0, sizeof(cmd));
676 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_CONFIGURE_DEVICE_RESOURCES);
677 : 0 : cmd.configure_device_resources =
678 : : (struct gve_adminq_configure_device_resources) {
679 [ # # ]: 0 : .counter_array = cpu_to_be64(counter_array_bus_addr),
680 [ # # ]: 0 : .num_counters = cpu_to_be32(num_counters),
681 [ # # ]: 0 : .irq_db_addr = cpu_to_be64(db_array_bus_addr),
682 [ # # ]: 0 : .num_irq_dbs = cpu_to_be32(num_ntfy_blks),
683 : : .irq_db_stride = cpu_to_be32(sizeof(*priv->irq_dbs)),
684 : : .ntfy_blk_msix_base_idx =
685 : : cpu_to_be32(GVE_NTFY_BLK_BASE_MSIX_IDX),
686 : 0 : .queue_format = priv->queue_format,
687 : : };
688 : :
689 : 0 : return gve_adminq_execute_cmd(priv, &cmd);
690 : : }
691 : :
692 [ # # ]: 0 : int gve_adminq_verify_driver_compatibility(struct gve_priv *priv,
693 : : u64 driver_info_len,
694 : : dma_addr_t driver_info_addr)
695 : : {
696 : : union gve_adminq_command cmd;
697 : :
698 : : memset(&cmd, 0, sizeof(cmd));
699 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY);
700 : 0 : cmd.verify_driver_compatibility = (struct gve_adminq_verify_driver_compatibility) {
701 [ # # ]: 0 : .driver_info_len = cpu_to_be64(driver_info_len),
702 [ # # ]: 0 : .driver_info_addr = cpu_to_be64(driver_info_addr),
703 : : };
704 : :
705 : 0 : return gve_adminq_execute_cmd(priv, &cmd);
706 : : }
707 : :
708 : 0 : int gve_adminq_deconfigure_device_resources(struct gve_priv *priv)
709 : : {
710 : : union gve_adminq_command cmd;
711 : :
712 : : memset(&cmd, 0, sizeof(cmd));
713 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_DECONFIGURE_DEVICE_RESOURCES);
714 : :
715 : 0 : return gve_adminq_execute_cmd(priv, &cmd);
716 : : }
717 : :
718 : 0 : static int gve_adminq_create_tx_queue(struct gve_priv *priv, u32 queue_index)
719 : : {
720 [ # # ]: 0 : struct gve_tx_queue *txq = priv->txqs[queue_index];
721 : : union gve_adminq_command cmd;
722 : :
723 : : memset(&cmd, 0, sizeof(cmd));
724 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_CREATE_TX_QUEUE);
725 [ # # ]: 0 : cmd.create_tx_queue = (struct gve_adminq_create_tx_queue) {
726 [ # # ]: 0 : .queue_id = cpu_to_be32(queue_index),
727 : : .queue_resources_addr =
728 [ # # ]: 0 : cpu_to_be64(txq->qres_mz->iova),
729 [ # # ]: 0 : .tx_ring_addr = cpu_to_be64(txq->tx_ring_phys_addr),
730 [ # # ]: 0 : .ntfy_id = cpu_to_be32(txq->ntfy_id),
731 [ # # ]: 0 : .tx_ring_size = cpu_to_be16(txq->nb_tx_desc),
732 : : };
733 : :
734 [ # # ]: 0 : if (gve_is_gqi(priv)) {
735 : : u32 qpl_id = priv->queue_format == GVE_GQI_RDA_FORMAT ?
736 [ # # ]: 0 : GVE_RAW_ADDRESSING_QPL_ID : txq->qpl->id;
737 : :
738 [ # # ]: 0 : cmd.create_tx_queue.queue_page_list_id = cpu_to_be32(qpl_id);
739 : : } else {
740 : 0 : cmd.create_tx_queue.tx_comp_ring_addr =
741 [ # # ]: 0 : cpu_to_be64(txq->compl_ring_phys_addr);
742 : 0 : cmd.create_tx_queue.tx_comp_ring_size =
743 [ # # ]: 0 : cpu_to_be16(txq->nb_complq_desc);
744 : : }
745 : :
746 : 0 : return gve_adminq_issue_cmd(priv, &cmd);
747 : : }
748 : :
749 : 0 : int gve_adminq_create_tx_queues(struct gve_priv *priv, u32 num_queues)
750 : : {
751 : : int err;
752 : : u32 i;
753 : :
754 : 0 : pthread_mutex_lock(&priv->adminq_lock);
755 : :
756 [ # # ]: 0 : for (i = 0; i < num_queues; i++) {
757 : 0 : err = gve_adminq_create_tx_queue(priv, i);
758 [ # # ]: 0 : if (err)
759 : 0 : goto unlock_and_return;
760 : : }
761 : :
762 : 0 : err = gve_adminq_kick_and_wait(priv);
763 : :
764 : 0 : unlock_and_return:
765 : 0 : pthread_mutex_unlock(&priv->adminq_lock);
766 : 0 : return err;
767 : : }
768 : :
769 : 0 : static int gve_adminq_create_rx_queue(struct gve_priv *priv, u32 queue_index)
770 : : {
771 [ # # ]: 0 : struct gve_rx_queue *rxq = priv->rxqs[queue_index];
772 : : union gve_adminq_command cmd;
773 : :
774 : : memset(&cmd, 0, sizeof(cmd));
775 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_CREATE_RX_QUEUE);
776 [ # # ]: 0 : cmd.create_rx_queue = (struct gve_adminq_create_rx_queue) {
777 [ # # ]: 0 : .queue_id = cpu_to_be32(queue_index),
778 [ # # ]: 0 : .ntfy_id = cpu_to_be32(rxq->ntfy_id),
779 [ # # ]: 0 : .queue_resources_addr = cpu_to_be64(rxq->qres_mz->iova),
780 [ # # ]: 0 : .rx_ring_size = cpu_to_be16(rxq->nb_rx_desc),
781 : : };
782 : :
783 [ # # ]: 0 : if (gve_is_gqi(priv)) {
784 : : u32 qpl_id = priv->queue_format == GVE_GQI_RDA_FORMAT ?
785 [ # # ]: 0 : GVE_RAW_ADDRESSING_QPL_ID : rxq->qpl->id;
786 : :
787 : 0 : cmd.create_rx_queue.rx_desc_ring_addr =
788 [ # # ]: 0 : cpu_to_be64(rxq->mz->iova);
789 : 0 : cmd.create_rx_queue.rx_data_ring_addr =
790 [ # # ]: 0 : cpu_to_be64(rxq->data_mz->iova);
791 [ # # ]: 0 : cmd.create_rx_queue.index = cpu_to_be32(queue_index);
792 [ # # ]: 0 : cmd.create_rx_queue.queue_page_list_id = cpu_to_be32(qpl_id);
793 [ # # ]: 0 : cmd.create_rx_queue.packet_buffer_size = cpu_to_be16(rxq->rx_buf_len);
794 : : } else {
795 : 0 : cmd.create_rx_queue.rx_desc_ring_addr =
796 [ # # ]: 0 : cpu_to_be64(rxq->compl_ring_phys_addr);
797 : 0 : cmd.create_rx_queue.rx_data_ring_addr =
798 [ # # ]: 0 : cpu_to_be64(rxq->rx_ring_phys_addr);
799 : 0 : cmd.create_rx_queue.packet_buffer_size =
800 [ # # ]: 0 : cpu_to_be16(rxq->rx_buf_len);
801 : 0 : cmd.create_rx_queue.rx_buff_ring_size =
802 [ # # ]: 0 : cpu_to_be16(rxq->nb_rx_desc);
803 : 0 : cmd.create_rx_queue.enable_rsc = !!(priv->enable_rsc);
804 : : }
805 : :
806 : 0 : return gve_adminq_issue_cmd(priv, &cmd);
807 : : }
808 : :
809 : 0 : int gve_adminq_create_rx_queues(struct gve_priv *priv, u32 num_queues)
810 : : {
811 : : int err;
812 : : u32 i;
813 : :
814 : 0 : pthread_mutex_lock(&priv->adminq_lock);
815 : :
816 [ # # ]: 0 : for (i = 0; i < num_queues; i++) {
817 : 0 : err = gve_adminq_create_rx_queue(priv, i);
818 [ # # ]: 0 : if (err)
819 : 0 : goto unlock_and_return;
820 : : }
821 : :
822 : 0 : err = gve_adminq_kick_and_wait(priv);
823 : :
824 : 0 : unlock_and_return:
825 : 0 : pthread_mutex_unlock(&priv->adminq_lock);
826 : 0 : return err;
827 : : }
828 : :
829 [ # # ]: 0 : static int gve_adminq_destroy_tx_queue(struct gve_priv *priv, u32 queue_index)
830 : : {
831 : : union gve_adminq_command cmd;
832 : : int err;
833 : :
834 : : memset(&cmd, 0, sizeof(cmd));
835 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_DESTROY_TX_QUEUE);
836 : 0 : cmd.destroy_tx_queue = (struct gve_adminq_destroy_tx_queue) {
837 [ # # ]: 0 : .queue_id = cpu_to_be32(queue_index),
838 : : };
839 : :
840 : 0 : err = gve_adminq_issue_cmd(priv, &cmd);
841 [ # # ]: 0 : if (err)
842 : 0 : return err;
843 : :
844 : : return 0;
845 : : }
846 : :
847 : 0 : int gve_adminq_destroy_tx_queues(struct gve_priv *priv, u32 num_queues)
848 : : {
849 : : int err;
850 : : u32 i;
851 : :
852 : 0 : pthread_mutex_lock(&priv->adminq_lock);
853 : :
854 [ # # ]: 0 : for (i = 0; i < num_queues; i++) {
855 : 0 : err = gve_adminq_destroy_tx_queue(priv, i);
856 [ # # ]: 0 : if (err)
857 : 0 : goto unlock_and_return;
858 : : }
859 : :
860 : 0 : err = gve_adminq_kick_and_wait(priv);
861 : :
862 : 0 : unlock_and_return:
863 : 0 : pthread_mutex_unlock(&priv->adminq_lock);
864 : 0 : return err;
865 : : }
866 : :
867 [ # # ]: 0 : static int gve_adminq_destroy_rx_queue(struct gve_priv *priv, u32 queue_index)
868 : : {
869 : : union gve_adminq_command cmd;
870 : : int err;
871 : :
872 : : memset(&cmd, 0, sizeof(cmd));
873 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_DESTROY_RX_QUEUE);
874 : 0 : cmd.destroy_rx_queue = (struct gve_adminq_destroy_rx_queue) {
875 [ # # ]: 0 : .queue_id = cpu_to_be32(queue_index),
876 : : };
877 : :
878 : 0 : err = gve_adminq_issue_cmd(priv, &cmd);
879 [ # # ]: 0 : if (err)
880 : 0 : return err;
881 : :
882 : : return 0;
883 : : }
884 : :
885 : 0 : int gve_adminq_destroy_rx_queues(struct gve_priv *priv, u32 num_queues)
886 : : {
887 : : int err;
888 : : u32 i;
889 : :
890 : 0 : pthread_mutex_lock(&priv->adminq_lock);
891 : :
892 [ # # ]: 0 : for (i = 0; i < num_queues; i++) {
893 : 0 : err = gve_adminq_destroy_rx_queue(priv, i);
894 [ # # ]: 0 : if (err)
895 : 0 : goto unlock_and_return;
896 : : }
897 : :
898 : 0 : err = gve_adminq_kick_and_wait(priv);
899 : :
900 : 0 : unlock_and_return:
901 : 0 : pthread_mutex_unlock(&priv->adminq_lock);
902 : 0 : return err;
903 : : }
904 : :
905 : 0 : static int gve_set_desc_cnt(struct gve_priv *priv,
906 : : struct gve_device_descriptor *descriptor)
907 : : {
908 [ # # ]: 0 : priv->default_tx_desc_cnt = be16_to_cpu(descriptor->tx_queue_entries);
909 [ # # ]: 0 : if (priv->default_tx_desc_cnt * sizeof(priv->txqs[0]->tx_desc_ring[0])
910 : : < PAGE_SIZE) {
911 : 0 : PMD_DRV_LOG(ERR, "Tx desc count %d too low",
912 : : priv->default_tx_desc_cnt);
913 : 0 : return -EINVAL;
914 : : }
915 [ # # ]: 0 : priv->default_rx_desc_cnt = be16_to_cpu(descriptor->rx_queue_entries);
916 [ # # ]: 0 : if (priv->default_rx_desc_cnt * sizeof(priv->rxqs[0]->rx_desc_ring[0])
917 : : < PAGE_SIZE) {
918 : 0 : PMD_DRV_LOG(ERR, "Rx desc count %d too low", priv->default_rx_desc_cnt);
919 : 0 : return -EINVAL;
920 : : }
921 : : return 0;
922 : : }
923 : :
924 : : static int
925 : 0 : gve_set_desc_cnt_dqo(struct gve_priv *priv,
926 : : const struct gve_device_descriptor *descriptor,
927 : : const struct gve_device_option_dqo_rda *dev_op_dqo_rda)
928 : : {
929 [ # # ]: 0 : priv->default_tx_desc_cnt = be16_to_cpu(descriptor->tx_queue_entries);
930 [ # # ]: 0 : priv->tx_compq_size = be16_to_cpu(dev_op_dqo_rda->tx_comp_ring_entries);
931 [ # # ]: 0 : priv->default_rx_desc_cnt = be16_to_cpu(descriptor->rx_queue_entries);
932 [ # # ]: 0 : priv->rx_bufq_size = be16_to_cpu(dev_op_dqo_rda->rx_buff_ring_entries);
933 : :
934 : 0 : return 0;
935 : : }
936 : :
937 : : static void
938 : : gve_set_min_desc_cnt(struct gve_priv *priv,
939 : : struct gve_device_option_modify_ring *modify_ring)
940 : : {
941 [ # # ]: 0 : priv->min_rx_desc_cnt = be16_to_cpu(modify_ring->min_ring_size.rx);
942 [ # # ]: 0 : priv->min_tx_desc_cnt = be16_to_cpu(modify_ring->min_ring_size.tx);
943 : 0 : }
944 : :
945 : : static void
946 : 0 : gve_set_max_desc_cnt(struct gve_priv *priv,
947 : : const struct gve_device_option_modify_ring *modify_ring)
948 : : {
949 [ # # ]: 0 : priv->max_rx_desc_cnt = be16_to_cpu(modify_ring->max_ring_size.rx);
950 [ # # ]: 0 : priv->max_tx_desc_cnt = be16_to_cpu(modify_ring->max_ring_size.tx);
951 : :
952 [ # # ]: 0 : if (priv->queue_format == GVE_DQO_RDA_FORMAT) {
953 : 0 : PMD_DRV_LOG(DEBUG, "Overriding max ring size from device for DQ "
954 : : "queue format to 4096.");
955 : 0 : priv->max_rx_desc_cnt = GVE_MAX_QUEUE_SIZE_DQO;
956 : 0 : priv->max_tx_desc_cnt = GVE_MAX_QUEUE_SIZE_DQO;
957 [ # # ]: 0 : } else if (priv->queue_format == GVE_GQI_QPL_FORMAT) {
958 : 0 : priv->max_rx_desc_cnt = RTE_MIN(priv->max_rx_desc_cnt,
959 : : GVE_MAX_RING_SIZE_GQ_QPL);
960 : 0 : priv->max_tx_desc_cnt = RTE_MIN(priv->max_tx_desc_cnt,
961 : : GVE_MAX_RING_SIZE_GQ_QPL);
962 : : }
963 : 0 : }
964 : :
965 : 0 : static void gve_enable_supported_features(struct gve_priv *priv,
966 : : u32 supported_features_mask,
967 : : const struct gve_device_option_flow_steering *dev_op_flow_steering,
968 : : const struct gve_device_option_modify_ring *dev_op_modify_ring,
969 : : const struct gve_device_option_jumbo_frames *dev_op_jumbo_frames,
970 : : const struct gve_device_option_nic_timestamp *dev_op_nic_timestamp)
971 : : {
972 [ # # ]: 0 : if (dev_op_flow_steering &&
973 [ # # ]: 0 : (supported_features_mask & GVE_SUP_FLOW_STEERING_MASK) &&
974 [ # # ]: 0 : dev_op_flow_steering->max_flow_rules) {
975 : 0 : priv->max_flow_rules =
976 [ # # ]: 0 : be32_to_cpu(dev_op_flow_steering->max_flow_rules);
977 : 0 : PMD_DRV_LOG(INFO,
978 : : "FLOW STEERING device option enabled with max rule limit of %u.",
979 : : priv->max_flow_rules);
980 : : }
981 [ # # ]: 0 : if (dev_op_modify_ring &&
982 [ # # ]: 0 : (supported_features_mask & GVE_SUP_MODIFY_RING_MASK)) {
983 : 0 : PMD_DRV_LOG(INFO, "MODIFY RING device option enabled.");
984 : : /* Min ring size set separately by virtue of it being optional. */
985 : 0 : gve_set_max_desc_cnt(priv, dev_op_modify_ring);
986 : : }
987 : :
988 : : /* Before control reaches this point, the page-size-capped max MTU from
989 : : * the gve_device_descriptor field has already been stored in
990 : : * priv->dev->max_mtu. We overwrite it with the true max MTU below.
991 : : */
992 [ # # ]: 0 : if (dev_op_jumbo_frames &&
993 [ # # ]: 0 : (supported_features_mask & GVE_SUP_JUMBO_FRAMES_MASK)) {
994 : 0 : PMD_DRV_LOG(INFO, "JUMBO FRAMES device option enabled.");
995 [ # # ]: 0 : priv->max_mtu = be16_to_cpu(dev_op_jumbo_frames->max_mtu);
996 : : }
997 [ # # ]: 0 : if (dev_op_nic_timestamp &&
998 [ # # ]: 0 : (supported_features_mask & GVE_SUP_NIC_TIMESTAMP_MASK)) {
999 : 0 : PMD_DRV_LOG(INFO, "NIC TIMESTAMP device option enabled.");
1000 : 0 : priv->nic_timestamp_supported = true;
1001 : : }
1002 : 0 : }
1003 : :
1004 : 0 : int gve_adminq_describe_device(struct gve_priv *priv)
1005 : : {
1006 : 0 : struct gve_device_option_jumbo_frames *dev_op_jumbo_frames = NULL;
1007 : 0 : struct gve_device_option_modify_ring *dev_op_modify_ring = NULL;
1008 : 0 : struct gve_device_option_flow_steering *dev_op_flow_steering = NULL;
1009 : 0 : struct gve_device_option_nic_timestamp *dev_op_nic_timestamp = NULL;
1010 : 0 : struct gve_device_option_gqi_rda *dev_op_gqi_rda = NULL;
1011 : 0 : struct gve_device_option_gqi_qpl *dev_op_gqi_qpl = NULL;
1012 : 0 : struct gve_device_option_dqo_rda *dev_op_dqo_rda = NULL;
1013 : : struct gve_device_descriptor *descriptor;
1014 : : struct gve_dma_mem descriptor_dma_mem;
1015 : : u32 supported_features_mask = 0;
1016 : : union gve_adminq_command cmd;
1017 : : int err = 0;
1018 : : u16 mtu;
1019 : :
1020 : : memset(&cmd, 0, sizeof(cmd));
1021 : 0 : descriptor = gve_alloc_dma_mem(&descriptor_dma_mem, PAGE_SIZE);
1022 [ # # ]: 0 : if (!descriptor)
1023 : : return -ENOMEM;
1024 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_DESCRIBE_DEVICE);
1025 : 0 : cmd.describe_device.device_descriptor_addr =
1026 [ # # ]: 0 : cpu_to_be64(descriptor_dma_mem.pa);
1027 : 0 : cmd.describe_device.device_descriptor_version =
1028 : : cpu_to_be32(GVE_ADMINQ_DEVICE_DESCRIPTOR_VERSION);
1029 : 0 : cmd.describe_device.available_length = cpu_to_be32(PAGE_SIZE);
1030 : :
1031 : 0 : err = gve_adminq_execute_cmd(priv, &cmd);
1032 [ # # ]: 0 : if (err)
1033 : 0 : goto free_device_descriptor;
1034 : :
1035 : 0 : err = gve_process_device_options(priv, descriptor, &dev_op_gqi_rda,
1036 : : &dev_op_gqi_qpl, &dev_op_dqo_rda,
1037 : : &dev_op_flow_steering,
1038 : : &dev_op_modify_ring,
1039 : : &dev_op_jumbo_frames,
1040 : : &dev_op_nic_timestamp);
1041 [ # # ]: 0 : if (err)
1042 : 0 : goto free_device_descriptor;
1043 : :
1044 : : /* If the GQI_RAW_ADDRESSING option is not enabled and the queue format
1045 : : * is not set to GqiRda, choose the queue format in a priority order:
1046 : : * DqoRda, GqiRda, GqiQpl. Use GqiQpl as default.
1047 : : */
1048 [ # # ]: 0 : if (dev_op_dqo_rda) {
1049 : 0 : priv->queue_format = GVE_DQO_RDA_FORMAT;
1050 : 0 : PMD_DRV_LOG(INFO, "Driver is running with DQO RDA queue format.");
1051 : : supported_features_mask =
1052 [ # # ]: 0 : be32_to_cpu(dev_op_dqo_rda->supported_features_mask);
1053 [ # # ]: 0 : } else if (dev_op_gqi_rda) {
1054 : 0 : priv->queue_format = GVE_GQI_RDA_FORMAT;
1055 : 0 : PMD_DRV_LOG(INFO, "Driver is running with GQI RDA queue format.");
1056 : : supported_features_mask =
1057 [ # # ]: 0 : be32_to_cpu(dev_op_gqi_rda->supported_features_mask);
1058 [ # # ]: 0 : } else if (priv->queue_format == GVE_GQI_RDA_FORMAT) {
1059 : 0 : PMD_DRV_LOG(INFO, "Driver is running with GQI RDA queue format.");
1060 : : } else {
1061 : 0 : priv->queue_format = GVE_GQI_QPL_FORMAT;
1062 [ # # ]: 0 : if (dev_op_gqi_qpl)
1063 : : supported_features_mask =
1064 [ # # ]: 0 : be32_to_cpu(dev_op_gqi_qpl->supported_features_mask);
1065 : 0 : PMD_DRV_LOG(INFO, "Driver is running with GQI QPL queue format.");
1066 : : }
1067 [ # # ]: 0 : if (gve_is_gqi(priv)) {
1068 : 0 : err = gve_set_desc_cnt(priv, descriptor);
1069 : : } else {
1070 : : /* DQO supports LRO. */
1071 : 0 : err = gve_set_desc_cnt_dqo(priv, descriptor, dev_op_dqo_rda);
1072 : : }
1073 [ # # ]: 0 : if (err)
1074 : 0 : goto free_device_descriptor;
1075 : :
1076 : 0 : priv->max_registered_pages =
1077 [ # # ]: 0 : be64_to_cpu(descriptor->max_registered_pages);
1078 [ # # ]: 0 : mtu = be16_to_cpu(descriptor->mtu);
1079 [ # # ]: 0 : if (mtu < ETH_MIN_MTU) {
1080 : 0 : PMD_DRV_LOG(ERR, "MTU %d below minimum MTU", mtu);
1081 : : err = -EINVAL;
1082 : 0 : goto free_device_descriptor;
1083 : : }
1084 : 0 : priv->max_mtu = mtu;
1085 [ # # ]: 0 : priv->num_event_counters = be16_to_cpu(descriptor->counters);
1086 : : rte_memcpy(priv->dev_addr.addr_bytes, descriptor->mac, ETH_ALEN);
1087 : 0 : PMD_DRV_LOG(INFO, "MAC addr: " RTE_ETHER_ADDR_PRT_FMT,
1088 : : RTE_ETHER_ADDR_BYTES(&priv->dev_addr));
1089 [ # # ]: 0 : priv->tx_pages_per_qpl = be16_to_cpu(descriptor->tx_pages_per_qpl);
1090 : :
1091 [ # # ]: 0 : priv->default_num_queues = be16_to_cpu(descriptor->default_num_queues);
1092 : :
1093 : 0 : gve_enable_supported_features(priv, supported_features_mask,
1094 : : dev_op_flow_steering, dev_op_modify_ring,
1095 : : dev_op_jumbo_frames, dev_op_nic_timestamp);
1096 : :
1097 : 0 : free_device_descriptor:
1098 : 0 : gve_free_dma_mem(&descriptor_dma_mem);
1099 : 0 : return err;
1100 : : }
1101 : :
1102 : 0 : int gve_adminq_register_page_list(struct gve_priv *priv,
1103 : : struct gve_queue_page_list *qpl)
1104 : : {
1105 : : struct gve_dma_mem page_list_dma_mem;
1106 : 0 : u32 num_entries = qpl->num_entries;
1107 : 0 : u32 size = num_entries * sizeof(qpl->page_buses[0]);
1108 : : union gve_adminq_command cmd;
1109 : : __be64 *page_list;
1110 : : int err;
1111 : : u32 i;
1112 : :
1113 : : memset(&cmd, 0, sizeof(cmd));
1114 : 0 : page_list = gve_alloc_dma_mem(&page_list_dma_mem, size);
1115 [ # # ]: 0 : if (!page_list)
1116 : : return -ENOMEM;
1117 : :
1118 [ # # ]: 0 : for (i = 0; i < num_entries; i++)
1119 [ # # ]: 0 : page_list[i] = cpu_to_be64(qpl->page_buses[i]);
1120 : :
1121 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_REGISTER_PAGE_LIST);
1122 : 0 : cmd.reg_page_list = (struct gve_adminq_register_page_list) {
1123 [ # # ]: 0 : .page_list_id = cpu_to_be32(qpl->id),
1124 [ # # ]: 0 : .num_pages = cpu_to_be32(num_entries),
1125 [ # # ]: 0 : .page_address_list_addr = cpu_to_be64(page_list_dma_mem.pa),
1126 : : };
1127 : :
1128 : 0 : err = gve_adminq_execute_cmd(priv, &cmd);
1129 : 0 : gve_free_dma_mem(&page_list_dma_mem);
1130 : 0 : return err;
1131 : : }
1132 : :
1133 [ # # ]: 0 : int gve_adminq_unregister_page_list(struct gve_priv *priv, u32 page_list_id)
1134 : : {
1135 : : union gve_adminq_command cmd;
1136 : :
1137 : : memset(&cmd, 0, sizeof(cmd));
1138 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_UNREGISTER_PAGE_LIST);
1139 : 0 : cmd.unreg_page_list = (struct gve_adminq_unregister_page_list) {
1140 [ # # ]: 0 : .page_list_id = cpu_to_be32(page_list_id),
1141 : : };
1142 : :
1143 : 0 : return gve_adminq_execute_cmd(priv, &cmd);
1144 : : }
1145 : :
1146 [ # # ]: 0 : int gve_adminq_set_mtu(struct gve_priv *priv, u64 mtu)
1147 : : {
1148 : : union gve_adminq_command cmd;
1149 : :
1150 : : memset(&cmd, 0, sizeof(cmd));
1151 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_SET_DRIVER_PARAMETER);
1152 : 0 : cmd.set_driver_param = (struct gve_adminq_set_driver_parameter) {
1153 : : .parameter_type = cpu_to_be32(GVE_SET_PARAM_MTU),
1154 [ # # ]: 0 : .parameter_value = cpu_to_be64(mtu),
1155 : : };
1156 : :
1157 : 0 : return gve_adminq_execute_cmd(priv, &cmd);
1158 : : }
1159 : :
1160 [ # # ]: 0 : int gve_adminq_report_stats(struct gve_priv *priv, u64 stats_report_len,
1161 : : dma_addr_t stats_report_addr, u64 interval)
1162 : : {
1163 : : union gve_adminq_command cmd;
1164 : :
1165 : : memset(&cmd, 0, sizeof(cmd));
1166 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_REPORT_STATS);
1167 : 0 : cmd.report_stats = (struct gve_adminq_report_stats) {
1168 [ # # ]: 0 : .stats_report_len = cpu_to_be64(stats_report_len),
1169 [ # # ]: 0 : .stats_report_addr = cpu_to_be64(stats_report_addr),
1170 [ # # ]: 0 : .interval = cpu_to_be64(interval),
1171 : : };
1172 : :
1173 : 0 : return gve_adminq_execute_cmd(priv, &cmd);
1174 : : }
1175 : :
1176 : 0 : int gve_adminq_report_link_speed(struct gve_priv *priv)
1177 : : {
1178 : : struct gve_dma_mem link_speed_region_dma_mem;
1179 : : union gve_adminq_command gvnic_cmd;
1180 : : u64 *link_speed_region;
1181 : : int err;
1182 : :
1183 : 0 : link_speed_region = gve_alloc_dma_mem(&link_speed_region_dma_mem,
1184 : : sizeof(*link_speed_region));
1185 : :
1186 [ # # ]: 0 : if (!link_speed_region)
1187 : : return -ENOMEM;
1188 : :
1189 : : memset(&gvnic_cmd, 0, sizeof(gvnic_cmd));
1190 : 0 : gvnic_cmd.opcode = cpu_to_be32(GVE_ADMINQ_REPORT_LINK_SPEED);
1191 : 0 : gvnic_cmd.report_link_speed.link_speed_address =
1192 [ # # ]: 0 : cpu_to_be64(link_speed_region_dma_mem.pa);
1193 : :
1194 : 0 : err = gve_adminq_execute_cmd(priv, &gvnic_cmd);
1195 : :
1196 [ # # ]: 0 : priv->link_speed = be64_to_cpu(*link_speed_region);
1197 : 0 : gve_free_dma_mem(&link_speed_region_dma_mem);
1198 : 0 : return err;
1199 : : }
1200 : :
1201 : 0 : int gve_adminq_get_ptype_map_dqo(struct gve_priv *priv,
1202 : : struct gve_ptype_lut *ptype_lut)
1203 : : {
1204 : : struct gve_dma_mem ptype_map_dma_mem;
1205 : : struct gve_ptype_map *ptype_map;
1206 : : union gve_adminq_command cmd;
1207 : : int err = 0;
1208 : : int i;
1209 : :
1210 : : memset(&cmd, 0, sizeof(cmd));
1211 : 0 : ptype_map = gve_alloc_dma_mem(&ptype_map_dma_mem, sizeof(*ptype_map));
1212 [ # # ]: 0 : if (!ptype_map)
1213 : : return -ENOMEM;
1214 : :
1215 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_GET_PTYPE_MAP);
1216 : 0 : cmd.get_ptype_map = (struct gve_adminq_get_ptype_map) {
1217 : : .ptype_map_len = cpu_to_be64(sizeof(*ptype_map)),
1218 [ # # ]: 0 : .ptype_map_addr = cpu_to_be64(ptype_map_dma_mem.pa),
1219 : : };
1220 : :
1221 : 0 : err = gve_adminq_execute_cmd(priv, &cmd);
1222 [ # # ]: 0 : if (err)
1223 : 0 : goto err;
1224 : :
1225 : : /* Populate ptype_lut. */
1226 [ # # ]: 0 : for (i = 0; i < GVE_NUM_PTYPES; i++) {
1227 : 0 : ptype_lut->ptypes[i].l3_type =
1228 : 0 : ptype_map->ptypes[i].l3_type;
1229 : 0 : ptype_lut->ptypes[i].l4_type =
1230 : 0 : ptype_map->ptypes[i].l4_type;
1231 : : }
1232 : 0 : err:
1233 : 0 : gve_free_dma_mem(&ptype_map_dma_mem);
1234 : 0 : return err;
1235 : : }
1236 : :
1237 : 0 : int gve_adminq_configure_rss(struct gve_priv *priv,
1238 : : struct gve_rss_config *rss_config)
1239 : : {
1240 : : struct gve_dma_mem indirection_table_dma_mem;
1241 : : struct gve_dma_mem rss_key_dma_mem;
1242 : : union gve_adminq_command cmd;
1243 : : __be32 *indir = NULL;
1244 : : u8 *key = NULL;
1245 : : int err = 0;
1246 : : int i;
1247 : :
1248 [ # # # # ]: 0 : if (!rss_config->indir_size || !rss_config->key_size)
1249 : : return -EINVAL;
1250 : :
1251 : 0 : indir = gve_alloc_dma_mem(&indirection_table_dma_mem,
1252 : 0 : rss_config->indir_size *
1253 : : sizeof(*rss_config->indir));
1254 [ # # ]: 0 : if (!indir) {
1255 : : err = -ENOMEM;
1256 : 0 : goto out;
1257 : : }
1258 [ # # ]: 0 : for (i = 0; i < rss_config->indir_size; i++)
1259 [ # # ]: 0 : indir[i] = cpu_to_be32(rss_config->indir[i]);
1260 : :
1261 : 0 : key = gve_alloc_dma_mem(&rss_key_dma_mem,
1262 : 0 : rss_config->key_size *
1263 : : sizeof(*rss_config->key));
1264 [ # # ]: 0 : if (!key) {
1265 : : err = -ENOMEM;
1266 : 0 : goto out;
1267 : : }
1268 [ # # ]: 0 : memcpy(key, rss_config->key, rss_config->key_size);
1269 : :
1270 : : memset(&cmd, 0, sizeof(cmd));
1271 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_CONFIGURE_RSS);
1272 : 0 : cmd.configure_rss = (struct gve_adminq_configure_rss) {
1273 [ # # ]: 0 : .hash_types = cpu_to_be16(rss_config->hash_types),
1274 : 0 : .halg = rss_config->alg,
1275 [ # # ]: 0 : .hkey_len = cpu_to_be16(rss_config->key_size),
1276 [ # # ]: 0 : .indir_len = cpu_to_be16(rss_config->indir_size),
1277 [ # # ]: 0 : .hkey_addr = cpu_to_be64(rss_key_dma_mem.pa),
1278 [ # # ]: 0 : .indir_addr = cpu_to_be64(indirection_table_dma_mem.pa),
1279 : : };
1280 : :
1281 : 0 : err = gve_adminq_execute_cmd(priv, &cmd);
1282 : :
1283 : 0 : out:
1284 [ # # ]: 0 : if (indir)
1285 : 0 : gve_free_dma_mem(&indirection_table_dma_mem);
1286 [ # # ]: 0 : if (key)
1287 : 0 : gve_free_dma_mem(&rss_key_dma_mem);
1288 : : return err;
1289 : : }
|