IB/hfi1: Fix user context tail allocation for DMA_RTAIL
authorMike Marciniszyn <mike.marciniszyn@intel.com>
Thu, 31 May 2018 18:30:09 +0000 (11:30 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 3 Jul 2018 09:24:54 +0000 (11:24 +0200)
commit 1bc0299d976e000ececc6acd76e33b4582646cb7 upstream.

The following code fails to allocate a buffer for the
tail address that the hardware DMAs into when the user
context DMA_RTAIL is set.

if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL)) {
rcd->rcvhdrtail_kvaddr = dma_zalloc_coherent(
&dd->pcidev->dev, PAGE_SIZE, &dma_hdrqtail,
                gfp_flags);
if (!rcd->rcvhdrtail_kvaddr)
goto bail_free;
rcd->rcvhdrqtailaddr_dma = dma_hdrqtail;
}

So the rcvhdrtail_kvaddr would then be NULL.

The mmap logic fails to check for a NULL rcvhdrtail_kvaddr.

The fix is to test for both user and kernel DMA_TAIL options
during the allocation as well as testing for a NULL
rcvhdrtail_kvaddr during the mmap processing.

Additionally, all downstream testing of the capmask for DMA_RTAIL
have been eliminated in favor of testing rcvhdrtail_kvaddr.

Cc: <stable@vger.kernel.org> # 4.9.x
Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/infiniband/hw/hfi1/chip.c
drivers/infiniband/hw/hfi1/file_ops.c
drivers/infiniband/hw/hfi1/init.c

index 2595622..33cf173 100644 (file)
@@ -6829,7 +6829,7 @@ static void rxe_kernel_unfreeze(struct hfi1_devdata *dd)
                }
                rcvmask = HFI1_RCVCTRL_CTXT_ENB;
                /* HFI1_RCVCTRL_TAILUPD_[ENB|DIS] needs to be set explicitly */
-               rcvmask |= HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL) ?
+               rcvmask |= rcd->rcvhdrtail_kvaddr ?
                        HFI1_RCVCTRL_TAILUPD_ENB : HFI1_RCVCTRL_TAILUPD_DIS;
                hfi1_rcvctrl(dd, rcvmask, rcd);
                hfi1_rcd_put(rcd);
@@ -8341,7 +8341,7 @@ static inline int check_packet_present(struct hfi1_ctxtdata *rcd)
        u32 tail;
        int present;
 
-       if (!HFI1_CAP_IS_KSET(DMA_RTAIL))
+       if (!rcd->rcvhdrtail_kvaddr)
                present = (rcd->seq_cnt ==
                                rhf_rcv_seq(rhf_to_cpu(get_rhf_addr(rcd))));
        else /* is RDMA rtail */
@@ -11813,7 +11813,7 @@ void hfi1_rcvctrl(struct hfi1_devdata *dd, unsigned int op,
                /* reset the tail and hdr addresses, and sequence count */
                write_kctxt_csr(dd, ctxt, RCV_HDR_ADDR,
                                rcd->rcvhdrq_dma);
-               if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL))
+               if (rcd->rcvhdrtail_kvaddr)
                        write_kctxt_csr(dd, ctxt, RCV_HDR_TAIL_ADDR,
                                        rcd->rcvhdrqtailaddr_dma);
                rcd->seq_cnt = 1;
@@ -11893,7 +11893,7 @@ void hfi1_rcvctrl(struct hfi1_devdata *dd, unsigned int op,
                rcvctrl |= RCV_CTXT_CTRL_INTR_AVAIL_SMASK;
        if (op & HFI1_RCVCTRL_INTRAVAIL_DIS)
                rcvctrl &= ~RCV_CTXT_CTRL_INTR_AVAIL_SMASK;
-       if (op & HFI1_RCVCTRL_TAILUPD_ENB && rcd->rcvhdrqtailaddr_dma)
+       if ((op & HFI1_RCVCTRL_TAILUPD_ENB) && rcd->rcvhdrtail_kvaddr)
                rcvctrl |= RCV_CTXT_CTRL_TAIL_UPD_SMASK;
        if (op & HFI1_RCVCTRL_TAILUPD_DIS) {
                /* See comment on RcvCtxtCtrl.TailUpd above */
index cb6ff9d..9abc5a9 100644 (file)
@@ -622,7 +622,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
                        ret = -EINVAL;
                        goto done;
                }
-               if (flags & VM_WRITE) {
+               if ((flags & VM_WRITE) || !uctxt->rcvhdrtail_kvaddr) {
                        ret = -EPERM;
                        goto done;
                }
index c5f5027..ee5cbdf 100644 (file)
@@ -1808,7 +1808,6 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
        u64 reg;
 
        if (!rcd->rcvhdrq) {
-               dma_addr_t dma_hdrqtail;
                gfp_t gfp_flags;
 
                /*
@@ -1834,13 +1833,13 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
                        goto bail;
                }
 
-               if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL)) {
+               if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL) ||
+                   HFI1_CAP_UGET_MASK(rcd->flags, DMA_RTAIL)) {
                        rcd->rcvhdrtail_kvaddr = dma_zalloc_coherent(
-                               &dd->pcidev->dev, PAGE_SIZE, &dma_hdrqtail,
-                               gfp_flags);
+                               &dd->pcidev->dev, PAGE_SIZE,
+                               &rcd->rcvhdrqtailaddr_dma, gfp_flags);
                        if (!rcd->rcvhdrtail_kvaddr)
                                goto bail_free;
-                       rcd->rcvhdrqtailaddr_dma = dma_hdrqtail;
                }
 
                rcd->rcvhdrq_size = amt;