diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-04-28 13:00:45 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-04-28 13:00:45 -0400 |
| commit | 14f974d7f0f1f93d8c35f496ae774ba0f1b3389a (patch) | |
| tree | f91018a260c8090311ef4cfde609a9487967daab | |
| parent | 72a6e35db32b63883e2e3d19cd6a515eac1f5d67 (diff) | |
| parent | 2557fabd6e29f349bfa0ac13f38ac98aa5eafc74 (diff) | |
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
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
| -rw-r--r-- | drivers/infiniband/core/uverbs.h | 1 | ||||
| -rw-r--r-- | drivers/infiniband/core/uverbs_main.c | 52 | ||||
| -rw-r--r-- | drivers/infiniband/hw/hns/hns_roce_qp.c | 2 | ||||
| -rw-r--r-- | drivers/infiniband/hw/mlx5/main.c | 12 | ||||
| -rw-r--r-- | drivers/infiniband/hw/mlx5/qp.c | 11 | ||||
| -rw-r--r-- | drivers/infiniband/sw/rdmavt/mr.c | 17 | ||||
| -rw-r--r-- | include/uapi/rdma/mlx5-abi.h | 1 |
7 files changed, 76 insertions, 20 deletions
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index ea0bc6885517..32cc8fe7902f 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h | |||
| @@ -160,6 +160,7 @@ struct ib_uverbs_file { | |||
| 160 | 160 | ||
| 161 | struct mutex umap_lock; | 161 | struct mutex umap_lock; |
| 162 | struct list_head umaps; | 162 | struct list_head umaps; |
| 163 | struct page *disassociate_page; | ||
| 163 | 164 | ||
| 164 | struct idr idr; | 165 | struct idr idr; |
| 165 | /* spinlock protects write access to idr */ | 166 | /* spinlock protects write access to idr */ |
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index f2e7ffe6fc54..7843e89235c3 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
| @@ -208,6 +208,9 @@ void ib_uverbs_release_file(struct kref *ref) | |||
| 208 | kref_put(&file->async_file->ref, | 208 | kref_put(&file->async_file->ref, |
| 209 | ib_uverbs_release_async_event_file); | 209 | ib_uverbs_release_async_event_file); |
| 210 | put_device(&file->device->dev); | 210 | put_device(&file->device->dev); |
| 211 | |||
| 212 | if (file->disassociate_page) | ||
| 213 | __free_pages(file->disassociate_page, 0); | ||
| 211 | kfree(file); | 214 | kfree(file); |
| 212 | } | 215 | } |
| 213 | 216 | ||
| @@ -877,9 +880,50 @@ static void rdma_umap_close(struct vm_area_struct *vma) | |||
| 877 | kfree(priv); | 880 | kfree(priv); |
| 878 | } | 881 | } |
| 879 | 882 | ||
| 883 | /* | ||
| 884 | * Once the zap_vma_ptes has been called touches to the VMA will come here and | ||
| 885 | * we return a dummy writable zero page for all the pfns. | ||
| 886 | */ | ||
| 887 | static vm_fault_t rdma_umap_fault(struct vm_fault *vmf) | ||
| 888 | { | ||
| 889 | struct ib_uverbs_file *ufile = vmf->vma->vm_file->private_data; | ||
| 890 | struct rdma_umap_priv *priv = vmf->vma->vm_private_data; | ||
| 891 | vm_fault_t ret = 0; | ||
| 892 | |||
| 893 | if (!priv) | ||
| 894 | return VM_FAULT_SIGBUS; | ||
| 895 | |||
| 896 | /* Read only pages can just use the system zero page. */ | ||
| 897 | if (!(vmf->vma->vm_flags & (VM_WRITE | VM_MAYWRITE))) { | ||
| 898 | vmf->page = ZERO_PAGE(vmf->vm_start); | ||
| 899 | get_page(vmf->page); | ||
| 900 | return 0; | ||
| 901 | } | ||
| 902 | |||
| 903 | mutex_lock(&ufile->umap_lock); | ||
| 904 | if (!ufile->disassociate_page) | ||
| 905 | ufile->disassociate_page = | ||
| 906 | alloc_pages(vmf->gfp_mask | __GFP_ZERO, 0); | ||
| 907 | |||
| 908 | if (ufile->disassociate_page) { | ||
| 909 | /* | ||
| 910 | * This VMA is forced to always be shared so this doesn't have | ||
| 911 | * to worry about COW. | ||
| 912 | */ | ||
| 913 | vmf->page = ufile->disassociate_page; | ||
| 914 | get_page(vmf->page); | ||
| 915 | } else { | ||
| 916 | ret = VM_FAULT_SIGBUS; | ||
| 917 | } | ||
| 918 | mutex_unlock(&ufile->umap_lock); | ||
| 919 | |||
| 920 | return ret; | ||
| 921 | } | ||
| 922 | |||
| 880 | static const struct vm_operations_struct rdma_umap_ops = { | 923 | static const struct vm_operations_struct rdma_umap_ops = { |
| 881 | .open = rdma_umap_open, | 924 | .open = rdma_umap_open, |
| 882 | .close = rdma_umap_close, | 925 | .close = rdma_umap_close, |
| 926 | .fault = rdma_umap_fault, | ||
| 883 | }; | 927 | }; |
| 884 | 928 | ||
| 885 | static struct rdma_umap_priv *rdma_user_mmap_pre(struct ib_ucontext *ucontext, | 929 | 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, | |||
| 889 | struct ib_uverbs_file *ufile = ucontext->ufile; | 933 | struct ib_uverbs_file *ufile = ucontext->ufile; |
| 890 | struct rdma_umap_priv *priv; | 934 | struct rdma_umap_priv *priv; |
| 891 | 935 | ||
| 936 | if (!(vma->vm_flags & VM_SHARED)) | ||
| 937 | return ERR_PTR(-EINVAL); | ||
| 938 | |||
| 892 | if (vma->vm_end - vma->vm_start != size) | 939 | if (vma->vm_end - vma->vm_start != size) |
| 893 | return ERR_PTR(-EINVAL); | 940 | return ERR_PTR(-EINVAL); |
| 894 | 941 | ||
| @@ -992,7 +1039,7 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile) | |||
| 992 | * at a time to get the lock ordering right. Typically there | 1039 | * at a time to get the lock ordering right. Typically there |
| 993 | * will only be one mm, so no big deal. | 1040 | * will only be one mm, so no big deal. |
| 994 | */ | 1041 | */ |
| 995 | down_write(&mm->mmap_sem); | 1042 | down_read(&mm->mmap_sem); |
| 996 | if (!mmget_still_valid(mm)) | 1043 | if (!mmget_still_valid(mm)) |
| 997 | goto skip_mm; | 1044 | goto skip_mm; |
| 998 | mutex_lock(&ufile->umap_lock); | 1045 | mutex_lock(&ufile->umap_lock); |
| @@ -1006,11 +1053,10 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile) | |||
| 1006 | 1053 | ||
| 1007 | zap_vma_ptes(vma, vma->vm_start, | 1054 | zap_vma_ptes(vma, vma->vm_start, |
| 1008 | vma->vm_end - vma->vm_start); | 1055 | vma->vm_end - vma->vm_start); |
| 1009 | vma->vm_flags &= ~(VM_SHARED | VM_MAYSHARE); | ||
| 1010 | } | 1056 | } |
| 1011 | mutex_unlock(&ufile->umap_lock); | 1057 | mutex_unlock(&ufile->umap_lock); |
| 1012 | skip_mm: | 1058 | skip_mm: |
| 1013 | up_write(&mm->mmap_sem); | 1059 | up_read(&mm->mmap_sem); |
| 1014 | mmput(mm); | 1060 | mmput(mm); |
| 1015 | } | 1061 | } |
| 1016 | } | 1062 | } |
diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c index 66cdf625534f..60cf9f03e941 100644 --- a/drivers/infiniband/hw/hns/hns_roce_qp.c +++ b/drivers/infiniband/hw/hns/hns_roce_qp.c | |||
| @@ -533,7 +533,7 @@ static int hns_roce_set_kernel_sq_size(struct hns_roce_dev *hr_dev, | |||
| 533 | 533 | ||
| 534 | static int hns_roce_qp_has_sq(struct ib_qp_init_attr *attr) | 534 | static int hns_roce_qp_has_sq(struct ib_qp_init_attr *attr) |
| 535 | { | 535 | { |
| 536 | if (attr->qp_type == IB_QPT_XRC_TGT) | 536 | if (attr->qp_type == IB_QPT_XRC_TGT || !attr->cap.max_send_wr) |
| 537 | return 0; | 537 | return 0; |
| 538 | 538 | ||
| 539 | return 1; | 539 | return 1; |
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 531ff20b32ad..d3dd290ae1b1 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c | |||
| @@ -1119,6 +1119,8 @@ static int mlx5_ib_query_device(struct ib_device *ibdev, | |||
| 1119 | if (MLX5_CAP_GEN(mdev, qp_packet_based)) | 1119 | if (MLX5_CAP_GEN(mdev, qp_packet_based)) |
| 1120 | resp.flags |= | 1120 | resp.flags |= |
| 1121 | MLX5_IB_QUERY_DEV_RESP_PACKET_BASED_CREDIT_MODE; | 1121 | MLX5_IB_QUERY_DEV_RESP_PACKET_BASED_CREDIT_MODE; |
| 1122 | |||
| 1123 | resp.flags |= MLX5_IB_QUERY_DEV_RESP_FLAGS_SCAT2CQE_DCT; | ||
| 1122 | } | 1124 | } |
| 1123 | 1125 | ||
| 1124 | if (field_avail(typeof(resp), sw_parsing_caps, | 1126 | 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, | |||
| 2066 | 2068 | ||
| 2067 | if (vma->vm_flags & VM_WRITE) | 2069 | if (vma->vm_flags & VM_WRITE) |
| 2068 | return -EPERM; | 2070 | return -EPERM; |
| 2071 | vma->vm_flags &= ~VM_MAYWRITE; | ||
| 2069 | 2072 | ||
| 2070 | if (!dev->mdev->clock_info_page) | 2073 | if (!dev->mdev->clock_info_page) |
| 2071 | return -EOPNOTSUPP; | 2074 | return -EOPNOTSUPP; |
| @@ -2231,19 +2234,18 @@ static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vm | |||
| 2231 | 2234 | ||
| 2232 | if (vma->vm_flags & VM_WRITE) | 2235 | if (vma->vm_flags & VM_WRITE) |
| 2233 | return -EPERM; | 2236 | return -EPERM; |
| 2237 | vma->vm_flags &= ~VM_MAYWRITE; | ||
| 2234 | 2238 | ||
| 2235 | /* Don't expose to user-space information it shouldn't have */ | 2239 | /* Don't expose to user-space information it shouldn't have */ |
| 2236 | if (PAGE_SIZE > 4096) | 2240 | if (PAGE_SIZE > 4096) |
| 2237 | return -EOPNOTSUPP; | 2241 | return -EOPNOTSUPP; |
| 2238 | 2242 | ||
| 2239 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
| 2240 | pfn = (dev->mdev->iseg_base + | 2243 | pfn = (dev->mdev->iseg_base + |
| 2241 | offsetof(struct mlx5_init_seg, internal_timer_h)) >> | 2244 | offsetof(struct mlx5_init_seg, internal_timer_h)) >> |
| 2242 | PAGE_SHIFT; | 2245 | PAGE_SHIFT; |
| 2243 | if (io_remap_pfn_range(vma, vma->vm_start, pfn, | 2246 | return rdma_user_mmap_io(&context->ibucontext, vma, pfn, |
| 2244 | PAGE_SIZE, vma->vm_page_prot)) | 2247 | PAGE_SIZE, |
| 2245 | return -EAGAIN; | 2248 | pgprot_noncached(vma->vm_page_prot)); |
| 2246 | break; | ||
| 2247 | case MLX5_IB_MMAP_CLOCK_INFO: | 2249 | case MLX5_IB_MMAP_CLOCK_INFO: |
| 2248 | return mlx5_ib_mmap_clock_info_page(dev, vma, context); | 2250 | return mlx5_ib_mmap_clock_info_page(dev, vma, context); |
| 2249 | 2251 | ||
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 7cd006da1dae..8870c350fda0 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c | |||
| @@ -1818,13 +1818,16 @@ static void configure_responder_scat_cqe(struct ib_qp_init_attr *init_attr, | |||
| 1818 | 1818 | ||
| 1819 | rcqe_sz = mlx5_ib_get_cqe_size(init_attr->recv_cq); | 1819 | rcqe_sz = mlx5_ib_get_cqe_size(init_attr->recv_cq); |
| 1820 | 1820 | ||
| 1821 | if (rcqe_sz == 128) { | 1821 | if (init_attr->qp_type == MLX5_IB_QPT_DCT) { |
| 1822 | MLX5_SET(qpc, qpc, cs_res, MLX5_RES_SCAT_DATA64_CQE); | 1822 | if (rcqe_sz == 128) |
| 1823 | MLX5_SET(dctc, qpc, cs_res, MLX5_RES_SCAT_DATA64_CQE); | ||
| 1824 | |||
| 1823 | return; | 1825 | return; |
| 1824 | } | 1826 | } |
| 1825 | 1827 | ||
| 1826 | if (init_attr->qp_type != MLX5_IB_QPT_DCT) | 1828 | MLX5_SET(qpc, qpc, cs_res, |
| 1827 | MLX5_SET(qpc, qpc, cs_res, MLX5_RES_SCAT_DATA32_CQE); | 1829 | rcqe_sz == 128 ? MLX5_RES_SCAT_DATA64_CQE : |
| 1830 | MLX5_RES_SCAT_DATA32_CQE); | ||
| 1828 | } | 1831 | } |
| 1829 | 1832 | ||
| 1830 | static void configure_requester_scat_cqe(struct mlx5_ib_dev *dev, | 1833 | static void configure_requester_scat_cqe(struct mlx5_ib_dev *dev, |
diff --git a/drivers/infiniband/sw/rdmavt/mr.c b/drivers/infiniband/sw/rdmavt/mr.c index 728795043496..0bb6e39dd03a 100644 --- a/drivers/infiniband/sw/rdmavt/mr.c +++ b/drivers/infiniband/sw/rdmavt/mr.c | |||
| @@ -608,11 +608,6 @@ static int rvt_set_page(struct ib_mr *ibmr, u64 addr) | |||
| 608 | if (unlikely(mapped_segs == mr->mr.max_segs)) | 608 | if (unlikely(mapped_segs == mr->mr.max_segs)) |
| 609 | return -ENOMEM; | 609 | return -ENOMEM; |
| 610 | 610 | ||
| 611 | if (mr->mr.length == 0) { | ||
| 612 | mr->mr.user_base = addr; | ||
| 613 | mr->mr.iova = addr; | ||
| 614 | } | ||
| 615 | |||
| 616 | m = mapped_segs / RVT_SEGSZ; | 611 | m = mapped_segs / RVT_SEGSZ; |
| 617 | n = mapped_segs % RVT_SEGSZ; | 612 | n = mapped_segs % RVT_SEGSZ; |
| 618 | mr->mr.map[m]->segs[n].vaddr = (void *)addr; | 613 | mr->mr.map[m]->segs[n].vaddr = (void *)addr; |
| @@ -630,17 +625,24 @@ static int rvt_set_page(struct ib_mr *ibmr, u64 addr) | |||
| 630 | * @sg_nents: number of entries in sg | 625 | * @sg_nents: number of entries in sg |
| 631 | * @sg_offset: offset in bytes into sg | 626 | * @sg_offset: offset in bytes into sg |
| 632 | * | 627 | * |
| 628 | * Overwrite rvt_mr length with mr length calculated by ib_sg_to_pages. | ||
| 629 | * | ||
| 633 | * Return: number of sg elements mapped to the memory region | 630 | * Return: number of sg elements mapped to the memory region |
| 634 | */ | 631 | */ |
| 635 | int rvt_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, | 632 | int rvt_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, |
| 636 | int sg_nents, unsigned int *sg_offset) | 633 | int sg_nents, unsigned int *sg_offset) |
| 637 | { | 634 | { |
| 638 | struct rvt_mr *mr = to_imr(ibmr); | 635 | struct rvt_mr *mr = to_imr(ibmr); |
| 636 | int ret; | ||
| 639 | 637 | ||
| 640 | mr->mr.length = 0; | 638 | mr->mr.length = 0; |
| 641 | mr->mr.page_shift = PAGE_SHIFT; | 639 | mr->mr.page_shift = PAGE_SHIFT; |
| 642 | return ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, | 640 | ret = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, rvt_set_page); |
| 643 | rvt_set_page); | 641 | mr->mr.user_base = ibmr->iova; |
| 642 | mr->mr.iova = ibmr->iova; | ||
| 643 | mr->mr.offset = ibmr->iova - (u64)mr->mr.map[0]->segs[0].vaddr; | ||
| 644 | mr->mr.length = (size_t)ibmr->length; | ||
| 645 | return ret; | ||
| 644 | } | 646 | } |
| 645 | 647 | ||
| 646 | /** | 648 | /** |
| @@ -671,6 +673,7 @@ int rvt_fast_reg_mr(struct rvt_qp *qp, struct ib_mr *ibmr, u32 key, | |||
| 671 | ibmr->rkey = key; | 673 | ibmr->rkey = key; |
| 672 | mr->mr.lkey = key; | 674 | mr->mr.lkey = key; |
| 673 | mr->mr.access_flags = access; | 675 | mr->mr.access_flags = access; |
| 676 | mr->mr.iova = ibmr->iova; | ||
| 674 | atomic_set(&mr->mr.lkey_invalid, 0); | 677 | atomic_set(&mr->mr.lkey_invalid, 0); |
| 675 | 678 | ||
| 676 | return 0; | 679 | return 0; |
diff --git a/include/uapi/rdma/mlx5-abi.h b/include/uapi/rdma/mlx5-abi.h index 87b3198f4b5d..f4d4010b7e3e 100644 --- a/include/uapi/rdma/mlx5-abi.h +++ b/include/uapi/rdma/mlx5-abi.h | |||
| @@ -238,6 +238,7 @@ enum mlx5_ib_query_dev_resp_flags { | |||
| 238 | MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_COMP = 1 << 0, | 238 | MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_COMP = 1 << 0, |
| 239 | MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_PAD = 1 << 1, | 239 | MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_PAD = 1 << 1, |
| 240 | MLX5_IB_QUERY_DEV_RESP_PACKET_BASED_CREDIT_MODE = 1 << 2, | 240 | MLX5_IB_QUERY_DEV_RESP_PACKET_BASED_CREDIT_MODE = 1 << 2, |
| 241 | MLX5_IB_QUERY_DEV_RESP_FLAGS_SCAT2CQE_DCT = 1 << 3, | ||
| 241 | }; | 242 | }; |
| 242 | 243 | ||
| 243 | enum mlx5_ib_tunnel_offloads { | 244 | enum mlx5_ib_tunnel_offloads { |
