Re: [PATCH for-next v3 4/6] RDMA-rxe: Isolate mr code from atomic_write_reply()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Jan 14, 2023 at 7:28 AM Bob Pearson <rpearsonhpe@xxxxxxxxx> wrote:
>
> Isolate mr specific code from atomic_write_reply() in rxe_resp.c into
> a subroutine rxe_mr_do_atomic_write() in rxe_mr.c.
> Check length for atomic write operation.
> Make iova_to_vaddr() static.
>
> Signed-off-by: Bob Pearson <rpearsonhpe@xxxxxxxxx>
> ---
> v3:
>   Fixed bug reported by kernel test robot. Ifdef'ed out atomic 8 byte
>   write if CONFIG_64BIT is not defined as orignally intended by the
>   developers of the atomic write implementation.
> link: https://lore.kernel.org/linux-rdma/202301131143.CmoyVcul-lkp@xxxxxxxxx/
>
>  drivers/infiniband/sw/rxe/rxe_loc.h  |  1 +
>  drivers/infiniband/sw/rxe/rxe_mr.c   | 50 ++++++++++++++++++++++++
>  drivers/infiniband/sw/rxe/rxe_resp.c | 58 +++++++++++-----------------
>  3 files changed, 73 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h
> index bcb1bbcf50df..fd70c71a9e4e 100644
> --- a/drivers/infiniband/sw/rxe/rxe_loc.h
> +++ b/drivers/infiniband/sw/rxe/rxe_loc.h
> @@ -74,6 +74,7 @@ int rxe_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg,
>  void *iova_to_vaddr(struct rxe_mr *mr, u64 iova, int length);
>  int rxe_mr_do_atomic_op(struct rxe_mr *mr, u64 iova, int opcode,
>                         u64 compare, u64 swap_add, u64 *orig_val);
> +int rxe_mr_do_atomic_write(struct rxe_mr *mr, u64 iova, void *addr);
>  struct rxe_mr *lookup_mr(struct rxe_pd *pd, int access, u32 key,
>                          enum rxe_mr_lookup_type type);
>  int mr_check_range(struct rxe_mr *mr, u64 iova, size_t length);
> diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c
> index 791731be6067..1e74f5e8e10b 100644
> --- a/drivers/infiniband/sw/rxe/rxe_mr.c
> +++ b/drivers/infiniband/sw/rxe/rxe_mr.c
> @@ -568,6 +568,56 @@ int rxe_mr_do_atomic_op(struct rxe_mr *mr, u64 iova, int opcode,
>         return 0;
>  }
>
> +/**
> + * rxe_mr_do_atomic_write() - write 64bit value to iova from addr
> + * @mr: memory region
> + * @iova: iova in mr
> + * @addr: source of data to write
> + *
> + * Returns:
> + *      0 on success
> + *     -1 for misaligned address
> + *     -2 for access errors
> + *     -3 for cpu without native 64 bit support
> + */
> +int rxe_mr_do_atomic_write(struct rxe_mr *mr, u64 iova, void *addr)
> +{
> +#if defined CONFIG_64BIT

IS_ENABLED is better?

Zhu Yanjun

> +       u64 *vaddr;
> +       u64 value;
> +       unsigned int length = 8;
> +
> +       /* See IBA oA19-28 */
> +       if (unlikely(mr->state != RXE_MR_STATE_VALID)) {
> +               rxe_dbg_mr(mr, "mr not valid");
> +               return -2;
> +       }
> +
> +       /* See IBA A19.4.2 */
> +       if (unlikely((uintptr_t)vaddr & 0x7 || iova & 0x7)) {
> +               rxe_dbg_mr(mr, "misaligned address");
> +               return -1;
> +       }
> +
> +       vaddr = iova_to_vaddr(mr, iova, length);
> +       if (unlikely(!vaddr)) {
> +               rxe_dbg_mr(mr, "iova out of range");
> +               return -2;
> +       }
> +
> +       /* this makes no sense. What of payload is not 8? */
> +       memcpy(&value, addr, length);
> +
> +       /* Do atomic write after all prior operations have completed */
> +       smp_store_release(vaddr, value);
> +
> +       return 0;
> +#else
> +       rxe_dbg_mr(mr, "64 bit integers not atomic");
> +       return -3;
> +#endif
> +}
> +
>  int advance_dma_data(struct rxe_dma_info *dma, unsigned int length)
>  {
>         struct rxe_sge          *sge    = &dma->sge[dma->cur_sge];
> diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
> index 02301e3f343c..1083cda22c65 100644
> --- a/drivers/infiniband/sw/rxe/rxe_resp.c
> +++ b/drivers/infiniband/sw/rxe/rxe_resp.c
> @@ -762,26 +762,33 @@ static enum resp_states atomic_reply(struct rxe_qp *qp,
>         return RESPST_ACKNOWLEDGE;
>  }
>
> -#ifdef CONFIG_64BIT
> -static enum resp_states do_atomic_write(struct rxe_qp *qp,
> -                                       struct rxe_pkt_info *pkt)
> +static enum resp_states atomic_write_reply(struct rxe_qp *qp,
> +                                          struct rxe_pkt_info *pkt)
>  {
> +       u64 iova = qp->resp.va + qp->resp.offset;
> +       struct resp_res *res = qp->resp.res;
>         struct rxe_mr *mr = qp->resp.mr;
> +       void *addr = payload_addr(pkt);
>         int payload = payload_size(pkt);
> -       u64 src, *dst;
> -
> -       if (mr->state != RXE_MR_STATE_VALID)
> -               return RESPST_ERR_RKEY_VIOLATION;
> +       int err;
>
> -       memcpy(&src, payload_addr(pkt), payload);
> +       if (!res) {
> +               res = rxe_prepare_res(qp, pkt, RXE_ATOMIC_WRITE_MASK);
> +               qp->resp.res = res;
> +       }
>
> -       dst = iova_to_vaddr(mr, qp->resp.va + qp->resp.offset, payload);
> -       /* check vaddr is 8 bytes aligned. */
> -       if (!dst || (uintptr_t)dst & 7)
> -               return RESPST_ERR_MISALIGNED_ATOMIC;
> +       if (res->replay)
> +               return RESPST_ACKNOWLEDGE;
>
> -       /* Do atomic write after all prior operations have completed */
> -       smp_store_release(dst, src);
> +       err = rxe_mr_do_atomic_write(mr, iova, addr);
> +       if (unlikely(err)) {
> +               if (err == -3)
> +                       return RESPST_ERR_UNSUPPORTED_OPCODE;
> +               else if (err == -2)
> +                       return RESPST_ERR_RKEY_VIOLATION;
> +               else
> +                       return RESPST_ERR_MISALIGNED_ATOMIC;
> +       }
>
>         /* decrease resp.resid to zero */
>         qp->resp.resid -= sizeof(payload);
> @@ -794,29 +801,8 @@ static enum resp_states do_atomic_write(struct rxe_qp *qp,
>
>         qp->resp.opcode = pkt->opcode;
>         qp->resp.status = IB_WC_SUCCESS;
> -       return RESPST_ACKNOWLEDGE;
> -}
> -#else
> -static enum resp_states do_atomic_write(struct rxe_qp *qp,
> -                                       struct rxe_pkt_info *pkt)
> -{
> -       return RESPST_ERR_UNSUPPORTED_OPCODE;
> -}
> -#endif /* CONFIG_64BIT */
> -
> -static enum resp_states atomic_write_reply(struct rxe_qp *qp,
> -                                          struct rxe_pkt_info *pkt)
> -{
> -       struct resp_res *res = qp->resp.res;
>
> -       if (!res) {
> -               res = rxe_prepare_res(qp, pkt, RXE_ATOMIC_WRITE_MASK);
> -               qp->resp.res = res;
> -       }
> -
> -       if (res->replay)
> -               return RESPST_ACKNOWLEDGE;
> -       return do_atomic_write(qp, pkt);
> +       return RESPST_ACKNOWLEDGE;
>  }
>
>  static struct sk_buff *prepare_ack_packet(struct rxe_qp *qp,
> --
> 2.37.2
>



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux