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