diff options
author | Roland Dreier <rolandd@cisco.com> | 2008-07-23 11:12:26 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-07-23 11:12:26 -0400 |
commit | 95d04f0735b4fc837bff9aedcc3f3efb20ddc3d1 (patch) | |
tree | 900cd7debae9827c3e20f5199307ae27e83ba862 /drivers/infiniband/hw/mlx4/qp.c | |
parent | e4044cfc493338cd09870bd45dc646336bb66e9f (diff) |
IB/mlx4: Add support for memory management extensions and local DMA L_Key
Add support for the following operations to mlx4 when device firmware
supports them:
- Send with invalidate and local invalidate send queue work requests;
- Allocate/free fast register MRs;
- Allocate/free fast register MR page lists;
- Fast register MR send queue work requests;
- Local DMA L_Key.
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/mlx4/qp.c')
-rw-r--r-- | drivers/infiniband/hw/mlx4/qp.c | 72 |
1 files changed, 67 insertions, 5 deletions
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index bda0859a5ac5..02a99bc4442e 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c | |||
@@ -78,6 +78,9 @@ static const __be32 mlx4_ib_opcode[] = { | |||
78 | [IB_WR_RDMA_READ] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_READ), | 78 | [IB_WR_RDMA_READ] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_READ), |
79 | [IB_WR_ATOMIC_CMP_AND_SWP] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_CS), | 79 | [IB_WR_ATOMIC_CMP_AND_SWP] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_CS), |
80 | [IB_WR_ATOMIC_FETCH_AND_ADD] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_FA), | 80 | [IB_WR_ATOMIC_FETCH_AND_ADD] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_FA), |
81 | [IB_WR_SEND_WITH_INV] = __constant_cpu_to_be32(MLX4_OPCODE_SEND_INVAL), | ||
82 | [IB_WR_LOCAL_INV] = __constant_cpu_to_be32(MLX4_OPCODE_LOCAL_INVAL), | ||
83 | [IB_WR_FAST_REG_MR] = __constant_cpu_to_be32(MLX4_OPCODE_FMR), | ||
81 | }; | 84 | }; |
82 | 85 | ||
83 | static struct mlx4_ib_sqp *to_msqp(struct mlx4_ib_qp *mqp) | 86 | static struct mlx4_ib_sqp *to_msqp(struct mlx4_ib_qp *mqp) |
@@ -976,6 +979,10 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, | |||
976 | context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pdn); | 979 | context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pdn); |
977 | context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28); | 980 | context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28); |
978 | 981 | ||
982 | /* Set "fast registration enabled" for all kernel QPs */ | ||
983 | if (!qp->ibqp.uobject) | ||
984 | context->params1 |= cpu_to_be32(1 << 11); | ||
985 | |||
979 | if (attr_mask & IB_QP_RNR_RETRY) { | 986 | if (attr_mask & IB_QP_RNR_RETRY) { |
980 | context->params1 |= cpu_to_be32(attr->rnr_retry << 13); | 987 | context->params1 |= cpu_to_be32(attr->rnr_retry << 13); |
981 | optpar |= MLX4_QP_OPTPAR_RNR_RETRY; | 988 | optpar |= MLX4_QP_OPTPAR_RNR_RETRY; |
@@ -1322,6 +1329,38 @@ static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq | |||
1322 | return cur + nreq >= wq->max_post; | 1329 | return cur + nreq >= wq->max_post; |
1323 | } | 1330 | } |
1324 | 1331 | ||
1332 | static __be32 convert_access(int acc) | ||
1333 | { | ||
1334 | return (acc & IB_ACCESS_REMOTE_ATOMIC ? cpu_to_be32(MLX4_WQE_FMR_PERM_ATOMIC) : 0) | | ||
1335 | (acc & IB_ACCESS_REMOTE_WRITE ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_WRITE) : 0) | | ||
1336 | (acc & IB_ACCESS_REMOTE_READ ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_READ) : 0) | | ||
1337 | (acc & IB_ACCESS_LOCAL_WRITE ? cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_WRITE) : 0) | | ||
1338 | cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_READ); | ||
1339 | } | ||
1340 | |||
1341 | static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg, struct ib_send_wr *wr) | ||
1342 | { | ||
1343 | struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(wr->wr.fast_reg.page_list); | ||
1344 | |||
1345 | fseg->flags = convert_access(wr->wr.fast_reg.access_flags); | ||
1346 | fseg->mem_key = cpu_to_be32(wr->wr.fast_reg.rkey); | ||
1347 | fseg->buf_list = cpu_to_be64(mfrpl->map); | ||
1348 | fseg->start_addr = cpu_to_be64(wr->wr.fast_reg.iova_start); | ||
1349 | fseg->reg_len = cpu_to_be64(wr->wr.fast_reg.length); | ||
1350 | fseg->offset = 0; /* XXX -- is this just for ZBVA? */ | ||
1351 | fseg->page_size = cpu_to_be32(wr->wr.fast_reg.page_shift); | ||
1352 | fseg->reserved[0] = 0; | ||
1353 | fseg->reserved[1] = 0; | ||
1354 | } | ||
1355 | |||
1356 | static void set_local_inv_seg(struct mlx4_wqe_local_inval_seg *iseg, u32 rkey) | ||
1357 | { | ||
1358 | iseg->flags = 0; | ||
1359 | iseg->mem_key = cpu_to_be32(rkey); | ||
1360 | iseg->guest_id = 0; | ||
1361 | iseg->pa = 0; | ||
1362 | } | ||
1363 | |||
1325 | static __always_inline void set_raddr_seg(struct mlx4_wqe_raddr_seg *rseg, | 1364 | static __always_inline void set_raddr_seg(struct mlx4_wqe_raddr_seg *rseg, |
1326 | u64 remote_addr, u32 rkey) | 1365 | u64 remote_addr, u32 rkey) |
1327 | { | 1366 | { |
@@ -1423,6 +1462,21 @@ static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr, | |||
1423 | return 0; | 1462 | return 0; |
1424 | } | 1463 | } |
1425 | 1464 | ||
1465 | static __be32 send_ieth(struct ib_send_wr *wr) | ||
1466 | { | ||
1467 | switch (wr->opcode) { | ||
1468 | case IB_WR_SEND_WITH_IMM: | ||
1469 | case IB_WR_RDMA_WRITE_WITH_IMM: | ||
1470 | return wr->ex.imm_data; | ||
1471 | |||
1472 | case IB_WR_SEND_WITH_INV: | ||
1473 | return cpu_to_be32(wr->ex.invalidate_rkey); | ||
1474 | |||
1475 | default: | ||
1476 | return 0; | ||
1477 | } | ||
1478 | } | ||
1479 | |||
1426 | int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | 1480 | int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, |
1427 | struct ib_send_wr **bad_wr) | 1481 | struct ib_send_wr **bad_wr) |
1428 | { | 1482 | { |
@@ -1469,11 +1523,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1469 | MLX4_WQE_CTRL_TCP_UDP_CSUM) : 0) | | 1523 | MLX4_WQE_CTRL_TCP_UDP_CSUM) : 0) | |
1470 | qp->sq_signal_bits; | 1524 | qp->sq_signal_bits; |
1471 | 1525 | ||
1472 | if (wr->opcode == IB_WR_SEND_WITH_IMM || | 1526 | ctrl->imm = send_ieth(wr); |
1473 | wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) | ||
1474 | ctrl->imm = wr->ex.imm_data; | ||
1475 | else | ||
1476 | ctrl->imm = 0; | ||
1477 | 1527 | ||
1478 | wqe += sizeof *ctrl; | 1528 | wqe += sizeof *ctrl; |
1479 | size = sizeof *ctrl / 16; | 1529 | size = sizeof *ctrl / 16; |
@@ -1505,6 +1555,18 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1505 | size += sizeof (struct mlx4_wqe_raddr_seg) / 16; | 1555 | size += sizeof (struct mlx4_wqe_raddr_seg) / 16; |
1506 | break; | 1556 | break; |
1507 | 1557 | ||
1558 | case IB_WR_LOCAL_INV: | ||
1559 | set_local_inv_seg(wqe, wr->ex.invalidate_rkey); | ||
1560 | wqe += sizeof (struct mlx4_wqe_local_inval_seg); | ||
1561 | size += sizeof (struct mlx4_wqe_local_inval_seg) / 16; | ||
1562 | break; | ||
1563 | |||
1564 | case IB_WR_FAST_REG_MR: | ||
1565 | set_fmr_seg(wqe, wr); | ||
1566 | wqe += sizeof (struct mlx4_wqe_fmr_seg); | ||
1567 | size += sizeof (struct mlx4_wqe_fmr_seg) / 16; | ||
1568 | break; | ||
1569 | |||
1508 | default: | 1570 | default: |
1509 | /* No extra segments required for sends */ | 1571 | /* No extra segments required for sends */ |
1510 | break; | 1572 | break; |