-// 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>
#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.
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;
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.
*
return parse_flex_obj;
}
+static int
+mlx5_devx_query_pkt_integrity_match(void *hcattr)
+{
+ return MLX5_GET(flow_table_nic_cap, hcattr,
+ ft_field_support_2_nic_receive.inner_l3_ok) &&
+ MLX5_GET(flow_table_nic_cap, hcattr,
+ ft_field_support_2_nic_receive.inner_l4_ok) &&
+ MLX5_GET(flow_table_nic_cap, hcattr,
+ ft_field_support_2_nic_receive.outer_l3_ok) &&
+ MLX5_GET(flow_table_nic_cap, hcattr,
+ ft_field_support_2_nic_receive.outer_l4_ok) &&
+ MLX5_GET(flow_table_nic_cap, hcattr,
+ ft_field_support_2_nic_receive
+ .inner_ipv4_checksum_ok) &&
+ MLX5_GET(flow_table_nic_cap, hcattr,
+ ft_field_support_2_nic_receive.inner_l4_checksum_ok) &&
+ MLX5_GET(flow_table_nic_cap, hcattr,
+ ft_field_support_2_nic_receive
+ .outer_ipv4_checksum_ok) &&
+ MLX5_GET(flow_table_nic_cap, hcattr,
+ ft_field_support_2_nic_receive.outer_l4_checksum_ok);
+}
+
/**
* Query HCA attributes.
* Using those attributes we can check on run time if the device
attr->roce = MLX5_GET(cmd_hca_cap, hcattr, roce);
attr->rq_ts_format = MLX5_GET(cmd_hca_cap, hcattr, rq_ts_format);
attr->sq_ts_format = MLX5_GET(cmd_hca_cap, hcattr, sq_ts_format);
+ attr->steering_format_version =
+ MLX5_GET(cmd_hca_cap, hcattr, steering_format_version);
attr->regex = MLX5_GET(cmd_hca_cap, hcattr, regexp);
attr->regexp_num_of_engines = MLX5_GET(cmd_hca_cap, hcattr,
regexp_num_of_engines);
MLX5_GENERAL_OBJ_TYPES_CAP_DEK);
attr->import_kek = !!(general_obj_types_supported &
MLX5_GENERAL_OBJ_TYPES_CAP_IMPORT_KEK);
+ attr->credential = !!(general_obj_types_supported &
+ MLX5_GENERAL_OBJ_TYPES_CAP_CREDENTIAL);
attr->crypto_login = !!(general_obj_types_supported &
MLX5_GENERAL_OBJ_TYPES_CAP_CRYPTO_LOGIN);
/* Add reading of other GENERAL_OBJ_TYPES_CAP bits above this line. */
attr->crypto = MLX5_GET(cmd_hca_cap, hcattr, crypto);
if (attr->crypto)
attr->aes_xts = MLX5_GET(cmd_hca_cap, hcattr, aes_xts);
+ attr->ct_offload = !!(MLX5_GET64(cmd_hca_cap, hcattr,
+ general_obj_types) &
+ MLX5_GENERAL_OBJ_TYPES_CAP_CONN_TRACK_OFFLOAD);
if (attr->qos.sup) {
MLX5_SET(query_hca_cap_in, in, op_mod,
MLX5_GET_HCA_CAP_OP_MOD_QOS_CAP |
return -1;
}
hcattr = MLX5_ADDR_OF(query_hca_cap_out, out, capability);
- attr->log_max_ft_sampler_num =
- MLX5_GET(flow_table_nic_cap,
- hcattr, flow_table_properties.log_max_ft_sampler_num);
-
+ attr->log_max_ft_sampler_num = MLX5_GET
+ (flow_table_nic_cap, hcattr,
+ flow_table_properties_nic_receive.log_max_ft_sampler_num);
+ attr->flow.tunnel_header_0_1 = MLX5_GET
+ (flow_table_nic_cap, hcattr,
+ ft_field_support_2_nic_receive.tunnel_header_0_1);
+ attr->pkt_integrity_match = mlx5_devx_query_pkt_integrity_match(hcattr);
+ attr->inner_ipv4_ihl = MLX5_GET
+ (flow_table_nic_cap, hcattr,
+ ft_field_support_2_nic_receive.inner_ipv4_ihl);
+ attr->outer_ipv4_ihl = MLX5_GET
+ (flow_table_nic_cap, hcattr,
+ ft_field_support_2_nic_receive.outer_ipv4_ihl);
/* Query HCA offloads for Ethernet protocol. */
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
hcattr = MLX5_ADDR_OF(query_hca_cap_out, out, capability);
attr->wqe_vlan_insert = MLX5_GET(per_protocol_networking_offload_caps,
hcattr, wqe_vlan_insert);
+ attr->csum_cap = MLX5_GET(per_protocol_networking_offload_caps,
+ hcattr, csum_cap);
attr->lro_cap = MLX5_GET(per_protocol_networking_offload_caps, hcattr,
lro_cap);
attr->tunnel_lro_gre = MLX5_GET(per_protocol_networking_offload_caps,
return flow_meter_aso_obj;
}
+/*
+ * Create general object of type CONN_TRACK_OFFLOAD using DevX API.
+ *
+ * @param[in] ctx
+ * Context returned from mlx5 open_device() glue function.
+ * @param [in] pd
+ * PD value to associate the CONN_TRACK_OFFLOAD ASO object with.
+ * @param [in] log_obj_size
+ * log_obj_size to allocate its power of 2 * objects
+ * in one CONN_TRACK_OFFLOAD bulk allocation.
+ *
+ * @return
+ * The DevX object created, NULL otherwise and rte_errno is set.
+ */
+struct mlx5_devx_obj *
+mlx5_devx_cmd_create_conn_track_offload_obj(void *ctx, uint32_t pd,
+ uint32_t log_obj_size)
+{
+ uint32_t in[MLX5_ST_SZ_DW(create_conn_track_aso_in)] = {0};
+ uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
+ struct mlx5_devx_obj *ct_aso_obj;
+ void *ptr;
+
+ ct_aso_obj = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*ct_aso_obj),
+ 0, SOCKET_ID_ANY);
+ if (!ct_aso_obj) {
+ DRV_LOG(ERR, "Failed to allocate CONN_TRACK_OFFLOAD object.");
+ rte_errno = ENOMEM;
+ return NULL;
+ }
+ ptr = MLX5_ADDR_OF(create_conn_track_aso_in, in, hdr);
+ MLX5_SET(general_obj_in_cmd_hdr, ptr, opcode,
+ MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
+ MLX5_SET(general_obj_in_cmd_hdr, ptr, obj_type,
+ MLX5_GENERAL_OBJ_TYPE_CONN_TRACK_OFFLOAD);
+ MLX5_SET(general_obj_in_cmd_hdr, ptr, log_obj_range, log_obj_size);
+ ptr = MLX5_ADDR_OF(create_conn_track_aso_in, in, conn_track_offload);
+ MLX5_SET(conn_track_offload, ptr, conn_track_aso_access_pd, pd);
+ ct_aso_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in),
+ out, sizeof(out));
+ if (!ct_aso_obj->obj) {
+ rte_errno = errno;
+ DRV_LOG(ERR, "Failed to create CONN_TRACK_OFFLOAD obj by using DevX.");
+ mlx5_free(ct_aso_obj);
+ return NULL;
+ }
+ ct_aso_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
+ return ct_aso_obj;
+}
+
/**
* Create general object of type GENEVE TLV option using DevX API.
*
return import_kek_obj;
}
+/**
+ * Create general object of type CREDENTIAL using DevX API.
+ *
+ * @param[in] ctx
+ * Context returned from mlx5 open_device() glue function.
+ * @param [in] attr
+ * Pointer to CREDENTIAL attributes structure.
+ *
+ * @return
+ * The DevX object created, NULL otherwise and rte_errno is set.
+ */
+struct mlx5_devx_obj *
+mlx5_devx_cmd_create_credential_obj(void *ctx,
+ struct mlx5_devx_credential_attr *attr)
+{
+ uint32_t in[MLX5_ST_SZ_DW(create_credential_in)] = {0};
+ uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
+ struct mlx5_devx_obj *credential_obj = NULL;
+ void *ptr = NULL, *credential_addr = NULL;
+
+ credential_obj = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*credential_obj),
+ 0, SOCKET_ID_ANY);
+ if (credential_obj == NULL) {
+ DRV_LOG(ERR, "Failed to allocate CREDENTIAL object data");
+ rte_errno = ENOMEM;
+ return NULL;
+ }
+ ptr = MLX5_ADDR_OF(create_credential_in, in, hdr);
+ MLX5_SET(general_obj_in_cmd_hdr, ptr, opcode,
+ MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
+ MLX5_SET(general_obj_in_cmd_hdr, ptr, obj_type,
+ MLX5_GENERAL_OBJ_TYPE_CREDENTIAL);
+ ptr = MLX5_ADDR_OF(create_credential_in, in, credential);
+ MLX5_SET(credential, ptr, credential_role, attr->credential_role);
+ credential_addr = MLX5_ADDR_OF(credential, ptr, credential);
+ memcpy(credential_addr, (void *)(attr->credential),
+ MLX5_CRYPTO_CREDENTIAL_SIZE);
+ credential_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in),
+ out, sizeof(out));
+ if (credential_obj->obj == NULL) {
+ rte_errno = errno;
+ DRV_LOG(ERR, "Failed to create CREDENTIAL object using DevX.");
+ mlx5_free(credential_obj);
+ return NULL;
+ }
+ credential_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
+ return credential_obj;
+}
+
/**
* Create general object of type CRYPTO_LOGIN using DevX API.
*
attr->session_import_kek_ptr);
credential_addr = MLX5_ADDR_OF(crypto_login, ptr, credential);
memcpy(credential_addr, (void *)(attr->credential),
- MLX5_CRYPTO_LOGIN_CREDENTIAL_SIZE);
+ MLX5_CRYPTO_CREDENTIAL_SIZE);
crypto_login_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in),
out, sizeof(out));
if (crypto_login_obj->obj == NULL) {