Commit 2d0e7ba4 authored by Michael Margolin's avatar Michael Margolin Committed by Leon Romanovsky
Browse files

RDMA/efa: Properly handle unexpected AQ completions



Do not try to handle admin command completion if it has an unexpected
command id and print a relevant error message.

Reviewed-by: default avatarFiras Jahjah <firasj@amazon.com>
Reviewed-by: default avatarYehuda Yitschak <yehuday@amazon.com>
Signed-off-by: default avatarMichael Margolin <mrgolin@amazon.com>
Link: https://lore.kernel.org/r/20240513064630.6247-1-mrgolin@amazon.com


Reviewed-by: default avatarGal Pressman <gal.pressman@linux.dev>
Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
parent e095405b
Loading
Loading
Loading
Loading
+17 −13
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
/*
 * Copyright 2018-2021 Amazon.com, Inc. or its affiliates. All rights reserved.
 * Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All rights reserved.
 */

#include "efa_com.h"
@@ -406,7 +406,7 @@ static struct efa_comp_ctx *efa_com_submit_admin_cmd(struct efa_com_admin_queue
	return comp_ctx;
}

static void efa_com_handle_single_admin_completion(struct efa_com_admin_queue *aq,
static int efa_com_handle_single_admin_completion(struct efa_com_admin_queue *aq,
						  struct efa_admin_acq_entry *cqe)
{
	struct efa_comp_ctx *comp_ctx;
@@ -416,11 +416,11 @@ static void efa_com_handle_single_admin_completion(struct efa_com_admin_queue *a
			 EFA_ADMIN_ACQ_COMMON_DESC_COMMAND_ID);

	comp_ctx = efa_com_get_comp_ctx(aq, cmd_id, false);
	if (!comp_ctx) {
	if (comp_ctx->status != EFA_CMD_SUBMITTED) {
		ibdev_err(aq->efa_dev,
			  "comp_ctx is NULL. Changing the admin queue running state\n");
		clear_bit(EFA_AQ_STATE_RUNNING_BIT, &aq->state);
		return;
			  "Received completion with unexpected command id[%d], sq producer: %d, sq consumer: %d, cq consumer: %d\n",
			  cmd_id, aq->sq.pc, aq->sq.cc, aq->cq.cc);
		return -EINVAL;
	}

	comp_ctx->status = EFA_CMD_COMPLETED;
@@ -428,14 +428,17 @@ static void efa_com_handle_single_admin_completion(struct efa_com_admin_queue *a

	if (!test_bit(EFA_AQ_STATE_POLLING_BIT, &aq->state))
		complete(&comp_ctx->wait_event);

	return 0;
}

static void efa_com_handle_admin_completion(struct efa_com_admin_queue *aq)
{
	struct efa_admin_acq_entry *cqe;
	u16 queue_size_mask;
	u16 comp_num = 0;
	u16 comp_cmds = 0;
	u8 phase;
	int err;
	u16 ci;

	queue_size_mask = aq->depth - 1;
@@ -453,10 +456,12 @@ static void efa_com_handle_admin_completion(struct efa_com_admin_queue *aq)
		 * phase bit was validated
		 */
		dma_rmb();
		efa_com_handle_single_admin_completion(aq, cqe);
		err = efa_com_handle_single_admin_completion(aq, cqe);
		if (!err)
			comp_cmds++;

		aq->cq.cc++;
		ci++;
		comp_num++;
		if (ci == aq->depth) {
			ci = 0;
			phase = !phase;
@@ -465,10 +470,9 @@ static void efa_com_handle_admin_completion(struct efa_com_admin_queue *aq)
		cqe = &aq->cq.entries[ci];
	}

	aq->cq.cc += comp_num;
	aq->cq.phase = phase;
	aq->sq.cc += comp_num;
	atomic64_add(comp_num, &aq->stats.completed_cmd);
	aq->sq.cc += comp_cmds;
	atomic64_add(comp_cmds, &aq->stats.completed_cmd);
}

static int efa_com_comp_status_to_errno(u8 comp_status)