Skip to content

Commit 5cdad90

Browse files
sagishahdavem330
authored andcommitted
gve: Batch AQ commands for creating and destroying queues.
Adds support for batching AQ commands and uses it for creating and destroying queues. Reviewed-by: Yangchun Fu <yangchun@google.com> Signed-off-by: Sagi Shahar <sagis@google.com> Signed-off-by: David Awogbemila <awogbemila@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 2f523dc commit 5cdad90

File tree

3 files changed

+211
-81
lines changed

3 files changed

+211
-81
lines changed

drivers/net/ethernet/google/gve/gve_adminq.c

Lines changed: 165 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -135,20 +135,71 @@ static int gve_adminq_parse_err(struct gve_priv *priv, u32 status)
135135
}
136136
}
137137

138+
/* Flushes all AQ commands currently queued and waits for them to complete.
139+
* If there are failures, it will return the first error.
140+
*/
141+
static int gve_adminq_kick_and_wait(struct gve_priv *priv)
142+
{
143+
u32 tail, head;
144+
int i;
145+
146+
tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
147+
head = priv->adminq_prod_cnt;
148+
149+
gve_adminq_kick_cmd(priv, head);
150+
if (!gve_adminq_wait_for_cmd(priv, head)) {
151+
dev_err(&priv->pdev->dev, "AQ commands timed out, need to reset AQ\n");
152+
priv->adminq_timeouts++;
153+
return -ENOTRECOVERABLE;
154+
}
155+
156+
for (i = tail; i < head; i++) {
157+
union gve_adminq_command *cmd;
158+
u32 status, err;
159+
160+
cmd = &priv->adminq[i & priv->adminq_mask];
161+
status = be32_to_cpu(READ_ONCE(cmd->status));
162+
err = gve_adminq_parse_err(priv, status);
163+
if (err)
164+
// Return the first error if we failed.
165+
return err;
166+
}
167+
168+
return 0;
169+
}
170+
138171
/* This function is not threadsafe - the caller is responsible for any
139172
* necessary locks.
140173
*/
141-
int gve_adminq_execute_cmd(struct gve_priv *priv,
142-
union gve_adminq_command *cmd_orig)
174+
static int gve_adminq_issue_cmd(struct gve_priv *priv,
175+
union gve_adminq_command *cmd_orig)
143176
{
144177
union gve_adminq_command *cmd;
145-
u32 status = 0;
146-
u32 prod_cnt;
147178
u32 opcode;
179+
u32 tail;
180+
181+
tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
182+
183+
// Check if next command will overflow the buffer.
184+
if (((priv->adminq_prod_cnt + 1) & priv->adminq_mask) == tail) {
185+
int err;
186+
187+
// Flush existing commands to make room.
188+
err = gve_adminq_kick_and_wait(priv);
189+
if (err)
190+
return err;
191+
192+
// Retry.
193+
tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
194+
if (((priv->adminq_prod_cnt + 1) & priv->adminq_mask) == tail) {
195+
// This should never happen. We just flushed the
196+
// command queue so there should be enough space.
197+
return -ENOMEM;
198+
}
199+
}
148200

149201
cmd = &priv->adminq[priv->adminq_prod_cnt & priv->adminq_mask];
150202
priv->adminq_prod_cnt++;
151-
prod_cnt = priv->adminq_prod_cnt;
152203

153204
memcpy(cmd, cmd_orig, sizeof(*cmd_orig));
154205
opcode = be32_to_cpu(READ_ONCE(cmd->opcode));
@@ -191,16 +242,30 @@ int gve_adminq_execute_cmd(struct gve_priv *priv,
191242
dev_err(&priv->pdev->dev, "unknown AQ command opcode %d\n", opcode);
192243
}
193244

194-
gve_adminq_kick_cmd(priv, prod_cnt);
195-
if (!gve_adminq_wait_for_cmd(priv, prod_cnt)) {
196-
dev_err(&priv->pdev->dev, "AQ command timed out, need to reset AQ\n");
197-
priv->adminq_timeouts++;
198-
return -ENOTRECOVERABLE;
199-
}
245+
return 0;
246+
}
200247

201-
memcpy(cmd_orig, cmd, sizeof(*cmd));
202-
status = be32_to_cpu(READ_ONCE(cmd->status));
203-
return gve_adminq_parse_err(priv, status);
248+
/* This function is not threadsafe - the caller is responsible for any
249+
* necessary locks.
250+
* The caller is also responsible for making sure there are no commands
251+
* waiting to be executed.
252+
*/
253+
static int gve_adminq_execute_cmd(struct gve_priv *priv, union gve_adminq_command *cmd_orig)
254+
{
255+
u32 tail, head;
256+
int err;
257+
258+
tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
259+
head = priv->adminq_prod_cnt;
260+
if (tail != head)
261+
// This is not a valid path
262+
return -EINVAL;
263+
264+
err = gve_adminq_issue_cmd(priv, cmd_orig);
265+
if (err)
266+
return err;
267+
268+
return gve_adminq_kick_and_wait(priv);
204269
}
205270

206271
/* The device specifies that the management vector can either be the first irq
@@ -245,29 +310,50 @@ int gve_adminq_deconfigure_device_resources(struct gve_priv *priv)
245310
return gve_adminq_execute_cmd(priv, &cmd);
246311
}
247312

248-
int gve_adminq_create_tx_queue(struct gve_priv *priv, u32 queue_index)
313+
static int gve_adminq_create_tx_queue(struct gve_priv *priv, u32 queue_index)
249314
{
250315
struct gve_tx_ring *tx = &priv->tx[queue_index];
251316
union gve_adminq_command cmd;
317+
int err;
252318

253319
memset(&cmd, 0, sizeof(cmd));
254320
cmd.opcode = cpu_to_be32(GVE_ADMINQ_CREATE_TX_QUEUE);
255321
cmd.create_tx_queue = (struct gve_adminq_create_tx_queue) {
256322
.queue_id = cpu_to_be32(queue_index),
257323
.reserved = 0,
258-
.queue_resources_addr = cpu_to_be64(tx->q_resources_bus),
324+
.queue_resources_addr =
325+
cpu_to_be64(tx->q_resources_bus),
259326
.tx_ring_addr = cpu_to_be64(tx->bus),
260327
.queue_page_list_id = cpu_to_be32(tx->tx_fifo.qpl->id),
261328
.ntfy_id = cpu_to_be32(tx->ntfy_id),
262329
};
263330

264-
return gve_adminq_execute_cmd(priv, &cmd);
331+
err = gve_adminq_issue_cmd(priv, &cmd);
332+
if (err)
333+
return err;
334+
335+
return 0;
265336
}
266337

267-
int gve_adminq_create_rx_queue(struct gve_priv *priv, u32 queue_index)
338+
int gve_adminq_create_tx_queues(struct gve_priv *priv, u32 num_queues)
339+
{
340+
int err;
341+
int i;
342+
343+
for (i = 0; i < num_queues; i++) {
344+
err = gve_adminq_create_tx_queue(priv, i);
345+
if (err)
346+
return err;
347+
}
348+
349+
return gve_adminq_kick_and_wait(priv);
350+
}
351+
352+
static int gve_adminq_create_rx_queue(struct gve_priv *priv, u32 queue_index)
268353
{
269354
struct gve_rx_ring *rx = &priv->rx[queue_index];
270355
union gve_adminq_command cmd;
356+
int err;
271357

272358
memset(&cmd, 0, sizeof(cmd));
273359
cmd.opcode = cpu_to_be32(GVE_ADMINQ_CREATE_RX_QUEUE);
@@ -282,33 +368,89 @@ int gve_adminq_create_rx_queue(struct gve_priv *priv, u32 queue_index)
282368
.queue_page_list_id = cpu_to_be32(rx->data.qpl->id),
283369
};
284370

285-
return gve_adminq_execute_cmd(priv, &cmd);
371+
err = gve_adminq_issue_cmd(priv, &cmd);
372+
if (err)
373+
return err;
374+
375+
return 0;
286376
}
287377

288-
int gve_adminq_destroy_tx_queue(struct gve_priv *priv, u32 queue_index)
378+
int gve_adminq_create_rx_queues(struct gve_priv *priv, u32 num_queues)
379+
{
380+
int err;
381+
int i;
382+
383+
for (i = 0; i < num_queues; i++) {
384+
err = gve_adminq_create_rx_queue(priv, i);
385+
if (err)
386+
return err;
387+
}
388+
389+
return gve_adminq_kick_and_wait(priv);
390+
}
391+
392+
static int gve_adminq_destroy_tx_queue(struct gve_priv *priv, u32 queue_index)
289393
{
290394
union gve_adminq_command cmd;
395+
int err;
291396

292397
memset(&cmd, 0, sizeof(cmd));
293398
cmd.opcode = cpu_to_be32(GVE_ADMINQ_DESTROY_TX_QUEUE);
294399
cmd.destroy_tx_queue = (struct gve_adminq_destroy_tx_queue) {
295400
.queue_id = cpu_to_be32(queue_index),
296401
};
297402

298-
return gve_adminq_execute_cmd(priv, &cmd);
403+
err = gve_adminq_issue_cmd(priv, &cmd);
404+
if (err)
405+
return err;
406+
407+
return 0;
299408
}
300409

301-
int gve_adminq_destroy_rx_queue(struct gve_priv *priv, u32 queue_index)
410+
int gve_adminq_destroy_tx_queues(struct gve_priv *priv, u32 num_queues)
411+
{
412+
int err;
413+
int i;
414+
415+
for (i = 0; i < num_queues; i++) {
416+
err = gve_adminq_destroy_tx_queue(priv, i);
417+
if (err)
418+
return err;
419+
}
420+
421+
return gve_adminq_kick_and_wait(priv);
422+
}
423+
424+
static int gve_adminq_destroy_rx_queue(struct gve_priv *priv, u32 queue_index)
302425
{
303426
union gve_adminq_command cmd;
427+
int err;
304428

305429
memset(&cmd, 0, sizeof(cmd));
306430
cmd.opcode = cpu_to_be32(GVE_ADMINQ_DESTROY_RX_QUEUE);
307431
cmd.destroy_rx_queue = (struct gve_adminq_destroy_rx_queue) {
308432
.queue_id = cpu_to_be32(queue_index),
309433
};
310434

311-
return gve_adminq_execute_cmd(priv, &cmd);
435+
err = gve_adminq_issue_cmd(priv, &cmd);
436+
if (err)
437+
return err;
438+
439+
return 0;
440+
}
441+
442+
int gve_adminq_destroy_rx_queues(struct gve_priv *priv, u32 num_queues)
443+
{
444+
int err;
445+
int i;
446+
447+
for (i = 0; i < num_queues; i++) {
448+
err = gve_adminq_destroy_rx_queue(priv, i);
449+
if (err)
450+
return err;
451+
}
452+
453+
return gve_adminq_kick_and_wait(priv);
312454
}
313455

314456
int gve_adminq_describe_device(struct gve_priv *priv)

drivers/net/ethernet/google/gve/gve_adminq.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -238,19 +238,17 @@ static_assert(sizeof(union gve_adminq_command) == 64);
238238
int gve_adminq_alloc(struct device *dev, struct gve_priv *priv);
239239
void gve_adminq_free(struct device *dev, struct gve_priv *priv);
240240
void gve_adminq_release(struct gve_priv *priv);
241-
int gve_adminq_execute_cmd(struct gve_priv *priv,
242-
union gve_adminq_command *cmd_orig);
243241
int gve_adminq_describe_device(struct gve_priv *priv);
244242
int gve_adminq_configure_device_resources(struct gve_priv *priv,
245243
dma_addr_t counter_array_bus_addr,
246244
u32 num_counters,
247245
dma_addr_t db_array_bus_addr,
248246
u32 num_ntfy_blks);
249247
int gve_adminq_deconfigure_device_resources(struct gve_priv *priv);
250-
int gve_adminq_create_tx_queue(struct gve_priv *priv, u32 queue_id);
251-
int gve_adminq_destroy_tx_queue(struct gve_priv *priv, u32 queue_id);
252-
int gve_adminq_create_rx_queue(struct gve_priv *priv, u32 queue_id);
253-
int gve_adminq_destroy_rx_queue(struct gve_priv *priv, u32 queue_id);
248+
int gve_adminq_create_tx_queues(struct gve_priv *priv, u32 num_queues);
249+
int gve_adminq_destroy_tx_queues(struct gve_priv *priv, u32 queue_id);
250+
int gve_adminq_create_rx_queues(struct gve_priv *priv, u32 num_queues);
251+
int gve_adminq_destroy_rx_queues(struct gve_priv *priv, u32 queue_id);
254252
int gve_adminq_register_page_list(struct gve_priv *priv,
255253
struct gve_queue_page_list *qpl);
256254
int gve_adminq_unregister_page_list(struct gve_priv *priv, u32 page_list_id);

0 commit comments

Comments
 (0)