From: Valentine Fatiev <valentinef@nvidia.com>
Subject: [PATCH] BACKPORT: drivers/infiniband/core/uverbs_main.c

Change-Id: I9f0164f6254ec35299c869597c5e253fe37490dc
---
 drivers/infiniband/core/uverbs_main.c | 65 ++++++++++++++++++++++++---
 1 file changed, 60 insertions(+), 5 deletions(-)

--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -29,6 +29,7 @@
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ 
  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
@@ -60,6 +61,9 @@
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("InfiniBand userspace verbs access");
 MODULE_LICENSE("Dual BSD/GPL");
+#ifdef RETPOLINE_MLNX
+MODULE_INFO(retpoline, "Y");
+#endif
 
 enum {
 	IB_UVERBS_MAJOR       = 231,
@@ -73,18 +77,26 @@ enum {
 
 static dev_t dynamic_uverbs_dev;
 
+#ifndef HAVE_IDA_ALLOC_MAX
+static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
+#else
 static DEFINE_IDA(uverbs_ida);
+#endif
 static int ib_uverbs_add_one(struct ib_device *device);
 static void ib_uverbs_remove_one(struct ib_device *device, void *client_data);
 
+#ifdef HAVE_DEVNODE_GET_CONST_DEVICE
 static char *uverbs_devnode(const struct device *dev, umode_t *mode)
+#else
+static char *uverbs_devnode(struct device *dev, umode_t *mode)
+#endif
 {
 	if (mode)
 		*mode = 0666;
 	return kasprintf(GFP_KERNEL, "infiniband/%s", dev_name(dev));
 }
 
-static const struct class uverbs_class = {
+static struct class uverbs_class = {
 	.name = "infiniband_verbs",
 	.devnode = uverbs_devnode,
 };
@@ -101,7 +113,6 @@ struct ib_ucontext *ib_uverbs_get_uconte
 	 * get_context, we get NULL or valid ucontext.
 	 */
 	struct ib_ucontext *ucontext = smp_load_acquire(&ufile->ucontext);
-
 	if (!srcu_dereference(ufile->device->ib_dev,
 			      &ufile->device->disassociate_srcu))
 		return ERR_PTR(-EIO);
@@ -353,7 +364,9 @@ const struct file_operations uverbs_even
 	.poll    = ib_uverbs_comp_event_poll,
 	.release = uverbs_uobject_fd_release,
 	.fasync  = ib_uverbs_comp_event_fasync,
+#ifdef no_llseek
 	.llseek	 = no_llseek,
+#endif
 };
 
 const struct file_operations uverbs_async_event_fops = {
@@ -362,7 +375,9 @@ const struct file_operations uverbs_asyn
 	.poll    = ib_uverbs_async_event_poll,
 	.release = uverbs_async_event_release,
 	.fasync  = ib_uverbs_async_event_fasync,
+#ifdef no_llseek
 	.llseek	 = no_llseek,
+#endif
 };
 
 void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
@@ -531,8 +546,14 @@ static ssize_t verify_hdr(struct ib_uver
 			if (hdr->out_words * 8 < method_elm->resp_size)
 				return -ENOSPC;
 
+#ifdef HAVE_ACCESS_OK_HAS_3_PARAMS 
+ 			if (!access_ok(VERIFY_WRITE,
+ 				       u64_to_user_ptr(ex_hdr->response),
+ 				       (hdr->out_words + ex_hdr->provider_out_words) * 8))
+#else
 			if (!access_ok(u64_to_user_ptr(ex_hdr->response),
 				       (hdr->out_words + ex_hdr->provider_out_words) * 8))
+#endif
 				return -EFAULT;
 		} else {
 			if (hdr->out_words || ex_hdr->provider_out_words)
@@ -810,7 +831,6 @@ static vm_fault_t rdma_umap_fault(struct
 
 	return ret;
 }
-
 static const struct vm_operations_struct rdma_umap_ops = {
 	.open = rdma_umap_open,
 	.close = rdma_umap_close,
@@ -856,7 +876,11 @@ void uverbs_user_mmap_disassociate(struc
 		 * at a time to get the lock ordering right. Typically there
 		 * will only be one mm, so no big deal.
 		 */
+#ifdef HAVE_MMAP_READ_LOCK
 		mmap_read_lock(mm);
+#else
+		down_read(&mm->mmap_sem);
+#endif
 		mutex_lock(&ufile->umap_lock);
 		list_for_each_entry_safe (priv, next_priv, &ufile->umaps,
 					  list) {
@@ -875,7 +899,11 @@ void uverbs_user_mmap_disassociate(struc
 			}
 		}
 		mutex_unlock(&ufile->umap_lock);
-		mmap_read_unlock(mm);
+#ifdef HAVE_MMAP_READ_LOCK
+       	mmap_read_unlock(mm);
+#else
+		up_read(&mm->mmap_sem);
+#endif
 		mmput(mm);
 	}
 }
@@ -956,7 +984,11 @@ static int ib_uverbs_open(struct inode *
 
 	setup_ufile_idr_uobject(file);
 
+#ifdef HAVE_STREAM_OPEN
 	return stream_open(inode, filp);
+#else
+	return nonseekable_open(inode, filp);
+#endif
 
 err_module:
 	module_put(ib_dev->ops.owner);
@@ -991,7 +1023,9 @@ static const struct file_operations uver
 	.write	 = ib_uverbs_write,
 	.open	 = ib_uverbs_open,
 	.release = ib_uverbs_close,
+#ifdef no_llseek
 	.llseek	 = no_llseek,
+#endif
 	.unlocked_ioctl = ib_uverbs_ioctl,
 	.compat_ioctl = compat_ptr_ioctl,
 };
@@ -1002,7 +1036,9 @@ static const struct file_operations uver
 	.mmap    = ib_uverbs_mmap,
 	.open	 = ib_uverbs_open,
 	.release = ib_uverbs_close,
+#ifdef no_llseek
 	.llseek	 = no_llseek,
+#endif
 	.unlocked_ioctl = ib_uverbs_ioctl,
 	.compat_ioctl = compat_ptr_ioctl,
 };
@@ -1143,13 +1179,21 @@ static int ib_uverbs_add_one(struct ib_d
 	rcu_assign_pointer(uverbs_dev->ib_dev, device);
 	uverbs_dev->num_comp_vectors = device->num_comp_vectors;
 
+#ifdef HAVE_IDA_ALLOC_MAX
 	devnum = ida_alloc_max(&uverbs_ida, IB_UVERBS_MAX_DEVICES - 1,
 			       GFP_KERNEL);
 	if (devnum < 0) {
+#else
+	devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
+	if (devnum >= IB_UVERBS_MAX_DEVICES) {
+#endif
 		ret = -ENOMEM;
 		goto err;
 	}
 	uverbs_dev->devnum = devnum;
+#ifndef HAVE_IDA_ALLOC_MAX
+	set_bit(devnum, dev_map);
+#endif
 	if (devnum >= IB_UVERBS_NUM_FIXED_MINOR)
 		base = dynamic_uverbs_dev + devnum - IB_UVERBS_NUM_FIXED_MINOR;
 	else
@@ -1174,7 +1218,11 @@ static int ib_uverbs_add_one(struct ib_d
 	return 0;
 
 err_uapi:
+#ifndef HAVE_IDA_ALLOC_MAX
+	clear_bit(devnum, dev_map);
+#else
 	ida_free(&uverbs_ida, devnum);
+#endif
 err:
 	if (refcount_dec_and_test(&uverbs_dev->refcount))
 		ib_uverbs_comp_dev(uverbs_dev);
@@ -1207,7 +1255,6 @@ static void ib_uverbs_free_hw_resources(
 
 		uverbs_destroy_ufile_hw(file, RDMA_REMOVE_DRIVER_REMOVE);
 		kref_put(&file->ref, ib_uverbs_release_file);
-
 		mutex_lock(&uverbs_dev->lists_mutex);
 	}
 	mutex_unlock(&uverbs_dev->lists_mutex);
@@ -1221,7 +1268,11 @@ static void ib_uverbs_remove_one(struct
 	int wait_clients = 1;
 
 	cdev_device_del(&uverbs_dev->cdev, &uverbs_dev->dev);
+#ifndef HAVE_IDA_ALLOC_MAX
+	clear_bit(uverbs_dev->devnum, dev_map);
+#else
 	ida_free(&uverbs_ida, uverbs_dev->devnum);
+#endif
 
 	if (device->ops.disassociate_ucontext) {
 		/* We disassociate HW resources and immediately return.
@@ -1310,7 +1361,11 @@ static void __exit ib_uverbs_cleanup(voi
 				 IB_UVERBS_NUM_FIXED_MINOR);
 	unregister_chrdev_region(dynamic_uverbs_dev,
 				 IB_UVERBS_NUM_DYNAMIC_MINOR);
+#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
+#ifdef HAVE_MMU_NOTIFIER_OPS_HAS_FREE_NOTIFIER
 	mmu_notifier_synchronize();
+#endif
+#endif
 }
 
 module_init(ib_uverbs_init);
