diff mbox series

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

Message ID 20230113232704.20072-5-rpearsonhpe@gmail.com (mailing list archive)
State Superseded
Headers show
Series RDMA/rxe: Replace mr page map with an xarray | expand

Commit Message

Bob Pearson Jan. 13, 2023, 11:27 p.m. UTC
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@gmail.com>
---
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@intel.com/

 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(-)

Comments

Zhijian Li (Fujitsu) Jan. 16, 2023, 2:11 a.m. UTC | #1
On 14/01/2023 07:27, Bob Pearson 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@gmail.com>
> ---
> 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@intel.com/
> 
>   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

Well, i'm not favor of such error code. especialy when it's not a staic subroutine.
Any comments from other maintainers ?


> + */
> +int rxe_mr_do_atomic_write(struct rxe_mr *mr, u64 iova, void *addr)
> +{
> +#if defined CONFIG_64BIT
> +	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)) {

vaddr used before being initialized


Thanks
Zhijian


> +		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,
Jason Gunthorpe Jan. 16, 2023, 1:53 p.m. UTC | #2
On Mon, Jan 16, 2023 at 02:11:29AM +0000, lizhijian@fujitsu.com wrote:
> > +/**
> > + * 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
> 
> Well, i'm not favor of such error code. especialy when it's not a staic subroutine.
> Any comments from other maintainers ?

It should at least have proper constants, but can it be structured to
avoid this in the first place?

Jason
Zhu Yanjun Jan. 17, 2023, 1:36 a.m. UTC | #3
On Sat, Jan 14, 2023 at 7:28 AM Bob Pearson <rpearsonhpe@gmail.com> 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@gmail.com>
> ---
> 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@intel.com/
>
>  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
>
Jason Gunthorpe Jan. 17, 2023, 1:47 p.m. UTC | #4
On Tue, Jan 17, 2023 at 09:36:02AM +0800, Zhu Yanjun wrote:
> On Sat, Jan 14, 2023 at 7:28 AM Bob Pearson <rpearsonhpe@gmail.com> 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@gmail.com>
> > ---
> > 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@intel.com/
> >
> >  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?

is_enabled won't work here because the code doesn't compile.

Jason
Bob Pearson Jan. 17, 2023, 4:45 p.m. UTC | #5
On 1/17/23 07:47, Jason Gunthorpe wrote:
> On Tue, Jan 17, 2023 at 09:36:02AM +0800, Zhu Yanjun wrote:
>> On Sat, Jan 14, 2023 at 7:28 AM Bob Pearson <rpearsonhpe@gmail.com> 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@gmail.com>
>>> ---
>>> 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@intel.com/
>>>
>>>  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?
> 
> is_enabled won't work here because the code doesn't compile.
> 
> Jason

exactly.
Zhu Yanjun Jan. 18, 2023, 12:18 a.m. UTC | #6
On Wed, Jan 18, 2023 at 12:45 AM Bob Pearson <rpearsonhpe@gmail.com> wrote:
>
> On 1/17/23 07:47, Jason Gunthorpe wrote:
> > On Tue, Jan 17, 2023 at 09:36:02AM +0800, Zhu Yanjun wrote:
> >> On Sat, Jan 14, 2023 at 7:28 AM Bob Pearson <rpearsonhpe@gmail.com> 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@gmail.com>
> >>> ---
> >>> 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@intel.com/
> >>>
> >>>  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?
> >
> > is_enabled won't work here because the code doesn't compile.
> >

drivers/infiniband/sw/rxe/rxe_net.c:

 45
 46 #if IS_ENABLED(CONFIG_IPV6)
 47 static struct dst_entry *rxe_find_route6(struct rxe_qp *qp,
 48                                          struct net_device *ndev,
 49                                          struct in6_addr *saddr,
 50                                          struct in6_addr *daddr)
 51 {
 52         struct dst_entry *ndst;
 53         struct flowi6 fl6 = { { 0 } };

Zhu Yanjun

> > Jason
>
> exactly.
Jason Gunthorpe Jan. 18, 2023, 1:54 p.m. UTC | #7
On Wed, Jan 18, 2023 at 08:18:06AM +0800, Zhu Yanjun wrote:
> On Wed, Jan 18, 2023 at 12:45 AM Bob Pearson <rpearsonhpe@gmail.com> wrote:
> >
> > On 1/17/23 07:47, Jason Gunthorpe wrote:
> > > On Tue, Jan 17, 2023 at 09:36:02AM +0800, Zhu Yanjun wrote:
> > >> On Sat, Jan 14, 2023 at 7:28 AM Bob Pearson <rpearsonhpe@gmail.com> 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@gmail.com>
> > >>> ---
> > >>> 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@intel.com/
> > >>>
> > >>>  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?
> > >
> > > is_enabled won't work here because the code doesn't compile.
> > >
> 
> drivers/infiniband/sw/rxe/rxe_net.c:
>
>  45
>  46 #if IS_ENABLED(CONFIG_IPV6)

You only need this pattern if the config symbol is tristate

CONFIG_64BIT is a bool

Jason
diff mbox series

Patch

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
+	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,