[openib-general] [PATCH][2/4] Low-level driver QP API

Roland Dreier roland at topspin.com
Fri Aug 13 10:49:25 PDT 2004


Index: src/linux-kernel/infiniband/hw/mthca/mthca_dev.h
===================================================================
--- src/linux-kernel/infiniband/hw/mthca/mthca_dev.h	(revision 621)
+++ src/linux-kernel/infiniband/hw/mthca/mthca_dev.h	(working copy)
@@ -229,7 +229,7 @@
 
 #define MTHCA_GET(dest, source, offset)                               \
 	do {                                                          \
-		void *__p = (void *) (source) + (offset);             \
+		void *__p = (char *) (source) + (offset);             \
 		switch (sizeof (dest)) {                              \
 			case 1: (dest) = *(u8 *) __p;       break;    \
 			case 2: (dest) = be16_to_cpup(__p); break;    \
@@ -241,7 +241,8 @@
 
 #define MTHCA_PUT(dest, source, offset)                               \
 	do {                                                          \
-		__typeof__(source) *__p = (void *) (dest) + (offset); \
+		__typeof__(source) *__p =                             \
+			(__typeof__(source) *) ((char *) (dest) + (offset)); \
 		switch (sizeof(source)) {                             \
 			case 1: *__p = (source);            break;    \
 			case 2: *__p = cpu_to_be16(source); break;    \
@@ -307,28 +308,29 @@
 
 void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
 		    enum ib_async_event event);
-int mthca_modify_qp(struct ib_qp *qp, struct ib_qp_attribute *attr);
-int mthca_post_send(struct ib_qp *ibqp, struct ib_send_param *param,
-		    int nreq);
-int mthca_post_receive(struct ib_qp *ibqp, struct ib_receive_param *param,
-		       int nreq);
+int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+		    int attr_mask, struct ib_qp_cap *qp_cap);
+int mthca_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+		    struct ib_send_wr **bad_wr);
+int mthca_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+		       struct ib_recv_wr **bad_wr);
 int mthca_free_err_wqe(struct mthca_qp *qp, int is_send,
 		       int index, int *dbd, u32 *new_wqe);
 int mthca_alloc_qp(struct mthca_dev *dev,
 		   struct mthca_pd *pd,
 		   struct mthca_cq *send_cq,
 		   struct mthca_cq *recv_cq,
-		   enum ib_transport transport,
-		   enum ib_wq_signal_policy send_policy,
-		   enum ib_wq_signal_policy recv_policy,
+		   enum ib_qp_type type,
+		   enum ib_sig_type send_policy,
+		   enum ib_sig_type recv_policy,
 		   struct mthca_qp *qp);
 int mthca_alloc_sqp(struct mthca_dev *dev,
 		    struct mthca_pd *pd,
 		    struct mthca_cq *send_cq,
 		    struct mthca_cq *recv_cq,
-		    enum ib_wq_signal_policy send_policy,
-		    enum ib_wq_signal_policy recv_policy,
-		    enum ib_special_qp_type type,
+		    enum ib_sig_type send_policy,
+		    enum ib_sig_type recv_policy,
+		    int qpn,
 		    int port,
 		    struct mthca_sqp *sqp);
 void mthca_free_qp(struct mthca_dev *dev, struct mthca_qp *qp);
Index: src/linux-kernel/infiniband/hw/mthca/mthca_provider.c
===================================================================
--- src/linux-kernel/infiniband/hw/mthca/mthca_provider.c	(revision 621)
+++ src/linux-kernel/infiniband/hw/mthca/mthca_provider.c	(working copy)
@@ -295,87 +295,77 @@
 	return 0;
 }
 
-static int mthca_qp_create(struct ib_pd *pd,
-			   struct ib_qp_create_param *param,
-			   struct ib_qp *ibqp)
+static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
+				     struct ib_qp_init_attr *init_attr,
+				     struct ib_qp_cap *qp_cap)
 {
+	struct mthca_qp *qp;
 	int err;
-	struct mthca_qp *qp = kmalloc(sizeof *qp, GFP_KERNEL);
-	if (!qp)
-		return -ENOMEM;
 
-	qp->ib_qp = ibqp;
+	switch (init_attr->qp_type) {
+	case IB_QPT_RC:
+	case IB_QPT_UC:
+	case IB_QPT_UD:
+	{
+		qp = kmalloc(sizeof *qp, GFP_KERNEL);
+		if (!qp)
+			return ERR_PTR(-ENOMEM);
 
-	qp->sq.max    = param->limit.max_outstanding_send_request;
-	qp->rq.max    = param->limit.max_outstanding_receive_request;
-	qp->sq.max_gs = param->limit.max_send_gather_element;
-	qp->rq.max_gs = param->limit.max_receive_scatter_element;
+		qp->sq.max    = init_attr->cap.max_send_wr;
+		qp->rq.max    = init_attr->cap.max_recv_wr;
+		qp->sq.max_gs = init_attr->cap.max_send_sge;
+		qp->rq.max_gs = init_attr->cap.max_recv_sge;
 
-	err = mthca_alloc_qp(to_mdev(pd->device), (struct mthca_pd *) pd,
-			     (struct mthca_cq *) param->send_queue,
-			     (struct mthca_cq *) param->receive_queue,
-			     param->transport, param->send_policy,
-			     param->receive_policy, qp);
-	if (err) {
-		kfree(qp);
-		return err;
+		err = mthca_alloc_qp(to_mdev(pd->device), (struct mthca_pd *) pd,
+				     (struct mthca_cq *) init_attr->send_cq,
+				     (struct mthca_cq *) init_attr->recv_cq,
+				     init_attr->qp_type, init_attr->sq_sig_type,
+				     init_attr->rq_sig_type, qp);
+		qp->ibqp.qp_num = qp->qpn;
+		break;
 	}
+	case IB_QPT_SMI:
+	case IB_QPT_GSI:
+	{
+		qp = kmalloc(sizeof (struct mthca_sqp), GFP_KERNEL);
+		if (!qp)
+			return ERR_PTR(-ENOMEM);
 
-	ibqp->private = qp;
-	ibqp->qpn = qp->qpn;
+		qp->sq.max    = init_attr->cap.max_send_wr;
+		qp->rq.max    = init_attr->cap.max_recv_wr;
+		qp->sq.max_gs = init_attr->cap.max_send_sge;
+		qp->rq.max_gs = init_attr->cap.max_recv_sge;
 
-	return 0;
-}
+		qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 : 1;
 
-static int mthca_special_qp_create(struct ib_pd *pd,
-				   struct ib_qp_create_param *param,
-				   u8 port,
-				   enum ib_special_qp_type qp_type,
-				   struct ib_qp *ibqp)
-{
-	struct mthca_qp *qp;
-	int err;
+		err = mthca_alloc_sqp(to_mdev(pd->device), (struct mthca_pd *) pd,
+				      (struct mthca_cq *) init_attr->send_cq,
+				      (struct mthca_cq *) init_attr->recv_cq,
+				      init_attr->sq_sig_type, init_attr->rq_sig_type,
+				      qp->ibqp.qp_num, init_attr->port_num,
+				      (struct mthca_sqp *) qp);
+		break;
+	}
+	default:
+		/* Don't support raw QPs */
+		return ERR_PTR(-ENOSYS);
+	}
 
-	/* Don't support raw QPs */
-	if (qp_type != IB_SMI_QP && qp_type != IB_GSI_QP)
-		return -ENOSYS;
-
-	ibqp->private = kmalloc(sizeof (struct mthca_sqp), GFP_KERNEL);
-	if (!ibqp->private)
-		return -ENOMEM;
-
-	((struct mthca_qp *) ibqp->private)->ib_qp = ibqp;
-
-	if (port < 1 || port > to_mdev(pd->device)->limits.num_ports)
-		return -EINVAL;
-
-	qp = ibqp->private;
-
-	qp->sq.max    = param->limit.max_outstanding_send_request;
-	qp->rq.max    = param->limit.max_outstanding_receive_request;
-	qp->sq.max_gs = param->limit.max_send_gather_element;
-	qp->rq.max_gs = param->limit.max_receive_scatter_element;
-
-	err = mthca_alloc_sqp(to_mdev(pd->device), (struct mthca_pd *) pd,
-			      (struct mthca_cq *) param->send_queue,
-			      (struct mthca_cq *) param->receive_queue,
-			      param->send_policy, param->receive_policy,
-			      qp_type, port, ibqp->private);
-
 	if (err) {
-		kfree(ibqp->private);
-		return err;
+		kfree(qp);
+		return ERR_PTR(err);
 	}
 
-	ibqp->qpn = qp_type == IB_SMI_QP ? 0 : 1;
+	*qp_cap = init_attr->cap;
+	qp_cap->max_inline_data = 0;
 
-	return 0;
+	return (struct ib_qp *) qp;
 }
 
-static int mthca_qp_destroy(struct ib_qp *qp)
+static int mthca_destroy_qp(struct ib_qp *qp)
 {
-	mthca_free_qp(to_mdev(qp->device), qp->private);
-	kfree(qp->private);
+	mthca_free_qp(to_mdev(qp->device), (struct mthca_qp *) qp);
+	kfree(qp);
 	return 0;
 }
 
@@ -495,10 +485,10 @@
 			page_list[n++] = buffer_list[i].addr + ((u64) j << shift);
 
 	access =
-		(acc & IB_MR_REMOTE_ATOMIC ? MTHCA_MPT_FLAG_ATOMIC       : 0) |
-		(acc & IB_MR_REMOTE_WRITE  ? MTHCA_MPT_FLAG_REMOTE_WRITE : 0) |
-		(acc & IB_MR_REMOTE_READ   ? MTHCA_MPT_FLAG_REMOTE_READ  : 0) |
-		(acc & IB_MR_LOCAL_WRITE   ? MTHCA_MPT_FLAG_LOCAL_WRITE  : 0) |
+		(acc & IB_ACCESS_REMOTE_ATOMIC ? MTHCA_MPT_FLAG_ATOMIC       : 0) |
+		(acc & IB_ACCESS_REMOTE_WRITE  ? MTHCA_MPT_FLAG_REMOTE_WRITE : 0) |
+		(acc & IB_ACCESS_REMOTE_READ   ? MTHCA_MPT_FLAG_REMOTE_READ  : 0) |
+		(acc & IB_ACCESS_LOCAL_WRITE   ? MTHCA_MPT_FLAG_LOCAL_WRITE  : 0) |
 		MTHCA_MPT_FLAG_LOCAL_READ;
 
 	mthca_dbg(to_mdev(pd->device), "Registering memory at %llx (iova %llx) "
@@ -547,12 +537,11 @@
 	dev->ib_dev.dealloc_pd           = mthca_dealloc_pd;
 	dev->ib_dev.create_ah            = mthca_ah_create;
 	dev->ib_dev.destroy_ah           = mthca_ah_destroy;
-	dev->ib_dev.qp_create            = mthca_qp_create;
-	dev->ib_dev.special_qp_create    = mthca_special_qp_create;
-	dev->ib_dev.qp_modify            = mthca_modify_qp;
-	dev->ib_dev.qp_destroy           = mthca_qp_destroy;
-	dev->ib_dev.send_post            = mthca_post_send;
-	dev->ib_dev.receive_post         = mthca_post_receive;
+	dev->ib_dev.create_qp            = mthca_create_qp;
+	dev->ib_dev.modify_qp            = mthca_modify_qp;
+	dev->ib_dev.destroy_qp           = mthca_destroy_qp;
+	dev->ib_dev.post_send            = mthca_post_send;
+	dev->ib_dev.post_recv            = mthca_post_receive;
 	dev->ib_dev.create_cq            = mthca_create_cq;
 	dev->ib_dev.destroy_cq           = mthca_destroy_cq;
 	dev->ib_dev.poll_cq              = mthca_poll_cq;
Index: src/linux-kernel/infiniband/hw/mthca/mthca_provider.h
===================================================================
--- src/linux-kernel/infiniband/hw/mthca/mthca_provider.h	(revision 607)
+++ src/linux-kernel/infiniband/hw/mthca/mthca_provider.h	(working copy)
@@ -141,19 +141,16 @@
 	void *last;
 	int   max_gs;
 	int   wqe_shift;
-	enum ib_wq_signal_policy policy;
+	enum ib_sig_type policy;
 };
 
 struct mthca_qp {
+	struct ib_qp           ibqp;
 	spinlock_t             lock;
 	atomic_t               refcount;
-	struct ib_qp          *ib_qp;
-	int                    qpn;
+	u32                    qpn;
 	int                    transport;
-	struct mthca_pd       *pd;
 	enum ib_qp_state       state;
-	u32                    cqn_send;
-	u32                    cqn_recv;
 	int                    is_direct;
 	struct mthca_mr        mr;
 
@@ -172,7 +169,6 @@
 
 struct mthca_sqp {
 	struct mthca_qp qp;
-	int             sqpn;
 	int             port;
 	int             pkey_index;
 	u32             qkey;
Index: src/linux-kernel/infiniband/hw/mthca/mthca_cmd.c
===================================================================
--- src/linux-kernel/infiniband/hw/mthca/mthca_cmd.c	(revision 576)
+++ src/linux-kernel/infiniband/hw/mthca/mthca_cmd.c	(working copy)
@@ -1240,16 +1240,16 @@
 	u8 op_mod;
 
 	switch (type) {
-	case IB_SMI_QP:
+	case IB_QPT_SMI:
 		op_mod = 0;
 		break;
-	case IB_GSI_QP:
+	case IB_QPT_GSI:
 		op_mod = 1;
 		break;
-	case IB_RAW_IPV6_QP:
+	case IB_QPT_RAW_IPV6:
 		op_mod = 2;
 		break;
-	case IB_RAW_ETHERTYPE_QP:
+	case IB_QPT_RAW_ETY:
 		op_mod = 3;
 		break;
 	default:
Index: src/linux-kernel/infiniband/hw/mthca/mthca_mcg.c
===================================================================
--- src/linux-kernel/infiniband/hw/mthca/mthca_mcg.c	(revision 621)
+++ src/linux-kernel/infiniband/hw/mthca/mthca_mcg.c	(working copy)
@@ -174,7 +174,7 @@
 
 	for (i = 0; i < MTHCA_QP_PER_MGM; ++i)
 		if (!(mgm->qp[i] & cpu_to_be32(1 << 31))) {
-			mgm->qp[i] = cpu_to_be32(ibqp->qpn | (1 << 31));
+			mgm->qp[i] = cpu_to_be32(ibqp->qp_num | (1 << 31));
 			break;
 		}
 
@@ -259,14 +259,14 @@
 	}
 
 	for (loc = -1, i = 0; i < MTHCA_QP_PER_MGM; ++i) {
-		if (mgm->qp[i] == cpu_to_be32(ibqp->qpn | (1 << 31)))
+		if (mgm->qp[i] == cpu_to_be32(ibqp->qp_num | (1 << 31)))
 			loc = i;
 		if (!(mgm->qp[i] & cpu_to_be32(1 << 31)))
 			break;
 	}
 
 	if (loc == -1) {
-		mthca_err(dev, "QP %06x not found in MGM\n", ibqp->qpn);
+		mthca_err(dev, "QP %06x not found in MGM\n", ibqp->qp_num);
 		err = -EINVAL;
 		goto out;
 	}
Index: src/linux-kernel/infiniband/hw/mthca/mthca_qp.c
===================================================================
--- src/linux-kernel/infiniband/hw/mthca/mthca_qp.c	(revision 607)
+++ src/linux-kernel/infiniband/hw/mthca/mthca_qp.c	(working copy)
@@ -279,7 +279,7 @@
 
 	event_record.device      = &dev->ib_dev;
 	event_record.event       = event;
-	event_record.modifier.qp = qp->ib_qp;
+	event_record.modifier.qp = (struct ib_qp *) qp;
 	ib_async_event_dispatch(&event_record);
 
 	if (atomic_dec_and_test(&qp->refcount))
@@ -289,13 +289,13 @@
 static int to_mthca_state(enum ib_qp_state ib_state)
 {
 	switch (ib_state) {
-	case IB_QP_STATE_RESET: return MTHCA_QP_STATE_RST;
-	case IB_QP_STATE_INIT:  return MTHCA_QP_STATE_INIT;
-	case IB_QP_STATE_RTR:   return MTHCA_QP_STATE_RTR;
-	case IB_QP_STATE_RTS:   return MTHCA_QP_STATE_RTS;
-	case IB_QP_STATE_SQD:   return MTHCA_QP_STATE_SQD;
-	case IB_QP_STATE_SQE:   return MTHCA_QP_STATE_SQE;
-	case IB_QP_STATE_ERROR: return MTHCA_QP_STATE_ERR;
+	case IB_QPS_RESET: return MTHCA_QP_STATE_RST;
+	case IB_QPS_INIT:  return MTHCA_QP_STATE_INIT;
+	case IB_QPS_RTR:   return MTHCA_QP_STATE_RTR;
+	case IB_QPS_RTS:   return MTHCA_QP_STATE_RTS;
+	case IB_QPS_SQD:   return MTHCA_QP_STATE_SQD;
+	case IB_QPS_SQE:   return MTHCA_QP_STATE_SQE;
+	case IB_QPS_ERR: return MTHCA_QP_STATE_ERR;
 	default:                return -1;
 	}
 }
@@ -318,148 +318,140 @@
 	int trans;
 	u32 req_param[NUM_TRANS];
 	u32 opt_param[NUM_TRANS];
-} state_table[IB_QP_STATE_ERROR + 1][IB_QP_STATE_ERROR + 1] = {
-	[IB_QP_STATE_RESET] = {
-		[IB_QP_STATE_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
-		[IB_QP_STATE_ERROR] = { .trans = MTHCA_TRANS_ANY2ERR },
-		[IB_QP_STATE_INIT]  = {
+} state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
+	[IB_QPS_RESET] = {
+		[IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
+		[IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR },
+		[IB_QPS_INIT]  = {
 			.trans = MTHCA_TRANS_RST2INIT,
 			.req_param = {
-				[UD]  = (IB_QP_ATTRIBUTE_PKEY_INDEX |
-					 IB_QP_ATTRIBUTE_PORT       |
-					 IB_QP_ATTRIBUTE_QKEY),
-				[RC]  = (IB_QP_ATTRIBUTE_PKEY_INDEX |
-					 IB_QP_ATTRIBUTE_PORT       |
-					 IB_QP_ATTRIBUTE_RDMA_ATOMIC_ENABLE),
-				[MLX] = (IB_QP_ATTRIBUTE_PKEY_INDEX |
-					 IB_QP_ATTRIBUTE_QKEY),
+				[UD]  = (IB_QP_PKEY_INDEX |
+					 IB_QP_PORT       |
+					 IB_QP_QKEY),
+				[RC]  = (IB_QP_PKEY_INDEX |
+					 IB_QP_PORT       |
+					 IB_QP_ACCESS_FLAGS),
+				[MLX] = (IB_QP_PKEY_INDEX |
+					 IB_QP_QKEY),
 			},
 			/* bug-for-bug compatibility with VAPI: */
 			.opt_param = {
-				[MLX] = IB_QP_ATTRIBUTE_PORT
+				[MLX] = IB_QP_PORT
 			}
 		},
 	},
-	[IB_QP_STATE_INIT]  = {
-		[IB_QP_STATE_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
-		[IB_QP_STATE_ERROR] = { .trans = MTHCA_TRANS_ANY2ERR },
-		[IB_QP_STATE_INIT]  = {
+	[IB_QPS_INIT]  = {
+		[IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
+		[IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR },
+		[IB_QPS_INIT]  = {
 			.trans = MTHCA_TRANS_INIT2INIT,
 			.opt_param = {
-				[UD]  = (IB_QP_ATTRIBUTE_PKEY_INDEX |
-					 IB_QP_ATTRIBUTE_PORT       |
-					 IB_QP_ATTRIBUTE_QKEY),
-				[RC]  = (IB_QP_ATTRIBUTE_PKEY_INDEX |
-					 IB_QP_ATTRIBUTE_PORT       |
-					 IB_QP_ATTRIBUTE_RDMA_ATOMIC_ENABLE),
-				[MLX] = (IB_QP_ATTRIBUTE_PKEY_INDEX |
-					 IB_QP_ATTRIBUTE_QKEY),
+				[UD]  = (IB_QP_PKEY_INDEX |
+					 IB_QP_PORT       |
+					 IB_QP_QKEY),
+				[RC]  = (IB_QP_PKEY_INDEX |
+					 IB_QP_PORT       |
+					 IB_QP_ACCESS_FLAGS),
+				[MLX] = (IB_QP_PKEY_INDEX |
+					 IB_QP_QKEY),
 			}
 		},
-		[IB_QP_STATE_RTR]   = {
+		[IB_QPS_RTR]   = {
 			.trans = MTHCA_TRANS_INIT2RTR,
 			.req_param = {
-				[RC]  = (IB_QP_ATTRIBUTE_ADDRESS             |
-					 IB_QP_ATTRIBUTE_PATH_MTU            |
-					 IB_QP_ATTRIBUTE_DESTINATION_QPN     |
-					 IB_QP_ATTRIBUTE_RECEIVE_PSN         |
-					 IB_QP_ATTRIBUTE_RESPONDER_RESOURCES |
-					 IB_QP_ATTRIBUTE_RNR_TIMEOUT),
+				[RC]  = (IB_QP_AV                  |
+					 IB_QP_PATH_MTU            |
+					 IB_QP_DEST_QPN            |
+					 IB_QP_RQ_PSN              |
+					 IB_QP_MAX_DEST_RD_ATOMIC  |
+					 IB_QP_MIN_RNR_TIMER),
 			},
 			.opt_param = {
-				[UD]  = (IB_QP_ATTRIBUTE_PKEY_INDEX |
-					 IB_QP_ATTRIBUTE_QKEY),
-				[RC]  = (IB_QP_ATTRIBUTE_ALT_ADDRESS           |
-					 IB_QP_ATTRIBUTE_ALT_PKEY_INDEX        |
-					 IB_QP_ATTRIBUTE_ALT_PORT              |
-					 IB_QP_ATTRIBUTE_ALT_LOCAL_ACK_TIMEOUT |
-					 IB_QP_ATTRIBUTE_RDMA_ATOMIC_ENABLE    |
-					 IB_QP_ATTRIBUTE_PKEY_INDEX),
-				[MLX] = (IB_QP_ATTRIBUTE_PKEY_INDEX |
-					 IB_QP_ATTRIBUTE_QKEY),
+				[UD]  = (IB_QP_PKEY_INDEX |
+					 IB_QP_QKEY),
+				[RC]  = (IB_QP_ALT_PATH     |
+					 IB_QP_ACCESS_FLAGS |
+					 IB_QP_PKEY_INDEX),
+				[MLX] = (IB_QP_PKEY_INDEX |
+					 IB_QP_QKEY),
 			}
 		}
 	},
-	[IB_QP_STATE_RTR]   = {
-		[IB_QP_STATE_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
-		[IB_QP_STATE_ERROR] = { .trans = MTHCA_TRANS_ANY2ERR },
-		[IB_QP_STATE_RTS]   = {
+	[IB_QPS_RTR]   = {
+		[IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
+		[IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR },
+		[IB_QPS_RTS]   = {
 			.trans = MTHCA_TRANS_RTR2RTS,
 			.req_param = {
-				[UD]  = IB_QP_ATTRIBUTE_SEND_PSN,
-				[RC]  = (IB_QP_ATTRIBUTE_LOCAL_ACK_TIMEOUT |
-					 IB_QP_ATTRIBUTE_RETRY_COUNT       |
-					 IB_QP_ATTRIBUTE_RNR_RETRY_COUNT   |
-					 IB_QP_ATTRIBUTE_SEND_PSN          |
-					 IB_QP_ATTRIBUTE_INITIATOR_DEPTH),
-				[MLX] = IB_QP_ATTRIBUTE_SEND_PSN,
+				[UD]  = IB_QP_SQ_PSN,
+				[RC]  = (IB_QP_TIMEOUT           |
+					 IB_QP_RETRY_CNT         |
+					 IB_QP_RNR_RETRY         |
+					 IB_QP_SQ_PSN            |
+					 IB_QP_MAX_QP_RD_ATOMIC),
+				[MLX] = IB_QP_SQ_PSN,
 			},
 			.opt_param = {
-				[UD]  = IB_QP_ATTRIBUTE_QKEY,
-				[RC]  = (IB_QP_ATTRIBUTE_ALT_ADDRESS           |
-					 IB_QP_ATTRIBUTE_ALT_PKEY_INDEX        |
-					 IB_QP_ATTRIBUTE_ALT_PORT              |
-					 IB_QP_ATTRIBUTE_ALT_LOCAL_ACK_TIMEOUT |
-					 IB_QP_ATTRIBUTE_RDMA_ATOMIC_ENABLE    |
-					 IB_QP_ATTRIBUTE_PKEY_INDEX            |
-					 IB_QP_ATTRIBUTE_RNR_TIMEOUT           |
-					 IB_QP_ATTRIBUTE_MIGRATION_STATE),
-				[MLX] = IB_QP_ATTRIBUTE_QKEY,
+				[UD]  = IB_QP_QKEY,
+				[RC]  = (IB_QP_ALT_PATH              |
+					 IB_QP_ACCESS_FLAGS          |
+					 IB_QP_PKEY_INDEX            |
+					 IB_QP_MIN_RNR_TIMER         |
+					 IB_QP_PATH_MIG_STATE),
+				[MLX] = IB_QP_QKEY,
 			}
 		}
 	},
-	[IB_QP_STATE_RTS]   = {
-		[IB_QP_STATE_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
-		[IB_QP_STATE_ERROR] = { .trans = MTHCA_TRANS_ANY2ERR },
-		[IB_QP_STATE_RTS]   = {
+	[IB_QPS_RTS]   = {
+		[IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
+		[IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR },
+		[IB_QPS_RTS]   = {
 			.trans = MTHCA_TRANS_RTS2RTS,
 			.opt_param = {
-				[UD]  = IB_QP_ATTRIBUTE_QKEY,
-				[RC]  = (IB_QP_ATTRIBUTE_RDMA_ATOMIC_ENABLE    |
-					 IB_QP_ATTRIBUTE_ALT_ADDRESS           |
-					 IB_QP_ATTRIBUTE_ALT_PKEY_INDEX        |
-					 IB_QP_ATTRIBUTE_ALT_PORT              |
-					 IB_QP_ATTRIBUTE_ALT_LOCAL_ACK_TIMEOUT |
-					 IB_QP_ATTRIBUTE_MIGRATION_STATE       |
-					 IB_QP_ATTRIBUTE_RNR_TIMEOUT),
-				[MLX] = IB_QP_ATTRIBUTE_QKEY,
+				[UD]  = IB_QP_QKEY,
+				[RC]  = (IB_QP_ACCESS_FLAGS          |
+					 IB_QP_ALT_PATH              |
+					 IB_QP_PATH_MIG_STATE        |
+					 IB_QP_MIN_RNR_TIMER),
+				[MLX] = IB_QP_QKEY,
 			}
 		},
-		[IB_QP_STATE_SQD]   = {
+		[IB_QPS_SQD]   = {
 			.trans = MTHCA_TRANS_RTS2SQD,
 		},
 	},
-	[IB_QP_STATE_SQD]   = {
-		[IB_QP_STATE_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
-		[IB_QP_STATE_ERROR] = { .trans = MTHCA_TRANS_ANY2ERR },
-		[IB_QP_STATE_RTS]   = {
+	[IB_QPS_SQD]   = {
+		[IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
+		[IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR },
+		[IB_QPS_RTS]   = {
 			.trans = MTHCA_TRANS_SQD2RTS,
 		},
-		[IB_QP_STATE_SQD]   = {
+		[IB_QPS_SQD]   = {
 			.trans = MTHCA_TRANS_SQD2SQD,
 		}
 	},
-	[IB_QP_STATE_SQE]   = {
-		[IB_QP_STATE_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
-		[IB_QP_STATE_ERROR] = { .trans = MTHCA_TRANS_ANY2ERR },
-		[IB_QP_STATE_RTS]   = {
+	[IB_QPS_SQE]   = {
+		[IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
+		[IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR },
+		[IB_QPS_RTS]   = {
 			.trans = MTHCA_TRANS_SQERR2RTS,
 		}
 	},
-	[IB_QP_STATE_ERROR] = {
-		[IB_QP_STATE_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
-		[IB_QP_STATE_ERROR] = { .trans = MTHCA_TRANS_ANY2ERR }
+	[IB_QPS_ERR] = {
+		[IB_QPS_RESET] = { .trans = MTHCA_TRANS_ANY2RST },
+		[IB_QPS_ERR] = { .trans = MTHCA_TRANS_ANY2ERR }
 	}
 };
 
-static void store_attrs(struct mthca_sqp *sqp, struct ib_qp_attribute *attr)
+static void store_attrs(struct mthca_sqp *sqp, struct ib_qp_attr *attr,
+			int attr_mask)
 {
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_PKEY_INDEX)
+	if (attr_mask & IB_QP_PKEY_INDEX)
 		sqp->pkey_index = attr->pkey_index;
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_QKEY)
+	if (attr_mask & IB_QP_QKEY)
 		sqp->qkey = attr->qkey;
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_SEND_PSN)
-		sqp->send_psn = attr->send_psn;
+	if (attr_mask & IB_QP_SQ_PSN)
+		sqp->send_psn = attr->sq_psn;
 }
 
 static void init_port(struct mthca_dev *dev, int port)
@@ -484,10 +476,11 @@
 		mthca_warn(dev, "INIT_IB returned status %02x.\n", status);
 }
 
-int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attribute *attr)
+int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+		    int attr_mask, struct ib_qp_cap *qp_cap)
 {
 	struct mthca_dev *dev = to_mdev(ibqp->device);
-	struct mthca_qp *qp = ibqp->private;
+	struct mthca_qp *qp = (struct mthca_qp *) ibqp;
 	enum ib_qp_state cur_state, new_state;
 	void *mailbox = NULL;
 	struct mthca_qp_param *qp_param;
@@ -500,10 +493,10 @@
 	cur_state = qp->state;
 	spin_unlock_irq(&qp->lock);
 
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_STATE) {
-		if (attr->state <= 0 || attr->state > IB_QP_STATE_ERROR)
+	if (attr_mask & IB_QP_STATE) {
+		if (attr->qp_state <= 0 || attr->qp_state > IB_QPS_ERR)
 			return -EINVAL;
-		new_state = attr->state;
+		new_state = attr->qp_state;
 	} else
 		new_state = cur_state;
 
@@ -516,22 +509,21 @@
 	req_param = state_table[cur_state][new_state].req_param[qp->transport];
 	opt_param = state_table[cur_state][new_state].opt_param[qp->transport];
 
-	if ((req_param & attr->valid_fields) != req_param) {
+	if ((req_param & attr_mask) != req_param) {
 		mthca_dbg(dev, "QP transition "
 			  "%d->%d missing req attr 0x%08x\n",
 			  cur_state, new_state,
-			  req_param & ~attr->valid_fields);
+			  req_param & ~attr_mask);
 		return -EINVAL;
 	}
 
-	if (attr->valid_fields & ~(req_param | opt_param |
-				   IB_QP_ATTRIBUTE_STATE)) {
+	if (attr_mask & ~(req_param | opt_param | IB_QP_STATE)) {
 		mthca_dbg(dev, "QP transition (transport %d) "
 			  "%d->%d has extra attr 0x%08x\n",
 			  qp->transport,
 			  cur_state, new_state,
-			  attr->valid_fields & ~(req_param | opt_param |
-						 IB_QP_ATTRIBUTE_STATE));
+			  attr_mask & ~(req_param | opt_param |
+						 IB_QP_STATE));
 		return -EINVAL;
 	}
 
@@ -545,18 +537,18 @@
 	qp_context->flags      = cpu_to_be32((to_mthca_state(new_state) << 28) |
 					     (to_mthca_st(qp->transport) << 16));
 	qp_context->flags     |= cpu_to_be32(MTHCA_QP_BIT_DE);
-	if (!(attr->valid_fields & IB_QP_ATTRIBUTE_MIGRATION_STATE))
+	if (!(attr_mask & IB_QP_PATH_MIG_STATE))
 		qp_context->flags |= cpu_to_be32(MTHCA_QP_PM_MIGRATED << 11);
 	else {
 		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PM_STATE);
-		switch (attr->migration_state) {
-		case IB_MIGRATED:
+		switch (attr->path_mig_state) {
+		case IB_MIG_MIGRATED:
 			qp_context->flags |= cpu_to_be32(MTHCA_QP_PM_MIGRATED << 11);
 			break;
-		case IB_REARM:
+		case IB_MIG_REARM:
 			qp_context->flags |= cpu_to_be32(MTHCA_QP_PM_REARM << 11);
 			break;
-		case IB_ARMED:
+		case IB_MIG_ARMED:
 			qp_context->flags |= cpu_to_be32(MTHCA_QP_PM_ARMED << 11);
 			break;
 		}
@@ -565,66 +557,68 @@
 	if (qp->transport == MLX || qp->transport == UD)
 		qp_context->mtu_msgmax = cpu_to_be32((IB_MTU_2048 << 29) |
 						     (11 << 24));
-	else if (attr->valid_fields & IB_QP_ATTRIBUTE_PATH_MTU) {
+	else if (attr_mask & IB_QP_PATH_MTU) {
 		qp_context->mtu_msgmax = cpu_to_be32((attr->path_mtu << 29) |
 						     (31 << 24));
 	}
 	qp_context->usr_page   = cpu_to_be32(MTHCA_KAR_PAGE);
 	qp_context->local_qpn  = cpu_to_be32(qp->qpn);
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_DESTINATION_QPN) {
-		qp_context->remote_qpn = cpu_to_be32(attr->destination_qpn);
+	if (attr_mask & IB_QP_DEST_QPN) {
+		qp_context->remote_qpn = cpu_to_be32(attr->dest_qp_num);
 	}
 
 	if (qp->transport == MLX)
 		qp_context->pri_path.port_pkey |=
 			cpu_to_be32(((struct mthca_sqp *) qp)->port << 24);
 	else {
-		if (attr->valid_fields & IB_QP_ATTRIBUTE_PORT) {
+		if (attr_mask & IB_QP_PORT) {
 			qp_context->pri_path.port_pkey |=
 				cpu_to_be32(attr->port << 24);
 			qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PORT_NUM);
 		}
 	}
 
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_PKEY_INDEX) {
+	if (attr_mask & IB_QP_PKEY_INDEX) {
 		qp_context->pri_path.port_pkey |=
 			cpu_to_be32(attr->pkey_index);
 		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PKEY_INDEX);
 	}
 
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_RNR_RETRY_COUNT) {
-		qp_context->pri_path.rnr_retry = attr->rnr_retry_count << 5;
+	if (attr_mask & IB_QP_RNR_RETRY) {
+		qp_context->pri_path.rnr_retry = attr->rnr_retry << 5;
 		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY);
 	}
 
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_ADDRESS) {
-		qp_context->pri_path.g_mylmc     = attr->address.source_path_bits & 0x7f;
-		qp_context->pri_path.rlid        = cpu_to_be16(attr->address.dlid);
-		qp_context->pri_path.static_rate = (!!attr->address.static_rate) << 3;
-		if (attr->address.use_grh) {
+	if (attr_mask & IB_QP_AV) {
+		qp_context->pri_path.g_mylmc     = attr->ah_attr.src_path_bits & 0x7f;
+		qp_context->pri_path.rlid        = cpu_to_be16(attr->ah_attr.dlid);
+		qp_context->pri_path.static_rate = (!!attr->ah_attr.static_rate) << 3;
+		if (attr->ah_attr.grh_flag) {
 			qp_context->pri_path.g_mylmc |= 1 << 7;
-			qp_context->pri_path.mgid_index = attr->address.source_gid_index;
-			qp_context->pri_path.hop_limit = attr->address.hop_limit;
+			qp_context->pri_path.mgid_index = attr->ah_attr.grh.sgid_index;
+			qp_context->pri_path.hop_limit = attr->ah_attr.grh.hop_limit;
 			qp_context->pri_path.sl_tclass_flowlabel =
-				cpu_to_be32((attr->address.service_level << 28) |
-					    (attr->address.traffic_class << 20) |
-					    (attr->address.flow_label));
+				cpu_to_be32((attr->ah_attr.sl << 28)                |
+					    (attr->ah_attr.grh.traffic_class << 20) |
+					    (attr->ah_attr.grh.flow_label));
 			memcpy(qp_context->pri_path.rgid,
-			       attr->address.dgid, 16);
+			       attr->ah_attr.grh.dgid.raw, 16);
+		} else {
+			qp_context->pri_path.sl_tclass_flowlabel =
+				cpu_to_be32(attr->ah_attr.sl << 28);
 		}
-
 		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH);	
 	}
 
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_LOCAL_ACK_TIMEOUT) {
-		qp_context->pri_path.ackto = attr->local_ack_timeout;
+	if (attr_mask & IB_QP_TIMEOUT) {
+		qp_context->pri_path.ackto = attr->timeout;
 		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ACK_TIMEOUT);
 	}
 
 	/* XXX alt_path */
 
 	/* leave rdd as 0 */
-	qp_context->pd         = cpu_to_be32(qp->pd->pd_num);
+	qp_context->pd         = cpu_to_be32(((struct mthca_pd *) ibqp->pd)->pd_num);
 	/* leave wqe_base as 0 (we always create an MR based at 0 for WQs) */
 	qp_context->wqe_lkey   = cpu_to_be32(qp->mr.ibmr.lkey);
 	qp_context->params1    = cpu_to_be32((MTHCA_ACK_REQ_FREQ << 28) |
@@ -632,34 +626,34 @@
 					     MTHCA_QP_BIT_SRE           |
 					     MTHCA_QP_BIT_SWE           |
 					     MTHCA_QP_BIT_SAE);
-	if (qp->sq.policy == IB_WQ_SIGNAL_ALL)
+	if (qp->sq.policy == IB_SIGNAL_ALL_WR)
 		qp_context->params1 |= cpu_to_be32(MTHCA_QP_BIT_SSC);
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_RETRY_COUNT) {
-		qp_context->params1 |= cpu_to_be32(attr->retry_count << 16);
+	if (attr_mask & IB_QP_RETRY_CNT) {
+		qp_context->params1 |= cpu_to_be32(attr->retry_cnt << 16);
 		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RETRY_COUNT);
 	}
 
 	/* XXX initiator resources */
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_SEND_PSN)
-		qp_context->next_send_psn = cpu_to_be32(attr->send_psn);
-	qp_context->cqn_snd    = cpu_to_be32(qp->cqn_send);
+	if (attr_mask & IB_QP_SQ_PSN)
+		qp_context->next_send_psn = cpu_to_be32(attr->sq_psn);
+	qp_context->cqn_snd = cpu_to_be32(((struct mthca_cq *) ibqp->send_cq)->cqn);
 
 	/* XXX RDMA/atomic enable, responder resources */
 
-	if (qp->rq.policy == IB_WQ_SIGNAL_ALL)
+	if (qp->rq.policy == IB_SIGNAL_ALL_WR)
 		qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC);
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_RNR_TIMEOUT) {
-		qp_context->rnr_nextrecvpsn |= cpu_to_be32(attr->rnr_timeout << 24);
+	if (attr_mask & IB_QP_MIN_RNR_TIMER) {
+		qp_context->rnr_nextrecvpsn |= cpu_to_be32(attr->min_rnr_timer << 24);
 		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_TIMEOUT);
 	}
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_RECEIVE_PSN)
-		qp_context->rnr_nextrecvpsn |= cpu_to_be32(attr->receive_psn);
+	if (attr_mask & IB_QP_RQ_PSN)
+		qp_context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn);
 
 	/* XXX ra_buff_indx */
 
-	qp_context->cqn_rcv    = cpu_to_be32(qp->cqn_recv);
+	qp_context->cqn_rcv = cpu_to_be32(((struct mthca_cq *) ibqp->recv_cq)->cqn);
 
-	if (attr->valid_fields & IB_QP_ATTRIBUTE_QKEY) {
+	if (attr_mask & IB_QP_QKEY) {
 		qp_context->qkey = cpu_to_be32(attr->qkey);
 		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_Q_KEY);
 	}
@@ -682,21 +676,21 @@
 	kfree(mailbox);
 
 	if (is_sqp(dev, qp))
-		store_attrs((struct mthca_sqp *) qp, attr);
+		store_attrs((struct mthca_sqp *) qp, attr, attr_mask);
 
 	/* 
 	 * If we are moving QP0 to RTR, bring the IB link up; if we
 	 * are moving QP0 to RESET or ERROR, bring the link back down.
 	 */
 	if (is_qp0(dev, qp)) {
-		if (cur_state != IB_QP_STATE_RTR &&
-		    new_state == IB_QP_STATE_RTR)
+		if (cur_state != IB_QPS_RTR &&
+		    new_state == IB_QPS_RTR)
 			init_port(dev, ((struct mthca_sqp *) qp)->port);
 
-		if (cur_state != IB_QP_STATE_RESET &&
-		    cur_state != IB_QP_STATE_ERROR &&
-		    (new_state == IB_QP_STATE_RESET ||
-		     new_state == IB_QP_STATE_ERROR))
+		if (cur_state != IB_QPS_RESET &&
+		    cur_state != IB_QPS_ERR &&
+		    (new_state == IB_QPS_RESET ||
+		     new_state == IB_QPS_ERR))
 			mthca_CLOSE_IB(dev, ((struct mthca_sqp *) qp)->port, &status);
 	}
 
@@ -711,6 +705,7 @@
  * queue)
  */
 static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
+			       struct mthca_pd *pd,
 			       struct mthca_qp *qp)
 {
 	int size;
@@ -809,9 +804,8 @@
 		}
 	}
 
-	err = mthca_mr_alloc_phys(dev, qp->pd->pd_num,
-				  dma_list, shift, npages,
-				  0, size,
+	err = mthca_mr_alloc_phys(dev, pd->pd_num, dma_list, shift,
+				  npages, 0, size,
 				  MTHCA_MPT_FLAG_LOCAL_WRITE |
 				  MTHCA_MPT_FLAG_LOCAL_READ,
 				  &qp->mr);
@@ -846,18 +840,15 @@
 				 struct mthca_pd *pd,
 				 struct mthca_cq *send_cq,
 				 struct mthca_cq *recv_cq,
-				 enum ib_wq_signal_policy send_policy,
-				 enum ib_wq_signal_policy recv_policy,
+				 enum ib_sig_type send_policy,
+				 enum ib_sig_type recv_policy,
 				 struct mthca_qp *qp)
 {
 	int err;
 
 	spin_lock_init(&qp->lock);
 	atomic_set(&qp->refcount, 1);
-	qp->pd       	 = pd;
-	qp->cqn_send 	 = send_cq->cqn;
-	qp->cqn_recv 	 = recv_cq->cqn;
-	qp->state    	 = IB_QP_STATE_RESET;
+	qp->state    	 = IB_QPS_RESET;
 	qp->sq.policy    = send_policy;
 	qp->rq.policy    = recv_policy;
 	qp->rq.cur       = 0;
@@ -869,7 +860,7 @@
 	qp->rq.last      = NULL;
 	qp->sq.last      = NULL;
 
-	err = mthca_alloc_wqe_buf(dev, qp);
+	err = mthca_alloc_wqe_buf(dev, pd, qp);
 	return err;
 }
 
@@ -877,18 +868,17 @@
 		   struct mthca_pd *pd,
 		   struct mthca_cq *send_cq,
 		   struct mthca_cq *recv_cq,
-		   enum ib_transport transport,
-		   enum ib_wq_signal_policy send_policy,
-		   enum ib_wq_signal_policy recv_policy,
+		   enum ib_qp_type type,
+		   enum ib_sig_type send_policy,
+		   enum ib_sig_type recv_policy,
 		   struct mthca_qp *qp)
 {
 	int err;
 
-	switch (transport) {
-	case IB_TRANSPORT_RC: qp->transport = RC; break;
-	case IB_TRANSPORT_UC: qp->transport = UC; break;
-	case IB_TRANSPORT_RD: qp->transport = RD; break;
-	case IB_TRANSPORT_UD: qp->transport = UD; break;
+	switch (type) {
+	case IB_QPT_RC: qp->transport = RC; break;
+	case IB_QPT_UC: qp->transport = UC; break;
+	case IB_QPT_UD: qp->transport = UD; break;
 	default: return -EINVAL;
 	}		
 
@@ -915,15 +905,14 @@
 		    struct mthca_pd *pd,
 		    struct mthca_cq *send_cq,
 		    struct mthca_cq *recv_cq,
-		    enum ib_wq_signal_policy send_policy,
-		    enum ib_wq_signal_policy recv_policy,
-		    enum ib_special_qp_type type,
+		    enum ib_sig_type send_policy,
+		    enum ib_sig_type recv_policy,
+		    int qpn,
 		    int port,
 		    struct mthca_sqp *sqp)
 {
 	int err = 0;
-	u32 mqpn = (type == IB_SMI_QP ? 0 : 2)
-		+ dev->qp_table.sqp_start + port - 1;
+	u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1;
 
 	sqp->header_buf_size = sqp->qp.sq.max * MTHCA_UD_HEADER_SIZE;
 	sqp->header_buf = pci_alloc_consistent(dev->pdev, sqp->header_buf_size,
@@ -941,7 +930,6 @@
 	if (err)
 		goto err_out;
 
-	sqp->sqpn = type == IB_SMI_QP ? 0 : 1;
 	sqp->port = port;
 	sqp->qp.qpn       = mqpn;
 	sqp->qp.transport = MLX;
@@ -985,9 +973,10 @@
 
 	mthca_MODIFY_QP(dev, MTHCA_TRANS_ANY2RST, qp->qpn, 0, NULL, 0, &status);
 
-	mthca_cq_clean(dev, qp->cqn_send, qp->qpn);
-	if (qp->cqn_recv != qp->cqn_send)
-		mthca_cq_clean(dev, qp->cqn_recv, qp->qpn);
+	mthca_cq_clean(dev, ((struct mthca_cq *) qp->ibqp.send_cq)->cqn, qp->qpn);
+	if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
+		mthca_cq_clean(dev, ((struct mthca_cq *) qp->ibqp.recv_cq)->cqn,
+			       qp->qpn);
 
 	mthca_free_mr(dev, &qp->mr);
 
@@ -1010,7 +999,7 @@
 	kfree(qp->wrid);
 
 	if (is_sqp(dev, qp)) {
-		atomic_dec(&qp->pd->sqp_count);
+		atomic_dec(&((struct mthca_pd *) &qp->ibqp.pd)->sqp_count);
 		pci_free_consistent(dev->pdev,
 				    ((struct mthca_sqp *) qp)->header_buf_size,
 				    ((struct mthca_sqp *) qp)->header_buf,
@@ -1022,19 +1011,19 @@
 
 /* Create UD header for an MLX send and build a data segment for it */
 static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
-			    int ind, struct ib_send_param *param,
+			    int ind, struct ib_send_wr *wr,
 			    struct mthca_mlx_seg *mlx,
 			    struct mthca_data_seg *data)
 {
 	int header_size;
 	int err;
 
-	err = mthca_read_ah(dev, (struct mthca_ah *) param->dest_address,
+	err = mthca_read_ah(dev, (struct mthca_ah *) wr->wr.ud.ah,
 			    &sqp->ud_header);
 	if (err)
 		return err;
 	mlx->flags &= ~cpu_to_be32(MTHCA_NEXT_SOLICIT | 1);
-	mlx->flags |= cpu_to_be32((!sqp->sqpn ? MTHCA_MLX_VL15 : 0) |
+	mlx->flags |= cpu_to_be32((!sqp->qp.ibqp.qp_num ? MTHCA_MLX_VL15 : 0) |
 				  (sqp->ud_header.lrh.destination_lid == 0xffff ?
 				   MTHCA_MLX_SLR : 0) |
 				  (sqp->ud_header.lrh.service_level << 8));
@@ -1045,102 +1034,92 @@
 			  sqp->ud_header.grh_present,
 			  &sqp->ud_header);
 
-	switch (param->op) {
-	case IB_OP_SEND:
+	switch (wr->opcode) {
+	case IB_WR_SEND:
 		sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY;
 		sqp->ud_header.immediate_present = 0;
 		break;
-	case IB_OP_SEND_IMMEDIATE:
+	case IB_WR_SEND_WITH_IMM:
 		sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
 		sqp->ud_header.immediate_present = 1;
-		sqp->ud_header.immediate_data = param->immediate_data;
+		sqp->ud_header.immediate_data = wr->imm_data;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	sqp->ud_header.lrh.virtual_lane    = !sqp->sqpn ? 15 : 0;
+	sqp->ud_header.lrh.virtual_lane    = !sqp->qp.ibqp.qp_num ? 15 : 0;
 	if (sqp->ud_header.lrh.destination_lid == 0xffff)
 		sqp->ud_header.lrh.source_lid = 0xffff;
-	sqp->ud_header.bth.solicited_event = param->solicited_event;
-	if (!sqp->sqpn)
+	sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
+	if (!sqp->qp.ibqp.qp_num)
 		ib_cached_pkey_get(&dev->ib_dev, sqp->port,
 				   sqp->pkey_index,
 				   &sqp->ud_header.bth.pkey);
 	else
 		ib_cached_pkey_get(&dev->ib_dev, sqp->port,
-				   param->pkey_index,
+				   wr->wr.ud.pkey_index,
 				   &sqp->ud_header.bth.pkey);
-	sqp->ud_header.bth.destination_qpn = param->dest_qpn;
+	sqp->ud_header.bth.destination_qpn = wr->wr.ud.remote_qpn;
 	sqp->ud_header.bth.psn = (sqp->send_psn++) & ((1 << 24) - 1);
-	sqp->ud_header.deth.qkey = param->dest_qkey & 0x80000000 ?
-		sqp->qkey : param->dest_qkey;
-	sqp->ud_header.deth.source_qpn = sqp->sqpn;
+	sqp->ud_header.deth.qkey = wr->wr.ud.remote_qkey & 0x80000000 ?
+		sqp->qkey : wr->wr.ud.remote_qkey;
+	sqp->ud_header.deth.source_qpn = sqp->qp.ibqp.qp_num;
 
 	header_size = ib_ud_header_pack(&sqp->ud_header,
 					sqp->header_buf +
 					ind * MTHCA_UD_HEADER_SIZE);
 
 	data->byte_count = cpu_to_be32(header_size);
-	data->lkey       = cpu_to_be32(sqp->qp.pd->ntmr.ibmr.lkey);
+	data->lkey       = cpu_to_be32(((struct mthca_pd *) sqp->qp.ibqp.pd)->ntmr.ibmr.lkey);
 	data->addr       = cpu_to_be64(sqp->header_dma +
 				       ind * MTHCA_UD_HEADER_SIZE);
 
 	return 0;
 }
 
-int mthca_post_send(struct ib_qp *ibqp, struct ib_send_param *param,
-		    int nreq)
+int mthca_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+		    struct ib_send_wr **bad_wr)
 {
 	struct mthca_dev *dev = to_mdev(ibqp->device);
-	struct mthca_qp *qp = ibqp->private;
+	struct mthca_qp *qp = (struct mthca_qp *) ibqp;
+	void *wqe;
+	void *prev_wqe;
 	unsigned long flags;
 	int err = 0;
-	int i, j;
+	int nreq;
+	int i;
 	int size;
 	int size0 = 0;
-	u8 op0 = 0;
 	u32 f0 = 0;
 	int ind;
-	void *wqe;
-	void *prev_wqe;
+	u8 op0 = 0;
 
 	static const u8 opcode[] = {
-		[IB_OP_RECEIVE]              = MTHCA_OPCODE_INVALID,
-		[IB_OP_SEND]                 = MTHCA_OPCODE_SEND,
-		[IB_OP_SEND_IMMEDIATE]       = MTHCA_OPCODE_SEND_IMM,
-		[IB_OP_RDMA_WRITE]           = MTHCA_OPCODE_RDMA_WRITE,
-		[IB_OP_RDMA_WRITE_IMMEDIATE] = MTHCA_OPCODE_RDMA_WRITE_IMM,
-		[IB_OP_RDMA_READ]            = MTHCA_OPCODE_RDMA_READ,
-		[IB_OP_COMPARE_SWAP]         = MTHCA_OPCODE_ATOMIC_CS,
-		[IB_OP_FETCH_ADD]            = MTHCA_OPCODE_ATOMIC_FA,
-		[IB_OP_MEMORY_WINDOW_BIND]   = MTHCA_OPCODE_BIND_MW
+		[IB_WR_SEND]                 = MTHCA_OPCODE_SEND,
+		[IB_WR_SEND_WITH_IMM]        = MTHCA_OPCODE_SEND_IMM,
+		[IB_WR_RDMA_WRITE]           = MTHCA_OPCODE_RDMA_WRITE,
+		[IB_WR_RDMA_WRITE_WITH_IMM]  = MTHCA_OPCODE_RDMA_WRITE_IMM,
+		[IB_WR_RDMA_READ]            = MTHCA_OPCODE_RDMA_READ,
+		[IB_WR_ATOMIC_CMP_AND_SWP]   = MTHCA_OPCODE_ATOMIC_CS,
+		[IB_WR_ATOMIC_FETCH_AND_ADD] = MTHCA_OPCODE_ATOMIC_FA,
 	};
 
-	if (nreq <= 0)
-		return -EINVAL;
-
 	spin_lock_irqsave(&qp->lock, flags);
 
 	/* XXX check that state is OK to post send */
 
-	if (qp->sq.cur + nreq > qp->sq.max) {
-		mthca_err(dev, "SQ full (%d posted, %d max, %d nreq)\n",
-			  qp->sq.cur, qp->sq.max, nreq);
-		err = -EINVAL;
-		goto out;
-	}
-
 	ind = qp->sq.next;
 
-	/*
-	 * XXX our semantics are wrong according to the verbs
-	 * extensions spec: an immediate error with one work request
-	 * should only cause that and subsequent requests not to be
-	 * posted, rather than all of the requests to be thrown out.
-	 */
+	for (nreq = 0; wr; ++nreq, wr = wr->next) {
+		if (qp->sq.cur + nreq >= qp->sq.max) {
+			mthca_err(dev, "SQ full (%d posted, %d max, %d nreq)\n",
+				  qp->sq.cur, qp->sq.max, nreq);
+			err = -ENOMEM;
+			*bad_wr = wr;
+			goto out;
+		}
 
-	for (i = 0; i < nreq; ++i) {
 		wqe = get_send_wqe(qp, ind);
 		prev_wqe = qp->sq.last;
 		qp->sq.last = wqe;
@@ -1148,53 +1127,58 @@
 		((struct mthca_next_seg *) wqe)->nda_op = 0;
 		((struct mthca_next_seg *) wqe)->ee_nds = 0;
 		((struct mthca_next_seg *) wqe)->flags =
-			cpu_to_be32((param->signaled ? MTHCA_NEXT_CQ_UPDATE : 0) |
-				    (param->solicited_event ? MTHCA_NEXT_SOLICIT : 0) |
-				    1);
-		if (param[i].op == IB_OP_SEND_IMMEDIATE ||
-		    param[i].op == IB_OP_RDMA_WRITE_IMMEDIATE)
+			((wr->send_flags & IB_SEND_SIGNALED) ?
+			 cpu_to_be32(MTHCA_NEXT_CQ_UPDATE) : 0) |
+			((wr->send_flags & IB_SEND_SOLICITED) ?
+			 cpu_to_be32(MTHCA_NEXT_SOLICIT) : 0)   |
+			cpu_to_be32(1);
+		if (wr->opcode == IB_WR_SEND_WITH_IMM ||
+		    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
 			((struct mthca_next_seg *) wqe)->flags =
-				cpu_to_be32(param->immediate_data);
+				cpu_to_be32(wr->imm_data);
 
 		wqe += sizeof (struct mthca_next_seg);
 		size = sizeof (struct mthca_next_seg) / 16;
 
 		if (qp->transport == UD) {
 			((struct mthca_ud_seg *) wqe)->lkey =
-				cpu_to_be32(((struct mthca_ah *) param->dest_address)->key);
+				cpu_to_be32(((struct mthca_ah *) wr->wr.ud.ah)->key);
 			((struct mthca_ud_seg *) wqe)->av_addr =
-				cpu_to_be64(((struct mthca_ah *) param->dest_address)->avdma);
+				cpu_to_be64(((struct mthca_ah *) wr->wr.ud.ah)->avdma);
 			((struct mthca_ud_seg *) wqe)->dqpn =
-				cpu_to_be32(param->dest_qpn);
+				cpu_to_be32(wr->wr.ud.remote_qpn);
 			((struct mthca_ud_seg *) wqe)->qkey =
-				cpu_to_be32(param->dest_qkey);
+				cpu_to_be32(wr->wr.ud.remote_qkey);
 
 			wqe += sizeof (struct mthca_ud_seg);
 			size += sizeof (struct mthca_ud_seg) / 16;
 		} else if (qp->transport == MLX) {
 			err = build_mlx_header(dev, (struct mthca_sqp *) qp,
-					       ind, param + i,
+					       ind, wr,
 					       wqe - sizeof (struct mthca_next_seg),
 					       wqe);
-			if (err)
+			if (err) {
+				*bad_wr = wr;
 				goto out;
+			}
 			wqe += sizeof (struct mthca_data_seg);
 			size += sizeof (struct mthca_data_seg) / 16;
 		}
 
-		if (param[i].num_gather_entries > qp->sq.max_gs) {
+		if (wr->num_sge > qp->sq.max_gs) {
 			mthca_err(dev, "too many gathers\n");
 			err = -EINVAL;
+			*bad_wr = wr;
 			goto out;
 		}
 
-		for (j = 0; j < param[i].num_gather_entries; ++j) {
+		for (i = 0; i < wr->num_sge; ++i) {
 			((struct mthca_data_seg *) wqe)->byte_count =
-				cpu_to_be32(param[i].gather_list[j].length);
+				cpu_to_be32(wr->sg_list[i].length);
 			((struct mthca_data_seg *) wqe)->lkey =
-				cpu_to_be32(param[i].gather_list[j].key);
+				cpu_to_be32(wr->sg_list[i].lkey);
 			((struct mthca_data_seg *) wqe)->addr =
-				cpu_to_be64(param[i].gather_list[j].address);
+				cpu_to_be64(wr->sg_list[i].addr);
 			wqe += sizeof (struct mthca_data_seg);
 			size += sizeof (struct mthca_data_seg) / 16;
 		}
@@ -1208,12 +1192,12 @@
 			size += sizeof (struct mthca_data_seg) / 16;
 		}
 
-		qp->wrid[ind + qp->rq.max] = param[i].work_request_id;
+		qp->wrid[ind + qp->rq.max] = wr->wr_id;
 
-		if (param[i].op >= ARRAY_SIZE(opcode) ||
-		    opcode[param[i].op] == MTHCA_OPCODE_INVALID) {
+		if (wr->opcode >= ARRAY_SIZE(opcode)) {
 			mthca_err(dev, "opcode invalid\n");
 			err = -EINVAL;
+			*bad_wr = wr;
 			goto out;
 		}
 
@@ -1221,15 +1205,15 @@
 			((struct mthca_next_seg *) prev_wqe)->nda_op =
 				cpu_to_be32(((ind << qp->sq.wqe_shift) +
 					     qp->send_wqe_offset) |
-					    opcode[param[i].op]);
+					    opcode[wr->opcode]);
 			smp_wmb();
 			((struct mthca_next_seg *) prev_wqe)->ee_nds =
-				cpu_to_be32((i ? 0 : MTHCA_NEXT_DBD) | size);
+				cpu_to_be32((size0 ? 0 : MTHCA_NEXT_DBD) | size);
 		}
 
-		if (!i) {
+		if (!size0) {
 			size0 = size;
-			op0   = opcode[param[i].op];
+			op0   = opcode[wr->opcode];
 		}
 
 		++ind;
@@ -1237,7 +1221,8 @@
 			ind -= qp->sq.max;
 	}
 
-	{
+out:
+	if (nreq) {
 		u32 doorbell[2];
 
 		doorbell[0] = cpu_to_be32(((qp->sq.next << qp->sq.wqe_shift) +
@@ -1254,48 +1239,39 @@
 	qp->sq.cur += nreq;
 	qp->sq.next = ind;
 
- out:
 	spin_unlock_irqrestore(&qp->lock, flags);
 	return err;
 }
 
-int mthca_post_receive(struct ib_qp *ibqp, struct ib_receive_param *param,
-		       int nreq)
+int mthca_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+		       struct ib_recv_wr **bad_wr)
 {
 	struct mthca_dev *dev = to_mdev(ibqp->device);
-	struct mthca_qp *qp = ibqp->private;
+	struct mthca_qp *qp = (struct mthca_qp *) ibqp;
 	unsigned long flags;
 	int err = 0;
-	int i, j;
+	int nreq;
+	int i;
 	int size;
 	int size0 = 0;
 	int ind;
 	void *wqe;
 	void *prev_wqe;
 
-	if (nreq <= 0)
-		return -EINVAL;
-
 	spin_lock_irqsave(&qp->lock, flags);
 	
 	/* XXX check that state is OK to post receive */
 
-	if (qp->rq.cur + nreq > qp->rq.max) {
-		mthca_err(dev, "RQ %06x full\n", qp->qpn);
-		err = -EINVAL;
-		goto out;
-	}
-
 	ind = qp->rq.next;
 
-	/*
-	 * XXX our semantics are wrong according to the verbs
-	 * extensions spec: an immediate error with one work request
-	 * should only cause that and subsequent requests not to be
-	 * posted, rather than all of the requests to be thrown out.
-	 */
+	for (nreq = 0; wr; ++nreq, wr = wr->next) {
+		if (qp->rq.cur + nreq >= qp->rq.max) {
+			mthca_err(dev, "RQ %06x full\n", qp->qpn);
+			err = -ENOMEM;
+			*bad_wr = wr;
+			goto out;
+		}
 
-	for (i = 0; i < nreq; ++i) {
 		wqe = get_recv_wqe(qp, ind);
 		prev_wqe = qp->rq.last;
 		qp->rq.last = wqe;
@@ -1304,28 +1280,30 @@
 		((struct mthca_next_seg *) wqe)->ee_nds = 
 			cpu_to_be32(MTHCA_NEXT_DBD);
 		((struct mthca_next_seg *) wqe)->flags =
-			cpu_to_be32(param->signaled ? MTHCA_NEXT_CQ_UPDATE : 0);
+			(wr->recv_flags & IB_RECV_SIGNALED) ?
+			cpu_to_be32(MTHCA_NEXT_CQ_UPDATE) : 0;
 
 		wqe += sizeof (struct mthca_next_seg);
 		size = sizeof (struct mthca_next_seg) / 16;
 
-		if (param[i].num_scatter_entries > qp->rq.max_gs) {
+		if (wr->num_sge > qp->rq.max_gs) {
 			err = -EINVAL;
+			*bad_wr = wr;
 			goto out;
 		}
 
-		for (j = 0; j < param[i].num_scatter_entries; ++j) {
+		for (i = 0; i < wr->num_sge; ++i) {
 			((struct mthca_data_seg *) wqe)->byte_count =
-				cpu_to_be32(param[i].scatter_list[j].length);
+				cpu_to_be32(wr->sg_list[i].length);
 			((struct mthca_data_seg *) wqe)->lkey =
-				cpu_to_be32(param[i].scatter_list[j].key);
+				cpu_to_be32(wr->sg_list[i].lkey);
 			((struct mthca_data_seg *) wqe)->addr =
-				cpu_to_be64(param[i].scatter_list[j].address);
+				cpu_to_be64(wr->sg_list[i].addr);
 			wqe += sizeof (struct mthca_data_seg);
 			size += sizeof (struct mthca_data_seg) / 16;
 		}
 
-		qp->wrid[ind] = param[i].work_request_id;
+		qp->wrid[ind] = wr->wr_id;
 
 		if (prev_wqe) {
 			((struct mthca_next_seg *) prev_wqe)->nda_op =
@@ -1335,7 +1313,7 @@
 				cpu_to_be32(MTHCA_NEXT_DBD | size);
 		}
 
-		if (!i)
+		if (!size0)
 			size0 = size;
 
 		++ind;
@@ -1343,7 +1321,8 @@
 			ind -= qp->rq.max;
 	}
 
-	{
+out:
+	if (nreq) {
 		u32 doorbell[2];
 
 		doorbell[0] = cpu_to_be32((qp->rq.next << qp->rq.wqe_shift) | size0);
@@ -1359,7 +1338,6 @@
 	qp->rq.cur += nreq;
 	qp->rq.next = ind;
 
- out:
 	spin_unlock_irqrestore(&qp->lock, flags);
 	return err;
 }
@@ -1413,7 +1391,7 @@
 	}
 
 	for (i = 0; i < 2; ++i) {
-		err = mthca_CONF_SPECIAL_QP(dev, i,
+		err = mthca_CONF_SPECIAL_QP(dev, i ? IB_QPT_GSI : IB_QPT_SMI,
 					    dev->qp_table.sqp_start + i * 2,
 					    &status);
 		if (err)




More information about the general mailing list