staging/rdma/hfi1: Correctly set RcvCtxtCtrl register
authorMitko Haralanov <mitko.haralanov@intel.com>
Wed, 3 Feb 2016 22:32:49 +0000 (14:32 -0800)
committerDoug Ledford <dledford@redhat.com>
Fri, 11 Mar 2016 01:37:50 +0000 (20:37 -0500)
The RcvCtxtCtrl register was being incorrectly set upon context
initialization and clean up resulting, in many cases, of contexts using
settings from previous contexts' initialization. This resulted in bad
and unexpected behavior. This was especially important for the TailUpd
bit, which requires special handling and if set incorrectly could lead
to severely degraded performance.

This patch fixes the handling of the RcvCtxtCtrl register, ensuring that
each context gets initialized with settings applicable only for that
context. It also ensures the proper setting for the TailUpd bit by
setting it to either 0 or 1 (as needed by the context's configuration)
explicitly.

Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Mitko Haralanov <mitko.haralanov@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/staging/rdma/hfi1/chip.c
drivers/staging/rdma/hfi1/file_ops.c
drivers/staging/rdma/hfi1/init.c

index a90e6e6699c0e2fa597c83f2514020fc3cee6de5..d10ba6732e72ab7aa63842ec86d537fdccfcfa31 100644 (file)
@@ -6684,11 +6684,17 @@ static void rxe_freeze(struct hfi1_devdata *dd)
  */
 static void rxe_kernel_unfreeze(struct hfi1_devdata *dd)
 {
+       u32 rcvmask;
        int i;
 
        /* enable all kernel contexts */
-       for (i = 0; i < dd->n_krcv_queues; i++)
-               hfi1_rcvctrl(dd, HFI1_RCVCTRL_CTXT_ENB, i);
+       for (i = 0; i < dd->n_krcv_queues; i++) {
+               rcvmask = HFI1_RCVCTRL_CTXT_ENB;
+               /* HFI1_RCVCTRL_TAILUPD_[ENB|DIS] needs to be set explicitly */
+               rcvmask |= HFI1_CAP_KGET_MASK(dd->rcd[i]->flags, DMA_RTAIL) ?
+                       HFI1_RCVCTRL_TAILUPD_ENB : HFI1_RCVCTRL_TAILUPD_DIS;
+               hfi1_rcvctrl(dd, rcvmask, i);
+       }
 
        /* enable port */
        add_rcvctrl(dd, RCV_CTRL_RCV_PORT_ENABLE_SMASK);
@@ -11255,6 +11261,7 @@ void hfi1_rcvctrl(struct hfi1_devdata *dd, unsigned int op, int ctxt)
                if (dd->rcvhdrtail_dummy_physaddr) {
                        write_kctxt_csr(dd, ctxt, RCV_HDR_TAIL_ADDR,
                                        dd->rcvhdrtail_dummy_physaddr);
+                       /* Enabling RcvCtxtCtrl.TailUpd is intentional. */
                        rcvctrl |= RCV_CTXT_CTRL_TAIL_UPD_SMASK;
                }
 
@@ -11266,8 +11273,11 @@ void hfi1_rcvctrl(struct hfi1_devdata *dd, unsigned int op, int ctxt)
                rcvctrl &= ~RCV_CTXT_CTRL_INTR_AVAIL_SMASK;
        if (op & HFI1_RCVCTRL_TAILUPD_ENB && rcd->rcvhdrqtailaddr_phys)
                rcvctrl |= RCV_CTXT_CTRL_TAIL_UPD_SMASK;
-       if (op & HFI1_RCVCTRL_TAILUPD_DIS)
-               rcvctrl &= ~RCV_CTXT_CTRL_TAIL_UPD_SMASK;
+       if (op & HFI1_RCVCTRL_TAILUPD_DIS) {
+               /* See comment on RcvCtxtCtrl.TailUpd above */
+               if (!(op & HFI1_RCVCTRL_CTXT_DIS))
+                       rcvctrl &= ~RCV_CTXT_CTRL_TAIL_UPD_SMASK;
+       }
        if (op & HFI1_RCVCTRL_TIDFLOW_ENB)
                rcvctrl |= RCV_CTXT_CTRL_TID_FLOW_ENABLE_SMASK;
        if (op & HFI1_RCVCTRL_TIDFLOW_DIS)
index d36588934f99a7f6095e5cac30a06d18266fe6e5..5c694fac3028f357f3355a566a7535daae78e280 100644 (file)
@@ -771,6 +771,7 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
        hfi1_rcvctrl(dd, HFI1_RCVCTRL_CTXT_DIS |
                     HFI1_RCVCTRL_TIDFLOW_DIS |
                     HFI1_RCVCTRL_INTRAVAIL_DIS |
+                    HFI1_RCVCTRL_TAILUPD_DIS |
                     HFI1_RCVCTRL_ONE_PKT_EGR_DIS |
                     HFI1_RCVCTRL_NO_RHQ_DROP_DIS |
                     HFI1_RCVCTRL_NO_EGR_DROP_DIS, uctxt->ctxt);
@@ -1156,8 +1157,16 @@ static int user_init(struct file *fp)
                rcvctrl_ops |= HFI1_RCVCTRL_NO_EGR_DROP_ENB;
        if (HFI1_CAP_KGET_MASK(uctxt->flags, NODROP_RHQ_FULL))
                rcvctrl_ops |= HFI1_RCVCTRL_NO_RHQ_DROP_ENB;
+       /*
+        * The RcvCtxtCtrl.TailUpd bit has to be explicitly written.
+        * We can't rely on the correct value to be set from prior
+        * uses of the chip or ctxt. Therefore, add the rcvctrl op
+        * for both cases.
+        */
        if (HFI1_CAP_KGET_MASK(uctxt->flags, DMA_RTAIL))
                rcvctrl_ops |= HFI1_RCVCTRL_TAILUPD_ENB;
+       else
+               rcvctrl_ops |= HFI1_RCVCTRL_TAILUPD_DIS;
        hfi1_rcvctrl(uctxt->dd, rcvctrl_ops, uctxt->ctxt);
 
        /* Notify any waiting slaves */
index 2851e90d0cd33cff5f4758337ce1980e6250e9b1..fc3d40a58cf3f6bf193362716815572787f03701 100644 (file)
@@ -589,8 +589,8 @@ static void enable_chip(struct hfi1_devdata *dd)
         * Enable kernel ctxts' receive and receive interrupt.
         * Other ctxts done as user opens and initializes them.
         */
-       rcvmask = HFI1_RCVCTRL_CTXT_ENB | HFI1_RCVCTRL_INTRAVAIL_ENB;
        for (i = 0; i < dd->first_user_ctxt; ++i) {
+               rcvmask = HFI1_RCVCTRL_CTXT_ENB | HFI1_RCVCTRL_INTRAVAIL_ENB;
                rcvmask |= HFI1_CAP_KGET_MASK(dd->rcd[i]->flags, DMA_RTAIL) ?
                        HFI1_RCVCTRL_TAILUPD_ENB : HFI1_RCVCTRL_TAILUPD_DIS;
                if (!HFI1_CAP_KGET_MASK(dd->rcd[i]->flags, MULTI_PKT_EGR))