/*
 * Copyright (c) 2015  Hauke Mehrtens <hauke@hauke-m.de>
 * 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 <linux/version.h>
#include <linux/seq_file.h>
#include <linux/export.h>
#include <linux/printk.h>
#include <linux/thermal.h>
#include <linux/slab.h>

#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);
