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_admin_queue_ok(priv);
280 : 0 : }
281 : :
282 [ # # ]: 0 : void gve_adminq_free(struct gve_priv *priv)
283 : : {
284 [ # # ]: 0 : if (!gve_get_admin_queue_ok(priv))
285 : : return;
286 : 0 : gve_adminq_release(priv);
287 : 0 : gve_free_dma_mem(&priv->adminq_dma_mem);
288 : : gve_clear_admin_queue_ok(priv);
289 : : }
290 : :
291 : : static void gve_adminq_kick_cmd(struct gve_priv *priv, u32 prod_cnt)
292 : : {
293 : 0 : iowrite32be(prod_cnt, &priv->reg_bar0->adminq_doorbell);
294 : 0 : }
295 : :
296 : : static bool gve_adminq_wait_for_cmd(struct gve_priv *priv, u32 prod_cnt)
297 : : {
298 : : int i;
299 : :
300 [ # # ]: 0 : for (i = 0; i < GVE_MAX_ADMINQ_EVENT_COUNTER_CHECK; i++) {
301 [ # # ]: 0 : if (ioread32be(&priv->reg_bar0->adminq_event_counter)
302 : : == prod_cnt)
303 : : return true;
304 : : msleep(GVE_ADMINQ_SLEEP_LEN);
305 : : }
306 : :
307 : : return false;
308 : : }
309 : :
310 : 0 : static int gve_adminq_parse_err(struct gve_priv *priv, u32 status)
311 : : {
312 [ # # ]: 0 : if (status != GVE_ADMINQ_COMMAND_PASSED &&
313 : : status != GVE_ADMINQ_COMMAND_UNSET) {
314 : 0 : PMD_DRV_LOG(ERR, "AQ command failed with status %d", status);
315 : 0 : priv->adminq_cmd_fail++;
316 : : }
317 [ # # # # : 0 : switch (status) {
# # # #
# ]
318 : : case GVE_ADMINQ_COMMAND_PASSED:
319 : : return 0;
320 : 0 : case GVE_ADMINQ_COMMAND_UNSET:
321 : 0 : PMD_DRV_LOG(ERR, "parse_aq_err: err and status both unset, this should not be possible.");
322 : 0 : return -EINVAL;
323 : 0 : case GVE_ADMINQ_COMMAND_ERROR_ABORTED:
324 : : case GVE_ADMINQ_COMMAND_ERROR_CANCELLED:
325 : : case GVE_ADMINQ_COMMAND_ERROR_DATALOSS:
326 : : case GVE_ADMINQ_COMMAND_ERROR_FAILED_PRECONDITION:
327 : : case GVE_ADMINQ_COMMAND_ERROR_UNAVAILABLE:
328 : 0 : return -EAGAIN;
329 : 0 : case GVE_ADMINQ_COMMAND_ERROR_ALREADY_EXISTS:
330 : : case GVE_ADMINQ_COMMAND_ERROR_INTERNAL_ERROR:
331 : : case GVE_ADMINQ_COMMAND_ERROR_INVALID_ARGUMENT:
332 : : case GVE_ADMINQ_COMMAND_ERROR_NOT_FOUND:
333 : : case GVE_ADMINQ_COMMAND_ERROR_OUT_OF_RANGE:
334 : : case GVE_ADMINQ_COMMAND_ERROR_UNKNOWN_ERROR:
335 : 0 : return -EINVAL;
336 : 0 : case GVE_ADMINQ_COMMAND_ERROR_DEADLINE_EXCEEDED:
337 : 0 : return -ETIMEDOUT;
338 : 0 : case GVE_ADMINQ_COMMAND_ERROR_PERMISSION_DENIED:
339 : : case GVE_ADMINQ_COMMAND_ERROR_UNAUTHENTICATED:
340 : 0 : return -EACCES;
341 : 0 : case GVE_ADMINQ_COMMAND_ERROR_RESOURCE_EXHAUSTED:
342 : 0 : return -ENOMEM;
343 : 0 : case GVE_ADMINQ_COMMAND_ERROR_UNIMPLEMENTED:
344 : 0 : return -ENOTSUP;
345 : 0 : default:
346 : 0 : PMD_DRV_LOG(ERR, "parse_aq_err: unknown status code %d",
347 : : status);
348 : 0 : return -EINVAL;
349 : : }
350 : : }
351 : :
352 : : /* Flushes all AQ commands currently queued and waits for them to complete.
353 : : * If there are failures, it will return the first error.
354 : : */
355 : 0 : static int gve_adminq_kick_and_wait(struct gve_priv *priv)
356 : : {
357 : : u32 tail, head;
358 : : u32 i;
359 : :
360 : 0 : tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
361 [ # # ]: 0 : head = priv->adminq_prod_cnt;
362 : :
363 : : gve_adminq_kick_cmd(priv, head);
364 [ # # ]: 0 : if (!gve_adminq_wait_for_cmd(priv, head)) {
365 : 0 : PMD_DRV_LOG(ERR, "AQ commands timed out, need to reset AQ");
366 : 0 : priv->adminq_timeouts++;
367 : 0 : return -ENOTRECOVERABLE;
368 : : }
369 : :
370 [ # # ]: 0 : for (i = tail; i < head; i++) {
371 : : union gve_adminq_command *cmd;
372 : : u32 status, err;
373 : :
374 : 0 : cmd = &priv->adminq[i & priv->adminq_mask];
375 : : status = be32_to_cpu(READ_ONCE32(cmd->status));
376 : 0 : err = gve_adminq_parse_err(priv, status);
377 [ # # ]: 0 : if (err)
378 : : /* Return the first error if we failed. */
379 : 0 : return err;
380 : : }
381 : :
382 : : return 0;
383 : : }
384 : :
385 : : /* This function is not threadsafe - the caller is responsible for any
386 : : * necessary locks.
387 : : */
388 : 0 : static int gve_adminq_issue_cmd(struct gve_priv *priv,
389 : : union gve_adminq_command *cmd_orig)
390 : : {
391 : : union gve_adminq_command *cmd;
392 : : u32 opcode;
393 : : u32 tail;
394 : :
395 : 0 : tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
396 : :
397 : : /* Check if next command will overflow the buffer. */
398 [ # # ]: 0 : if (((priv->adminq_prod_cnt + 1) & priv->adminq_mask) ==
399 : : (tail & priv->adminq_mask)) {
400 : : int err;
401 : :
402 : : /* Flush existing commands to make room. */
403 : 0 : err = gve_adminq_kick_and_wait(priv);
404 [ # # ]: 0 : if (err)
405 : : return err;
406 : :
407 : : /* Retry. */
408 : 0 : tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
409 [ # # ]: 0 : if (((priv->adminq_prod_cnt + 1) & priv->adminq_mask) ==
410 : : (tail & priv->adminq_mask)) {
411 : : /* This should never happen. We just flushed the
412 : : * command queue so there should be enough space.
413 : : */
414 : : return -ENOMEM;
415 : : }
416 : : }
417 : :
418 : 0 : cmd = &priv->adminq[priv->adminq_prod_cnt & priv->adminq_mask];
419 : 0 : priv->adminq_prod_cnt++;
420 : :
421 : : memcpy(cmd, cmd_orig, sizeof(*cmd_orig));
422 : : opcode = be32_to_cpu(READ_ONCE32(cmd->opcode));
423 : :
424 [ # # # # : 0 : switch (opcode) {
# # # # #
# # # # #
# # ]
425 : 0 : case GVE_ADMINQ_DESCRIBE_DEVICE:
426 : 0 : priv->adminq_describe_device_cnt++;
427 : 0 : break;
428 : 0 : case GVE_ADMINQ_CONFIGURE_DEVICE_RESOURCES:
429 : 0 : priv->adminq_cfg_device_resources_cnt++;
430 : 0 : break;
431 : 0 : case GVE_ADMINQ_REGISTER_PAGE_LIST:
432 : 0 : priv->adminq_register_page_list_cnt++;
433 : 0 : break;
434 : 0 : case GVE_ADMINQ_UNREGISTER_PAGE_LIST:
435 : 0 : priv->adminq_unregister_page_list_cnt++;
436 : 0 : break;
437 : 0 : case GVE_ADMINQ_CREATE_TX_QUEUE:
438 : 0 : priv->adminq_create_tx_queue_cnt++;
439 : 0 : break;
440 : 0 : case GVE_ADMINQ_CREATE_RX_QUEUE:
441 : 0 : priv->adminq_create_rx_queue_cnt++;
442 : 0 : break;
443 : 0 : case GVE_ADMINQ_DESTROY_TX_QUEUE:
444 : 0 : priv->adminq_destroy_tx_queue_cnt++;
445 : 0 : break;
446 : 0 : case GVE_ADMINQ_DESTROY_RX_QUEUE:
447 : 0 : priv->adminq_destroy_rx_queue_cnt++;
448 : 0 : break;
449 : 0 : case GVE_ADMINQ_DECONFIGURE_DEVICE_RESOURCES:
450 : 0 : priv->adminq_dcfg_device_resources_cnt++;
451 : 0 : break;
452 : 0 : case GVE_ADMINQ_CONFIGURE_RSS:
453 : 0 : priv->adminq_cfg_rss_cnt++;
454 : 0 : break;
455 : 0 : case GVE_ADMINQ_SET_DRIVER_PARAMETER:
456 : 0 : priv->adminq_set_driver_parameter_cnt++;
457 : 0 : break;
458 : 0 : case GVE_ADMINQ_REPORT_STATS:
459 : 0 : priv->adminq_report_stats_cnt++;
460 : 0 : break;
461 : 0 : case GVE_ADMINQ_REPORT_LINK_SPEED:
462 : 0 : priv->adminq_report_link_speed_cnt++;
463 : 0 : break;
464 : 0 : case GVE_ADMINQ_GET_PTYPE_MAP:
465 : 0 : priv->adminq_get_ptype_map_cnt++;
466 : 0 : break;
467 : 0 : case GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY:
468 : 0 : priv->adminq_verify_driver_compatibility_cnt++;
469 : 0 : break;
470 : 0 : default:
471 : 0 : PMD_DRV_LOG(ERR, "unknown AQ command opcode %d", opcode);
472 : : }
473 : :
474 : : return 0;
475 : : }
476 : :
477 : : /* This function is not threadsafe - the caller is responsible for any
478 : : * necessary locks.
479 : : * The caller is also responsible for making sure there are no commands
480 : : * waiting to be executed.
481 : : */
482 : 0 : static int gve_adminq_execute_cmd(struct gve_priv *priv,
483 : : union gve_adminq_command *cmd_orig)
484 : : {
485 : : u32 tail, head;
486 : : int err;
487 : :
488 : 0 : tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
489 : 0 : head = priv->adminq_prod_cnt;
490 [ # # ]: 0 : if (tail != head)
491 : : /* This is not a valid path */
492 : : return -EINVAL;
493 : :
494 : 0 : err = gve_adminq_issue_cmd(priv, cmd_orig);
495 [ # # ]: 0 : if (err)
496 : : return err;
497 : :
498 : 0 : return gve_adminq_kick_and_wait(priv);
499 : : }
500 : :
501 : : /* The device specifies that the management vector can either be the first irq
502 : : * or the last irq. ntfy_blk_msix_base_idx indicates the first irq assigned to
503 : : * the ntfy blks. It if is 0 then the management vector is last, if it is 1 then
504 : : * the management vector is first.
505 : : *
506 : : * gve arranges the msix vectors so that the management vector is last.
507 : : */
508 : : #define GVE_NTFY_BLK_BASE_MSIX_IDX 0
509 [ # # ]: 0 : int gve_adminq_configure_device_resources(struct gve_priv *priv,
510 : : dma_addr_t counter_array_bus_addr,
511 : : u32 num_counters,
512 : : dma_addr_t db_array_bus_addr,
513 : : u32 num_ntfy_blks)
514 : : {
515 : : union gve_adminq_command cmd;
516 : :
517 : : memset(&cmd, 0, sizeof(cmd));
518 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_CONFIGURE_DEVICE_RESOURCES);
519 : 0 : cmd.configure_device_resources =
520 : : (struct gve_adminq_configure_device_resources) {
521 [ # # ]: 0 : .counter_array = cpu_to_be64(counter_array_bus_addr),
522 [ # # ]: 0 : .num_counters = cpu_to_be32(num_counters),
523 [ # # ]: 0 : .irq_db_addr = cpu_to_be64(db_array_bus_addr),
524 [ # # ]: 0 : .num_irq_dbs = cpu_to_be32(num_ntfy_blks),
525 : : .irq_db_stride = cpu_to_be32(sizeof(*priv->irq_dbs)),
526 : : .ntfy_blk_msix_base_idx =
527 : : cpu_to_be32(GVE_NTFY_BLK_BASE_MSIX_IDX),
528 : 0 : .queue_format = priv->queue_format,
529 : : };
530 : :
531 : 0 : return gve_adminq_execute_cmd(priv, &cmd);
532 : : }
533 : :
534 [ # # ]: 0 : int gve_adminq_verify_driver_compatibility(struct gve_priv *priv,
535 : : u64 driver_info_len,
536 : : dma_addr_t driver_info_addr)
537 : : {
538 : : union gve_adminq_command cmd;
539 : :
540 : : memset(&cmd, 0, sizeof(cmd));
541 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY);
542 : 0 : cmd.verify_driver_compatibility = (struct gve_adminq_verify_driver_compatibility) {
543 [ # # ]: 0 : .driver_info_len = cpu_to_be64(driver_info_len),
544 [ # # ]: 0 : .driver_info_addr = cpu_to_be64(driver_info_addr),
545 : : };
546 : :
547 : 0 : return gve_adminq_execute_cmd(priv, &cmd);
548 : : }
549 : :
550 : 0 : int gve_adminq_deconfigure_device_resources(struct gve_priv *priv)
551 : : {
552 : : union gve_adminq_command cmd;
553 : :
554 : : memset(&cmd, 0, sizeof(cmd));
555 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_DECONFIGURE_DEVICE_RESOURCES);
556 : :
557 : 0 : return gve_adminq_execute_cmd(priv, &cmd);
558 : : }
559 : :
560 : 0 : static int gve_adminq_create_tx_queue(struct gve_priv *priv, u32 queue_index)
561 : : {
562 [ # # ]: 0 : struct gve_tx_queue *txq = priv->txqs[queue_index];
563 : : union gve_adminq_command cmd;
564 : :
565 : : memset(&cmd, 0, sizeof(cmd));
566 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_CREATE_TX_QUEUE);
567 [ # # ]: 0 : cmd.create_tx_queue = (struct gve_adminq_create_tx_queue) {
568 [ # # ]: 0 : .queue_id = cpu_to_be32(queue_index),
569 : : .queue_resources_addr =
570 [ # # ]: 0 : cpu_to_be64(txq->qres_mz->iova),
571 [ # # ]: 0 : .tx_ring_addr = cpu_to_be64(txq->tx_ring_phys_addr),
572 [ # # ]: 0 : .ntfy_id = cpu_to_be32(txq->ntfy_id),
573 [ # # ]: 0 : .tx_ring_size = cpu_to_be16(txq->nb_tx_desc),
574 : : };
575 : :
576 [ # # ]: 0 : if (gve_is_gqi(priv)) {
577 : : u32 qpl_id = priv->queue_format == GVE_GQI_RDA_FORMAT ?
578 [ # # ]: 0 : GVE_RAW_ADDRESSING_QPL_ID : txq->qpl->id;
579 : :
580 [ # # ]: 0 : cmd.create_tx_queue.queue_page_list_id = cpu_to_be32(qpl_id);
581 : : } else {
582 : 0 : cmd.create_tx_queue.tx_comp_ring_addr =
583 [ # # ]: 0 : cpu_to_be64(txq->compl_ring_phys_addr);
584 : 0 : cmd.create_tx_queue.tx_comp_ring_size =
585 [ # # ]: 0 : cpu_to_be16(txq->nb_complq_desc);
586 : : }
587 : :
588 : 0 : return gve_adminq_issue_cmd(priv, &cmd);
589 : : }
590 : :
591 : 0 : int gve_adminq_create_tx_queues(struct gve_priv *priv, u32 num_queues)
592 : : {
593 : : int err;
594 : : u32 i;
595 : :
596 [ # # ]: 0 : for (i = 0; i < num_queues; i++) {
597 : 0 : err = gve_adminq_create_tx_queue(priv, i);
598 [ # # ]: 0 : if (err)
599 : 0 : return err;
600 : : }
601 : :
602 : 0 : return gve_adminq_kick_and_wait(priv);
603 : : }
604 : :
605 : 0 : static int gve_adminq_create_rx_queue(struct gve_priv *priv, u32 queue_index)
606 : : {
607 [ # # ]: 0 : struct gve_rx_queue *rxq = priv->rxqs[queue_index];
608 : : union gve_adminq_command cmd;
609 : :
610 : : memset(&cmd, 0, sizeof(cmd));
611 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_CREATE_RX_QUEUE);
612 [ # # ]: 0 : cmd.create_rx_queue = (struct gve_adminq_create_rx_queue) {
613 [ # # ]: 0 : .queue_id = cpu_to_be32(queue_index),
614 [ # # ]: 0 : .ntfy_id = cpu_to_be32(rxq->ntfy_id),
615 [ # # ]: 0 : .queue_resources_addr = cpu_to_be64(rxq->qres_mz->iova),
616 [ # # ]: 0 : .rx_ring_size = cpu_to_be16(rxq->nb_rx_desc),
617 : : };
618 : :
619 [ # # ]: 0 : if (gve_is_gqi(priv)) {
620 : : u32 qpl_id = priv->queue_format == GVE_GQI_RDA_FORMAT ?
621 [ # # ]: 0 : GVE_RAW_ADDRESSING_QPL_ID : rxq->qpl->id;
622 : :
623 : 0 : cmd.create_rx_queue.rx_desc_ring_addr =
624 [ # # ]: 0 : cpu_to_be64(rxq->mz->iova),
625 : 0 : cmd.create_rx_queue.rx_data_ring_addr =
626 [ # # ]: 0 : cpu_to_be64(rxq->data_mz->iova),
627 [ # # ]: 0 : cmd.create_rx_queue.index = cpu_to_be32(queue_index);
628 [ # # ]: 0 : cmd.create_rx_queue.queue_page_list_id = cpu_to_be32(qpl_id);
629 [ # # ]: 0 : cmd.create_rx_queue.packet_buffer_size = cpu_to_be16(rxq->rx_buf_len);
630 : : } else {
631 : 0 : cmd.create_rx_queue.rx_desc_ring_addr =
632 [ # # ]: 0 : cpu_to_be64(rxq->compl_ring_phys_addr);
633 : 0 : cmd.create_rx_queue.rx_data_ring_addr =
634 [ # # ]: 0 : cpu_to_be64(rxq->rx_ring_phys_addr);
635 : 0 : cmd.create_rx_queue.packet_buffer_size =
636 [ # # ]: 0 : cpu_to_be16(rxq->rx_buf_len);
637 : 0 : cmd.create_rx_queue.rx_buff_ring_size =
638 [ # # ]: 0 : cpu_to_be16(rxq->nb_rx_desc);
639 : 0 : cmd.create_rx_queue.enable_rsc = !!(priv->enable_rsc);
640 : : }
641 : :
642 : 0 : return gve_adminq_issue_cmd(priv, &cmd);
643 : : }
644 : :
645 : 0 : int gve_adminq_create_rx_queues(struct gve_priv *priv, u32 num_queues)
646 : : {
647 : : int err;
648 : : u32 i;
649 : :
650 [ # # ]: 0 : for (i = 0; i < num_queues; i++) {
651 : 0 : err = gve_adminq_create_rx_queue(priv, i);
652 [ # # ]: 0 : if (err)
653 : 0 : return err;
654 : : }
655 : :
656 : 0 : return gve_adminq_kick_and_wait(priv);
657 : : }
658 : :
659 [ # # ]: 0 : static int gve_adminq_destroy_tx_queue(struct gve_priv *priv, u32 queue_index)
660 : : {
661 : : union gve_adminq_command cmd;
662 : : int err;
663 : :
664 : : memset(&cmd, 0, sizeof(cmd));
665 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_DESTROY_TX_QUEUE);
666 : 0 : cmd.destroy_tx_queue = (struct gve_adminq_destroy_tx_queue) {
667 [ # # ]: 0 : .queue_id = cpu_to_be32(queue_index),
668 : : };
669 : :
670 : 0 : err = gve_adminq_issue_cmd(priv, &cmd);
671 [ # # ]: 0 : if (err)
672 : 0 : return err;
673 : :
674 : : return 0;
675 : : }
676 : :
677 : 0 : int gve_adminq_destroy_tx_queues(struct gve_priv *priv, u32 num_queues)
678 : : {
679 : : int err;
680 : : u32 i;
681 : :
682 [ # # ]: 0 : for (i = 0; i < num_queues; i++) {
683 : 0 : err = gve_adminq_destroy_tx_queue(priv, i);
684 [ # # ]: 0 : if (err)
685 : 0 : return err;
686 : : }
687 : :
688 : 0 : return gve_adminq_kick_and_wait(priv);
689 : : }
690 : :
691 [ # # ]: 0 : static int gve_adminq_destroy_rx_queue(struct gve_priv *priv, u32 queue_index)
692 : : {
693 : : union gve_adminq_command cmd;
694 : : int err;
695 : :
696 : : memset(&cmd, 0, sizeof(cmd));
697 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_DESTROY_RX_QUEUE);
698 : 0 : cmd.destroy_rx_queue = (struct gve_adminq_destroy_rx_queue) {
699 [ # # ]: 0 : .queue_id = cpu_to_be32(queue_index),
700 : : };
701 : :
702 : 0 : err = gve_adminq_issue_cmd(priv, &cmd);
703 [ # # ]: 0 : if (err)
704 : 0 : return err;
705 : :
706 : : return 0;
707 : : }
708 : :
709 : 0 : int gve_adminq_destroy_rx_queues(struct gve_priv *priv, u32 num_queues)
710 : : {
711 : : int err;
712 : : u32 i;
713 : :
714 [ # # ]: 0 : for (i = 0; i < num_queues; i++) {
715 : 0 : err = gve_adminq_destroy_rx_queue(priv, i);
716 [ # # ]: 0 : if (err)
717 : 0 : return err;
718 : : }
719 : :
720 : 0 : return gve_adminq_kick_and_wait(priv);
721 : : }
722 : :
723 : 0 : static int gve_set_desc_cnt(struct gve_priv *priv,
724 : : struct gve_device_descriptor *descriptor)
725 : : {
726 [ # # ]: 0 : priv->default_tx_desc_cnt = be16_to_cpu(descriptor->tx_queue_entries);
727 [ # # ]: 0 : if (priv->default_tx_desc_cnt * sizeof(priv->txqs[0]->tx_desc_ring[0])
728 : : < PAGE_SIZE) {
729 : 0 : PMD_DRV_LOG(ERR, "Tx desc count %d too low",
730 : : priv->default_tx_desc_cnt);
731 : 0 : return -EINVAL;
732 : : }
733 [ # # ]: 0 : priv->default_rx_desc_cnt = be16_to_cpu(descriptor->rx_queue_entries);
734 [ # # ]: 0 : if (priv->default_rx_desc_cnt * sizeof(priv->rxqs[0]->rx_desc_ring[0])
735 : : < PAGE_SIZE) {
736 : 0 : PMD_DRV_LOG(ERR, "Rx desc count %d too low", priv->default_rx_desc_cnt);
737 : 0 : return -EINVAL;
738 : : }
739 : : return 0;
740 : : }
741 : :
742 : : static int
743 : 0 : gve_set_desc_cnt_dqo(struct gve_priv *priv,
744 : : const struct gve_device_descriptor *descriptor,
745 : : const struct gve_device_option_dqo_rda *dev_op_dqo_rda)
746 : : {
747 [ # # ]: 0 : priv->default_tx_desc_cnt = be16_to_cpu(descriptor->tx_queue_entries);
748 [ # # ]: 0 : priv->tx_compq_size = be16_to_cpu(dev_op_dqo_rda->tx_comp_ring_entries);
749 [ # # ]: 0 : priv->default_rx_desc_cnt = be16_to_cpu(descriptor->rx_queue_entries);
750 [ # # ]: 0 : priv->rx_bufq_size = be16_to_cpu(dev_op_dqo_rda->rx_buff_ring_entries);
751 : :
752 : 0 : return 0;
753 : : }
754 : :
755 : : static void
756 : : gve_set_min_desc_cnt(struct gve_priv *priv,
757 : : struct gve_device_option_modify_ring *modify_ring)
758 : : {
759 [ # # ]: 0 : priv->min_rx_desc_cnt = be16_to_cpu(modify_ring->min_ring_size.rx);
760 [ # # ]: 0 : priv->min_tx_desc_cnt = be16_to_cpu(modify_ring->min_ring_size.tx);
761 : 0 : }
762 : :
763 : : static void
764 : 0 : gve_set_max_desc_cnt(struct gve_priv *priv,
765 : : const struct gve_device_option_modify_ring *modify_ring)
766 : : {
767 [ # # ]: 0 : if (priv->queue_format == GVE_DQO_RDA_FORMAT) {
768 : 0 : PMD_DRV_LOG(DEBUG, "Overriding max ring size from device for DQ "
769 : : "queue format to 4096.");
770 : 0 : priv->max_rx_desc_cnt = GVE_MAX_QUEUE_SIZE_DQO;
771 : 0 : priv->max_tx_desc_cnt = GVE_MAX_QUEUE_SIZE_DQO;
772 : 0 : return;
773 : : }
774 [ # # ]: 0 : priv->max_rx_desc_cnt = be16_to_cpu(modify_ring->max_ring_size.rx);
775 [ # # ]: 0 : priv->max_tx_desc_cnt = be16_to_cpu(modify_ring->max_ring_size.tx);
776 : : }
777 : :
778 : 0 : static void gve_enable_supported_features(struct gve_priv *priv,
779 : : u32 supported_features_mask,
780 : : const struct gve_device_option_modify_ring *dev_op_modify_ring,
781 : : const struct gve_device_option_jumbo_frames *dev_op_jumbo_frames)
782 : : {
783 [ # # ]: 0 : if (dev_op_modify_ring &&
784 [ # # ]: 0 : (supported_features_mask & GVE_SUP_MODIFY_RING_MASK)) {
785 : 0 : PMD_DRV_LOG(INFO, "MODIFY RING device option enabled.");
786 : : /* Min ring size set separately by virtue of it being optional. */
787 : 0 : gve_set_max_desc_cnt(priv, dev_op_modify_ring);
788 : : }
789 : :
790 : : /* Before control reaches this point, the page-size-capped max MTU from
791 : : * the gve_device_descriptor field has already been stored in
792 : : * priv->dev->max_mtu. We overwrite it with the true max MTU below.
793 : : */
794 [ # # ]: 0 : if (dev_op_jumbo_frames &&
795 [ # # ]: 0 : (supported_features_mask & GVE_SUP_JUMBO_FRAMES_MASK)) {
796 : 0 : PMD_DRV_LOG(INFO, "JUMBO FRAMES device option enabled.");
797 [ # # ]: 0 : priv->max_mtu = be16_to_cpu(dev_op_jumbo_frames->max_mtu);
798 : : }
799 : 0 : }
800 : :
801 : 0 : int gve_adminq_describe_device(struct gve_priv *priv)
802 : : {
803 : 0 : struct gve_device_option_jumbo_frames *dev_op_jumbo_frames = NULL;
804 : 0 : struct gve_device_option_modify_ring *dev_op_modify_ring = NULL;
805 : 0 : struct gve_device_option_gqi_rda *dev_op_gqi_rda = NULL;
806 : 0 : struct gve_device_option_gqi_qpl *dev_op_gqi_qpl = NULL;
807 : 0 : struct gve_device_option_dqo_rda *dev_op_dqo_rda = NULL;
808 : : struct gve_device_descriptor *descriptor;
809 : : struct gve_dma_mem descriptor_dma_mem;
810 : : u32 supported_features_mask = 0;
811 : : union gve_adminq_command cmd;
812 : : int err = 0;
813 : : u16 mtu;
814 : :
815 : : memset(&cmd, 0, sizeof(cmd));
816 : 0 : descriptor = gve_alloc_dma_mem(&descriptor_dma_mem, PAGE_SIZE);
817 [ # # ]: 0 : if (!descriptor)
818 : : return -ENOMEM;
819 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_DESCRIBE_DEVICE);
820 : 0 : cmd.describe_device.device_descriptor_addr =
821 [ # # ]: 0 : cpu_to_be64(descriptor_dma_mem.pa);
822 : 0 : cmd.describe_device.device_descriptor_version =
823 : : cpu_to_be32(GVE_ADMINQ_DEVICE_DESCRIPTOR_VERSION);
824 : 0 : cmd.describe_device.available_length = cpu_to_be32(PAGE_SIZE);
825 : :
826 : 0 : err = gve_adminq_execute_cmd(priv, &cmd);
827 [ # # ]: 0 : if (err)
828 : 0 : goto free_device_descriptor;
829 : :
830 : 0 : err = gve_process_device_options(priv, descriptor, &dev_op_gqi_rda,
831 : : &dev_op_gqi_qpl, &dev_op_dqo_rda,
832 : : &dev_op_modify_ring,
833 : : &dev_op_jumbo_frames);
834 [ # # ]: 0 : if (err)
835 : 0 : goto free_device_descriptor;
836 : :
837 : : /* If the GQI_RAW_ADDRESSING option is not enabled and the queue format
838 : : * is not set to GqiRda, choose the queue format in a priority order:
839 : : * DqoRda, GqiRda, GqiQpl. Use GqiQpl as default.
840 : : */
841 [ # # ]: 0 : if (dev_op_dqo_rda) {
842 : 0 : priv->queue_format = GVE_DQO_RDA_FORMAT;
843 : 0 : PMD_DRV_LOG(INFO, "Driver is running with DQO RDA queue format.");
844 : : supported_features_mask =
845 [ # # ]: 0 : be32_to_cpu(dev_op_dqo_rda->supported_features_mask);
846 [ # # ]: 0 : } else if (dev_op_gqi_rda) {
847 : 0 : priv->queue_format = GVE_GQI_RDA_FORMAT;
848 : 0 : PMD_DRV_LOG(INFO, "Driver is running with GQI RDA queue format.");
849 : : supported_features_mask =
850 [ # # ]: 0 : be32_to_cpu(dev_op_gqi_rda->supported_features_mask);
851 [ # # ]: 0 : } else if (priv->queue_format == GVE_GQI_RDA_FORMAT) {
852 : 0 : PMD_DRV_LOG(INFO, "Driver is running with GQI RDA queue format.");
853 : : } else {
854 : 0 : priv->queue_format = GVE_GQI_QPL_FORMAT;
855 [ # # ]: 0 : if (dev_op_gqi_qpl)
856 : : supported_features_mask =
857 [ # # ]: 0 : be32_to_cpu(dev_op_gqi_qpl->supported_features_mask);
858 : 0 : PMD_DRV_LOG(INFO, "Driver is running with GQI QPL queue format.");
859 : : }
860 [ # # ]: 0 : if (gve_is_gqi(priv)) {
861 : 0 : err = gve_set_desc_cnt(priv, descriptor);
862 : : } else {
863 : : /* DQO supports LRO. */
864 : 0 : err = gve_set_desc_cnt_dqo(priv, descriptor, dev_op_dqo_rda);
865 : : }
866 [ # # ]: 0 : if (err)
867 : 0 : goto free_device_descriptor;
868 : :
869 : 0 : priv->max_registered_pages =
870 [ # # ]: 0 : be64_to_cpu(descriptor->max_registered_pages);
871 [ # # ]: 0 : mtu = be16_to_cpu(descriptor->mtu);
872 [ # # ]: 0 : if (mtu < ETH_MIN_MTU) {
873 : 0 : PMD_DRV_LOG(ERR, "MTU %d below minimum MTU", mtu);
874 : : err = -EINVAL;
875 : 0 : goto free_device_descriptor;
876 : : }
877 : 0 : priv->max_mtu = mtu;
878 [ # # ]: 0 : priv->num_event_counters = be16_to_cpu(descriptor->counters);
879 [ # # ]: 0 : rte_memcpy(priv->dev_addr.addr_bytes, descriptor->mac, ETH_ALEN);
880 : 0 : PMD_DRV_LOG(INFO, "MAC addr: " RTE_ETHER_ADDR_PRT_FMT,
881 : : RTE_ETHER_ADDR_BYTES(&priv->dev_addr));
882 [ # # ]: 0 : priv->tx_pages_per_qpl = be16_to_cpu(descriptor->tx_pages_per_qpl);
883 : :
884 [ # # ]: 0 : priv->default_num_queues = be16_to_cpu(descriptor->default_num_queues);
885 : :
886 : 0 : gve_enable_supported_features(priv, supported_features_mask,
887 : : dev_op_modify_ring,
888 : : dev_op_jumbo_frames);
889 : :
890 : 0 : free_device_descriptor:
891 : 0 : gve_free_dma_mem(&descriptor_dma_mem);
892 : 0 : return err;
893 : : }
894 : :
895 : 0 : int gve_adminq_register_page_list(struct gve_priv *priv,
896 : : struct gve_queue_page_list *qpl)
897 : : {
898 : : struct gve_dma_mem page_list_dma_mem;
899 : 0 : u32 num_entries = qpl->num_entries;
900 : 0 : u32 size = num_entries * sizeof(qpl->page_buses[0]);
901 : : union gve_adminq_command cmd;
902 : : __be64 *page_list;
903 : : int err;
904 : : u32 i;
905 : :
906 : : memset(&cmd, 0, sizeof(cmd));
907 : 0 : page_list = gve_alloc_dma_mem(&page_list_dma_mem, size);
908 [ # # ]: 0 : if (!page_list)
909 : : return -ENOMEM;
910 : :
911 [ # # ]: 0 : for (i = 0; i < num_entries; i++)
912 [ # # ]: 0 : page_list[i] = cpu_to_be64(qpl->page_buses[i]);
913 : :
914 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_REGISTER_PAGE_LIST);
915 : 0 : cmd.reg_page_list = (struct gve_adminq_register_page_list) {
916 [ # # ]: 0 : .page_list_id = cpu_to_be32(qpl->id),
917 [ # # ]: 0 : .num_pages = cpu_to_be32(num_entries),
918 [ # # ]: 0 : .page_address_list_addr = cpu_to_be64(page_list_dma_mem.pa),
919 : : };
920 : :
921 : 0 : err = gve_adminq_execute_cmd(priv, &cmd);
922 : 0 : gve_free_dma_mem(&page_list_dma_mem);
923 : 0 : return err;
924 : : }
925 : :
926 [ # # ]: 0 : int gve_adminq_unregister_page_list(struct gve_priv *priv, u32 page_list_id)
927 : : {
928 : : union gve_adminq_command cmd;
929 : :
930 : : memset(&cmd, 0, sizeof(cmd));
931 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_UNREGISTER_PAGE_LIST);
932 : 0 : cmd.unreg_page_list = (struct gve_adminq_unregister_page_list) {
933 [ # # ]: 0 : .page_list_id = cpu_to_be32(page_list_id),
934 : : };
935 : :
936 : 0 : return gve_adminq_execute_cmd(priv, &cmd);
937 : : }
938 : :
939 [ # # ]: 0 : int gve_adminq_set_mtu(struct gve_priv *priv, u64 mtu)
940 : : {
941 : : union gve_adminq_command cmd;
942 : :
943 : : memset(&cmd, 0, sizeof(cmd));
944 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_SET_DRIVER_PARAMETER);
945 : 0 : cmd.set_driver_param = (struct gve_adminq_set_driver_parameter) {
946 : : .parameter_type = cpu_to_be32(GVE_SET_PARAM_MTU),
947 [ # # ]: 0 : .parameter_value = cpu_to_be64(mtu),
948 : : };
949 : :
950 : 0 : return gve_adminq_execute_cmd(priv, &cmd);
951 : : }
952 : :
953 [ # # ]: 0 : int gve_adminq_report_stats(struct gve_priv *priv, u64 stats_report_len,
954 : : dma_addr_t stats_report_addr, u64 interval)
955 : : {
956 : : union gve_adminq_command cmd;
957 : :
958 : : memset(&cmd, 0, sizeof(cmd));
959 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_REPORT_STATS);
960 : 0 : cmd.report_stats = (struct gve_adminq_report_stats) {
961 [ # # ]: 0 : .stats_report_len = cpu_to_be64(stats_report_len),
962 [ # # ]: 0 : .stats_report_addr = cpu_to_be64(stats_report_addr),
963 [ # # ]: 0 : .interval = cpu_to_be64(interval),
964 : : };
965 : :
966 : 0 : return gve_adminq_execute_cmd(priv, &cmd);
967 : : }
968 : :
969 : 0 : int gve_adminq_report_link_speed(struct gve_priv *priv)
970 : : {
971 : : struct gve_dma_mem link_speed_region_dma_mem;
972 : : union gve_adminq_command gvnic_cmd;
973 : : u64 *link_speed_region;
974 : : int err;
975 : :
976 : 0 : link_speed_region = gve_alloc_dma_mem(&link_speed_region_dma_mem,
977 : : sizeof(*link_speed_region));
978 : :
979 [ # # ]: 0 : if (!link_speed_region)
980 : : return -ENOMEM;
981 : :
982 : : memset(&gvnic_cmd, 0, sizeof(gvnic_cmd));
983 : 0 : gvnic_cmd.opcode = cpu_to_be32(GVE_ADMINQ_REPORT_LINK_SPEED);
984 : 0 : gvnic_cmd.report_link_speed.link_speed_address =
985 [ # # ]: 0 : cpu_to_be64(link_speed_region_dma_mem.pa);
986 : :
987 : 0 : err = gve_adminq_execute_cmd(priv, &gvnic_cmd);
988 : :
989 [ # # ]: 0 : priv->link_speed = be64_to_cpu(*link_speed_region);
990 : 0 : gve_free_dma_mem(&link_speed_region_dma_mem);
991 : 0 : return err;
992 : : }
993 : :
994 : 0 : int gve_adminq_get_ptype_map_dqo(struct gve_priv *priv,
995 : : struct gve_ptype_lut *ptype_lut)
996 : : {
997 : : struct gve_dma_mem ptype_map_dma_mem;
998 : : struct gve_ptype_map *ptype_map;
999 : : union gve_adminq_command cmd;
1000 : : int err = 0;
1001 : : int i;
1002 : :
1003 : : memset(&cmd, 0, sizeof(cmd));
1004 : 0 : ptype_map = gve_alloc_dma_mem(&ptype_map_dma_mem, sizeof(*ptype_map));
1005 [ # # ]: 0 : if (!ptype_map)
1006 : : return -ENOMEM;
1007 : :
1008 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_GET_PTYPE_MAP);
1009 : 0 : cmd.get_ptype_map = (struct gve_adminq_get_ptype_map) {
1010 : : .ptype_map_len = cpu_to_be64(sizeof(*ptype_map)),
1011 [ # # ]: 0 : .ptype_map_addr = cpu_to_be64(ptype_map_dma_mem.pa),
1012 : : };
1013 : :
1014 : 0 : err = gve_adminq_execute_cmd(priv, &cmd);
1015 [ # # ]: 0 : if (err)
1016 : 0 : goto err;
1017 : :
1018 : : /* Populate ptype_lut. */
1019 [ # # ]: 0 : for (i = 0; i < GVE_NUM_PTYPES; i++) {
1020 : 0 : ptype_lut->ptypes[i].l3_type =
1021 : 0 : ptype_map->ptypes[i].l3_type;
1022 : 0 : ptype_lut->ptypes[i].l4_type =
1023 : 0 : ptype_map->ptypes[i].l4_type;
1024 : : }
1025 : 0 : err:
1026 : 0 : gve_free_dma_mem(&ptype_map_dma_mem);
1027 : 0 : return err;
1028 : : }
1029 : :
1030 : 0 : int gve_adminq_configure_rss(struct gve_priv *priv,
1031 : : struct gve_rss_config *rss_config)
1032 : : {
1033 : : struct gve_dma_mem indirection_table_dma_mem;
1034 : : struct gve_dma_mem rss_key_dma_mem;
1035 : : union gve_adminq_command cmd;
1036 : : __be32 *indir = NULL;
1037 : : u8 *key = NULL;
1038 : : int err = 0;
1039 : : int i;
1040 : :
1041 [ # # # # ]: 0 : if (!rss_config->indir_size || !rss_config->key_size)
1042 : : return -EINVAL;
1043 : :
1044 : 0 : indir = gve_alloc_dma_mem(&indirection_table_dma_mem,
1045 : 0 : rss_config->indir_size *
1046 : : sizeof(*rss_config->indir));
1047 [ # # ]: 0 : if (!indir) {
1048 : : err = -ENOMEM;
1049 : 0 : goto out;
1050 : : }
1051 [ # # ]: 0 : for (i = 0; i < rss_config->indir_size; i++)
1052 [ # # ]: 0 : indir[i] = cpu_to_be32(rss_config->indir[i]);
1053 : :
1054 : 0 : key = gve_alloc_dma_mem(&rss_key_dma_mem,
1055 : 0 : rss_config->key_size *
1056 : : sizeof(*rss_config->key));
1057 [ # # ]: 0 : if (!key) {
1058 : : err = -ENOMEM;
1059 : 0 : goto out;
1060 : : }
1061 [ # # ]: 0 : memcpy(key, rss_config->key, rss_config->key_size);
1062 : :
1063 : : memset(&cmd, 0, sizeof(cmd));
1064 : 0 : cmd.opcode = cpu_to_be32(GVE_ADMINQ_CONFIGURE_RSS);
1065 : 0 : cmd.configure_rss = (struct gve_adminq_configure_rss) {
1066 [ # # ]: 0 : .hash_types = cpu_to_be16(rss_config->hash_types),
1067 : 0 : .halg = rss_config->alg,
1068 [ # # ]: 0 : .hkey_len = cpu_to_be16(rss_config->key_size),
1069 [ # # ]: 0 : .indir_len = cpu_to_be16(rss_config->indir_size),
1070 [ # # ]: 0 : .hkey_addr = cpu_to_be64(rss_key_dma_mem.pa),
1071 [ # # ]: 0 : .indir_addr = cpu_to_be64(indirection_table_dma_mem.pa),
1072 : : };
1073 : :
1074 : 0 : err = gve_adminq_execute_cmd(priv, &cmd);
1075 : :
1076 : 0 : out:
1077 [ # # ]: 0 : if (indir)
1078 : 0 : gve_free_dma_mem(&indirection_table_dma_mem);
1079 [ # # ]: 0 : if (key)
1080 : 0 : gve_free_dma_mem(&rss_key_dma_mem);
1081 : : return err;
1082 : : }
1083 : :
|