Commit 14f974d7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull rdma fixes from Jason Gunthorpe:
 "One core bug fix and a few driver ones

   - FRWR memory registration for hfi1/qib didn't work with with some
     iovas causing a NFSoRDMA failure regression due to a fix in the NFS
     side

   - A command flow error in mlx5 allowed user space to send a corrupt
     command (and also smash the kernel stack we've since learned)

   - Fix a regression and some bugs with device hot unplug that was
     discovered while reviewing Andrea's patches

   - hns has a failure if the user asks for certain QP configurations"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
  RDMA/hns: Bugfix for mapping user db
  RDMA/ucontext: Fix regression with disassociate
  RDMA/mlx5: Use rdma_user_map_io for mapping BAR pages
  RDMA/mlx5: Do not allow the user to write to the clock page
  IB/mlx5: Fix scatter to CQE in DCT QP creation
  IB/rdmavt: Fix frwr memory registration
parents 72a6e35d 2557fabd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -160,6 +160,7 @@ struct ib_uverbs_file {

	struct mutex umap_lock;
	struct list_head umaps;
	struct page *disassociate_page;

	struct idr		idr;
	/* spinlock protects write access to idr */
+49 −3
Original line number Diff line number Diff line
@@ -208,6 +208,9 @@ void ib_uverbs_release_file(struct kref *ref)
		kref_put(&file->async_file->ref,
			 ib_uverbs_release_async_event_file);
	put_device(&file->device->dev);

	if (file->disassociate_page)
		__free_pages(file->disassociate_page, 0);
	kfree(file);
}

@@ -877,9 +880,50 @@ static void rdma_umap_close(struct vm_area_struct *vma)
	kfree(priv);
}

/*
 * Once the zap_vma_ptes has been called touches to the VMA will come here and
 * we return a dummy writable zero page for all the pfns.
 */
static vm_fault_t rdma_umap_fault(struct vm_fault *vmf)
{
	struct ib_uverbs_file *ufile = vmf->vma->vm_file->private_data;
	struct rdma_umap_priv *priv = vmf->vma->vm_private_data;
	vm_fault_t ret = 0;

	if (!priv)
		return VM_FAULT_SIGBUS;

	/* Read only pages can just use the system zero page. */
	if (!(vmf->vma->vm_flags & (VM_WRITE | VM_MAYWRITE))) {
		vmf->page = ZERO_PAGE(vmf->vm_start);
		get_page(vmf->page);
		return 0;
	}

	mutex_lock(&ufile->umap_lock);
	if (!ufile->disassociate_page)
		ufile->disassociate_page =
			alloc_pages(vmf->gfp_mask | __GFP_ZERO, 0);

	if (ufile->disassociate_page) {
		/*
		 * This VMA is forced to always be shared so this doesn't have
		 * to worry about COW.
		 */
		vmf->page = ufile->disassociate_page;
		get_page(vmf->page);
	} else {
		ret = VM_FAULT_SIGBUS;
	}
	mutex_unlock(&ufile->umap_lock);

	return ret;
}

static const struct vm_operations_struct rdma_umap_ops = {
	.open = rdma_umap_open,
	.close = rdma_umap_close,
	.fault = rdma_umap_fault,
};

static struct rdma_umap_priv *rdma_user_mmap_pre(struct ib_ucontext *ucontext,
@@ -889,6 +933,9 @@ static struct rdma_umap_priv *rdma_user_mmap_pre(struct ib_ucontext *ucontext,
	struct ib_uverbs_file *ufile = ucontext->ufile;
	struct rdma_umap_priv *priv;

	if (!(vma->vm_flags & VM_SHARED))
		return ERR_PTR(-EINVAL);

	if (vma->vm_end - vma->vm_start != size)
		return ERR_PTR(-EINVAL);

@@ -992,7 +1039,7 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
		 * at a time to get the lock ordering right. Typically there
		 * will only be one mm, so no big deal.
		 */
		down_write(&mm->mmap_sem);
		down_read(&mm->mmap_sem);
		if (!mmget_still_valid(mm))
			goto skip_mm;
		mutex_lock(&ufile->umap_lock);
@@ -1006,11 +1053,10 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)

			zap_vma_ptes(vma, vma->vm_start,
				     vma->vm_end - vma->vm_start);
			vma->vm_flags &= ~(VM_SHARED | VM_MAYSHARE);
		}
		mutex_unlock(&ufile->umap_lock);
	skip_mm:
		up_write(&mm->mmap_sem);
		up_read(&mm->mmap_sem);
		mmput(mm);
	}
}
+1 −1
Original line number Diff line number Diff line
@@ -533,7 +533,7 @@ static int hns_roce_set_kernel_sq_size(struct hns_roce_dev *hr_dev,

static int hns_roce_qp_has_sq(struct ib_qp_init_attr *attr)
{
	if (attr->qp_type == IB_QPT_XRC_TGT)
	if (attr->qp_type == IB_QPT_XRC_TGT || !attr->cap.max_send_wr)
		return 0;

	return 1;
+7 −5
Original line number Diff line number Diff line
@@ -1119,6 +1119,8 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
		if (MLX5_CAP_GEN(mdev, qp_packet_based))
			resp.flags |=
				MLX5_IB_QUERY_DEV_RESP_PACKET_BASED_CREDIT_MODE;

		resp.flags |= MLX5_IB_QUERY_DEV_RESP_FLAGS_SCAT2CQE_DCT;
	}

	if (field_avail(typeof(resp), sw_parsing_caps,
@@ -2066,6 +2068,7 @@ static int mlx5_ib_mmap_clock_info_page(struct mlx5_ib_dev *dev,

	if (vma->vm_flags & VM_WRITE)
		return -EPERM;
	vma->vm_flags &= ~VM_MAYWRITE;

	if (!dev->mdev->clock_info_page)
		return -EOPNOTSUPP;
@@ -2231,19 +2234,18 @@ static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vm

		if (vma->vm_flags & VM_WRITE)
			return -EPERM;
		vma->vm_flags &= ~VM_MAYWRITE;

		/* Don't expose to user-space information it shouldn't have */
		if (PAGE_SIZE > 4096)
			return -EOPNOTSUPP;

		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
		pfn = (dev->mdev->iseg_base +
		       offsetof(struct mlx5_init_seg, internal_timer_h)) >>
			PAGE_SHIFT;
		if (io_remap_pfn_range(vma, vma->vm_start, pfn,
				       PAGE_SIZE, vma->vm_page_prot))
			return -EAGAIN;
		break;
		return rdma_user_mmap_io(&context->ibucontext, vma, pfn,
					 PAGE_SIZE,
					 pgprot_noncached(vma->vm_page_prot));
	case MLX5_IB_MMAP_CLOCK_INFO:
		return mlx5_ib_mmap_clock_info_page(dev, vma, context);

+7 −4
Original line number Diff line number Diff line
@@ -1818,13 +1818,16 @@ static void configure_responder_scat_cqe(struct ib_qp_init_attr *init_attr,

	rcqe_sz = mlx5_ib_get_cqe_size(init_attr->recv_cq);

	if (rcqe_sz == 128) {
		MLX5_SET(qpc, qpc, cs_res, MLX5_RES_SCAT_DATA64_CQE);
	if (init_attr->qp_type == MLX5_IB_QPT_DCT) {
		if (rcqe_sz == 128)
			MLX5_SET(dctc, qpc, cs_res, MLX5_RES_SCAT_DATA64_CQE);

		return;
	}

	if (init_attr->qp_type != MLX5_IB_QPT_DCT)
		MLX5_SET(qpc, qpc, cs_res, MLX5_RES_SCAT_DATA32_CQE);
	MLX5_SET(qpc, qpc, cs_res,
		 rcqe_sz == 128 ? MLX5_RES_SCAT_DATA64_CQE :
				  MLX5_RES_SCAT_DATA32_CQE);
}

static void configure_requester_scat_cqe(struct mlx5_ib_dev *dev,
Loading