IB/rdamvt: Fix rdmavt s_ack_queue sizing
authorMike Marciniszyn <mike.marciniszyn@intel.com>
Tue, 24 May 2016 19:50:40 +0000 (12:50 -0700)
committerDoug Ledford <dledford@redhat.com>
Thu, 26 May 2016 16:21:10 +0000 (12:21 -0400)
rdmavt allows the driver to specify the size of the ack queue, but
only uses it for the modify QP limit testing for setting the atomic
limit value.

The driver dependent size is now used to size the s_ack_queue ring
dynamicially.

Since the driver knows its size, the driver will use its define
for any ring size dependent code.

Reviewed-by: Mitko Haralanov <mitko.haralanov@intel.com>
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/sw/rdmavt/qp.c
include/rdma/rdma_vt.h
include/rdma/rdmavt_qp.h

index dd03b23a6a7ce1f052eaa2f33c89e70ce02ddf5d..5fa4d4d81ee0cfcc5389897c904e343ff4903897 100644 (file)
@@ -397,6 +397,7 @@ static void free_qpn(struct rvt_qpn_table *qpt, u32 qpn)
 static void rvt_clear_mr_refs(struct rvt_qp *qp, int clr_sends)
 {
        unsigned n;
+       struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device);
 
        if (test_and_clear_bit(RVT_R_REWIND_SGE, &qp->r_aflags))
                rvt_put_ss(&qp->s_rdma_read_sge);
@@ -431,7 +432,7 @@ static void rvt_clear_mr_refs(struct rvt_qp *qp, int clr_sends)
        if (qp->ibqp.qp_type != IB_QPT_RC)
                return;
 
-       for (n = 0; n < ARRAY_SIZE(qp->s_ack_queue); n++) {
+       for (n = 0; n < rvt_max_atomic(rdi); n++) {
                struct rvt_ack_entry *e = &qp->s_ack_queue[n];
 
                if (e->opcode == IB_OPCODE_RC_RDMA_READ_REQUEST &&
@@ -569,7 +570,12 @@ static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
        qp->s_ssn = 1;
        qp->s_lsn = 0;
        qp->s_mig_state = IB_MIG_MIGRATED;
-       memset(qp->s_ack_queue, 0, sizeof(qp->s_ack_queue));
+       if (qp->s_ack_queue)
+               memset(
+                       qp->s_ack_queue,
+                       0,
+                       rvt_max_atomic(rdi) *
+                               sizeof(*qp->s_ack_queue));
        qp->r_head_ack_queue = 0;
        qp->s_tail_ack_queue = 0;
        qp->s_num_rd_atomic = 0;
@@ -677,6 +683,16 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
                        goto bail_swq;
 
                RCU_INIT_POINTER(qp->next, NULL);
+               if (init_attr->qp_type == IB_QPT_RC) {
+                       qp->s_ack_queue =
+                               kzalloc_node(
+                                       sizeof(*qp->s_ack_queue) *
+                                        rvt_max_atomic(rdi),
+                                       gfp,
+                                       rdi->dparms.node);
+                       if (!qp->s_ack_queue)
+                               goto bail_qp;
+               }
 
                /*
                 * Driver needs to set up it's private QP structure and do any
@@ -857,6 +873,7 @@ bail_driver_priv:
        rdi->driver_f.qp_priv_free(rdi, qp);
 
 bail_qp:
+       kfree(qp->s_ack_queue);
        kfree(qp);
 
 bail_swq:
@@ -1284,6 +1301,7 @@ int rvt_destroy_qp(struct ib_qp *ibqp)
                vfree(qp->r_rq.wq);
        vfree(qp->s_wq);
        rdi->driver_f.qp_priv_free(rdi, qp);
+       kfree(qp->s_ack_queue);
        kfree(qp);
        return 0;
 }
index 3f12da9384a157b87317409f42d5bf0e68fb7c04..16274e2133cdcca109fa0d40f1b9bf591493d27e 100644 (file)
@@ -425,6 +425,15 @@ static inline unsigned rvt_get_npkeys(struct rvt_dev_info *rdi)
        return rdi->dparms.npkeys;
 }
 
+/*
+ * Return the max atomic suitable for determining
+ * the size of the ack ring buffer in a QP.
+ */
+static inline unsigned int rvt_max_atomic(struct rvt_dev_info *rdi)
+{
+       return rdi->dparms.max_rdma_atomic + 1;
+}
+
 /*
  * Return the indexed PKEY from the port PKEY table.
  */
index 0e1ff2abfe927290acd42accd85598c950e89cd4..6d23b879416ac0f5249f33d7fd4713323e704961 100644 (file)
@@ -211,8 +211,6 @@ struct rvt_mmap_info {
        unsigned size;
 };
 
-#define RVT_MAX_RDMA_ATOMIC    16
-
 /*
  * This structure holds the information that the send tasklet needs
  * to send a RDMA read response or atomic operation.
@@ -282,8 +280,7 @@ struct rvt_qp {
        atomic_t refcount ____cacheline_aligned_in_smp;
        wait_queue_head_t wait;
 
-       struct rvt_ack_entry s_ack_queue[RVT_MAX_RDMA_ATOMIC + 1]
-               ____cacheline_aligned_in_smp;
+       struct rvt_ack_entry *s_ack_queue;
        struct rvt_sge_state s_rdma_read_sge;
 
        spinlock_t r_lock ____cacheline_aligned_in_smp;      /* used for APM */