net/mlx5: FPGA, Add FW commands for FPGA QPs
authorIlan Tayari <ilant@mellanox.com>
Mon, 27 Mar 2017 11:52:09 +0000 (14:52 +0300)
committerSaeed Mahameed <saeedm@mellanox.com>
Tue, 27 Jun 2017 13:36:47 +0000 (16:36 +0300)
The FPGA QP is a high-bandwidth communication channel between the host
CPU and the FPGA device. It allows performing DMA operations between
host memory and the FPGA logic via the ConnectX chip.

Add ConnectX FW commands which create and manipulate FPGA QPs.

Signed-off-by: Ilan Tayari <ilant@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/fpga/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/fpga/cmd.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mlx5/mlx5_ifc_fpga.h

index 4d5bd01f1ebb76b9f32f96eb4c4e0dedf2cdc66e..f5a2c605749ff2dad1db091bb93d3b6957fa4058 100644 (file)
@@ -307,6 +307,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
        case MLX5_CMD_OP_SET_FLOW_TABLE_ROOT:
        case MLX5_CMD_OP_DEALLOC_ENCAP_HEADER:
        case MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT:
+       case MLX5_CMD_OP_FPGA_DESTROY_QP:
                return MLX5_CMD_STAT_OK;
 
        case MLX5_CMD_OP_QUERY_HCA_CAP:
@@ -419,6 +420,10 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
        case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
        case MLX5_CMD_OP_ALLOC_ENCAP_HEADER:
        case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
+       case MLX5_CMD_OP_FPGA_CREATE_QP:
+       case MLX5_CMD_OP_FPGA_MODIFY_QP:
+       case MLX5_CMD_OP_FPGA_QUERY_QP:
+       case MLX5_CMD_OP_FPGA_QUERY_QP_COUNTERS:
                *status = MLX5_DRIVER_STATUS_ABORTED;
                *synd = MLX5_DRIVER_SYND;
                return -EIO;
@@ -585,6 +590,11 @@ const char *mlx5_command_str(int command)
        MLX5_COMMAND_STR_CASE(DEALLOC_ENCAP_HEADER);
        MLX5_COMMAND_STR_CASE(ALLOC_MODIFY_HEADER_CONTEXT);
        MLX5_COMMAND_STR_CASE(DEALLOC_MODIFY_HEADER_CONTEXT);
+       MLX5_COMMAND_STR_CASE(FPGA_CREATE_QP);
+       MLX5_COMMAND_STR_CASE(FPGA_MODIFY_QP);
+       MLX5_COMMAND_STR_CASE(FPGA_QUERY_QP);
+       MLX5_COMMAND_STR_CASE(FPGA_QUERY_QP_COUNTERS);
+       MLX5_COMMAND_STR_CASE(FPGA_DESTROY_QP);
        default: return "unknown command opcode";
        }
 }
index 99cba644b4fc9454a8f17fe85e083204d5f1d462..8308ccbad85a7c0a8ad844ac50b007b90d9ae8d2 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/etherdevice.h>
 #include <linux/mlx5/cmd.h>
 #include <linux/mlx5/driver.h>
+#include <linux/mlx5/device.h>
 
 #include "mlx5_core.h"
 #include "fpga/cmd.h"
@@ -62,3 +63,100 @@ int mlx5_fpga_query(struct mlx5_core_dev *dev, struct mlx5_fpga_query *query)
        query->oper_image = MLX5_GET(fpga_ctrl, out, flash_select_oper);
        return 0;
 }
+
+int mlx5_fpga_create_qp(struct mlx5_core_dev *dev, void *fpga_qpc,
+                       u32 *fpga_qpn)
+{
+       u32 in[MLX5_ST_SZ_DW(fpga_create_qp_in)] = {0};
+       u32 out[MLX5_ST_SZ_DW(fpga_create_qp_out)];
+       int ret;
+
+       MLX5_SET(fpga_create_qp_in, in, opcode, MLX5_CMD_OP_FPGA_CREATE_QP);
+       memcpy(MLX5_ADDR_OF(fpga_create_qp_in, in, fpga_qpc), fpga_qpc,
+              MLX5_FLD_SZ_BYTES(fpga_create_qp_in, fpga_qpc));
+
+       ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+       if (ret)
+               return ret;
+
+       memcpy(fpga_qpc, MLX5_ADDR_OF(fpga_create_qp_out, out, fpga_qpc),
+              MLX5_FLD_SZ_BYTES(fpga_create_qp_out, fpga_qpc));
+       *fpga_qpn = MLX5_GET(fpga_create_qp_out, out, fpga_qpn);
+       return ret;
+}
+
+int mlx5_fpga_modify_qp(struct mlx5_core_dev *dev, u32 fpga_qpn,
+                       enum mlx5_fpga_qpc_field_select fields,
+                       void *fpga_qpc)
+{
+       u32 in[MLX5_ST_SZ_DW(fpga_modify_qp_in)] = {0};
+       u32 out[MLX5_ST_SZ_DW(fpga_modify_qp_out)];
+
+       MLX5_SET(fpga_modify_qp_in, in, opcode, MLX5_CMD_OP_FPGA_MODIFY_QP);
+       MLX5_SET(fpga_modify_qp_in, in, field_select, fields);
+       MLX5_SET(fpga_modify_qp_in, in, fpga_qpn, fpga_qpn);
+       memcpy(MLX5_ADDR_OF(fpga_modify_qp_in, in, fpga_qpc), fpga_qpc,
+              MLX5_FLD_SZ_BYTES(fpga_modify_qp_in, fpga_qpc));
+
+       return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+
+int mlx5_fpga_query_qp(struct mlx5_core_dev *dev,
+                      u32 fpga_qpn, void *fpga_qpc)
+{
+       u32 in[MLX5_ST_SZ_DW(fpga_query_qp_in)] = {0};
+       u32 out[MLX5_ST_SZ_DW(fpga_query_qp_out)];
+       int ret;
+
+       MLX5_SET(fpga_query_qp_in, in, opcode, MLX5_CMD_OP_FPGA_QUERY_QP);
+       MLX5_SET(fpga_query_qp_in, in, fpga_qpn, fpga_qpn);
+
+       ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+       if (ret)
+               return ret;
+
+       memcpy(fpga_qpc, MLX5_ADDR_OF(fpga_query_qp_out, in, fpga_qpc),
+              MLX5_FLD_SZ_BYTES(fpga_query_qp_out, fpga_qpc));
+       return ret;
+}
+
+int mlx5_fpga_destroy_qp(struct mlx5_core_dev *dev, u32 fpga_qpn)
+{
+       u32 in[MLX5_ST_SZ_DW(fpga_destroy_qp_in)] = {0};
+       u32 out[MLX5_ST_SZ_DW(fpga_destroy_qp_out)];
+
+       MLX5_SET(fpga_destroy_qp_in, in, opcode, MLX5_CMD_OP_FPGA_DESTROY_QP);
+       MLX5_SET(fpga_destroy_qp_in, in, fpga_qpn, fpga_qpn);
+
+       return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+
+int mlx5_fpga_query_qp_counters(struct mlx5_core_dev *dev, u32 fpga_qpn,
+                               bool clear, struct mlx5_fpga_qp_counters *data)
+{
+       u32 in[MLX5_ST_SZ_DW(fpga_query_qp_counters_in)] = {0};
+       u32 out[MLX5_ST_SZ_DW(fpga_query_qp_counters_out)];
+       int ret;
+
+       MLX5_SET(fpga_query_qp_counters_in, in, opcode,
+                MLX5_CMD_OP_FPGA_QUERY_QP_COUNTERS);
+       MLX5_SET(fpga_query_qp_counters_in, in, clear, clear);
+       MLX5_SET(fpga_query_qp_counters_in, in, fpga_qpn, fpga_qpn);
+
+       ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+       if (ret)
+               return ret;
+
+       data->rx_ack_packets = MLX5_GET64(fpga_query_qp_counters_out, out,
+                                         rx_ack_packets);
+       data->rx_send_packets = MLX5_GET64(fpga_query_qp_counters_out, out,
+                                          rx_send_packets);
+       data->tx_ack_packets = MLX5_GET64(fpga_query_qp_counters_out, out,
+                                         tx_ack_packets);
+       data->tx_send_packets = MLX5_GET64(fpga_query_qp_counters_out, out,
+                                          tx_send_packets);
+       data->rx_total_drop = MLX5_GET64(fpga_query_qp_counters_out, out,
+                                        rx_total_drop);
+
+       return ret;
+}
index a74396a61bc37fa9af81b134186003eb82de5661..b851580d846f6674cb2e5450da502e0dd10cbb20 100644 (file)
@@ -53,7 +53,28 @@ struct mlx5_fpga_query {
        enum mlx5_fpga_status status;
 };
 
+enum mlx5_fpga_qpc_field_select {
+       MLX5_FPGA_QPC_STATE = BIT(0),
+};
+
+struct mlx5_fpga_qp_counters {
+       u64 rx_ack_packets;
+       u64 rx_send_packets;
+       u64 tx_ack_packets;
+       u64 tx_send_packets;
+       u64 rx_total_drop;
+};
+
 int mlx5_fpga_caps(struct mlx5_core_dev *dev, u32 *caps);
 int mlx5_fpga_query(struct mlx5_core_dev *dev, struct mlx5_fpga_query *query);
 
+int mlx5_fpga_create_qp(struct mlx5_core_dev *dev, void *fpga_qpc,
+                       u32 *fpga_qpn);
+int mlx5_fpga_modify_qp(struct mlx5_core_dev *dev, u32 fpga_qpn,
+                       enum mlx5_fpga_qpc_field_select fields, void *fpga_qpc);
+int mlx5_fpga_query_qp(struct mlx5_core_dev *dev, u32 fpga_qpn, void *fpga_qpc);
+int mlx5_fpga_query_qp_counters(struct mlx5_core_dev *dev, u32 fpga_qpn,
+                               bool clear, struct mlx5_fpga_qp_counters *data);
+int mlx5_fpga_destroy_qp(struct mlx5_core_dev *dev, u32 fpga_qpn);
+
 #endif /* __MLX5_FPGA_H__ */
index d6b99d5d0f2418557f75de12d4d44ff00fe2bedf..a8b3fcaa33ff93835b841191ef9e0881bb3ef633 100644 (file)
@@ -232,6 +232,11 @@ enum {
        MLX5_CMD_OP_DEALLOC_ENCAP_HEADER          = 0x93e,
        MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT   = 0x940,
        MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT = 0x941,
+       MLX5_CMD_OP_FPGA_CREATE_QP                = 0x960,
+       MLX5_CMD_OP_FPGA_MODIFY_QP                = 0x961,
+       MLX5_CMD_OP_FPGA_QUERY_QP                 = 0x962,
+       MLX5_CMD_OP_FPGA_DESTROY_QP               = 0x963,
+       MLX5_CMD_OP_FPGA_QUERY_QP_COUNTERS        = 0x964,
        MLX5_CMD_OP_MAX
 };
 
index 0032d10ac6cfc8d0dcf97c55930b20e73d892327..30d4b697fab69d2ec15ded7cef678fecc7b96933 100644 (file)
@@ -141,4 +141,203 @@ struct mlx5_ifc_fpga_error_event_bits {
        u8         reserved_at_60[0x80];
 };
 
+enum mlx5_ifc_fpga_qp_state {
+       MLX5_FPGA_QPC_STATE_INIT    = 0x0,
+       MLX5_FPGA_QPC_STATE_ACTIVE  = 0x1,
+       MLX5_FPGA_QPC_STATE_ERROR   = 0x2,
+};
+
+enum mlx5_ifc_fpga_qp_type {
+       MLX5_FPGA_QPC_QP_TYPE_SHELL_QP    = 0x0,
+       MLX5_FPGA_QPC_QP_TYPE_SANDBOX_QP  = 0x1,
+};
+
+enum mlx5_ifc_fpga_qp_service_type {
+       MLX5_FPGA_QPC_ST_RC  = 0x0,
+};
+
+struct mlx5_ifc_fpga_qpc_bits {
+       u8         state[0x4];
+       u8         reserved_at_4[0x1b];
+       u8         qp_type[0x1];
+
+       u8         reserved_at_20[0x4];
+       u8         st[0x4];
+       u8         reserved_at_28[0x10];
+       u8         traffic_class[0x8];
+
+       u8         ether_type[0x10];
+       u8         prio[0x3];
+       u8         dei[0x1];
+       u8         vid[0xc];
+
+       u8         reserved_at_60[0x20];
+
+       u8         reserved_at_80[0x8];
+       u8         next_rcv_psn[0x18];
+
+       u8         reserved_at_a0[0x8];
+       u8         next_send_psn[0x18];
+
+       u8         reserved_at_c0[0x10];
+       u8         pkey[0x10];
+
+       u8         reserved_at_e0[0x8];
+       u8         remote_qpn[0x18];
+
+       u8         reserved_at_100[0x15];
+       u8         rnr_retry[0x3];
+       u8         reserved_at_118[0x5];
+       u8         retry_count[0x3];
+
+       u8         reserved_at_120[0x20];
+
+       u8         reserved_at_140[0x10];
+       u8         remote_mac_47_32[0x10];
+
+       u8         remote_mac_31_0[0x20];
+
+       u8         remote_ip[16][0x8];
+
+       u8         reserved_at_200[0x40];
+
+       u8         reserved_at_240[0x10];
+       u8         fpga_mac_47_32[0x10];
+
+       u8         fpga_mac_31_0[0x20];
+
+       u8         fpga_ip[16][0x8];
+};
+
+struct mlx5_ifc_fpga_create_qp_in_bits {
+       u8         opcode[0x10];
+       u8         reserved_at_10[0x10];
+
+       u8         reserved_at_20[0x10];
+       u8         op_mod[0x10];
+
+       u8         reserved_at_40[0x40];
+
+       struct mlx5_ifc_fpga_qpc_bits fpga_qpc;
+};
+
+struct mlx5_ifc_fpga_create_qp_out_bits {
+       u8         status[0x8];
+       u8         reserved_at_8[0x18];
+
+       u8         syndrome[0x20];
+
+       u8         reserved_at_40[0x8];
+       u8         fpga_qpn[0x18];
+
+       u8         reserved_at_60[0x20];
+
+       struct mlx5_ifc_fpga_qpc_bits fpga_qpc;
+};
+
+struct mlx5_ifc_fpga_modify_qp_in_bits {
+       u8         opcode[0x10];
+       u8         reserved_at_10[0x10];
+
+       u8         reserved_at_20[0x10];
+       u8         op_mod[0x10];
+
+       u8         reserved_at_40[0x8];
+       u8         fpga_qpn[0x18];
+
+       u8         field_select[0x20];
+
+       struct mlx5_ifc_fpga_qpc_bits fpga_qpc;
+};
+
+struct mlx5_ifc_fpga_modify_qp_out_bits {
+       u8         status[0x8];
+       u8         reserved_at_8[0x18];
+
+       u8         syndrome[0x20];
+
+       u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_fpga_query_qp_in_bits {
+       u8         opcode[0x10];
+       u8         reserved_at_10[0x10];
+
+       u8         reserved_at_20[0x10];
+       u8         op_mod[0x10];
+
+       u8         reserved_at_40[0x8];
+       u8         fpga_qpn[0x18];
+
+       u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_fpga_query_qp_out_bits {
+       u8         status[0x8];
+       u8         reserved_at_8[0x18];
+
+       u8         syndrome[0x20];
+
+       u8         reserved_at_40[0x40];
+
+       struct mlx5_ifc_fpga_qpc_bits fpga_qpc;
+};
+
+struct mlx5_ifc_fpga_query_qp_counters_in_bits {
+       u8         opcode[0x10];
+       u8         reserved_at_10[0x10];
+
+       u8         reserved_at_20[0x10];
+       u8         op_mod[0x10];
+
+       u8         clear[0x1];
+       u8         reserved_at_41[0x7];
+       u8         fpga_qpn[0x18];
+
+       u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_fpga_query_qp_counters_out_bits {
+       u8         status[0x8];
+       u8         reserved_at_8[0x18];
+
+       u8         syndrome[0x20];
+
+       u8         reserved_at_40[0x40];
+
+       u8         rx_ack_packets[0x40];
+
+       u8         rx_send_packets[0x40];
+
+       u8         tx_ack_packets[0x40];
+
+       u8         tx_send_packets[0x40];
+
+       u8         rx_total_drop[0x40];
+
+       u8         reserved_at_1c0[0x1c0];
+};
+
+struct mlx5_ifc_fpga_destroy_qp_in_bits {
+       u8         opcode[0x10];
+       u8         reserved_at_10[0x10];
+
+       u8         reserved_at_20[0x10];
+       u8         op_mod[0x10];
+
+       u8         reserved_at_40[0x8];
+       u8         fpga_qpn[0x18];
+
+       u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_fpga_destroy_qp_out_bits {
+       u8         status[0x8];
+       u8         reserved_at_8[0x18];
+
+       u8         syndrome[0x20];
+
+       u8         reserved_at_40[0x40];
+};
+
 #endif /* MLX5_IFC_FPGA_H */