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

Change-Id: I16786695be3b70fde20de9b26b9eac06de91273c
---
 drivers/infiniband/core/device.c | 122 +++++++++++++++++++++++++++----
 1 file changed, 107 insertions(+), 15 deletions(-)

--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -46,6 +46,9 @@
 #include <rdma/ib_addr.h>
 #include <rdma/ib_cache.h>
 #include <rdma/rdma_counter.h>
+#ifdef HAVE_BASECODE_EXTRAS
+#include <linux/sizes.h>
+#endif
 
 #include "core_priv.h"
 #include "restrack.h"
@@ -53,6 +56,9 @@
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("core kernel InfiniBand API");
 MODULE_LICENSE("Dual BSD/GPL");
+#ifdef RETPOLINE_MLNX
+MODULE_INFO(retpoline, "Y");
+#endif
 
 struct workqueue_struct *ib_comp_wq;
 struct workqueue_struct *ib_comp_unbound_wq;
@@ -186,11 +192,17 @@ static DECLARE_HASHTABLE(ndev_hash, 5);
 static void free_netdevs(struct ib_device *ib_dev);
 static void ib_unregister_work(struct work_struct *work);
 static void __ib_unregister_device(struct ib_device *device);
+#if defined(HAVE_REGISTER_BLOCKING_LSM_NOTIFIER) || defined (HAVE_REGISTER_LSM_NOTIFIER)
 static int ib_security_change(struct notifier_block *nb, unsigned long event,
 			      void *lsm_data);
 static void ib_policy_change_task(struct work_struct *work);
 static DECLARE_WORK(ib_policy_change_work, ib_policy_change_task);
 
+static struct notifier_block ibdev_lsm_nb = {
+	.notifier_call = ib_security_change,
+};
+#endif
+
 static void __ibdev_printk(const char *level, const struct ib_device *ibdev,
 			   struct va_format *vaf)
 {
@@ -251,10 +263,6 @@ define_ibdev_printk_level(ibdev_warn, KE
 define_ibdev_printk_level(ibdev_notice, KERN_NOTICE);
 define_ibdev_printk_level(ibdev_info, KERN_INFO);
 
-static struct notifier_block ibdev_lsm_nb = {
-	.notifier_call = ib_security_change,
-};
-
 static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
 				 struct net *net);
 
@@ -423,6 +431,7 @@ int ib_device_rename(struct ib_device *i
 	}
 
 	strscpy(ibdev->name, name, IB_DEVICE_NAME_MAX);
+
 	ret = rename_compat_devs(ibdev);
 
 	downgrade_write(&devices_rwsem);
@@ -454,17 +463,32 @@ static int alloc_name(struct ib_device *
 {
 	struct ib_device *device;
 	unsigned long index;
-	struct ida inuse;
-	int rc;
 	int i;
+#ifdef HAVE_IDA_ALLOC
+       struct ida inuse;
+       int rc;
+#else
+	unsigned long *inuse;
 
+	inuse = (unsigned long *) get_zeroed_page(GFP_KERNEL);
+	if (!inuse)
+		return -ENOMEM;
+#endif
+#ifdef HAVE_LOCKUP_ASSERT_HELD_EXCLUSIVE
+      lockdep_assert_held_exclusive(&devices_rwsem);
+#elif defined(HAVE_LOCKUP_ASSERT_HELD_WRITE)
 	lockdep_assert_held_write(&devices_rwsem);
-	ida_init(&inuse);
+#endif
+
+#ifdef HAVE_IDA_ALLOC
+       ida_init(&inuse);
+#endif
 	xa_for_each (&devices, index, device) {
 		char buf[IB_DEVICE_NAME_MAX];
 
 		if (sscanf(dev_name(&device->dev), name, &i) != 1)
 			continue;
+#ifdef HAVE_IDA_ALLOC
 		if (i < 0 || i >= INT_MAX)
 			continue;
 		snprintf(buf, sizeof buf, name, i);
@@ -484,6 +508,17 @@ static int alloc_name(struct ib_device *
 out:
 	ida_destroy(&inuse);
 	return rc;
+#else
+	if (i < 0 || i >= PAGE_SIZE * 8)
+		continue;
+	snprintf(buf, sizeof buf, name, i);
+	if (!strcmp(buf, dev_name(&device->dev)))
+		set_bit(i, inuse);
+	}
+	i = find_first_zero_bit(inuse, PAGE_SIZE * 8);
+	free_page((unsigned long) inuse);
+	return dev_set_name(&ibdev->dev, name, i);
+#endif
 }
 
 static void ib_device_release(struct device *device)
@@ -511,7 +546,11 @@ static void ib_device_release(struct dev
 	kfree_rcu(dev, rcu_head);
 }
 
+#ifdef HAVE_NET_NAMESPACE_GET_CONST_DEVICE
 static int ib_device_uevent(const struct device *device,
+#else
+static int ib_device_uevent(struct device *device,
+#endif
 			    struct kobj_uevent_env *env)
 {
 	if (add_uevent_var(env, "NAME=%s", dev_name(device)))
@@ -524,7 +563,11 @@ static int ib_device_uevent(const struct
 	return 0;
 }
 
+#ifdef HAVE_NET_NAMESPACE_GET_CONST_DEVICE
 static const void *net_namespace(const struct device *d)
+#else
+static const void *net_namespace(struct device *d)
+#endif
 {
 	const struct ib_core_device *coredev =
 			container_of(d, struct ib_core_device, dev);
@@ -879,6 +922,7 @@ void ib_get_device_fw_str(struct ib_devi
 }
 EXPORT_SYMBOL(ib_get_device_fw_str);
 
+#if defined(HAVE_REGISTER_BLOCKING_LSM_NOTIFIER) || defined (HAVE_REGISTER_LSM_NOTIFIER)
 static void ib_policy_change_task(struct work_struct *work)
 {
 	struct ib_device *dev;
@@ -908,6 +952,7 @@ static int ib_security_change(struct not
 
 	return NOTIFY_OK;
 }
+#endif /* HAVE_REGISTER_BLOCKING_LSM_NOTIFIER */
 
 static void compatdev_release(struct device *dev)
 {
@@ -1379,7 +1424,6 @@ int ib_register_device(struct ib_device
 	 */
 	WARN_ON(dma_device && !dma_device->dma_parms);
 	device->dma_device = dma_device;
-
 	ret = setup_device(device);
 	if (ret)
 		return ret;
@@ -1396,9 +1440,7 @@ int ib_register_device(struct ib_device
 	ret = ib_setup_device_attrs(device);
 	if (ret)
 		goto cache_cleanup;
-
 	ib_device_register_rdmacg(device);
-
 	rdma_counter_init(device);
 
 	/*
@@ -1610,6 +1652,7 @@ static void ib_unregister_work(struct wo
  * Drivers using this API must use ib_unregister_driver before module unload
  * to ensure that all scheduled unregistrations have completed.
  */
+#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
 void ib_unregister_device_queued(struct ib_device *ib_dev)
 {
 	WARN_ON(!refcount_read(&ib_dev->refcount));
@@ -1619,6 +1662,7 @@ void ib_unregister_device_queued(struct
 		put_device(&ib_dev->dev);
 }
 EXPORT_SYMBOL(ib_unregister_device_queued);
+#endif
 
 /*
  * The caller must pass in a device that has the kref held and the refcount
@@ -2178,16 +2222,26 @@ int ib_device_set_netdev(struct ib_devic
 		return 0;
 	}
 
+#ifdef HAVE_NETDEV_HOLD
 	if (old_ndev)
 		netdev_tracker_free(ndev, &pdata->netdev_tracker);
+#endif
 	if (ndev)
+#ifdef HAVE_NETDEV_HOLD
 		netdev_hold(ndev, &pdata->netdev_tracker, GFP_ATOMIC);
+#else
+		dev_hold(ndev);
+#endif
 	rcu_assign_pointer(pdata->netdev, ndev);
 	spin_unlock_irqrestore(&pdata->netdev_lock, flags);
 
 	add_ndev_hash(pdata);
 	if (old_ndev)
+#ifdef HAVE_NETDEV_HOLD
 		__dev_put(old_ndev);
+#else
+		dev_put(old_ndev);
+#endif
 
 	return 0;
 }
@@ -2220,7 +2274,11 @@ static void free_netdevs(struct ib_devic
 			 * comparisons after the put
 			 */
 			rcu_assign_pointer(pdata->netdev, NULL);
+#ifdef HAVE_NETDEV_HOLD
 			netdev_put(ndev, &pdata->netdev_tracker);
+#else
+			dev_put(ndev);
+#endif
 		}
 		spin_unlock_irqrestore(&pdata->netdev_lock, flags);
 	}
@@ -2278,9 +2336,10 @@ struct ib_device *ib_device_get_by_netde
 {
 	struct ib_device *res = NULL;
 	struct ib_port_data *cur;
+        COMPAT_HL_NODE;
 
 	rcu_read_lock();
-	hash_for_each_possible_rcu (ndev_hash, cur, ndev_hash_link,
+	compat_hash_for_each_possible_rcu (ndev_hash, cur, ndev_hash_link,
 				    (uintptr_t)ndev) {
 		if (rcu_access_pointer(cur->netdev) == ndev &&
 		    (driver_id == RDMA_DRIVER_UNKNOWN ||
@@ -2695,6 +2754,9 @@ void ib_set_device_ops(struct ib_device
 	SET_DEVICE_OP(dev_ops, get_vf_config);
 	SET_DEVICE_OP(dev_ops, get_vf_guid);
 	SET_DEVICE_OP(dev_ops, get_vf_stats);
+#ifndef HAVE_MMU_INTERVAL_NOTIFIER
+	SET_DEVICE_OP(dev_ops, invalidate_range);
+#endif
 	SET_DEVICE_OP(dev_ops, iw_accept);
 	SET_DEVICE_OP(dev_ops, iw_add_ref);
 	SET_DEVICE_OP(dev_ops, iw_connect);
@@ -2804,14 +2866,26 @@ static int __init ib_core_init(void)
 		goto err;
 
 	ib_comp_wq = alloc_workqueue("ib-comp-wq",
-			WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_SYSFS, 0);
+#ifdef HAVE_BASECODE_EXTRAS
+			0 |
+#endif
+			WQ_HIGHPRI
+			| WQ_MEM_RECLAIM
+			| WQ_SYSFS
+			, 0);
 	if (!ib_comp_wq)
 		goto err_unbound;
 
 	ib_comp_unbound_wq =
 		alloc_workqueue("ib-comp-unb-wq",
-				WQ_UNBOUND | WQ_HIGHPRI | WQ_MEM_RECLAIM |
-				WQ_SYSFS, WQ_UNBOUND_MAX_ACTIVE);
+#ifdef HAVE_BASECODE_EXTRAS
+			0 |
+#endif
+			WQ_UNBOUND
+			| WQ_HIGHPRI
+			| WQ_MEM_RECLAIM
+			| WQ_SYSFS
+			, WQ_UNBOUND_MAX_ACTIVE);
 	if (!ib_comp_unbound_wq)
 		goto err_comp;
 
@@ -2841,11 +2915,17 @@ static int __init ib_core_init(void)
 		goto err_mad;
 	}
 
+#if defined(HAVE_REGISTER_BLOCKING_LSM_NOTIFIER) || defined(HAVE_REGISTER_LSM_NOTIFIER)
+#ifdef HAVE_REGISTER_BLOCKING_LSM_NOTIFIER
 	ret = register_blocking_lsm_notifier(&ibdev_lsm_nb);
+#elif defined(HAVE_REGISTER_LSM_NOTIFIER)
+       ret = register_lsm_notifier(&ibdev_lsm_nb);
+#endif /* HAVE_REGISTER_BLOCKING_LSM_NOTIFIER */
 	if (ret) {
 		pr_warn("Couldn't register LSM notifier. ret %d\n", ret);
 		goto err_sa;
 	}
+#endif
 
 	ret = register_pernet_device(&rdma_dev_net_ops);
 	if (ret) {
@@ -2868,9 +2948,15 @@ err_parent:
 	nldev_exit();
 	unregister_pernet_device(&rdma_dev_net_ops);
 err_compat:
+#if defined(HAVE_REGISTER_BLOCKING_LSM_NOTIFIER) || defined(HAVE_REGISTER_LSM_NOTIFIER)
+#ifdef HAVE_REGISTER_BLOCKING_LSM_NOTIFIER
 	unregister_blocking_lsm_notifier(&ibdev_lsm_nb);
+#elif defined(HAVE_REGISTER_LSM_NOTIFIER)
+	unregister_lsm_notifier(&ibdev_lsm_nb);
+#endif /* HAVE_REGISTER_BLOCKING_LSM_NOTIFIER */
 err_sa:
 	ib_sa_cleanup();
+#endif
 err_mad:
 	ib_mad_cleanup();
 err_addr:
@@ -2894,7 +2980,11 @@ static void __exit ib_core_cleanup(void)
 	rdma_nl_unregister(RDMA_NL_LS);
 	nldev_exit();
 	unregister_pernet_device(&rdma_dev_net_ops);
+#ifdef HAVE_REGISTER_BLOCKING_LSM_NOTIFIER
 	unregister_blocking_lsm_notifier(&ibdev_lsm_nb);
+#elif defined(HAVE_REGISTER_LSM_NOTIFIER)
+	unregister_lsm_notifier(&ibdev_lsm_nb);
+#endif
 	ib_sa_cleanup();
 	ib_mad_cleanup();
 	addr_cleanup();
@@ -2904,7 +2994,9 @@ static void __exit ib_core_cleanup(void)
 	destroy_workqueue(ib_comp_wq);
 	/* Make sure that any pending umem accounting work is done. */
 	destroy_workqueue(ib_wq);
+#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
 	destroy_workqueue(ib_unreg_wq);
+#endif
 	WARN_ON(!xa_empty(&clients));
 	WARN_ON(!xa_empty(&devices));
 }
