0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/etherdevice.h>
0034 #include <linux/mlx5/driver.h>
0035 #include <linux/mlx5/device.h>
0036
0037 #include "mlx5_core.h"
0038 #include "fpga/cmd.h"
0039
0040 #define MLX5_FPGA_ACCESS_REG_SZ (MLX5_ST_SZ_DW(fpga_access_reg) + \
0041 MLX5_FPGA_ACCESS_REG_SIZE_MAX)
0042
0043 int mlx5_fpga_access_reg(struct mlx5_core_dev *dev, u8 size, u64 addr,
0044 void *buf, bool write)
0045 {
0046 u32 in[MLX5_FPGA_ACCESS_REG_SZ] = {0};
0047 u32 out[MLX5_FPGA_ACCESS_REG_SZ];
0048 int err;
0049
0050 if (size & 3)
0051 return -EINVAL;
0052 if (addr & 3)
0053 return -EINVAL;
0054 if (size > MLX5_FPGA_ACCESS_REG_SIZE_MAX)
0055 return -EINVAL;
0056
0057 MLX5_SET(fpga_access_reg, in, size, size);
0058 MLX5_SET64(fpga_access_reg, in, address, addr);
0059 if (write)
0060 memcpy(MLX5_ADDR_OF(fpga_access_reg, in, data), buf, size);
0061
0062 err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
0063 MLX5_REG_FPGA_ACCESS_REG, 0, write);
0064 if (err)
0065 return err;
0066
0067 if (!write)
0068 memcpy(buf, MLX5_ADDR_OF(fpga_access_reg, out, data), size);
0069
0070 return 0;
0071 }
0072
0073 int mlx5_fpga_caps(struct mlx5_core_dev *dev)
0074 {
0075 u32 in[MLX5_ST_SZ_DW(fpga_cap)] = {0};
0076
0077 return mlx5_core_access_reg(dev, in, sizeof(in), dev->caps.fpga,
0078 MLX5_ST_SZ_BYTES(fpga_cap),
0079 MLX5_REG_FPGA_CAP, 0, 0);
0080 }
0081
0082 int mlx5_fpga_ctrl_op(struct mlx5_core_dev *dev, u8 op)
0083 {
0084 u32 in[MLX5_ST_SZ_DW(fpga_ctrl)] = {0};
0085 u32 out[MLX5_ST_SZ_DW(fpga_ctrl)];
0086
0087 MLX5_SET(fpga_ctrl, in, operation, op);
0088
0089 return mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
0090 MLX5_REG_FPGA_CTRL, 0, true);
0091 }
0092
0093 int mlx5_fpga_sbu_caps(struct mlx5_core_dev *dev, void *caps, int size)
0094 {
0095 unsigned int cap_size = MLX5_CAP_FPGA(dev, sandbox_extended_caps_len);
0096 u64 addr = MLX5_CAP64_FPGA(dev, sandbox_extended_caps_addr);
0097 unsigned int read;
0098 int ret = 0;
0099
0100 if (cap_size > size) {
0101 mlx5_core_warn(dev, "Not enough buffer %u for FPGA SBU caps %u",
0102 size, cap_size);
0103 return -EINVAL;
0104 }
0105
0106 while (cap_size > 0) {
0107 read = min_t(unsigned int, cap_size,
0108 MLX5_FPGA_ACCESS_REG_SIZE_MAX);
0109
0110 ret = mlx5_fpga_access_reg(dev, read, addr, caps, false);
0111 if (ret) {
0112 mlx5_core_warn(dev, "Error reading FPGA SBU caps %u bytes at address 0x%llx: %d",
0113 read, addr, ret);
0114 return ret;
0115 }
0116
0117 cap_size -= read;
0118 addr += read;
0119 caps += read;
0120 }
0121
0122 return ret;
0123 }
0124
0125 int mlx5_fpga_query(struct mlx5_core_dev *dev, struct mlx5_fpga_query *query)
0126 {
0127 u32 in[MLX5_ST_SZ_DW(fpga_ctrl)] = {0};
0128 u32 out[MLX5_ST_SZ_DW(fpga_ctrl)];
0129 int err;
0130
0131 err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
0132 MLX5_REG_FPGA_CTRL, 0, false);
0133 if (err)
0134 return err;
0135
0136 query->status = MLX5_GET(fpga_ctrl, out, status);
0137 query->admin_image = MLX5_GET(fpga_ctrl, out, flash_select_admin);
0138 query->oper_image = MLX5_GET(fpga_ctrl, out, flash_select_oper);
0139 return 0;
0140 }
0141
0142 int mlx5_fpga_create_qp(struct mlx5_core_dev *dev, void *fpga_qpc,
0143 u32 *fpga_qpn)
0144 {
0145 u32 out[MLX5_ST_SZ_DW(fpga_create_qp_out)] = {};
0146 u32 in[MLX5_ST_SZ_DW(fpga_create_qp_in)] = {};
0147 int ret;
0148
0149 MLX5_SET(fpga_create_qp_in, in, opcode, MLX5_CMD_OP_FPGA_CREATE_QP);
0150 memcpy(MLX5_ADDR_OF(fpga_create_qp_in, in, fpga_qpc), fpga_qpc,
0151 MLX5_FLD_SZ_BYTES(fpga_create_qp_in, fpga_qpc));
0152
0153 ret = mlx5_cmd_exec_inout(dev, fpga_create_qp, in, out);
0154 if (ret)
0155 return ret;
0156
0157 memcpy(fpga_qpc, MLX5_ADDR_OF(fpga_create_qp_out, out, fpga_qpc),
0158 MLX5_FLD_SZ_BYTES(fpga_create_qp_out, fpga_qpc));
0159 *fpga_qpn = MLX5_GET(fpga_create_qp_out, out, fpga_qpn);
0160 return ret;
0161 }
0162
0163 int mlx5_fpga_modify_qp(struct mlx5_core_dev *dev, u32 fpga_qpn,
0164 enum mlx5_fpga_qpc_field_select fields,
0165 void *fpga_qpc)
0166 {
0167 u32 in[MLX5_ST_SZ_DW(fpga_modify_qp_in)] = {};
0168
0169 MLX5_SET(fpga_modify_qp_in, in, opcode, MLX5_CMD_OP_FPGA_MODIFY_QP);
0170 MLX5_SET(fpga_modify_qp_in, in, field_select, fields);
0171 MLX5_SET(fpga_modify_qp_in, in, fpga_qpn, fpga_qpn);
0172 memcpy(MLX5_ADDR_OF(fpga_modify_qp_in, in, fpga_qpc), fpga_qpc,
0173 MLX5_FLD_SZ_BYTES(fpga_modify_qp_in, fpga_qpc));
0174
0175 return mlx5_cmd_exec_in(dev, fpga_modify_qp, in);
0176 }
0177
0178 int mlx5_fpga_query_qp(struct mlx5_core_dev *dev,
0179 u32 fpga_qpn, void *fpga_qpc)
0180 {
0181 u32 out[MLX5_ST_SZ_DW(fpga_query_qp_out)] = {};
0182 u32 in[MLX5_ST_SZ_DW(fpga_query_qp_in)] = {};
0183 int ret;
0184
0185 MLX5_SET(fpga_query_qp_in, in, opcode, MLX5_CMD_OP_FPGA_QUERY_QP);
0186 MLX5_SET(fpga_query_qp_in, in, fpga_qpn, fpga_qpn);
0187
0188 ret = mlx5_cmd_exec_inout(dev, fpga_query_qp, in, out);
0189 if (ret)
0190 return ret;
0191
0192 memcpy(fpga_qpc, MLX5_ADDR_OF(fpga_query_qp_out, out, fpga_qpc),
0193 MLX5_FLD_SZ_BYTES(fpga_query_qp_out, fpga_qpc));
0194 return ret;
0195 }
0196
0197 int mlx5_fpga_destroy_qp(struct mlx5_core_dev *dev, u32 fpga_qpn)
0198 {
0199 u32 in[MLX5_ST_SZ_DW(fpga_destroy_qp_in)] = {};
0200
0201 MLX5_SET(fpga_destroy_qp_in, in, opcode, MLX5_CMD_OP_FPGA_DESTROY_QP);
0202 MLX5_SET(fpga_destroy_qp_in, in, fpga_qpn, fpga_qpn);
0203
0204 return mlx5_cmd_exec_in(dev, fpga_destroy_qp, in);
0205 }
0206
0207 int mlx5_fpga_query_qp_counters(struct mlx5_core_dev *dev, u32 fpga_qpn,
0208 bool clear, struct mlx5_fpga_qp_counters *data)
0209 {
0210 u32 out[MLX5_ST_SZ_DW(fpga_query_qp_counters_out)] = {};
0211 u32 in[MLX5_ST_SZ_DW(fpga_query_qp_counters_in)] = {};
0212 int ret;
0213
0214 MLX5_SET(fpga_query_qp_counters_in, in, opcode,
0215 MLX5_CMD_OP_FPGA_QUERY_QP_COUNTERS);
0216 MLX5_SET(fpga_query_qp_counters_in, in, clear, clear);
0217 MLX5_SET(fpga_query_qp_counters_in, in, fpga_qpn, fpga_qpn);
0218
0219 ret = mlx5_cmd_exec_inout(dev, fpga_query_qp_counters, in, out);
0220 if (ret)
0221 return ret;
0222
0223 data->rx_ack_packets = MLX5_GET64(fpga_query_qp_counters_out, out,
0224 rx_ack_packets);
0225 data->rx_send_packets = MLX5_GET64(fpga_query_qp_counters_out, out,
0226 rx_send_packets);
0227 data->tx_ack_packets = MLX5_GET64(fpga_query_qp_counters_out, out,
0228 tx_ack_packets);
0229 data->tx_send_packets = MLX5_GET64(fpga_query_qp_counters_out, out,
0230 tx_send_packets);
0231 data->rx_total_drop = MLX5_GET64(fpga_query_qp_counters_out, out,
0232 rx_total_drop);
0233
0234 return ret;
0235 }