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