Merge tag 'compat-ioctl-5.5' of git://git.kernel.org:/pub/scm/linux/kernel/git/arnd...
[linux-2.6-block.git] / drivers / infiniband / core / uverbs_main.c
index c4c652e870444020f8b9658e21ecad0e362f9a94..970d8e31dd658ccd81cd5d029d38567257675d13 100644 (file)
@@ -772,6 +772,8 @@ out_unlock:
        return (ret) ? : count;
 }
 
+static const struct vm_operations_struct rdma_umap_ops;
+
 static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
 {
        struct ib_uverbs_file *file = filp->private_data;
@@ -785,45 +787,13 @@ static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
                ret = PTR_ERR(ucontext);
                goto out;
        }
-
+       vma->vm_ops = &rdma_umap_ops;
        ret = ucontext->device->ops.mmap(ucontext, vma);
 out:
        srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
        return ret;
 }
 
-/*
- * Each time we map IO memory into user space this keeps track of the mapping.
- * When the device is hot-unplugged we 'zap' the mmaps in user space to point
- * to the zero page and allow the hot unplug to proceed.
- *
- * This is necessary for cases like PCI physical hot unplug as the actual BAR
- * memory may vanish after this and access to it from userspace could MCE.
- *
- * RDMA drivers supporting disassociation must have their user space designed
- * to cope in some way with their IO pages going to the zero page.
- */
-struct rdma_umap_priv {
-       struct vm_area_struct *vma;
-       struct list_head list;
-};
-
-static const struct vm_operations_struct rdma_umap_ops;
-
-static void rdma_umap_priv_init(struct rdma_umap_priv *priv,
-                               struct vm_area_struct *vma)
-{
-       struct ib_uverbs_file *ufile = vma->vm_file->private_data;
-
-       priv->vma = vma;
-       vma->vm_private_data = priv;
-       vma->vm_ops = &rdma_umap_ops;
-
-       mutex_lock(&ufile->umap_lock);
-       list_add(&priv->list, &ufile->umaps);
-       mutex_unlock(&ufile->umap_lock);
-}
-
 /*
  * The VMA has been dup'd, initialize the vm_private_data with a new tracking
  * struct
@@ -849,7 +819,7 @@ static void rdma_umap_open(struct vm_area_struct *vma)
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
                goto out_unlock;
-       rdma_umap_priv_init(priv, vma);
+       rdma_umap_priv_init(priv, vma, opriv->entry);
 
        up_read(&ufile->hw_destroy_rwsem);
        return;
@@ -880,6 +850,9 @@ static void rdma_umap_close(struct vm_area_struct *vma)
         * this point.
         */
        mutex_lock(&ufile->umap_lock);
+       if (priv->entry)
+               rdma_user_mmap_entry_put(priv->entry);
+
        list_del(&priv->list);
        mutex_unlock(&ufile->umap_lock);
        kfree(priv);
@@ -931,44 +904,6 @@ static const struct vm_operations_struct rdma_umap_ops = {
        .fault = rdma_umap_fault,
 };
 
-/*
- * Map IO memory into a process. This is to be called by drivers as part of
- * their mmap() functions if they wish to send something like PCI-E BAR memory
- * to userspace.
- */
-int rdma_user_mmap_io(struct ib_ucontext *ucontext, struct vm_area_struct *vma,
-                     unsigned long pfn, unsigned long size, pgprot_t prot)
-{
-       struct ib_uverbs_file *ufile = ucontext->ufile;
-       struct rdma_umap_priv *priv;
-
-       if (!(vma->vm_flags & VM_SHARED))
-               return -EINVAL;
-
-       if (vma->vm_end - vma->vm_start != size)
-               return -EINVAL;
-
-       /* Driver is using this wrong, must be called by ib_uverbs_mmap */
-       if (WARN_ON(!vma->vm_file ||
-                   vma->vm_file->private_data != ufile))
-               return -EINVAL;
-       lockdep_assert_held(&ufile->device->disassociate_srcu);
-
-       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       vma->vm_page_prot = prot;
-       if (io_remap_pfn_range(vma, vma->vm_start, pfn, size, prot)) {
-               kfree(priv);
-               return -EAGAIN;
-       }
-
-       rdma_umap_priv_init(priv, vma);
-       return 0;
-}
-EXPORT_SYMBOL(rdma_user_mmap_io);
-
 void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
 {
        struct rdma_umap_priv *priv, *next_priv;
@@ -1018,6 +953,11 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
 
                        zap_vma_ptes(vma, vma->vm_start,
                                     vma->vm_end - vma->vm_start);
+
+                       if (priv->entry) {
+                               rdma_user_mmap_entry_put(priv->entry);
+                               priv->entry = NULL;
+                       }
                }
                mutex_unlock(&ufile->umap_lock);
        skip_mm: