Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1bc0299d authored by Mike Marciniszyn's avatar Mike Marciniszyn Committed by Jason Gunthorpe
Browse files

IB/hfi1: Fix user context tail allocation for DMA_RTAIL



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: default avatarMichael J. Ruhl <michael.j.ruhl@intel.com>
Signed-off-by: default avatarMike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 8c61b245
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -6841,7 +6841,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);
@@ -8367,7 +8367,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 */
@@ -11843,7 +11843,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;
@@ -11923,7 +11923,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 */
+1 −1
Original line number Diff line number Diff line
@@ -505,7 +505,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;
		}
+4 −5
Original line number Diff line number Diff line
@@ -1853,7 +1853,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;

		/*
@@ -1878,13 +1877,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;