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
0034 #include <net/addrconf.h>
0035 #include <linux/etherdevice.h>
0036 #include <linux/mlx5/vport.h>
0037
0038 #include "mlx5_core.h"
0039 #include "lib/mlx5.h"
0040 #include "fpga/conn.h"
0041
0042 #define MLX5_FPGA_PKEY 0xFFFF
0043 #define MLX5_FPGA_PKEY_INDEX 0
0044 #define MLX5_FPGA_RECV_SIZE 2048
0045 #define MLX5_FPGA_PORT_NUM 1
0046 #define MLX5_FPGA_CQ_BUDGET 64
0047
0048 static int mlx5_fpga_conn_map_buf(struct mlx5_fpga_conn *conn,
0049 struct mlx5_fpga_dma_buf *buf)
0050 {
0051 struct device *dma_device;
0052 int err = 0;
0053
0054 if (unlikely(!buf->sg[0].data))
0055 goto out;
0056
0057 dma_device = mlx5_core_dma_dev(conn->fdev->mdev);
0058 buf->sg[0].dma_addr = dma_map_single(dma_device, buf->sg[0].data,
0059 buf->sg[0].size, buf->dma_dir);
0060 err = dma_mapping_error(dma_device, buf->sg[0].dma_addr);
0061 if (unlikely(err)) {
0062 mlx5_fpga_warn(conn->fdev, "DMA error on sg 0: %d\n", err);
0063 err = -ENOMEM;
0064 goto out;
0065 }
0066
0067 if (!buf->sg[1].data)
0068 goto out;
0069
0070 buf->sg[1].dma_addr = dma_map_single(dma_device, buf->sg[1].data,
0071 buf->sg[1].size, buf->dma_dir);
0072 err = dma_mapping_error(dma_device, buf->sg[1].dma_addr);
0073 if (unlikely(err)) {
0074 mlx5_fpga_warn(conn->fdev, "DMA error on sg 1: %d\n", err);
0075 dma_unmap_single(dma_device, buf->sg[0].dma_addr,
0076 buf->sg[0].size, buf->dma_dir);
0077 err = -ENOMEM;
0078 }
0079
0080 out:
0081 return err;
0082 }
0083
0084 static void mlx5_fpga_conn_unmap_buf(struct mlx5_fpga_conn *conn,
0085 struct mlx5_fpga_dma_buf *buf)
0086 {
0087 struct device *dma_device;
0088
0089 dma_device = mlx5_core_dma_dev(conn->fdev->mdev);
0090 if (buf->sg[1].data)
0091 dma_unmap_single(dma_device, buf->sg[1].dma_addr,
0092 buf->sg[1].size, buf->dma_dir);
0093
0094 if (likely(buf->sg[0].data))
0095 dma_unmap_single(dma_device, buf->sg[0].dma_addr,
0096 buf->sg[0].size, buf->dma_dir);
0097 }
0098
0099 static int mlx5_fpga_conn_post_recv(struct mlx5_fpga_conn *conn,
0100 struct mlx5_fpga_dma_buf *buf)
0101 {
0102 struct mlx5_wqe_data_seg *data;
0103 unsigned int ix;
0104 int err = 0;
0105
0106 err = mlx5_fpga_conn_map_buf(conn, buf);
0107 if (unlikely(err))
0108 goto out;
0109
0110 if (unlikely(conn->qp.rq.pc - conn->qp.rq.cc >= conn->qp.rq.size)) {
0111 mlx5_fpga_conn_unmap_buf(conn, buf);
0112 return -EBUSY;
0113 }
0114
0115 ix = conn->qp.rq.pc & (conn->qp.rq.size - 1);
0116 data = mlx5_wq_cyc_get_wqe(&conn->qp.wq.rq, ix);
0117 data->byte_count = cpu_to_be32(buf->sg[0].size);
0118 data->lkey = cpu_to_be32(conn->fdev->conn_res.mkey);
0119 data->addr = cpu_to_be64(buf->sg[0].dma_addr);
0120
0121 conn->qp.rq.pc++;
0122 conn->qp.rq.bufs[ix] = buf;
0123
0124
0125 dma_wmb();
0126 *conn->qp.wq.rq.db = cpu_to_be32(conn->qp.rq.pc & 0xffff);
0127 out:
0128 return err;
0129 }
0130
0131 static void mlx5_fpga_conn_notify_hw(struct mlx5_fpga_conn *conn, void *wqe)
0132 {
0133
0134 dma_wmb();
0135 *conn->qp.wq.sq.db = cpu_to_be32(conn->qp.sq.pc);
0136
0137 wmb();
0138 mlx5_write64(wqe, conn->fdev->conn_res.uar->map + MLX5_BF_OFFSET);
0139 }
0140
0141 static void mlx5_fpga_conn_post_send(struct mlx5_fpga_conn *conn,
0142 struct mlx5_fpga_dma_buf *buf)
0143 {
0144 struct mlx5_wqe_ctrl_seg *ctrl;
0145 struct mlx5_wqe_data_seg *data;
0146 unsigned int ix, sgi;
0147 int size = 1;
0148
0149 ix = conn->qp.sq.pc & (conn->qp.sq.size - 1);
0150
0151 ctrl = mlx5_wq_cyc_get_wqe(&conn->qp.wq.sq, ix);
0152 data = (void *)(ctrl + 1);
0153
0154 for (sgi = 0; sgi < ARRAY_SIZE(buf->sg); sgi++) {
0155 if (!buf->sg[sgi].data)
0156 break;
0157 data->byte_count = cpu_to_be32(buf->sg[sgi].size);
0158 data->lkey = cpu_to_be32(conn->fdev->conn_res.mkey);
0159 data->addr = cpu_to_be64(buf->sg[sgi].dma_addr);
0160 data++;
0161 size++;
0162 }
0163
0164 ctrl->imm = 0;
0165 ctrl->fm_ce_se = MLX5_WQE_CTRL_CQ_UPDATE;
0166 ctrl->opmod_idx_opcode = cpu_to_be32(((conn->qp.sq.pc & 0xffff) << 8) |
0167 MLX5_OPCODE_SEND);
0168 ctrl->qpn_ds = cpu_to_be32(size | (conn->qp.qpn << 8));
0169
0170 conn->qp.sq.pc++;
0171 conn->qp.sq.bufs[ix] = buf;
0172 mlx5_fpga_conn_notify_hw(conn, ctrl);
0173 }
0174
0175 int mlx5_fpga_conn_send(struct mlx5_fpga_conn *conn,
0176 struct mlx5_fpga_dma_buf *buf)
0177 {
0178 unsigned long flags;
0179 int err;
0180
0181 if (!conn->qp.active)
0182 return -ENOTCONN;
0183
0184 buf->dma_dir = DMA_TO_DEVICE;
0185 err = mlx5_fpga_conn_map_buf(conn, buf);
0186 if (err)
0187 return err;
0188
0189 spin_lock_irqsave(&conn->qp.sq.lock, flags);
0190
0191 if (conn->qp.sq.pc - conn->qp.sq.cc >= conn->qp.sq.size) {
0192 list_add_tail(&buf->list, &conn->qp.sq.backlog);
0193 goto out_unlock;
0194 }
0195
0196 mlx5_fpga_conn_post_send(conn, buf);
0197
0198 out_unlock:
0199 spin_unlock_irqrestore(&conn->qp.sq.lock, flags);
0200 return err;
0201 }
0202
0203 static int mlx5_fpga_conn_post_recv_buf(struct mlx5_fpga_conn *conn)
0204 {
0205 struct mlx5_fpga_dma_buf *buf;
0206 int err;
0207
0208 buf = kzalloc(sizeof(*buf) + MLX5_FPGA_RECV_SIZE, 0);
0209 if (!buf)
0210 return -ENOMEM;
0211
0212 buf->sg[0].data = (void *)(buf + 1);
0213 buf->sg[0].size = MLX5_FPGA_RECV_SIZE;
0214 buf->dma_dir = DMA_FROM_DEVICE;
0215
0216 err = mlx5_fpga_conn_post_recv(conn, buf);
0217 if (err)
0218 kfree(buf);
0219
0220 return err;
0221 }
0222
0223 static int mlx5_fpga_conn_create_mkey(struct mlx5_core_dev *mdev, u32 pdn,
0224 u32 *mkey)
0225 {
0226 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
0227 void *mkc;
0228 u32 *in;
0229 int err;
0230
0231 in = kvzalloc(inlen, GFP_KERNEL);
0232 if (!in)
0233 return -ENOMEM;
0234
0235 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
0236 MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_PA);
0237 MLX5_SET(mkc, mkc, lw, 1);
0238 MLX5_SET(mkc, mkc, lr, 1);
0239
0240 MLX5_SET(mkc, mkc, pd, pdn);
0241 MLX5_SET(mkc, mkc, length64, 1);
0242 MLX5_SET(mkc, mkc, qpn, 0xffffff);
0243
0244 err = mlx5_core_create_mkey(mdev, mkey, in, inlen);
0245
0246 kvfree(in);
0247 return err;
0248 }
0249
0250 static void mlx5_fpga_conn_rq_cqe(struct mlx5_fpga_conn *conn,
0251 struct mlx5_cqe64 *cqe, u8 status)
0252 {
0253 struct mlx5_fpga_dma_buf *buf;
0254 int ix, err;
0255
0256 ix = be16_to_cpu(cqe->wqe_counter) & (conn->qp.rq.size - 1);
0257 buf = conn->qp.rq.bufs[ix];
0258 conn->qp.rq.bufs[ix] = NULL;
0259 conn->qp.rq.cc++;
0260
0261 if (unlikely(status && (status != MLX5_CQE_SYNDROME_WR_FLUSH_ERR)))
0262 mlx5_fpga_warn(conn->fdev, "RQ buf %p on FPGA QP %u completion status %d\n",
0263 buf, conn->fpga_qpn, status);
0264 else
0265 mlx5_fpga_dbg(conn->fdev, "RQ buf %p on FPGA QP %u completion status %d\n",
0266 buf, conn->fpga_qpn, status);
0267
0268 mlx5_fpga_conn_unmap_buf(conn, buf);
0269
0270 if (unlikely(status || !conn->qp.active)) {
0271 conn->qp.active = false;
0272 kfree(buf);
0273 return;
0274 }
0275
0276 buf->sg[0].size = be32_to_cpu(cqe->byte_cnt);
0277 mlx5_fpga_dbg(conn->fdev, "Message with %u bytes received successfully\n",
0278 buf->sg[0].size);
0279 conn->recv_cb(conn->cb_arg, buf);
0280
0281 buf->sg[0].size = MLX5_FPGA_RECV_SIZE;
0282 err = mlx5_fpga_conn_post_recv(conn, buf);
0283 if (unlikely(err)) {
0284 mlx5_fpga_warn(conn->fdev,
0285 "Failed to re-post recv buf: %d\n", err);
0286 kfree(buf);
0287 }
0288 }
0289
0290 static void mlx5_fpga_conn_sq_cqe(struct mlx5_fpga_conn *conn,
0291 struct mlx5_cqe64 *cqe, u8 status)
0292 {
0293 struct mlx5_fpga_dma_buf *buf, *nextbuf;
0294 unsigned long flags;
0295 int ix;
0296
0297 spin_lock_irqsave(&conn->qp.sq.lock, flags);
0298
0299 ix = be16_to_cpu(cqe->wqe_counter) & (conn->qp.sq.size - 1);
0300 buf = conn->qp.sq.bufs[ix];
0301 conn->qp.sq.bufs[ix] = NULL;
0302 conn->qp.sq.cc++;
0303
0304
0305 if (unlikely(!list_empty(&conn->qp.sq.backlog))) {
0306 if (likely(conn->qp.active)) {
0307 nextbuf = list_first_entry(&conn->qp.sq.backlog,
0308 struct mlx5_fpga_dma_buf, list);
0309 list_del(&nextbuf->list);
0310 mlx5_fpga_conn_post_send(conn, nextbuf);
0311 }
0312 }
0313
0314 spin_unlock_irqrestore(&conn->qp.sq.lock, flags);
0315
0316 if (unlikely(status && (status != MLX5_CQE_SYNDROME_WR_FLUSH_ERR)))
0317 mlx5_fpga_warn(conn->fdev, "SQ buf %p on FPGA QP %u completion status %d\n",
0318 buf, conn->fpga_qpn, status);
0319 else
0320 mlx5_fpga_dbg(conn->fdev, "SQ buf %p on FPGA QP %u completion status %d\n",
0321 buf, conn->fpga_qpn, status);
0322
0323 mlx5_fpga_conn_unmap_buf(conn, buf);
0324
0325 if (likely(buf->complete))
0326 buf->complete(conn, conn->fdev, buf, status);
0327
0328 if (unlikely(status))
0329 conn->qp.active = false;
0330 }
0331
0332 static void mlx5_fpga_conn_handle_cqe(struct mlx5_fpga_conn *conn,
0333 struct mlx5_cqe64 *cqe)
0334 {
0335 u8 opcode, status = 0;
0336
0337 opcode = get_cqe_opcode(cqe);
0338
0339 switch (opcode) {
0340 case MLX5_CQE_REQ_ERR:
0341 status = ((struct mlx5_err_cqe *)cqe)->syndrome;
0342 fallthrough;
0343 case MLX5_CQE_REQ:
0344 mlx5_fpga_conn_sq_cqe(conn, cqe, status);
0345 break;
0346
0347 case MLX5_CQE_RESP_ERR:
0348 status = ((struct mlx5_err_cqe *)cqe)->syndrome;
0349 fallthrough;
0350 case MLX5_CQE_RESP_SEND:
0351 mlx5_fpga_conn_rq_cqe(conn, cqe, status);
0352 break;
0353 default:
0354 mlx5_fpga_warn(conn->fdev, "Unexpected cqe opcode %u\n",
0355 opcode);
0356 }
0357 }
0358
0359 static void mlx5_fpga_conn_arm_cq(struct mlx5_fpga_conn *conn)
0360 {
0361 mlx5_cq_arm(&conn->cq.mcq, MLX5_CQ_DB_REQ_NOT,
0362 conn->fdev->conn_res.uar->map, conn->cq.wq.cc);
0363 }
0364
0365 static inline void mlx5_fpga_conn_cqes(struct mlx5_fpga_conn *conn,
0366 unsigned int budget)
0367 {
0368 struct mlx5_cqe64 *cqe;
0369
0370 while (budget) {
0371 cqe = mlx5_cqwq_get_cqe(&conn->cq.wq);
0372 if (!cqe)
0373 break;
0374
0375 budget--;
0376 mlx5_cqwq_pop(&conn->cq.wq);
0377 mlx5_fpga_conn_handle_cqe(conn, cqe);
0378 mlx5_cqwq_update_db_record(&conn->cq.wq);
0379 }
0380 if (!budget) {
0381 tasklet_schedule(&conn->cq.tasklet);
0382 return;
0383 }
0384
0385 mlx5_fpga_dbg(conn->fdev, "Re-arming CQ with cc# %u\n", conn->cq.wq.cc);
0386
0387 wmb();
0388 mlx5_fpga_conn_arm_cq(conn);
0389 }
0390
0391 static void mlx5_fpga_conn_cq_tasklet(struct tasklet_struct *t)
0392 {
0393 struct mlx5_fpga_conn *conn = from_tasklet(conn, t, cq.tasklet);
0394
0395 if (unlikely(!conn->qp.active))
0396 return;
0397 mlx5_fpga_conn_cqes(conn, MLX5_FPGA_CQ_BUDGET);
0398 }
0399
0400 static void mlx5_fpga_conn_cq_complete(struct mlx5_core_cq *mcq,
0401 struct mlx5_eqe *eqe)
0402 {
0403 struct mlx5_fpga_conn *conn;
0404
0405 conn = container_of(mcq, struct mlx5_fpga_conn, cq.mcq);
0406 if (unlikely(!conn->qp.active))
0407 return;
0408 mlx5_fpga_conn_cqes(conn, MLX5_FPGA_CQ_BUDGET);
0409 }
0410
0411 static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size)
0412 {
0413 struct mlx5_fpga_device *fdev = conn->fdev;
0414 struct mlx5_core_dev *mdev = fdev->mdev;
0415 u32 temp_cqc[MLX5_ST_SZ_DW(cqc)] = {0};
0416 u32 out[MLX5_ST_SZ_DW(create_cq_out)];
0417 struct mlx5_wq_param wqp;
0418 struct mlx5_cqe64 *cqe;
0419 int inlen, err, eqn;
0420 void *cqc, *in;
0421 __be64 *pas;
0422 u32 i;
0423
0424 cq_size = roundup_pow_of_two(cq_size);
0425 MLX5_SET(cqc, temp_cqc, log_cq_size, ilog2(cq_size));
0426
0427 wqp.buf_numa_node = mdev->priv.numa_node;
0428 wqp.db_numa_node = mdev->priv.numa_node;
0429
0430 err = mlx5_cqwq_create(mdev, &wqp, temp_cqc, &conn->cq.wq,
0431 &conn->cq.wq_ctrl);
0432 if (err)
0433 return err;
0434
0435 for (i = 0; i < mlx5_cqwq_get_size(&conn->cq.wq); i++) {
0436 cqe = mlx5_cqwq_get_wqe(&conn->cq.wq, i);
0437 cqe->op_own = MLX5_CQE_INVALID << 4 | MLX5_CQE_OWNER_MASK;
0438 }
0439
0440 inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
0441 sizeof(u64) * conn->cq.wq_ctrl.buf.npages;
0442 in = kvzalloc(inlen, GFP_KERNEL);
0443 if (!in) {
0444 err = -ENOMEM;
0445 goto err_cqwq;
0446 }
0447
0448 err = mlx5_vector2eqn(mdev, smp_processor_id(), &eqn);
0449 if (err) {
0450 kvfree(in);
0451 goto err_cqwq;
0452 }
0453
0454 cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context);
0455 MLX5_SET(cqc, cqc, log_cq_size, ilog2(cq_size));
0456 MLX5_SET(cqc, cqc, c_eqn_or_apu_element, eqn);
0457 MLX5_SET(cqc, cqc, uar_page, fdev->conn_res.uar->index);
0458 MLX5_SET(cqc, cqc, log_page_size, conn->cq.wq_ctrl.buf.page_shift -
0459 MLX5_ADAPTER_PAGE_SHIFT);
0460 MLX5_SET64(cqc, cqc, dbr_addr, conn->cq.wq_ctrl.db.dma);
0461
0462 pas = (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas);
0463 mlx5_fill_page_frag_array(&conn->cq.wq_ctrl.buf, pas);
0464
0465 err = mlx5_core_create_cq(mdev, &conn->cq.mcq, in, inlen, out, sizeof(out));
0466 kvfree(in);
0467
0468 if (err)
0469 goto err_cqwq;
0470
0471 conn->cq.mcq.cqe_sz = 64;
0472 conn->cq.mcq.set_ci_db = conn->cq.wq_ctrl.db.db;
0473 conn->cq.mcq.arm_db = conn->cq.wq_ctrl.db.db + 1;
0474 *conn->cq.mcq.set_ci_db = 0;
0475 *conn->cq.mcq.arm_db = 0;
0476 conn->cq.mcq.vector = 0;
0477 conn->cq.mcq.comp = mlx5_fpga_conn_cq_complete;
0478 conn->cq.mcq.uar = fdev->conn_res.uar;
0479 tasklet_setup(&conn->cq.tasklet, mlx5_fpga_conn_cq_tasklet);
0480
0481 mlx5_fpga_dbg(fdev, "Created CQ #0x%x\n", conn->cq.mcq.cqn);
0482
0483 goto out;
0484
0485 err_cqwq:
0486 mlx5_wq_destroy(&conn->cq.wq_ctrl);
0487 out:
0488 return err;
0489 }
0490
0491 static void mlx5_fpga_conn_destroy_cq(struct mlx5_fpga_conn *conn)
0492 {
0493 tasklet_disable(&conn->cq.tasklet);
0494 tasklet_kill(&conn->cq.tasklet);
0495 mlx5_core_destroy_cq(conn->fdev->mdev, &conn->cq.mcq);
0496 mlx5_wq_destroy(&conn->cq.wq_ctrl);
0497 }
0498
0499 static int mlx5_fpga_conn_create_wq(struct mlx5_fpga_conn *conn, void *qpc)
0500 {
0501 struct mlx5_fpga_device *fdev = conn->fdev;
0502 struct mlx5_core_dev *mdev = fdev->mdev;
0503 struct mlx5_wq_param wqp;
0504
0505 wqp.buf_numa_node = mdev->priv.numa_node;
0506 wqp.db_numa_node = mdev->priv.numa_node;
0507
0508 return mlx5_wq_qp_create(mdev, &wqp, qpc, &conn->qp.wq,
0509 &conn->qp.wq_ctrl);
0510 }
0511
0512 static int mlx5_fpga_conn_create_qp(struct mlx5_fpga_conn *conn,
0513 unsigned int tx_size, unsigned int rx_size)
0514 {
0515 struct mlx5_fpga_device *fdev = conn->fdev;
0516 u32 out[MLX5_ST_SZ_DW(create_qp_out)] = {};
0517 struct mlx5_core_dev *mdev = fdev->mdev;
0518 u32 temp_qpc[MLX5_ST_SZ_DW(qpc)] = {};
0519 void *in = NULL, *qpc;
0520 int err, inlen;
0521
0522 conn->qp.rq.pc = 0;
0523 conn->qp.rq.cc = 0;
0524 conn->qp.rq.size = roundup_pow_of_two(rx_size);
0525 conn->qp.sq.pc = 0;
0526 conn->qp.sq.cc = 0;
0527 conn->qp.sq.size = roundup_pow_of_two(tx_size);
0528
0529 MLX5_SET(qpc, temp_qpc, log_rq_stride, ilog2(MLX5_SEND_WQE_DS) - 4);
0530 MLX5_SET(qpc, temp_qpc, log_rq_size, ilog2(conn->qp.rq.size));
0531 MLX5_SET(qpc, temp_qpc, log_sq_size, ilog2(conn->qp.sq.size));
0532 err = mlx5_fpga_conn_create_wq(conn, temp_qpc);
0533 if (err)
0534 goto out;
0535
0536 conn->qp.rq.bufs = kvcalloc(conn->qp.rq.size,
0537 sizeof(conn->qp.rq.bufs[0]),
0538 GFP_KERNEL);
0539 if (!conn->qp.rq.bufs) {
0540 err = -ENOMEM;
0541 goto err_wq;
0542 }
0543
0544 conn->qp.sq.bufs = kvcalloc(conn->qp.sq.size,
0545 sizeof(conn->qp.sq.bufs[0]),
0546 GFP_KERNEL);
0547 if (!conn->qp.sq.bufs) {
0548 err = -ENOMEM;
0549 goto err_rq_bufs;
0550 }
0551
0552 inlen = MLX5_ST_SZ_BYTES(create_qp_in) +
0553 MLX5_FLD_SZ_BYTES(create_qp_in, pas[0]) *
0554 conn->qp.wq_ctrl.buf.npages;
0555 in = kvzalloc(inlen, GFP_KERNEL);
0556 if (!in) {
0557 err = -ENOMEM;
0558 goto err_sq_bufs;
0559 }
0560
0561 qpc = MLX5_ADDR_OF(create_qp_in, in, qpc);
0562 MLX5_SET(qpc, qpc, uar_page, fdev->conn_res.uar->index);
0563 MLX5_SET(qpc, qpc, log_page_size,
0564 conn->qp.wq_ctrl.buf.page_shift - MLX5_ADAPTER_PAGE_SHIFT);
0565 MLX5_SET(qpc, qpc, fre, 1);
0566 MLX5_SET(qpc, qpc, rlky, 1);
0567 MLX5_SET(qpc, qpc, st, MLX5_QP_ST_RC);
0568 MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED);
0569 MLX5_SET(qpc, qpc, pd, fdev->conn_res.pdn);
0570 MLX5_SET(qpc, qpc, log_rq_stride, ilog2(MLX5_SEND_WQE_DS) - 4);
0571 MLX5_SET(qpc, qpc, log_rq_size, ilog2(conn->qp.rq.size));
0572 MLX5_SET(qpc, qpc, rq_type, MLX5_NON_ZERO_RQ);
0573 MLX5_SET(qpc, qpc, log_sq_size, ilog2(conn->qp.sq.size));
0574 MLX5_SET(qpc, qpc, cqn_snd, conn->cq.mcq.cqn);
0575 MLX5_SET(qpc, qpc, cqn_rcv, conn->cq.mcq.cqn);
0576 MLX5_SET(qpc, qpc, ts_format, mlx5_get_qp_default_ts(mdev));
0577 MLX5_SET64(qpc, qpc, dbr_addr, conn->qp.wq_ctrl.db.dma);
0578 if (MLX5_CAP_GEN(mdev, cqe_version) == 1)
0579 MLX5_SET(qpc, qpc, user_index, 0xFFFFFF);
0580
0581 mlx5_fill_page_frag_array(&conn->qp.wq_ctrl.buf,
0582 (__be64 *)MLX5_ADDR_OF(create_qp_in, in, pas));
0583
0584 MLX5_SET(create_qp_in, in, opcode, MLX5_CMD_OP_CREATE_QP);
0585 err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
0586 if (err)
0587 goto err_sq_bufs;
0588
0589 conn->qp.qpn = MLX5_GET(create_qp_out, out, qpn);
0590 mlx5_fpga_dbg(fdev, "Created QP #0x%x\n", conn->qp.qpn);
0591
0592 goto out;
0593
0594 err_sq_bufs:
0595 kvfree(conn->qp.sq.bufs);
0596 err_rq_bufs:
0597 kvfree(conn->qp.rq.bufs);
0598 err_wq:
0599 mlx5_wq_destroy(&conn->qp.wq_ctrl);
0600 out:
0601 kvfree(in);
0602 return err;
0603 }
0604
0605 static void mlx5_fpga_conn_free_recv_bufs(struct mlx5_fpga_conn *conn)
0606 {
0607 int ix;
0608
0609 for (ix = 0; ix < conn->qp.rq.size; ix++) {
0610 if (!conn->qp.rq.bufs[ix])
0611 continue;
0612 mlx5_fpga_conn_unmap_buf(conn, conn->qp.rq.bufs[ix]);
0613 kfree(conn->qp.rq.bufs[ix]);
0614 conn->qp.rq.bufs[ix] = NULL;
0615 }
0616 }
0617
0618 static void mlx5_fpga_conn_flush_send_bufs(struct mlx5_fpga_conn *conn)
0619 {
0620 struct mlx5_fpga_dma_buf *buf, *temp;
0621 int ix;
0622
0623 for (ix = 0; ix < conn->qp.sq.size; ix++) {
0624 buf = conn->qp.sq.bufs[ix];
0625 if (!buf)
0626 continue;
0627 conn->qp.sq.bufs[ix] = NULL;
0628 mlx5_fpga_conn_unmap_buf(conn, buf);
0629 if (!buf->complete)
0630 continue;
0631 buf->complete(conn, conn->fdev, buf, MLX5_CQE_SYNDROME_WR_FLUSH_ERR);
0632 }
0633 list_for_each_entry_safe(buf, temp, &conn->qp.sq.backlog, list) {
0634 mlx5_fpga_conn_unmap_buf(conn, buf);
0635 if (!buf->complete)
0636 continue;
0637 buf->complete(conn, conn->fdev, buf, MLX5_CQE_SYNDROME_WR_FLUSH_ERR);
0638 }
0639 }
0640
0641 static void mlx5_fpga_conn_destroy_qp(struct mlx5_fpga_conn *conn)
0642 {
0643 struct mlx5_core_dev *dev = conn->fdev->mdev;
0644 u32 in[MLX5_ST_SZ_DW(destroy_qp_in)] = {};
0645
0646 MLX5_SET(destroy_qp_in, in, opcode, MLX5_CMD_OP_DESTROY_QP);
0647 MLX5_SET(destroy_qp_in, in, qpn, conn->qp.qpn);
0648 mlx5_cmd_exec_in(dev, destroy_qp, in);
0649
0650 mlx5_fpga_conn_free_recv_bufs(conn);
0651 mlx5_fpga_conn_flush_send_bufs(conn);
0652 kvfree(conn->qp.sq.bufs);
0653 kvfree(conn->qp.rq.bufs);
0654 mlx5_wq_destroy(&conn->qp.wq_ctrl);
0655 }
0656
0657 static int mlx5_fpga_conn_reset_qp(struct mlx5_fpga_conn *conn)
0658 {
0659 struct mlx5_core_dev *mdev = conn->fdev->mdev;
0660 u32 in[MLX5_ST_SZ_DW(qp_2rst_in)] = {};
0661
0662 mlx5_fpga_dbg(conn->fdev, "Modifying QP %u to RST\n", conn->qp.qpn);
0663
0664 MLX5_SET(qp_2rst_in, in, opcode, MLX5_CMD_OP_2RST_QP);
0665 MLX5_SET(qp_2rst_in, in, qpn, conn->qp.qpn);
0666
0667 return mlx5_cmd_exec_in(mdev, qp_2rst, in);
0668 }
0669
0670 static int mlx5_fpga_conn_init_qp(struct mlx5_fpga_conn *conn)
0671 {
0672 u32 in[MLX5_ST_SZ_DW(rst2init_qp_in)] = {};
0673 struct mlx5_fpga_device *fdev = conn->fdev;
0674 struct mlx5_core_dev *mdev = fdev->mdev;
0675 u32 *qpc;
0676
0677 mlx5_fpga_dbg(conn->fdev, "Modifying QP %u to INIT\n", conn->qp.qpn);
0678
0679 qpc = MLX5_ADDR_OF(rst2init_qp_in, in, qpc);
0680
0681 MLX5_SET(qpc, qpc, st, MLX5_QP_ST_RC);
0682 MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED);
0683 MLX5_SET(qpc, qpc, primary_address_path.pkey_index, MLX5_FPGA_PKEY_INDEX);
0684 MLX5_SET(qpc, qpc, primary_address_path.vhca_port_num, MLX5_FPGA_PORT_NUM);
0685 MLX5_SET(qpc, qpc, pd, conn->fdev->conn_res.pdn);
0686 MLX5_SET(qpc, qpc, cqn_snd, conn->cq.mcq.cqn);
0687 MLX5_SET(qpc, qpc, cqn_rcv, conn->cq.mcq.cqn);
0688 MLX5_SET64(qpc, qpc, dbr_addr, conn->qp.wq_ctrl.db.dma);
0689
0690 MLX5_SET(rst2init_qp_in, in, opcode, MLX5_CMD_OP_RST2INIT_QP);
0691 MLX5_SET(rst2init_qp_in, in, qpn, conn->qp.qpn);
0692
0693 return mlx5_cmd_exec_in(mdev, rst2init_qp, in);
0694 }
0695
0696 static int mlx5_fpga_conn_rtr_qp(struct mlx5_fpga_conn *conn)
0697 {
0698 u32 in[MLX5_ST_SZ_DW(init2rtr_qp_in)] = {};
0699 struct mlx5_fpga_device *fdev = conn->fdev;
0700 struct mlx5_core_dev *mdev = fdev->mdev;
0701 u32 *qpc;
0702
0703 mlx5_fpga_dbg(conn->fdev, "QP RTR\n");
0704
0705 qpc = MLX5_ADDR_OF(init2rtr_qp_in, in, qpc);
0706
0707 MLX5_SET(qpc, qpc, mtu, MLX5_QPC_MTU_1K_BYTES);
0708 MLX5_SET(qpc, qpc, log_msg_max, (u8)MLX5_CAP_GEN(mdev, log_max_msg));
0709 MLX5_SET(qpc, qpc, remote_qpn, conn->fpga_qpn);
0710 MLX5_SET(qpc, qpc, next_rcv_psn,
0711 MLX5_GET(fpga_qpc, conn->fpga_qpc, next_send_psn));
0712 MLX5_SET(qpc, qpc, primary_address_path.pkey_index, MLX5_FPGA_PKEY_INDEX);
0713 MLX5_SET(qpc, qpc, primary_address_path.vhca_port_num, MLX5_FPGA_PORT_NUM);
0714 ether_addr_copy(MLX5_ADDR_OF(qpc, qpc, primary_address_path.rmac_47_32),
0715 MLX5_ADDR_OF(fpga_qpc, conn->fpga_qpc, fpga_mac_47_32));
0716 MLX5_SET(qpc, qpc, primary_address_path.udp_sport,
0717 MLX5_CAP_ROCE(mdev, r_roce_min_src_udp_port));
0718 MLX5_SET(qpc, qpc, primary_address_path.src_addr_index,
0719 conn->qp.sgid_index);
0720 MLX5_SET(qpc, qpc, primary_address_path.hop_limit, 0);
0721 memcpy(MLX5_ADDR_OF(qpc, qpc, primary_address_path.rgid_rip),
0722 MLX5_ADDR_OF(fpga_qpc, conn->fpga_qpc, fpga_ip),
0723 MLX5_FLD_SZ_BYTES(qpc, primary_address_path.rgid_rip));
0724
0725 MLX5_SET(init2rtr_qp_in, in, opcode, MLX5_CMD_OP_INIT2RTR_QP);
0726 MLX5_SET(init2rtr_qp_in, in, qpn, conn->qp.qpn);
0727
0728 return mlx5_cmd_exec_in(mdev, init2rtr_qp, in);
0729 }
0730
0731 static int mlx5_fpga_conn_rts_qp(struct mlx5_fpga_conn *conn)
0732 {
0733 struct mlx5_fpga_device *fdev = conn->fdev;
0734 u32 in[MLX5_ST_SZ_DW(rtr2rts_qp_in)] = {};
0735 struct mlx5_core_dev *mdev = fdev->mdev;
0736 u32 *qpc;
0737
0738 mlx5_fpga_dbg(conn->fdev, "QP RTS\n");
0739
0740 qpc = MLX5_ADDR_OF(rtr2rts_qp_in, in, qpc);
0741
0742 MLX5_SET(qpc, qpc, log_ack_req_freq, 8);
0743 MLX5_SET(qpc, qpc, min_rnr_nak, 0x12);
0744 MLX5_SET(qpc, qpc, primary_address_path.ack_timeout, 0x12);
0745 MLX5_SET(qpc, qpc, next_send_psn,
0746 MLX5_GET(fpga_qpc, conn->fpga_qpc, next_rcv_psn));
0747 MLX5_SET(qpc, qpc, retry_count, 7);
0748 MLX5_SET(qpc, qpc, rnr_retry, 7);
0749
0750 MLX5_SET(rtr2rts_qp_in, in, opcode, MLX5_CMD_OP_RTR2RTS_QP);
0751 MLX5_SET(rtr2rts_qp_in, in, qpn, conn->qp.qpn);
0752 MLX5_SET(rtr2rts_qp_in, in, opt_param_mask, MLX5_QP_OPTPAR_RNR_TIMEOUT);
0753
0754 return mlx5_cmd_exec_in(mdev, rtr2rts_qp, in);
0755 }
0756
0757 static int mlx5_fpga_conn_connect(struct mlx5_fpga_conn *conn)
0758 {
0759 struct mlx5_fpga_device *fdev = conn->fdev;
0760 int err;
0761
0762 MLX5_SET(fpga_qpc, conn->fpga_qpc, state, MLX5_FPGA_QPC_STATE_ACTIVE);
0763 err = mlx5_fpga_modify_qp(conn->fdev->mdev, conn->fpga_qpn,
0764 MLX5_FPGA_QPC_STATE, &conn->fpga_qpc);
0765 if (err) {
0766 mlx5_fpga_err(fdev, "Failed to activate FPGA RC QP: %d\n", err);
0767 goto out;
0768 }
0769
0770 err = mlx5_fpga_conn_reset_qp(conn);
0771 if (err) {
0772 mlx5_fpga_err(fdev, "Failed to change QP state to reset\n");
0773 goto err_fpga_qp;
0774 }
0775
0776 err = mlx5_fpga_conn_init_qp(conn);
0777 if (err) {
0778 mlx5_fpga_err(fdev, "Failed to modify QP from RESET to INIT\n");
0779 goto err_fpga_qp;
0780 }
0781 conn->qp.active = true;
0782
0783 while (!mlx5_fpga_conn_post_recv_buf(conn))
0784 ;
0785
0786 err = mlx5_fpga_conn_rtr_qp(conn);
0787 if (err) {
0788 mlx5_fpga_err(fdev, "Failed to change QP state from INIT to RTR\n");
0789 goto err_recv_bufs;
0790 }
0791
0792 err = mlx5_fpga_conn_rts_qp(conn);
0793 if (err) {
0794 mlx5_fpga_err(fdev, "Failed to change QP state from RTR to RTS\n");
0795 goto err_recv_bufs;
0796 }
0797 goto out;
0798
0799 err_recv_bufs:
0800 mlx5_fpga_conn_free_recv_bufs(conn);
0801 err_fpga_qp:
0802 MLX5_SET(fpga_qpc, conn->fpga_qpc, state, MLX5_FPGA_QPC_STATE_INIT);
0803 if (mlx5_fpga_modify_qp(conn->fdev->mdev, conn->fpga_qpn,
0804 MLX5_FPGA_QPC_STATE, &conn->fpga_qpc))
0805 mlx5_fpga_err(fdev, "Failed to revert FPGA QP to INIT\n");
0806 out:
0807 return err;
0808 }
0809
0810 struct mlx5_fpga_conn *mlx5_fpga_conn_create(struct mlx5_fpga_device *fdev,
0811 struct mlx5_fpga_conn_attr *attr,
0812 enum mlx5_ifc_fpga_qp_type qp_type)
0813 {
0814 struct mlx5_fpga_conn *ret, *conn;
0815 u8 *remote_mac, *remote_ip;
0816 int err;
0817
0818 if (!attr->recv_cb)
0819 return ERR_PTR(-EINVAL);
0820
0821 conn = kzalloc(sizeof(*conn), GFP_KERNEL);
0822 if (!conn)
0823 return ERR_PTR(-ENOMEM);
0824
0825 conn->fdev = fdev;
0826 INIT_LIST_HEAD(&conn->qp.sq.backlog);
0827
0828 spin_lock_init(&conn->qp.sq.lock);
0829
0830 conn->recv_cb = attr->recv_cb;
0831 conn->cb_arg = attr->cb_arg;
0832
0833 remote_mac = MLX5_ADDR_OF(fpga_qpc, conn->fpga_qpc, remote_mac_47_32);
0834 err = mlx5_query_mac_address(fdev->mdev, remote_mac);
0835 if (err) {
0836 mlx5_fpga_err(fdev, "Failed to query local MAC: %d\n", err);
0837 ret = ERR_PTR(err);
0838 goto err;
0839 }
0840
0841
0842 remote_ip = MLX5_ADDR_OF(fpga_qpc, conn->fpga_qpc, remote_ip);
0843 remote_ip[0] = 0xfe;
0844 remote_ip[1] = 0x80;
0845 addrconf_addr_eui48(&remote_ip[8], remote_mac);
0846
0847 err = mlx5_core_reserved_gid_alloc(fdev->mdev, &conn->qp.sgid_index);
0848 if (err) {
0849 mlx5_fpga_err(fdev, "Failed to allocate SGID: %d\n", err);
0850 ret = ERR_PTR(err);
0851 goto err;
0852 }
0853
0854 err = mlx5_core_roce_gid_set(fdev->mdev, conn->qp.sgid_index,
0855 MLX5_ROCE_VERSION_2,
0856 MLX5_ROCE_L3_TYPE_IPV6,
0857 remote_ip, remote_mac, true, 0,
0858 MLX5_FPGA_PORT_NUM);
0859 if (err) {
0860 mlx5_fpga_err(fdev, "Failed to set SGID: %d\n", err);
0861 ret = ERR_PTR(err);
0862 goto err_rsvd_gid;
0863 }
0864 mlx5_fpga_dbg(fdev, "Reserved SGID index %u\n", conn->qp.sgid_index);
0865
0866
0867
0868
0869 err = mlx5_fpga_conn_create_cq(conn,
0870 (attr->tx_size + attr->rx_size) * 2);
0871 if (err) {
0872 mlx5_fpga_err(fdev, "Failed to create CQ: %d\n", err);
0873 ret = ERR_PTR(err);
0874 goto err_gid;
0875 }
0876
0877 mlx5_fpga_conn_arm_cq(conn);
0878
0879 err = mlx5_fpga_conn_create_qp(conn, attr->tx_size, attr->rx_size);
0880 if (err) {
0881 mlx5_fpga_err(fdev, "Failed to create QP: %d\n", err);
0882 ret = ERR_PTR(err);
0883 goto err_cq;
0884 }
0885
0886 MLX5_SET(fpga_qpc, conn->fpga_qpc, state, MLX5_FPGA_QPC_STATE_INIT);
0887 MLX5_SET(fpga_qpc, conn->fpga_qpc, qp_type, qp_type);
0888 MLX5_SET(fpga_qpc, conn->fpga_qpc, st, MLX5_FPGA_QPC_ST_RC);
0889 MLX5_SET(fpga_qpc, conn->fpga_qpc, ether_type, ETH_P_8021Q);
0890 MLX5_SET(fpga_qpc, conn->fpga_qpc, vid, 0);
0891 MLX5_SET(fpga_qpc, conn->fpga_qpc, next_rcv_psn, 1);
0892 MLX5_SET(fpga_qpc, conn->fpga_qpc, next_send_psn, 0);
0893 MLX5_SET(fpga_qpc, conn->fpga_qpc, pkey, MLX5_FPGA_PKEY);
0894 MLX5_SET(fpga_qpc, conn->fpga_qpc, remote_qpn, conn->qp.qpn);
0895 MLX5_SET(fpga_qpc, conn->fpga_qpc, rnr_retry, 7);
0896 MLX5_SET(fpga_qpc, conn->fpga_qpc, retry_count, 7);
0897
0898 err = mlx5_fpga_create_qp(fdev->mdev, &conn->fpga_qpc,
0899 &conn->fpga_qpn);
0900 if (err) {
0901 mlx5_fpga_err(fdev, "Failed to create FPGA RC QP: %d\n", err);
0902 ret = ERR_PTR(err);
0903 goto err_qp;
0904 }
0905
0906 err = mlx5_fpga_conn_connect(conn);
0907 if (err) {
0908 ret = ERR_PTR(err);
0909 goto err_conn;
0910 }
0911
0912 mlx5_fpga_dbg(fdev, "FPGA QPN is %u\n", conn->fpga_qpn);
0913 ret = conn;
0914 goto out;
0915
0916 err_conn:
0917 mlx5_fpga_destroy_qp(conn->fdev->mdev, conn->fpga_qpn);
0918 err_qp:
0919 mlx5_fpga_conn_destroy_qp(conn);
0920 err_cq:
0921 mlx5_fpga_conn_destroy_cq(conn);
0922 err_gid:
0923 mlx5_core_roce_gid_set(fdev->mdev, conn->qp.sgid_index, 0, 0, NULL,
0924 NULL, false, 0, MLX5_FPGA_PORT_NUM);
0925 err_rsvd_gid:
0926 mlx5_core_reserved_gid_free(fdev->mdev, conn->qp.sgid_index);
0927 err:
0928 kfree(conn);
0929 out:
0930 return ret;
0931 }
0932
0933 void mlx5_fpga_conn_destroy(struct mlx5_fpga_conn *conn)
0934 {
0935 conn->qp.active = false;
0936 tasklet_disable(&conn->cq.tasklet);
0937 synchronize_irq(conn->cq.mcq.irqn);
0938
0939 mlx5_fpga_destroy_qp(conn->fdev->mdev, conn->fpga_qpn);
0940 mlx5_fpga_conn_destroy_qp(conn);
0941 mlx5_fpga_conn_destroy_cq(conn);
0942
0943 mlx5_core_roce_gid_set(conn->fdev->mdev, conn->qp.sgid_index, 0, 0,
0944 NULL, NULL, false, 0, MLX5_FPGA_PORT_NUM);
0945 mlx5_core_reserved_gid_free(conn->fdev->mdev, conn->qp.sgid_index);
0946 kfree(conn);
0947 }
0948
0949 int mlx5_fpga_conn_device_init(struct mlx5_fpga_device *fdev)
0950 {
0951 int err;
0952
0953 err = mlx5_nic_vport_enable_roce(fdev->mdev);
0954 if (err) {
0955 mlx5_fpga_err(fdev, "Failed to enable RoCE: %d\n", err);
0956 goto out;
0957 }
0958
0959 fdev->conn_res.uar = mlx5_get_uars_page(fdev->mdev);
0960 if (IS_ERR(fdev->conn_res.uar)) {
0961 err = PTR_ERR(fdev->conn_res.uar);
0962 mlx5_fpga_err(fdev, "get_uars_page failed, %d\n", err);
0963 goto err_roce;
0964 }
0965 mlx5_fpga_dbg(fdev, "Allocated UAR index %u\n",
0966 fdev->conn_res.uar->index);
0967
0968 err = mlx5_core_alloc_pd(fdev->mdev, &fdev->conn_res.pdn);
0969 if (err) {
0970 mlx5_fpga_err(fdev, "alloc pd failed, %d\n", err);
0971 goto err_uar;
0972 }
0973 mlx5_fpga_dbg(fdev, "Allocated PD %u\n", fdev->conn_res.pdn);
0974
0975 err = mlx5_fpga_conn_create_mkey(fdev->mdev, fdev->conn_res.pdn,
0976 &fdev->conn_res.mkey);
0977 if (err) {
0978 mlx5_fpga_err(fdev, "create mkey failed, %d\n", err);
0979 goto err_dealloc_pd;
0980 }
0981 mlx5_fpga_dbg(fdev, "Created mkey 0x%x\n", fdev->conn_res.mkey);
0982
0983 return 0;
0984
0985 err_dealloc_pd:
0986 mlx5_core_dealloc_pd(fdev->mdev, fdev->conn_res.pdn);
0987 err_uar:
0988 mlx5_put_uars_page(fdev->mdev, fdev->conn_res.uar);
0989 err_roce:
0990 mlx5_nic_vport_disable_roce(fdev->mdev);
0991 out:
0992 return err;
0993 }
0994
0995 void mlx5_fpga_conn_device_cleanup(struct mlx5_fpga_device *fdev)
0996 {
0997 mlx5_core_destroy_mkey(fdev->mdev, fdev->conn_res.mkey);
0998 mlx5_core_dealloc_pd(fdev->mdev, fdev->conn_res.pdn);
0999 mlx5_put_uars_page(fdev->mdev, fdev->conn_res.uar);
1000 mlx5_nic_vport_disable_roce(fdev->mdev);
1001 }