RDMA/efa: Add checksum support for admin responses

EFA devices added support for CRC16 checksum on admin responses and to
expose it to the driver the API version increased to 0.2. Add a check
for support on device init and if supported validate the checksum on
each admin response the driver receives. If the checksum validation
failed, drop the CQE.

Add the CRC16 module to Kconfig to have the in-tree dependency.

Reviewed-by: Firas Jahjah <firasj@amazon.com>
Reviewed-by: Michael Margolin <mrgolin@amazon.com>
Signed-off-by: Yonatan Nachum <ynachum@amazon.com>
Link: https://patch.msgid.link/20260409074905.3126023-1-ynachum@amazon.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
Yonatan Nachum 2026-04-09 07:49:05 +00:00 committed by Leon Romanovsky
parent c67bd97369
commit 7de165740c
5 changed files with 55 additions and 20 deletions

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
# Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved.
# Copyright 2018-2026 Amazon.com, Inc. or its affiliates. All rights reserved.
#
# Amazon fabric device configuration
#
@ -8,6 +8,7 @@ config INFINIBAND_EFA
tristate "Amazon Elastic Fabric Adapter (EFA) support"
depends on PCI_MSI && 64BIT && !CPU_BIG_ENDIAN
depends on INFINIBAND_USER_ACCESS
select CRC16
help
This driver supports Amazon Elastic Fabric Adapter (EFA).

View File

@ -6,9 +6,6 @@
#ifndef _EFA_ADMIN_CMDS_H_
#define _EFA_ADMIN_CMDS_H_
#define EFA_ADMIN_API_VERSION_MAJOR 0
#define EFA_ADMIN_API_VERSION_MINOR 1
/* EFA admin queue opcodes */
enum efa_admin_aq_opcode {
EFA_ADMIN_CREATE_QP = 1,

View File

@ -1,18 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
/*
* Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All rights reserved.
* Copyright 2018-2026 Amazon.com, Inc. or its affiliates. All rights reserved.
*/
#ifndef _EFA_ADMIN_H_
#define _EFA_ADMIN_H_
#define EFA_ADMIN_API_VERSION_MAJOR 0
#define EFA_ADMIN_API_VERSION_MINOR 2
enum efa_admin_aq_completion_status {
EFA_ADMIN_SUCCESS = 0,
EFA_ADMIN_RESOURCE_ALLOCATION_FAILURE = 1,
EFA_ADMIN_BAD_OPCODE = 2,
EFA_ADMIN_UNSUPPORTED_OPCODE = 3,
EFA_ADMIN_MALFORMED_REQUEST = 4,
/* Additional status is provided in ACQ entry extended_status */
EFA_ADMIN_ILLEGAL_PARAMETER = 5,
EFA_ADMIN_UNKNOWN_ERROR = 6,
EFA_ADMIN_RESOURCE_BUSY = 7,
@ -78,13 +80,10 @@ struct efa_admin_acq_common_desc {
*/
u8 flags;
u16 extended_status;
/* Poly 0x8005 CRC16 with initial value 0xFFFF and final XOR of 0xFFFF */
u16 checksum;
/*
* indicates to the driver which AQ entry has been consumed by the
* device and could be reused
*/
u16 sq_head_indx;
u16 reserved;
};
struct efa_admin_acq_entry {

View File

@ -3,6 +3,7 @@
* Copyright 2018-2026 Amazon.com, Inc. or its affiliates. All rights reserved.
*/
#include <linux/crc16.h>
#include <linux/log2.h>
#include "efa_com.h"
@ -22,6 +23,14 @@
#define EFA_CTRL_MINOR 0
#define EFA_CTRL_SUB_MINOR 1
#define EFA_CRC16_INIT_VAL 0xffff
#define EFA_CRC_MIN_ADMIN_API_VERSION_MAJOR 0
#define EFA_CRC_MIN_ADMIN_API_VERSION_MINOR 2
#define EFA_MIN_ADMIN_API_VERSION_MAJOR 0
#define EFA_MIN_ADMIN_API_VERSION_MINOR 1
enum efa_cmd_status {
EFA_CMD_UNUSED,
EFA_CMD_ALLOCATED,
@ -167,9 +176,8 @@ static int efa_com_admin_init_cq(struct efa_com_dev *edev)
struct efa_com_admin_queue *aq = &edev->aq;
struct efa_com_admin_cq *cq = &aq->cq;
u16 size = aq->depth * sizeof(*cq->entries);
u32 acq_caps = 0;
u32 addr_high;
u32 addr_low;
u32 acq_caps = 0, crc_min_ver = 0;
u32 addr_high, addr_low;
cq->entries =
dma_alloc_coherent(aq->dmadev, size, &cq->dma_addr, GFP_KERNEL);
@ -178,6 +186,11 @@ static int efa_com_admin_init_cq(struct efa_com_dev *edev)
spin_lock_init(&cq->lock);
EFA_SET(&crc_min_ver, EFA_REGS_VERSION_MAJOR_VERSION, EFA_CRC_MIN_ADMIN_API_VERSION_MAJOR);
EFA_SET(&crc_min_ver, EFA_REGS_VERSION_MINOR_VERSION, EFA_CRC_MIN_ADMIN_API_VERSION_MINOR);
if (edev->dev_api_ver >= crc_min_ver)
cq->validate_checksum = true;
cq->cc = 0;
cq->phase = 1;
@ -409,12 +422,35 @@ static int efa_com_submit_admin_cmd(struct efa_com_admin_queue *aq,
return 0;
}
static bool efa_com_cqe_checksum_valid(struct efa_com_admin_queue *aq,
struct efa_admin_acq_entry *cqe)
{
u16 cqe_checksum = cqe->acq_common_descriptor.checksum;
u16 calc_checksum;
cqe->acq_common_descriptor.checksum = 0;
calc_checksum = crc16(EFA_CRC16_INIT_VAL, (u8 *)cqe, sizeof(*cqe)) ^ EFA_CRC16_INIT_VAL;
if (calc_checksum != cqe_checksum) {
ibdev_err(aq->efa_dev,
"Received completion with invalid checksum, cqe[%u], calc[%u], sq producer[%d], sq consumer[%d], cq consumer[%d]\n",
cqe_checksum, calc_checksum, aq->sq.pc, aq->sq.cc,
aq->cq.cc);
return false;
}
return true;
}
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;
u16 cmd_id;
if (aq->cq.validate_checksum && !efa_com_cqe_checksum_valid(aq, cqe))
return -EINVAL;
cmd_id = EFA_GET(&cqe->acq_common_descriptor.command,
EFA_ADMIN_ACQ_COMMON_DESC_COMMAND_ID);
@ -954,16 +990,16 @@ int efa_com_validate_version(struct efa_com_dev *edev)
EFA_GET(&ver, EFA_REGS_VERSION_MAJOR_VERSION),
EFA_GET(&ver, EFA_REGS_VERSION_MINOR_VERSION));
EFA_SET(&min_ver, EFA_REGS_VERSION_MAJOR_VERSION,
EFA_ADMIN_API_VERSION_MAJOR);
EFA_SET(&min_ver, EFA_REGS_VERSION_MINOR_VERSION,
EFA_ADMIN_API_VERSION_MINOR);
EFA_SET(&min_ver, EFA_REGS_VERSION_MAJOR_VERSION, EFA_MIN_ADMIN_API_VERSION_MAJOR);
EFA_SET(&min_ver, EFA_REGS_VERSION_MINOR_VERSION, EFA_MIN_ADMIN_API_VERSION_MINOR);
if (ver < min_ver) {
ibdev_err(edev->efa_dev,
"EFA version is lower than the minimal version the driver supports\n");
return -EOPNOTSUPP;
}
edev->dev_api_ver = ver;
ibdev_dbg(
edev->efa_dev,
"efa controller version: %d.%d.%d implementation version %d\n",

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
/*
* Copyright 2018-2025 Amazon.com, Inc. or its affiliates. All rights reserved.
* Copyright 2018-2026 Amazon.com, Inc. or its affiliates. All rights reserved.
*/
#ifndef _EFA_COM_H_
@ -25,6 +25,7 @@ struct efa_com_admin_cq {
struct efa_admin_acq_entry *entries;
dma_addr_t dma_addr;
spinlock_t lock; /* Protects ACQ */
bool validate_checksum;
u16 cc; /* consumer counter */
u8 phase;
@ -112,6 +113,7 @@ struct efa_com_dev {
u32 supported_features;
u32 dma_addr_bits;
u32 dev_api_ver;
struct efa_com_mmio_read mmio_read;
};