From 52409fae3e4b8d16b68b61902fc09075cd97b75d Mon Sep 17 00:00:00 2001 From: Dominik Sliwa Date: Sun, 2 Jul 2017 16:41:37 +0200 Subject: Backports generated from 4.11 kernel Initial commit. Signed-off-by: Dominik Sliwa --- compat/backport-4.3.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 compat/backport-4.3.c (limited to 'compat/backport-4.3.c') diff --git a/compat/backport-4.3.c b/compat/backport-4.3.c new file mode 100644 index 0000000..2d8a5e5 --- /dev/null +++ b/compat/backport-4.3.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2015 Hauke Mehrtens + * Copyright (c) 2015 - 2016 Intel Deutschland GmbH + * + * Backport functionality introduced in Linux 4.3. + * + * 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 +#include +#include +#include +#include +#include + +#if LINUX_VERSION_IS_GEQ(3,8,0) +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_IS_GEQ(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_IS_GEQ(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_IS_GEQ(3, 19, 0) + assign_ops(set_emul_temp); +#endif /* LINUX_VERSION_IS_GEQ(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); + +#endif /* >= 3.8.0 */ + +static void seq_set_overflow(struct seq_file *m) +{ + m->count = m->size; +} + +/* A complete analogue of print_hex_dump() */ +void seq_hex_dump(struct seq_file *m, const char *prefix_str, int prefix_type, + int rowsize, int groupsize, const void *buf, size_t len, + bool ascii) +{ + const u8 *ptr = buf; + int i, linelen, remaining = len; + int ret; + + if (rowsize != 16 && rowsize != 32) + rowsize = 16; + + for (i = 0; i < len && !seq_has_overflowed(m); i += rowsize) { + linelen = min(remaining, rowsize); + remaining -= rowsize; + + switch (prefix_type) { + case DUMP_PREFIX_ADDRESS: + seq_printf(m, "%s%p: ", prefix_str, ptr + i); + break; + case DUMP_PREFIX_OFFSET: + seq_printf(m, "%s%.8x: ", prefix_str, i); + break; + default: + seq_printf(m, "%s", prefix_str); + break; + } + + ret = hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize, + m->buf + m->count, m->size - m->count, + ascii); + if (ret >= m->size - m->count) { + seq_set_overflow(m); + } else { + m->count += ret; + seq_putc(m, '\n'); + } + } +} +EXPORT_SYMBOL_GPL(seq_hex_dump); + +ssize_t strscpy(char *dest, const char *src, size_t count) +{ + long res = 0; + + if (count == 0) + return -E2BIG; + + while (count) { + char c; + + c = src[res]; + dest[res] = c; + if (!c) + return res; + res++; + count--; + } + + /* Hit buffer length without finding a NUL; force NUL-termination. */ + if (res) + dest[res-1] = '\0'; + + return -E2BIG; +} +EXPORT_SYMBOL_GPL(strscpy); -- cgit v1.2.3