iw_cxgb4: enforce qp/cq id requirements
authorHariprasad S <hariprasad@chelsio.com>
Tue, 21 Apr 2015 20:15:01 +0000 (01:45 +0530)
committerDoug Ledford <dledford@redhat.com>
Tue, 5 May 2015 13:18:01 +0000 (09:18 -0400)
Currently the iw_cxgb4 implementation requires the qp and cq qid densities
to match as well as the qp and cq id ranges.  So fail a device open if
the device configuration doesn't meet the requirements.

The reason for these restictions has to do with the fact that IQ qid X
has a UGTS register in the same bar2 page as EQ qid X.  Thus both qids
need to be allocated to the same user process for security reasons.
The logic that does this (the qpid allocator in iw_cxgb4/resource.c)
handles this but requires the above restrictions.

Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/cxgb4/device.c

index 7ed32537eb59d3ce4f73d034cd634fc39cf3c57c..83209bb38285e7edbaa43c2f446188446f5019bb 100644 (file)
@@ -764,6 +764,29 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
 
        c4iw_init_dev_ucontext(rdev, &rdev->uctx);
 
+       /*
+        * This implementation assumes udb_density == ucq_density!  Eventually
+        * we might need to support this but for now fail the open. Also the
+        * cqid and qpid range must match for now.
+        */
+       if (rdev->lldi.udb_density != rdev->lldi.ucq_density) {
+               pr_err(MOD "%s: unsupported udb/ucq densities %u/%u\n",
+                      pci_name(rdev->lldi.pdev), rdev->lldi.udb_density,
+                      rdev->lldi.ucq_density);
+               err = -EINVAL;
+               goto err1;
+       }
+       if (rdev->lldi.vr->qp.start != rdev->lldi.vr->cq.start ||
+           rdev->lldi.vr->qp.size != rdev->lldi.vr->cq.size) {
+               pr_err(MOD "%s: unsupported qp and cq id ranges "
+                      "qp start %u size %u cq start %u size %u\n",
+                      pci_name(rdev->lldi.pdev), rdev->lldi.vr->qp.start,
+                      rdev->lldi.vr->qp.size, rdev->lldi.vr->cq.size,
+                      rdev->lldi.vr->cq.size);
+               err = -EINVAL;
+               goto err1;
+       }
+
        /*
         * qpshift is the number of bits to shift the qpid left in order
         * to get the correct address of the doorbell for that qp.