backports: simplify and fix thermal backport with multiple NICs

This is equivalent to two commits added to iwlwifi-backports, but in a
way that applies to the released Cores:

commit ee1678a4610c ("backports: simplify and fix thermal backport with multiple NICs")
commit 80a9e6d43f2a ("backports: fix thermal compilation with kernel < 3.19")

It fixes the thermal backports when we have more than one NIC using
the thermal framework.

type=maintenance

Change-Id: I698e725d18c9f8e69cbe4bb0e12c26ef89a9c3c6
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Reviewed-on: https://git-amr-3.devtools.intel.com/gerrit/43771
Tested-by: ec ger unix iil jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM>
x-iwlwifi-stack-dev: 32a3f36080e5f3b5ec34e2be904e78fe4c069a3f
diff --git a/backport-include/linux/thermal.h b/backport-include/linux/thermal.h
index 8bf59e5..2bf0b56 100644
--- a/backport-include/linux/thermal.h
+++ b/backport-include/linux/thermal.h
@@ -8,71 +8,13 @@
 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) */
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0))
-/* Declare the < 4.3.0 struct so we can use it when calling the outer
- * kernel.
- */
-#ifndef CONFIG_BTNS_PMIC
-struct old_thermal_zone_device_ops {
-	int (*bind) (struct thermal_zone_device *,
-		     struct thermal_cooling_device *);
-	int (*unbind) (struct thermal_zone_device *,
-		       struct thermal_cooling_device *);
-	int (*get_temp) (struct thermal_zone_device *, unsigned long *);
-	int (*get_mode) (struct thermal_zone_device *,
-			 enum thermal_device_mode *);
-	int (*set_mode) (struct thermal_zone_device *,
-		enum thermal_device_mode);
-	int (*get_trip_type) (struct thermal_zone_device *, int,
-		enum thermal_trip_type *);
-	int (*get_trip_temp) (struct thermal_zone_device *, int,
-			      unsigned long *);
-	int (*set_trip_temp) (struct thermal_zone_device *, int,
-			      unsigned long);
-	int (*get_trip_hyst) (struct thermal_zone_device *, int,
-			      unsigned long *);
-	int (*set_trip_hyst) (struct thermal_zone_device *, int,
-			      unsigned long);
-	int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
-	int (*set_emul_temp) (struct thermal_zone_device *, unsigned long);
-	int (*get_trend) (struct thermal_zone_device *, int,
-			  enum thermal_trend *);
-	int (*notify) (struct thermal_zone_device *, int,
-		       enum thermal_trip_type);
-};
-#else /* !CONFIG_BTNS_PMIC */
-struct old_thermal_zone_device_ops {
-	int (*bind) (struct thermal_zone_device *,
-		     struct thermal_cooling_device *);
-	int (*unbind) (struct thermal_zone_device *,
-		       struct thermal_cooling_device *);
-	int (*get_temp) (struct thermal_zone_device *, long *);
-	int (*get_mode) (struct thermal_zone_device *,
-			 enum thermal_device_mode *);
-	int (*set_mode) (struct thermal_zone_device *,
-		enum thermal_device_mode);
-	int (*get_trip_type) (struct thermal_zone_device *, int,
-		enum thermal_trip_type *);
-	int (*get_trip_temp) (struct thermal_zone_device *, int, long *);
-	int (*set_trip_temp) (struct thermal_zone_device *, int, long);
-	int (*get_trip_hyst) (struct thermal_zone_device *, int, long *);
-	int (*set_trip_hyst) (struct thermal_zone_device *, int, long);
-	int (*get_slope) (struct thermal_zone_device *, long *);
-	int (*set_slope) (struct thermal_zone_device *, long);
-	int (*get_intercept) (struct thermal_zone_device *, long *);
-	int (*set_intercept) (struct thermal_zone_device *, long);
-	int (*get_crit_temp) (struct thermal_zone_device *, long *);
-	int (*set_emul_temp) (struct thermal_zone_device *, unsigned long);
-	int (*get_trend) (struct thermal_zone_device *, int,
-			  enum thermal_trend *);
-	int (*notify) (struct thermal_zone_device *, int,
-		       enum thermal_trip_type);
-};
-#endif /* !CONFIG_BTNS_PMIC */
+
+typedef struct thermal_zone_device_ops old_thermal_zone_device_ops_t;
 
 /* also add a way to call the old register and unregister functions */
 static inline struct thermal_zone_device *old_thermal_zone_device_register(
 	const char *type, int trips, int mask, void *devdata,
-	struct old_thermal_zone_device_ops *_ops,
+	old_thermal_zone_device_ops_t *_ops,
 	const struct thermal_zone_params *_tzp,
 	int passive_delay, int polling_delay)
 {
@@ -94,7 +36,6 @@
 	thermal_zone_device_unregister(dev);
 }
 
-#undef thermal_zone_device_ops
 #ifndef CONFIG_BTNS_PMIC
 struct backport_thermal_zone_device_ops {
 	int (*bind) (struct thermal_zone_device *,
@@ -118,19 +59,6 @@
 			  enum thermal_trend *);
 	int (*notify) (struct thermal_zone_device *, int,
 		       enum thermal_trip_type);
-
-	/* These ops hold the original callbacks set by the
-	 * registrant, because we'll add our hooks to the ones called
-	 * by the framework.  Luckily someone made this ops struct
-	 * non-const so we can mangle them.
-	 */
-	int (*_get_temp) (struct thermal_zone_device *, int *);
-	int (*_get_trip_temp) (struct thermal_zone_device *, int, int *);
-	int (*_set_trip_temp) (struct thermal_zone_device *, int, int);
-	int (*_get_trip_hyst) (struct thermal_zone_device *, int, int *);
-	int (*_set_trip_hyst) (struct thermal_zone_device *, int, int);
-	int (*_get_crit_temp) (struct thermal_zone_device *, int *);
-	int (*_set_emul_temp) (struct thermal_zone_device *, int);
 };
 #else /* CONFIG_BTNS_PMIC */
 struct backport_thermal_zone_device_ops {
@@ -159,19 +87,6 @@
 			  enum thermal_trend *);
 	int (*notify) (struct thermal_zone_device *, int,
 		       enum thermal_trip_type);
-
-	/* These ops hold the original callbacks set by the
-	 * registrant, because we'll add our hooks to the ones called
-	 * by the framework.  Luckily someone made this ops struct
-	 * non-const so we can mangle them.
-	 */
-	int (*_get_temp) (struct thermal_zone_device *, int *);
-	int (*_get_trip_temp) (struct thermal_zone_device *, int, int *);
-	int (*_set_trip_temp) (struct thermal_zone_device *, int, int);
-	int (*_get_trip_hyst) (struct thermal_zone_device *, int, int *);
-	int (*_set_trip_hyst) (struct thermal_zone_device *, int, int);
-	int (*_get_crit_temp) (struct thermal_zone_device *, int *);
-	int (*_set_emul_temp) (struct thermal_zone_device *, int);
 };
 #endif /* CONFIG_BTNS_PMIC */
 #define thermal_zone_device_ops LINUX_BACKPORT(thermal_zone_device_ops)
diff --git a/compat/backport-4.3.c b/compat/backport-4.3.c
index 75a916e..036e03c 100644
--- a/compat/backport-4.3.c
+++ b/compat/backport-4.3.c
@@ -9,20 +9,27 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/version.h>
 #include <linux/seq_file.h>
 #include <linux/export.h>
 #include <linux/printk.h>
 #include <linux/thermal.h>
+#include <linux/slab.h>
+
+struct backport_thermal_ops_wrapper {
+	old_thermal_zone_device_ops_t ops;
+	struct thermal_zone_device_ops *driver_ops;
+};
 
 #ifndef CONFIG_BTNS_PMIC
 static int backport_thermal_get_temp(struct thermal_zone_device *dev,
 				     unsigned long *temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 	int _temp, ret;
 
-	ret = ops->_get_temp(dev, &_temp);
+	ret = wrapper->driver_ops->get_temp(dev, &_temp);
 	if (!ret)
 		*temp = (unsigned long)_temp;
 
@@ -32,11 +39,11 @@
 static int backport_thermal_get_trip_temp(struct thermal_zone_device *dev,
 					  int i, unsigned long *temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 	int _temp, ret;
 
-	ret = ops->_get_trip_temp(dev, i,  &_temp);
+	ret = wrapper->driver_ops->get_trip_temp(dev, i,  &_temp);
 	if (!ret)
 		*temp = (unsigned long)_temp;
 
@@ -46,20 +53,20 @@
 static int backport_thermal_set_trip_temp(struct thermal_zone_device *dev,
 					  int i, unsigned long temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 
-	return ops->_set_trip_temp(dev, i, (int)temp);
+	return wrapper->driver_ops->set_trip_temp(dev, i, (int)temp);
 }
 
 static int backport_thermal_get_trip_hyst(struct thermal_zone_device *dev,
 					  int i, unsigned long *temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 	int _temp, ret;
 
-	ret = ops->_get_trip_hyst(dev, i, &_temp);
+	ret = wrapper->driver_ops->get_trip_hyst(dev, i, &_temp);
 	if (!ret)
 		*temp = (unsigned long)_temp;
 
@@ -69,43 +76,45 @@
 static int backport_thermal_set_trip_hyst(struct thermal_zone_device *dev,
 					  int i, unsigned long temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 
-	return ops->_set_trip_hyst(dev, i, (int)temp);
+	return wrapper->driver_ops->set_trip_hyst(dev, i, (int)temp);
 }
 
 static int backport_thermal_get_crit_temp(struct thermal_zone_device *dev,
 					  unsigned long *temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 	int _temp, ret;
 
-	ret = ops->_get_crit_temp(dev, &_temp);
+	ret = wrapper->driver_ops->get_crit_temp(dev, &_temp);
 	if (!ret)
 		*temp = (unsigned long)_temp;
 
 	return ret;
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
 static int backport_thermal_set_emul_temp(struct thermal_zone_device *dev,
 					  unsigned long temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 
-	return ops->_set_emul_temp(dev, (int)temp);
+	return wrapper->driver_ops->set_emul_temp(dev, (int)temp);
 }
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) */
 #else /* !CONFIG_BTNS_PMIC */
 static int backport_thermal_get_temp(struct thermal_zone_device *dev,
 				     long *temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 	int _temp, ret;
 
-	ret = ops->_get_temp(dev, &_temp);
+	ret = wrapper->driver_ops->get_temp(dev, &_temp);
 	if (!ret)
 		*temp = (long)_temp;
 
@@ -115,11 +124,11 @@
 static int backport_thermal_get_trip_temp(struct thermal_zone_device *dev,
 					  int i, long *temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 	int _temp, ret;
 
-	ret = ops->_get_trip_temp(dev, i,  &_temp);
+	ret = wrapper->driver_ops->get_trip_temp(dev, i,  &_temp);
 	if (!ret)
 		*temp = (long)_temp;
 
@@ -129,20 +138,20 @@
 static int backport_thermal_set_trip_temp(struct thermal_zone_device *dev,
 					  int i, long temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 
-	return ops->_set_trip_temp(dev, i, (int)temp);
+	return wrapper->driver_ops->set_trip_temp(dev, i, (int)temp);
 }
 
 static int backport_thermal_get_trip_hyst(struct thermal_zone_device *dev,
 					  int i, long *temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 	int _temp, ret;
 
-	ret = ops->_get_trip_hyst(dev, i, &_temp);
+	ret = wrapper->driver_ops->get_trip_hyst(dev, i, &_temp);
 	if (!ret)
 		*temp = (long)_temp;
 
@@ -152,20 +161,20 @@
 static int backport_thermal_set_trip_hyst(struct thermal_zone_device *dev,
 					  int i, long temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 
-	return ops->_set_trip_hyst(dev, i, (int)temp);
+	return wrapper->driver_ops->set_trip_hyst(dev, i, (int)temp);
 }
 
 static int backport_thermal_get_crit_temp(struct thermal_zone_device *dev,
 					  long *temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 	int _temp, ret;
 
-	ret = ops->_get_crit_temp(dev, &_temp);
+	ret = wrapper->driver_ops->get_crit_temp(dev, &_temp);
 	if (!ret)
 		*temp = (long)_temp;
 
@@ -175,35 +184,43 @@
 static int backport_thermal_set_emul_temp(struct thermal_zone_device *dev,
 					  unsigned long temp)
 {
-	struct backport_thermal_zone_device_ops *ops =
-		(struct backport_thermal_zone_device_ops *)dev->ops;
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 
-	return ops->_set_emul_temp(dev, (int)temp);
+	return wrapper->driver_ops->set_emul_temp(dev, (int)temp);
 }
 #endif /* !CONFIG_BTNS_PMIC */
 
 struct thermal_zone_device *backport_thermal_zone_device_register(
 	const char *type, int trips, int mask, void *devdata,
-	struct backport_thermal_zone_device_ops *ops,
+	struct thermal_zone_device_ops *ops,
 	const struct thermal_zone_params *tzp,
 	int passive_delay, int polling_delay)
 {
-	/* It's okay to cast here, because the backport is a superset
-	 * of the old struct.
-	 */
-	struct old_thermal_zone_device_ops *_ops =
-		(struct old_thermal_zone_device_ops *)ops;
+	struct backport_thermal_ops_wrapper *wrapper = kzalloc(sizeof(*wrapper), GFP_KERNEL);
+	struct thermal_zone_device *ret;
 
-	/* store the registrant's ops for the backport ops to use */
-#define copy_ops(_op) ops->_##_op = ops->_op
-	copy_ops(get_temp);
-	copy_ops(get_trip_temp);
-	copy_ops(set_trip_temp);
-	copy_ops(get_trip_hyst);
-	copy_ops(set_trip_hyst);
-	copy_ops(get_crit_temp);
-	copy_ops(set_emul_temp);
-#undef copy_ops
+	if (!wrapper)
+		return NULL;
+
+	wrapper->driver_ops = ops;
+
+#define copy(_op)		\
+	wrapper->ops._op = ops->_op
+
+	copy(bind);
+	copy(unbind);
+	copy(get_mode);
+	copy(set_mode);
+	copy(get_trip_type);
+	copy(get_trend);
+	copy(notify);
+#ifdef CONFIG_BTNS_PMIC
+	copy(get_slope);
+	copy(set_slope);
+	copy(get_intercept);
+	copy(set_intercept);
+#endif
 
 	/* Assign the backport ops to the old struct to get the
 	 * correct types.  But only assign if the registrant defined
@@ -211,7 +228,7 @@
 	 */
 #define assign_ops(_op)		\
 	if (ops->_op)		\
-		_ops->_op = backport_thermal_##_op
+		wrapper->ops._op = backport_thermal_##_op
 
 	assign_ops(get_temp);
 	assign_ops(get_trip_temp);
@@ -219,35 +236,27 @@
 	assign_ops(get_trip_hyst);
 	assign_ops(set_trip_hyst);
 	assign_ops(get_crit_temp);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
 	assign_ops(set_emul_temp);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) */
 #undef assign_ops
 
-	return old_thermal_zone_device_register(type, trips, mask, devdata,
-						_ops, tzp, passive_delay,
-						polling_delay);
+	ret = old_thermal_zone_device_register(type, trips, mask, devdata,
+					       &wrapper->ops, tzp, passive_delay,
+					       polling_delay);
+	if (!ret)
+		kfree(wrapper);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(backport_thermal_zone_device_register);
 
 void backport_thermal_zone_device_unregister(struct thermal_zone_device *dev)
 {
-	/* It's okay to cast here, because the backport is a superset
-	 * of the old struct.
-	 */
-	struct thermal_zone_device_ops *ops =
-		(struct thermal_zone_device_ops *)dev->ops;
-
-	/* restore the registrant's original ops to the right place */
-#define restore_ops(_op) ops->_op = ops->_##_op
-	restore_ops(get_temp);
-	restore_ops(get_trip_temp);
-	restore_ops(set_trip_temp);
-	restore_ops(get_trip_hyst);
-	restore_ops(set_trip_hyst);
-	restore_ops(get_crit_temp);
-	restore_ops(set_emul_temp);
-#undef restore_ops
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
 
 	old_thermal_zone_device_unregister(dev);
+	kfree(wrapper);
 }
 EXPORT_SYMBOL_GPL(backport_thermal_zone_device_unregister);
 
diff --git a/versions b/versions
index a92422a..3963298 100644
--- a/versions
+++ b/versions
@@ -2,5 +2,5 @@
 BACKPORTED_KERNEL_VERSION="(see git)"
 BACKPORTED_KERNEL_NAME="iwlwifi"
 BACKPORTS_BUILD_TSTAMP=__DATE__ \" \" __TIME__
-BACKPORTS_GIT_TRACKED="iwlwifi-stack-public:release/LinuxCore18:5209:67426b9e"
+BACKPORTS_GIT_TRACKED="iwlwifi-stack-public:release/LinuxCore18:5210:32a3f360"
 BACKPORTS_BRANCH_TSTAMP="Feb 08 2016 08:09:37"