common/mlx5: support DevX register write access
authorDekel Peled <dekelp@nvidia.com>
Tue, 4 May 2021 17:54:59 +0000 (20:54 +0300)
committerThomas Monjalon <thomas@monjalon.net>
Tue, 4 May 2021 20:49:37 +0000 (22:49 +0200)
This patch adds support of write operation to NIC registers.

Signed-off-by: Dekel Peled <dekelp@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
drivers/common/mlx5/mlx5_devx_cmds.c
drivers/common/mlx5/mlx5_devx_cmds.h
drivers/common/mlx5/version.map

index 39360f7..e168375 100644 (file)
@@ -1,5 +1,6 @@
-// SPDX-License-Identifier: BSD-3-Clause
-/* Copyright 2018 Mellanox Technologies, Ltd */
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2018 Mellanox Technologies, Ltd
+ */
 
 #include <unistd.h>
 
@@ -12,7 +13,6 @@
 #include "mlx5_common_log.h"
 #include "mlx5_malloc.h"
 
-
 /**
  * Perform read access to the registers. Reads data from register
  * and writes ones to the specified buffer.
@@ -61,7 +61,7 @@ mlx5_devx_cmd_register_read(void *ctx, uint16_t reg_id, uint32_t arg,
        if (status) {
                int syndrome = MLX5_GET(access_register_out, out, syndrome);
 
-               DRV_LOG(DEBUG, "Failed to access NIC register 0x%X, "
+               DRV_LOG(DEBUG, "Failed to read access NIC register 0x%X, "
                               "status %x, syndrome = %x",
                               reg_id, status, syndrome);
                return -1;
@@ -74,6 +74,70 @@ error:
        return rc;
 }
 
+/**
+ * Perform write access to the registers.
+ *
+ * @param[in] ctx
+ *   Context returned from mlx5 open_device() glue function.
+ * @param[in] reg_id
+ *   Register identifier according to the PRM.
+ * @param[in] arg
+ *   Register access auxiliary parameter according to the PRM.
+ * @param[out] data
+ *   Pointer to the buffer containing data to write.
+ * @param[in] dw_cnt
+ *   Buffer size in double words (32bit units).
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int
+mlx5_devx_cmd_register_write(void *ctx, uint16_t reg_id, uint32_t arg,
+                            uint32_t *data, uint32_t dw_cnt)
+{
+       uint32_t in[MLX5_ST_SZ_DW(access_register_in) +
+                   MLX5_ACCESS_REGISTER_DATA_DWORD_MAX] = {0};
+       uint32_t out[MLX5_ST_SZ_DW(access_register_out)] = {0};
+       int status, rc;
+       void *ptr;
+
+       MLX5_ASSERT(data && dw_cnt);
+       MLX5_ASSERT(dw_cnt <= MLX5_ACCESS_REGISTER_DATA_DWORD_MAX);
+       if (dw_cnt > MLX5_ACCESS_REGISTER_DATA_DWORD_MAX) {
+               DRV_LOG(ERR, "Data to write exceeds max size");
+               return -1;
+       }
+       MLX5_SET(access_register_in, in, opcode,
+                MLX5_CMD_OP_ACCESS_REGISTER_USER);
+       MLX5_SET(access_register_in, in, op_mod,
+                MLX5_ACCESS_REGISTER_IN_OP_MOD_WRITE);
+       MLX5_SET(access_register_in, in, register_id, reg_id);
+       MLX5_SET(access_register_in, in, argument, arg);
+       ptr = MLX5_ADDR_OF(access_register_in, in, register_data);
+       memcpy(ptr, data, dw_cnt * sizeof(uint32_t));
+       rc = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out));
+
+       rc = mlx5_glue->devx_general_cmd(ctx, in,
+                                        MLX5_ST_SZ_BYTES(access_register_in) +
+                                        dw_cnt * sizeof(uint32_t),
+                                        out, sizeof(out));
+       if (rc)
+               goto error;
+       status = MLX5_GET(access_register_out, out, status);
+       if (status) {
+               int syndrome = MLX5_GET(access_register_out, out, syndrome);
+
+               DRV_LOG(DEBUG, "Failed to write access NIC register 0x%X, "
+                              "status %x, syndrome = %x",
+                              reg_id, status, syndrome);
+               return -1;
+       }
+       return 0;
+error:
+       rc = (rc > 0) ? -rc : rc;
+       return rc;
+}
+
 /**
  * Allocate flow counters via devx interface.
  *
index fca1e6c..660e7d9 100644 (file)
@@ -565,6 +565,10 @@ __rte_internal
 int mlx5_devx_cmd_register_read(void *ctx, uint16_t reg_id,
                                uint32_t arg, uint32_t *data, uint32_t dw_cnt);
 
+__rte_internal
+int mlx5_devx_cmd_register_write(void *ctx, uint16_t reg_id,
+                                uint32_t arg, uint32_t *data, uint32_t dw_cnt);
+
 __rte_internal
 struct mlx5_devx_obj *
 mlx5_devx_cmd_create_geneve_tlv_option(void *ctx,
index 04b2179..c630696 100644 (file)
@@ -53,6 +53,7 @@ INTERNAL {
        mlx5_devx_cmd_queue_counter_alloc; # WINDOWS_NO_EXPORT
        mlx5_devx_cmd_queue_counter_query; # WINDOWS_NO_EXPORT
        mlx5_devx_cmd_register_read;
+       mlx5_devx_cmd_register_write;
        mlx5_devx_cmd_wq_query; # WINDOWS_NO_EXPORT
 
        mlx5_devx_cq_create;