All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] backports: add some scatterlist backports for <3.9 and <3.11
@ 2016-07-15 19:01 Johannes Berg
  2016-07-15 19:01 ` [PATCH 2/2] backport: add proper thermal backport Johannes Berg
  0 siblings, 1 reply; 2+ messages in thread
From: Johannes Berg @ 2016-07-15 19:01 UTC (permalink / raw)
  To: backports; +Cc: luca, Luca Coelho

From: Luca Coelho <luciano.coelho@intel.com>

There were some changes and additions in kernel 3.9 and again in 3.11.
Add the needed backports accordingly.

Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 backport/backport-include/linux/scatterlist.h |  92 ++++++++++++++
 backport/compat/Makefile                      |   1 +
 backport/compat/backport-3.11.c               | 124 +++++++++++++++++++
 backport/compat/compat-3.9.c                  | 166 ++++++++++++++++++++++++++
 4 files changed, 383 insertions(+)
 create mode 100644 backport/backport-include/linux/scatterlist.h
 create mode 100644 backport/compat/backport-3.11.c

diff --git a/backport/backport-include/linux/scatterlist.h b/backport/backport-include/linux/scatterlist.h
new file mode 100644
index 000000000000..47335588ad85
--- /dev/null
+++ b/backport/backport-include/linux/scatterlist.h
@@ -0,0 +1,92 @@
+#ifndef __BACKPORT_SCATTERLIST_H
+#define __BACKPORT_SCATTERLIST_H
+#include_next <linux/scatterlist.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
+
+/*
+ * sg page iterator
+ *
+ * Iterates over sg entries page-by-page.  On each successful iteration,
+ * @piter->page points to the current page, @piter->sg to the sg holding this
+ * page and @piter->sg_pgoffset to the page's page offset within the sg. The
+ * iteration will stop either when a maximum number of sg entries was reached
+ * or a terminating sg (sg_last(sg) == true) was reached.
+ */
+struct sg_page_iter {
+	struct page             *page;          /* current page */
+	struct scatterlist      *sg;            /* sg holding the page */
+	unsigned int            sg_pgoffset;    /* page offset within the sg */
+
+	/* these are internal states, keep away */
+	unsigned int            __nents;        /* remaining sg entries */
+	int                     __pg_advance;   /* nr pages to advance at the
+						 * next step */
+};
+
+struct backport_sg_mapping_iter {
+	/* the following three fields can be accessed directly */
+	struct page		*page;		/* currently mapped page */
+	void			*addr;		/* pointer to the mapped area */
+	size_t			length;		/* length of the mapped area */
+	size_t			consumed;	/* number of consumed bytes */
+	struct sg_page_iter	piter;		/* page iterator */
+
+	/* these are internal states, keep away */
+	unsigned int		__offset;	/* offset within page */
+	unsigned int		__remaining;	/* remaining bytes on page */
+	unsigned int		__flags;
+};
+#define sg_mapping_iter LINUX_BACKPORT(sg_mapping_iter)
+
+/**
+ * sg_page_iter_page - get the current page held by the page iterator
+ * @piter:	page iterator holding the page
+ */
+static inline struct page *sg_page_iter_page(struct sg_page_iter *piter)
+{
+	return nth_page(sg_page(piter->sg), piter->sg_pgoffset);
+}
+
+bool __sg_page_iter_next(struct sg_page_iter *piter);
+void __sg_page_iter_start(struct sg_page_iter *piter,
+			  struct scatterlist *sglist, unsigned int nents,
+			  unsigned long pgoffset);
+
+void backport_sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
+		    unsigned int nents, unsigned int flags);
+bool backport_sg_miter_next(struct sg_mapping_iter *miter);
+void backport_sg_miter_stop(struct sg_mapping_iter *miter);
+#define sg_miter_start LINUX_BACKPORT(sg_miter_start)
+#define sg_miter_next LINUX_BACKPORT(sg_miter_next)
+#define sg_miter_stop LINUX_BACKPORT(sg_miter_stop)
+
+/**
+ * for_each_sg_page - iterate over the pages of the given sg list
+ * @sglist:    sglist to iterate over
+ * @piter:     page iterator to hold current page, sg, sg_pgoffset
+ * @nents:     maximum number of sg entries to iterate over
+ * @pgoffset:  starting page offset
+ */
+#define for_each_sg_page(sglist, piter, nents, pgoffset)		\
+	for (__sg_page_iter_start((piter), (sglist), (nents), (pgoffset)); \
+	     __sg_page_iter_next(piter);)
+
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0) */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)
+size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, void *buf,
+		      size_t buflen, off_t skip, bool to_buffer);
+
+#define sg_pcopy_to_buffer LINUX_BACKPORT(sg_pcopy_to_buffer)
+
+static inline
+size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents,
+			  void *buf, size_t buflen, off_t skip)
+{
+	return sg_copy_buffer(sgl, nents, buf, buflen, skip, true);
+}
+
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) */
+
+#endif /* __BACKPORT_SCATTERLIST_H */
diff --git a/backport/compat/Makefile b/backport/compat/Makefile
index 6013083e22b1..8cf1a7b83c8f 100644
--- a/backport/compat/Makefile
+++ b/backport/compat/Makefile
@@ -18,6 +18,7 @@ compat-$(CPTCFG_KERNEL_3_7) += compat-3.7.o
 compat-$(CPTCFG_KERNEL_3_8) += compat-3.8.o
 compat-$(CPTCFG_KERNEL_3_9) += compat-3.9.o
 compat-$(CPTCFG_KERNEL_3_10) += backport-3.10.o
+compat-$(CPTCFG_KERNEL_3_11) += backport-3.11.o
 compat-$(CPTCFG_KERNEL_3_12) += backport-3.12.o
 compat-$(CPTCFG_KERNEL_3_13) += backport-3.13.o
 compat-$(CPTCFG_KERNEL_3_14) += backport-3.14.o
diff --git a/backport/compat/backport-3.11.c b/backport/compat/backport-3.11.c
new file mode 100644
index 000000000000..7f9ff3419344
--- /dev/null
+++ b/backport/compat/backport-3.11.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2016 Intel Deutschland GmbH
+ *
+ * Backport functionality introduced in Linux 3.11.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+
+static bool sg_miter_get_next_page(struct sg_mapping_iter *miter)
+{
+	if (!miter->__remaining) {
+		struct scatterlist *sg;
+		unsigned long pgoffset;
+
+		if (!__sg_page_iter_next(&miter->piter))
+			return false;
+
+		sg = miter->piter.sg;
+		pgoffset = miter->piter.sg_pgoffset;
+
+		miter->__offset = pgoffset ? 0 : sg->offset;
+		miter->__remaining = sg->offset + sg->length -
+				(pgoffset << PAGE_SHIFT) - miter->__offset;
+		miter->__remaining = min_t(unsigned long, miter->__remaining,
+					   PAGE_SIZE - miter->__offset);
+	}
+
+	return true;
+}
+
+/**
+ * sg_miter_skip - reposition mapping iterator
+ * @miter: sg mapping iter to be skipped
+ * @offset: number of bytes to plus the current location
+ *
+ * Description:
+ *   Sets the offset of @miter to its current location plus @offset bytes.
+ *   If mapping iterator @miter has been proceeded by sg_miter_next(), this
+ *   stops @miter.
+ *
+ * Context:
+ *   Don't care if @miter is stopped, or not proceeded yet.
+ *   Otherwise, preemption disabled if the SG_MITER_ATOMIC is set.
+ *
+ * Returns:
+ *   true if @miter contains the valid mapping.  false if end of sg
+ *   list is reached.
+ */
+static bool sg_miter_skip(struct sg_mapping_iter *miter, off_t offset)
+{
+	sg_miter_stop(miter);
+
+	while (offset) {
+		off_t consumed;
+
+		if (!sg_miter_get_next_page(miter))
+			return false;
+
+		consumed = min_t(off_t, offset, miter->__remaining);
+		miter->__offset += consumed;
+		miter->__remaining -= consumed;
+		offset -= consumed;
+	}
+
+	return true;
+}
+
+/**
+ * sg_copy_buffer - Copy data between a linear buffer and an SG list
+ * @sgl:		 The SG list
+ * @nents:		 Number of SG entries
+ * @buf:		 Where to copy from
+ * @buflen:		 The number of bytes to copy
+ * @skip:		 Number of bytes to skip before copying
+ * @to_buffer:		 transfer direction (true == from an sg list to a
+ *			 buffer, false == from a buffer to an sg list
+ *
+ * Returns the number of copied bytes.
+ *
+ **/
+size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, void *buf,
+		      size_t buflen, off_t skip, bool to_buffer)
+{
+	unsigned int offset = 0;
+	struct sg_mapping_iter miter;
+	unsigned long flags;
+	unsigned int sg_flags = SG_MITER_ATOMIC;
+
+	if (to_buffer)
+		sg_flags |= SG_MITER_FROM_SG;
+	else
+		sg_flags |= SG_MITER_TO_SG;
+
+	sg_miter_start(&miter, sgl, nents, sg_flags);
+
+	if (!sg_miter_skip(&miter, skip))
+		return false;
+
+	local_irq_save(flags);
+
+	while (sg_miter_next(&miter) && offset < buflen) {
+		unsigned int len;
+
+		len = min(miter.length, buflen - offset);
+
+		if (to_buffer)
+			memcpy(buf + offset, miter.addr, len);
+		else
+			memcpy(miter.addr, buf + offset, len);
+
+		offset += len;
+	}
+
+	sg_miter_stop(&miter);
+
+	local_irq_restore(flags);
+	return offset;
+}
+EXPORT_SYMBOL_GPL(sg_copy_buffer);
diff --git a/backport/compat/compat-3.9.c b/backport/compat/compat-3.9.c
index 5a4f52390cbe..93889b550327 100644
--- a/backport/compat/compat-3.9.c
+++ b/backport/compat/compat-3.9.c
@@ -15,6 +15,8 @@
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/etherdevice.h>
+#include <linux/scatterlist.h>
+#include <linux/highmem.h>
 #include <net/inet_frag.h>
 #include <net/sock.h>
 
@@ -70,3 +72,167 @@ void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
 		LIMIT_NETDEBUG(KERN_WARNING "%s%s", prefix, msg);
 }
 EXPORT_SYMBOL_GPL(inet_frag_maybe_warn_overflow);
+
+void __sg_page_iter_start(struct sg_page_iter *piter,
+			  struct scatterlist *sglist, unsigned int nents,
+			  unsigned long pgoffset)
+{
+	piter->__pg_advance = 0;
+	piter->__nents = nents;
+
+	piter->page = NULL;
+	piter->sg = sglist;
+	piter->sg_pgoffset = pgoffset;
+}
+EXPORT_SYMBOL_GPL(__sg_page_iter_start);
+
+static int sg_page_count(struct scatterlist *sg)
+{
+	return PAGE_ALIGN(sg->offset + sg->length) >> PAGE_SHIFT;
+}
+
+bool __sg_page_iter_next(struct sg_page_iter *piter)
+{
+	if (!piter->__nents || !piter->sg)
+		return false;
+
+	piter->sg_pgoffset += piter->__pg_advance;
+	piter->__pg_advance = 1;
+
+	while (piter->sg_pgoffset >= sg_page_count(piter->sg)) {
+		piter->sg_pgoffset -= sg_page_count(piter->sg);
+		piter->sg = sg_next(piter->sg);
+		if (!--piter->__nents || !piter->sg)
+			return false;
+	}
+	piter->page = nth_page(sg_page(piter->sg), piter->sg_pgoffset);
+
+	return true;
+}
+EXPORT_SYMBOL_GPL(__sg_page_iter_next);
+
+static bool sg_miter_get_next_page(struct sg_mapping_iter *miter)
+{
+	if (!miter->__remaining) {
+		struct scatterlist *sg;
+		unsigned long pgoffset;
+
+		if (!__sg_page_iter_next(&miter->piter))
+			return false;
+
+		sg = miter->piter.sg;
+		pgoffset = miter->piter.sg_pgoffset;
+
+		miter->__offset = pgoffset ? 0 : sg->offset;
+		miter->__remaining = sg->offset + sg->length -
+				(pgoffset << PAGE_SHIFT) - miter->__offset;
+		miter->__remaining = min_t(unsigned long, miter->__remaining,
+					   PAGE_SIZE - miter->__offset);
+	}
+
+	return true;
+}
+
+/**
+ * sg_miter_start - start mapping iteration over a sg list
+ * @miter: sg mapping iter to be started
+ * @sgl: sg list to iterate over
+ * @nents: number of sg entries
+ *
+ * Description:
+ *   Starts mapping iterator @miter.
+ *
+ * Context:
+ *   Don't care.
+ */
+void backport_sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
+		    unsigned int nents, unsigned int flags)
+{
+	memset(miter, 0, sizeof(struct sg_mapping_iter));
+
+	__sg_page_iter_start(&miter->piter, sgl, nents, 0);
+	WARN_ON(!(flags & (SG_MITER_TO_SG | SG_MITER_FROM_SG)));
+	miter->__flags = flags;
+}
+EXPORT_SYMBOL_GPL(backport_sg_miter_start);
+
+/**
+ * sg_miter_next - proceed mapping iterator to the next mapping
+ * @miter: sg mapping iter to proceed
+ *
+ * Description:
+ *   Proceeds @miter to the next mapping.  @miter should have been started
+ *   using sg_miter_start().  On successful return, @miter->page,
+ *   @miter->addr and @miter->length point to the current mapping.
+ *
+ * Context:
+ *   Preemption disabled if SG_MITER_ATOMIC.  Preemption must stay disabled
+ *   till @miter is stopped.  May sleep if !SG_MITER_ATOMIC.
+ *
+ * Returns:
+ *   true if @miter contains the next mapping.  false if end of sg
+ *   list is reached.
+ */
+bool backport_sg_miter_next(struct sg_mapping_iter *miter)
+{
+	sg_miter_stop(miter);
+
+	/*
+	 * Get to the next page if necessary.
+	 * __remaining, __offset is adjusted by sg_miter_stop
+	 */
+	if (!sg_miter_get_next_page(miter))
+		return false;
+
+	miter->page = sg_page_iter_page(&miter->piter);
+	miter->consumed = miter->length = miter->__remaining;
+
+	if (miter->__flags & SG_MITER_ATOMIC)
+		miter->addr = kmap_atomic(miter->page) + miter->__offset;
+	else
+		miter->addr = kmap(miter->page) + miter->__offset;
+
+	return true;
+}
+EXPORT_SYMBOL_GPL(backport_sg_miter_next);
+
+/**
+ * sg_miter_stop - stop mapping iteration
+ * @miter: sg mapping iter to be stopped
+ *
+ * Description:
+ *   Stops mapping iterator @miter.  @miter should have been started
+ *   using sg_miter_start().  A stopped iteration can be resumed by
+ *   calling sg_miter_next() on it.  This is useful when resources (kmap)
+ *   need to be released during iteration.
+ *
+ * Context:
+ *   Preemption disabled if the SG_MITER_ATOMIC is set.  Don't care
+ *   otherwise.
+ */
+void backport_sg_miter_stop(struct sg_mapping_iter *miter)
+{
+	WARN_ON(miter->consumed > miter->length);
+
+	/* drop resources from the last iteration */
+	if (miter->addr) {
+		miter->__offset += miter->consumed;
+		miter->__remaining -= miter->consumed;
+
+		if ((miter->__flags & SG_MITER_TO_SG) &&
+		    !PageSlab(miter->page))
+			flush_kernel_dcache_page(miter->page);
+
+		if (miter->__flags & SG_MITER_ATOMIC) {
+			WARN_ON_ONCE(preemptible());
+			kunmap_atomic(miter->addr);
+		} else
+			kunmap(miter->page);
+
+		miter->page = NULL;
+		miter->addr = NULL;
+		miter->length = 0;
+		miter->consumed = 0;
+	}
+}
+EXPORT_SYMBOL_GPL(backport_sg_miter_stop);
-- 
2.8.1

--
To unsubscribe from this list: send the line "unsubscribe backports" in

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH 2/2] backport: add proper thermal backport
  2016-07-15 19:01 [PATCH 1/2] backports: add some scatterlist backports for <3.9 and <3.11 Johannes Berg
@ 2016-07-15 19:01 ` Johannes Berg
  0 siblings, 0 replies; 2+ messages in thread
From: Johannes Berg @ 2016-07-15 19:01 UTC (permalink / raw)
  To: backports; +Cc: luca, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

There were some API changes in the thermal framework in kernel version
4.3 and also earlier in 3.10.  Backport what is needed to support
older kernels.

The 4.3 change is a bit tricky, because it changes the prototypes of
some ops. The solution for that is to add hook functions that will
intercept the calls from the thermal framework and convert them to
calls that the backported driver provides (namely convert unsigned
longs to ints).

Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 backport/backport-include/linux/thermal.h          |  93 ++++++++++--
 backport/compat/backport-4.3.c                     | 157 +++++++++++++++++++++
 .../network/0070-thermal/iwlwifi.patch             |  56 --------
 3 files changed, 239 insertions(+), 67 deletions(-)
 delete mode 100644 patches/collateral-evolutions/network/0070-thermal/iwlwifi.patch

diff --git a/backport/backport-include/linux/thermal.h b/backport/backport-include/linux/thermal.h
index 595f5c5fe735..115af16fb228 100644
--- a/backport/backport-include/linux/thermal.h
+++ b/backport/backport-include/linux/thermal.h
@@ -3,17 +3,6 @@
 #include_next <linux/thermal.h>
 #include <linux/version.h>
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
-#define thermal_zone_device_register(type, trips, mask, devdata, ops, tzp, passive_delay, polling_delay) \
-	thermal_zone_device_register(type, trips, devdata, ops, 0, 0, passive_delay, polling_delay)
-#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
-#define thermal_zone_device_register(type, trips, mask, devdata, ops, tzp, passive_delay, polling_delay) \
-	thermal_zone_device_register(type, trips, mask, devdata, ops, 0, 0, passive_delay, polling_delay)
-#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
-#define thermal_zone_device_register(type, trips, mask, devdata, ops, tzp, passive_delay, polling_delay) \
-	thermal_zone_device_register(type, trips, mask, devdata, ops, passive_delay, polling_delay)
-#endif /* < 3.8 */
-
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
 #define thermal_notify_framework LINUX_BACKPORT(thermal_notify_framework)
 static inline void thermal_notify_framework(struct thermal_zone_device *tz, int trip)
@@ -24,4 +13,86 @@ static inline void thermal_notify_framework(struct thermal_zone_device *tz, int
 #define thermal_notify_framework(tz, trip) notify_thermal_framework(tz, trip)
 #endif /* < 3.10 */
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0))
+
+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,
+	old_thermal_zone_device_ops_t *_ops,
+	const struct thermal_zone_params *_tzp,
+	int passive_delay, int polling_delay)
+{
+	struct thermal_zone_device_ops *ops =
+		(struct thermal_zone_device_ops *) _ops;
+
+	/* cast the const away */
+	struct thermal_zone_params *tzp =
+		(struct thermal_zone_params *)_tzp;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
+	return thermal_zone_device_register(type, trips, devdata, ops,
+					    0, 0, passive_delay, polling_delay);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+	return thermal_zone_device_register(type, trips, mask, devdata, ops,
+					    0, 0, passive_delay, polling_delay);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
+	return thermal_zone_device_register(type, trips, mask, devdata, ops,
+					    passive_delay, polling_delay);
+#else
+	return thermal_zone_device_register(type, trips, mask, devdata,
+					    ops, tzp, passive_delay,
+					    polling_delay);
+#endif
+}
+
+static inline
+void old_thermal_zone_device_unregister(struct thermal_zone_device *dev)
+{
+	thermal_zone_device_unregister(dev);
+}
+
+struct backport_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 *, int *);
+	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, 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);
+	int (*get_trend) (struct thermal_zone_device *, int,
+			  enum thermal_trend *);
+	int (*notify) (struct thermal_zone_device *, int,
+		       enum thermal_trip_type);
+};
+#define thermal_zone_device_ops LINUX_BACKPORT(thermal_zone_device_ops)
+
+#undef thermal_zone_device_register
+struct thermal_zone_device *backport_thermal_zone_device_register(
+	const char *type, int trips, int mask, void *devdata,
+	struct thermal_zone_device_ops *ops,
+	const struct thermal_zone_params *tzp,
+	int passive_delay, int polling_delay);
+
+#define thermal_zone_device_register \
+	LINUX_BACKPORT(thermal_zone_device_register)
+
+#undef thermal_zone_device_unregister
+void backport_thermal_zone_device_unregister(struct thermal_zone_device *);
+#define thermal_zone_device_unregister			\
+	LINUX_BACKPORT(thermal_zone_device_unregister)
+
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0)*/
+
 #endif /* __BACKPORT_THERMAL_H__ */
diff --git a/backport/compat/backport-4.3.c b/backport/compat/backport-4.3.c
index d15c92c9c302..eff3e7f4dea1 100644
--- a/backport/compat/backport-4.3.c
+++ b/backport/compat/backport-4.3.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2015  Hauke Mehrtens <hauke@hauke-m.de>
+ * Copyright (c) 2015 - 2016 Intel Deutschland GmbH
  *
  * Backport functionality introduced in Linux 4.3.
  *
@@ -8,9 +9,165 @@
  * 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;
+};
+
+static int backport_thermal_get_temp(struct thermal_zone_device *dev,
+				     unsigned long *temp)
+{
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
+	int _temp, ret;
+
+	ret = wrapper->driver_ops->get_temp(dev, &_temp);
+	if (!ret)
+		*temp = (unsigned long)_temp;
+
+	return ret;
+}
+
+static int backport_thermal_get_trip_temp(struct thermal_zone_device *dev,
+					  int i, unsigned long *temp)
+{
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
+	int _temp, ret;
+
+	ret = wrapper->driver_ops->get_trip_temp(dev, i,  &_temp);
+	if (!ret)
+		*temp = (unsigned long)_temp;
+
+	return ret;
+}
+
+static int backport_thermal_set_trip_temp(struct thermal_zone_device *dev,
+					  int i, unsigned long temp)
+{
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
+
+	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_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
+	int _temp, ret;
+
+	ret = wrapper->driver_ops->get_trip_hyst(dev, i, &_temp);
+	if (!ret)
+		*temp = (unsigned long)_temp;
+
+	return ret;
+}
+
+static int backport_thermal_set_trip_hyst(struct thermal_zone_device *dev,
+					  int i, unsigned long temp)
+{
+	struct backport_thermal_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
+
+	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_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
+	int _temp, ret;
+
+	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_ops_wrapper *wrapper =
+		container_of(dev->ops, struct backport_thermal_ops_wrapper, ops);
+
+	return wrapper->driver_ops->set_emul_temp(dev, (int)temp);
+}
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) */
+
+struct thermal_zone_device *backport_thermal_zone_device_register(
+	const char *type, int trips, int mask, void *devdata,
+	struct thermal_zone_device_ops *ops,
+	const struct thermal_zone_params *tzp,
+	int passive_delay, int polling_delay)
+{
+	struct backport_thermal_ops_wrapper *wrapper = kzalloc(sizeof(*wrapper), GFP_KERNEL);
+	struct thermal_zone_device *ret;
+
+	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);
+
+	/* Assign the backport ops to the old struct to get the
+	 * correct types.  But only assign if the registrant defined
+	 * the ops.
+	 */
+#define assign_ops(_op)		\
+	if (ops->_op)		\
+		wrapper->ops._op = backport_thermal_##_op
+
+	assign_ops(get_temp);
+	assign_ops(get_trip_temp);
+	assign_ops(set_trip_temp);
+	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
+
+	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)
+{
+	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);
 
 static void seq_set_overflow(struct seq_file *m)
 {
diff --git a/patches/collateral-evolutions/network/0070-thermal/iwlwifi.patch b/patches/collateral-evolutions/network/0070-thermal/iwlwifi.patch
deleted file mode 100644
index 1b37844cf255..000000000000
--- a/patches/collateral-evolutions/network/0070-thermal/iwlwifi.patch
+++ /dev/null
@@ -1,56 +0,0 @@
---- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
-+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
-@@ -637,7 +637,11 @@ send:
- }
- 
- static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device,
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0)
-+				  unsigned long *temperature)
-+#else
- 				  int *temperature)
-+#endif
- {
- 	struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata;
- 	int ret;
-@@ -662,7 +666,11 @@ out:
- }
- 
- static int iwl_mvm_tzone_get_trip_temp(struct thermal_zone_device *device,
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0)
-+				       int trip, unsigned long *temp)
-+#else
- 				       int trip, int *temp)
-+#endif
- {
- 	struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata;
- 
-@@ -685,8 +693,13 @@ static int iwl_mvm_tzone_get_trip_type(s
- 	return 0;
- }
- 
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
- static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device,
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0)
-+				       int trip, unsigned long temp)
-+#else
- 				       int trip, int temp)
-+#endif
- {
- 	struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata;
- 	struct iwl_mvm_thermal_device *tzone;
-@@ -739,12 +752,15 @@ out:
- 	mutex_unlock(&mvm->mutex);
- 	return ret;
- }
-+#endif /* >= 3.6 */
- 
- static  struct thermal_zone_device_ops tzone_ops = {
- 	.get_temp = iwl_mvm_tzone_get_temp,
- 	.get_trip_temp = iwl_mvm_tzone_get_trip_temp,
- 	.get_trip_type = iwl_mvm_tzone_get_trip_type,
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
- 	.set_trip_temp = iwl_mvm_tzone_set_trip_temp,
-+#endif
- };
- 
- /* make all trips writable */
-- 
2.8.1

--
To unsubscribe from this list: send the line "unsubscribe backports" in

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2016-07-15 19:01 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-15 19:01 [PATCH 1/2] backports: add some scatterlist backports for <3.9 and <3.11 Johannes Berg
2016-07-15 19:01 ` [PATCH 2/2] backport: add proper thermal backport Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.