IB/rdmavt: Add modify qp

Add modify qp and supporting functions.

Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
diff --git a/include/rdma/rdma_vt.h b/include/rdma/rdma_vt.h
index 36e4fb4c..1c7123f 100644
--- a/include/rdma/rdma_vt.h
+++ b/include/rdma/rdma_vt.h
@@ -55,6 +55,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/list.h>
+#include <linux/hash.h>
 #include <rdma/ib_verbs.h>
 #include <rdma/rdmavt_mr.h>
 #include <rdma/rdmavt_qp.h>
@@ -194,6 +195,10 @@
 	u8 qos_shift;
 	char cq_name[RVT_CQN_MAX];
 	int node;
+	int max_rdma_atomic;
+	int psn_mask;
+	int psn_shift;
+	int psn_modify_mask;
 };
 
 /* Protection domain */
@@ -233,6 +238,15 @@
 	void (*notify_qp_reset)(struct rvt_qp *qp);
 	void (*schedule_send)(struct rvt_qp *qp);
 	void (*do_send)(struct rvt_qp *qp);
+	int (*get_pmtu_from_attr)(struct rvt_dev_info *rdi, struct rvt_qp *qp,
+				  struct ib_qp_attr *attr);
+	void (*flush_qp_waiters)(struct rvt_qp *qp);
+	void (*stop_send_queue)(struct rvt_qp *qp);
+	void (*quiesce_qp)(struct rvt_qp *qp);
+	void (*notify_error_qp)(struct rvt_qp *qp);
+	u32 (*mtu_from_qp)(struct rvt_dev_info *rdi, struct rvt_qp *qp,
+			   u32 pmtu);
+	int (*mtu_to_path_mtu)(u32 mtu);
 
 	/*--------------------*/
 	/* Optional functions */
@@ -340,6 +354,34 @@
 		return rdi->ports[port_index]->pkey_table[index];
 }
 
+/**
+ * rvt_lookup_qpn - return the QP with the given QPN
+ * @ibp: the ibport
+ * @qpn: the QP number to look up
+ *
+ * The caller must hold the rcu_read_lock(), and keep the lock until
+ * the returned qp is no longer in use.
+ */
+/* TODO: Remove this and put in rdmavt/qp.h when no longer needed by drivers */
+static inline struct rvt_qp *rvt_lookup_qpn(struct rvt_dev_info *rdi,
+					    struct rvt_ibport *rvp,
+					    u32 qpn) __must_hold(RCU)
+{
+	struct rvt_qp *qp = NULL;
+
+	if (unlikely(qpn <= 1)) {
+		qp = rcu_dereference(rvp->qp[qpn]);
+	} else {
+		u32 n = hash_32(qpn, rdi->qp_dev->qp_table_bits);
+
+		for (qp = rcu_dereference(rdi->qp_dev->qp_table[n]); qp;
+			qp = rcu_dereference(qp->next))
+			if (qp->ibqp.qp_num == qpn)
+				break;
+	}
+	return qp;
+}
+
 int rvt_register_device(struct rvt_dev_info *rvd);
 void rvt_unregister_device(struct rvt_dev_info *rvd);
 int rvt_check_ah(struct ib_device *ibdev, struct ib_ah_attr *ah_attr);
diff --git a/include/rdma/rdmavt_mr.h b/include/rdma/rdmavt_mr.h
index ea60476..4aa8171 100644
--- a/include/rdma/rdmavt_mr.h
+++ b/include/rdma/rdmavt_mr.h
@@ -127,4 +127,13 @@
 	atomic_inc(&mr->refcount);
 }
 
+static inline void rvt_put_ss(struct rvt_sge_state *ss)
+{
+	while (ss->num_sge) {
+		rvt_put_mr(ss->sge.mr);
+		if (--ss->num_sge)
+			ss->sge = *ss->sg_list++;
+	}
+}
+
 #endif          /* DEF_RDMAVT_INCMRH */
diff --git a/include/rdma/rdmavt_qp.h b/include/rdma/rdmavt_qp.h
index 3189f19..e66bcc9 100644
--- a/include/rdma/rdmavt_qp.h
+++ b/include/rdma/rdmavt_qp.h
@@ -355,6 +355,7 @@
 #define RVT_QPNMAP_ENTRIES          (RVT_QPN_MAX / PAGE_SIZE / BITS_PER_BYTE)
 #define RVT_BITS_PER_PAGE           (PAGE_SIZE * BITS_PER_BYTE)
 #define RVT_BITS_PER_PAGE_MASK      (RVT_BITS_PER_PAGE - 1)
+#define RVT_QPN_MASK		    0xFFFFFF
 
 /*
  * QPN-map pages start out as NULL, they get allocated upon
@@ -397,6 +398,25 @@
 				      sizeof(struct rvt_sge)) * n);
 }
 
+/*
+ * Since struct rvt_rwqe is not a fixed size, we can't simply index into
+ * struct rvt_rwq.wq.  This function does the array index computation.
+ */
+static inline struct rvt_rwqe *rvt_get_rwqe_ptr(struct rvt_rq *rq, unsigned n)
+{
+	return (struct rvt_rwqe *)
+		((char *)rq->wq->wq +
+		 (sizeof(struct rvt_rwqe) +
+		  rq->max_sge * sizeof(struct ib_sge)) * n);
+}
+
 extern const int  ib_rvt_state_ops[];
 
+struct rvt_dev_info;
+void rvt_remove_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp);
+void rvt_clear_mr_refs(struct rvt_qp *qp, int clr_sends);
+int rvt_error_qp(struct rvt_qp *qp, enum ib_wc_status err);
+void rvt_free_qpn(struct rvt_qpn_table *qpt, u32 qpn);
+void rvt_dec_qp_cnt(struct rvt_dev_info *rdi);
+
 #endif          /* DEF_RDMAVT_INCQP_H */