[PATCH] RDMA/rvt: Do not use a kernel header in the ABI

From: Jason Gunthorpe
Date: Mon Jul 08 2019 - 11:17:48 EST


rvt was using ib_sge as part of it's ABI, which is not allowed. Introduce
a new struct with the same layout and use it instead.

Fixes: dabac6e460ce ("IB/hfi1: Move receive work queue struct into uapi dir=
ectory")
Reported-by: Stephen Rothwell <sfr@xxxxxxxxxxxxxxxx>
Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxxxx>
---
drivers/infiniband/sw/rdmavt/qp.c | 32 ++++++++++++++++++++++++++-----
include/uapi/rdma/rvt-abi.h | 9 +++++++--
2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdma=
vt/qp.c
index 11b4d3c1efd486..0b0a241c57ff37 100644
--- a/drivers/infiniband/sw/rdmavt/qp.c
+++ b/drivers/infiniband/sw/rdmavt/qp.c
@@ -1847,8 +1847,11 @@ int rvt_post_recv(struct ib_qp *ibqp, const struct i=
b_recv_wr *wr,
wqe =3D rvt_get_rwqe_ptr(&qp->r_rq, wq->head);
wqe->wr_id =3D wr->wr_id;
wqe->num_sge =3D wr->num_sge;
- for (i =3D 0; i < wr->num_sge; i++)
- wqe->sg_list[i] =3D wr->sg_list[i];
+ for (i =3D 0; i < wr->num_sge; i++) {
+ wqe->sg_list[i].addr =3D wr->sg_list[i].addr;
+ wqe->sg_list[i].length =3D wr->sg_list[i].length;
+ wqe->sg_list[i].lkey =3D wr->sg_list[i].lkey;
+ }
/*
* Make sure queue entry is written
* before the head index.
@@ -2250,8 +2253,11 @@ int rvt_post_srq_recv(struct ib_srq *ibsrq, const st=
ruct ib_recv_wr *wr,
wqe =3D rvt_get_rwqe_ptr(&srq->rq, wq->head);
wqe->wr_id =3D wr->wr_id;
wqe->num_sge =3D wr->num_sge;
- for (i =3D 0; i < wr->num_sge; i++)
- wqe->sg_list[i] =3D wr->sg_list[i];
+ for (i =3D 0; i < wr->num_sge; i++) {
+ wqe->sg_list[i].addr =3D wr->sg_list[i].addr;
+ wqe->sg_list[i].length =3D wr->sg_list[i].length;
+ wqe->sg_list[i].lkey =3D wr->sg_list[i].lkey;
+ }
/* Make sure queue entry is written before the head index. */
smp_store_release(&wq->head, next);
spin_unlock_irqrestore(&srq->rq.kwq->p_lock, flags);
@@ -2259,6 +2265,22 @@ int rvt_post_srq_recv(struct ib_srq *ibsrq, const st=
ruct ib_recv_wr *wr,
return 0;
}
=20
+/*
+ * rvt used the internal kernel struct as part of its ABI, for now make su=
re
+ * the kernel struct does not change layout. FIXME: rvt should never cast =
the
+ * user struct to a kernel struct.
+ */
+static struct ib_sge *rvt_cast_sge(struct rvt_wqe_sge *sge)
+{
+ BUILD_BUG_ON(offsetof(struct ib_sge, addr) !=3D
+ offsetof(struct rvt_wqe_sge, addr));
+ BUILD_BUG_ON(offsetof(struct ib_sge, length) !=3D
+ offsetof(struct rvt_wqe_sge, length));
+ BUILD_BUG_ON(offsetof(struct ib_sge, lkey) !=3D
+ offsetof(struct rvt_wqe_sge, lkey));
+ return (struct ib_sge *)sge;
+}
+
/*
* Validate a RWQE and fill in the SGE state.
* Return 1 if OK.
@@ -2282,7 +2304,7 @@ static int init_sge(struct rvt_qp *qp, struct rvt_rwq=
e *wqe)
continue;
/* Check LKEY */
ret =3D rvt_lkey_ok(rkt, pd, j ? &ss->sg_list[j - 1] : &ss->sge,
- NULL, &wqe->sg_list[i],
+ NULL, rvt_cast_sge(&wqe->sg_list[i]),
IB_ACCESS_LOCAL_WRITE);
if (unlikely(ret <=3D 0))
goto bad_lkey;
diff --git a/include/uapi/rdma/rvt-abi.h b/include/uapi/rdma/rvt-abi.h
index d2e35d24f1a9e6..7328293c715cfb 100644
--- a/include/uapi/rdma/rvt-abi.h
+++ b/include/uapi/rdma/rvt-abi.h
@@ -10,11 +10,16 @@
=20
#include <linux/types.h>
#include <rdma/ib_user_verbs.h>
-#include <rdma/ib_verbs.h>
#ifndef RDMA_ATOMIC_UAPI
#define RDMA_ATOMIC_UAPI(_type, _name) struct{ _type val; } _name
#endif
=20
+struct rvt_wqe_sge {
+ __aligned_u64 addr;
+ __u32 length;
+ __u32 lkey;
+};
+
/*
* This structure is used to contain the head pointer, tail pointer,
* and completion queue entries as a single memory allocation so
@@ -39,7 +44,7 @@ struct rvt_rwqe {
__u64 wr_id;
__u8 num_sge;
__u8 padding[7];
- struct ib_sge sg_list[];
+ struct rvt_wqe_sge sg_list[];
};
=20
/*
--=20
2.21.0