]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
RDMA/efa: Add checksum support for admin responses
authorYonatan Nachum <ynachum@amazon.com>
Thu, 9 Apr 2026 07:49:05 +0000 (07:49 +0000)
committerLeon Romanovsky <leon@kernel.org>
Mon, 18 May 2026 08:58:41 +0000 (04:58 -0400)
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>
drivers/infiniband/hw/efa/Kconfig
drivers/infiniband/hw/efa/efa_admin_cmds_defs.h
drivers/infiniband/hw/efa/efa_admin_defs.h
drivers/infiniband/hw/efa/efa_com.c
drivers/infiniband/hw/efa/efa_com.h

index 457e18ba1d5701eac1450e1d57ebbb0bb77d8db3..ff7f7c0870b3a2282c19a8e8fe89e2dbdf9ccf0f 100644 (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).
 
index ad34ea5da6b07632b3c4edc0c7bd200c57c5fb84..826790ca9d839340e958f84c797b10b12dcd974e 100644 (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,
index 35700c93e639e46127d88f7bd9c45a3a0928e8ec..02f86edabed86813e07c222554721955b6096aeb 100644 (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 {
index e97b5f0d700388bf577afd5fd3ee4e6a82a944c2..7cc3f4af0bb9d225a9a8668ba6bd2d6c8bd06e59 100644 (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"
 #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",
index 4d9ca97e42962f43b762ebc2c5d132d37b57e18c..f8c692b0e092e7270d0bda65430182562540cd80 100644 (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;
 };