2 * Copyright (c) 2015 Hauke Mehrtens <hauke@hauke-m.de>
3 * Copyright (c) 2015 - 2016 Intel Deutschland GmbH
5 * Backport functionality introduced in Linux 4.3.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/version.h>
13 #include <linux/seq_file.h>
14 #include <linux/export.h>
15 #include <linux/printk.h>
16 #include <linux/thermal.h>
17 #include <linux/slab.h>
20 #if LINUX_VERSION_IS_GEQ(3,8,0)
21 struct backport_thermal_ops_wrapper
{
22 old_thermal_zone_device_ops_t ops
;
23 struct thermal_zone_device_ops
*driver_ops
;
26 static int backport_thermal_get_temp(struct thermal_zone_device
*dev
,
29 struct backport_thermal_ops_wrapper
*wrapper
=
30 container_of(dev
->ops
, struct backport_thermal_ops_wrapper
, ops
);
33 ret
= wrapper
->driver_ops
->get_temp(dev
, &_temp
);
35 *temp
= (unsigned long)_temp
;
40 static int backport_thermal_get_trip_temp(struct thermal_zone_device
*dev
,
41 int i
, unsigned long *temp
)
43 struct backport_thermal_ops_wrapper
*wrapper
=
44 container_of(dev
->ops
, struct backport_thermal_ops_wrapper
, ops
);
47 ret
= wrapper
->driver_ops
->get_trip_temp(dev
, i
, &_temp
);
49 *temp
= (unsigned long)_temp
;
54 static int backport_thermal_set_trip_temp(struct thermal_zone_device
*dev
,
55 int i
, unsigned long temp
)
57 struct backport_thermal_ops_wrapper
*wrapper
=
58 container_of(dev
->ops
, struct backport_thermal_ops_wrapper
, ops
);
60 return wrapper
->driver_ops
->set_trip_temp(dev
, i
, (int)temp
);
63 static int backport_thermal_get_trip_hyst(struct thermal_zone_device
*dev
,
64 int i
, unsigned long *temp
)
66 struct backport_thermal_ops_wrapper
*wrapper
=
67 container_of(dev
->ops
, struct backport_thermal_ops_wrapper
, ops
);
70 ret
= wrapper
->driver_ops
->get_trip_hyst(dev
, i
, &_temp
);
72 *temp
= (unsigned long)_temp
;
77 static int backport_thermal_set_trip_hyst(struct thermal_zone_device
*dev
,
78 int i
, unsigned long temp
)
80 struct backport_thermal_ops_wrapper
*wrapper
=
81 container_of(dev
->ops
, struct backport_thermal_ops_wrapper
, ops
);
83 return wrapper
->driver_ops
->set_trip_hyst(dev
, i
, (int)temp
);
86 static int backport_thermal_get_crit_temp(struct thermal_zone_device
*dev
,
89 struct backport_thermal_ops_wrapper
*wrapper
=
90 container_of(dev
->ops
, struct backport_thermal_ops_wrapper
, ops
);
93 ret
= wrapper
->driver_ops
->get_crit_temp(dev
, &_temp
);
95 *temp
= (unsigned long)_temp
;
100 #if LINUX_VERSION_IS_GEQ(3, 19, 0)
101 static int backport_thermal_set_emul_temp(struct thermal_zone_device
*dev
,
104 struct backport_thermal_ops_wrapper
*wrapper
=
105 container_of(dev
->ops
, struct backport_thermal_ops_wrapper
, ops
);
107 return wrapper
->driver_ops
->set_emul_temp(dev
, (int)temp
);
109 #endif /* LINUX_VERSION_IS_GEQ(3, 19, 0) */
111 struct thermal_zone_device
*backport_thermal_zone_device_register(
112 const char *type
, int trips
, int mask
, void *devdata
,
113 struct thermal_zone_device_ops
*ops
,
114 const struct thermal_zone_params
*tzp
,
115 int passive_delay
, int polling_delay
)
117 struct backport_thermal_ops_wrapper
*wrapper
= kzalloc(sizeof(*wrapper
), GFP_KERNEL
);
118 struct thermal_zone_device
*ret
;
123 wrapper
->driver_ops
= ops
;
126 wrapper->ops._op = ops->_op
136 /* Assign the backport ops to the old struct to get the
137 * correct types. But only assign if the registrant defined
140 #define assign_ops(_op) \
142 wrapper->ops._op = backport_thermal_##_op
144 assign_ops(get_temp
);
145 assign_ops(get_trip_temp
);
146 assign_ops(set_trip_temp
);
147 assign_ops(get_trip_hyst
);
148 assign_ops(set_trip_hyst
);
149 assign_ops(get_crit_temp
);
150 #if LINUX_VERSION_IS_GEQ(3, 19, 0)
151 assign_ops(set_emul_temp
);
152 #endif /* LINUX_VERSION_IS_GEQ(3, 19, 0) */
155 ret
= old_thermal_zone_device_register(type
, trips
, mask
, devdata
,
156 &wrapper
->ops
, tzp
, passive_delay
,
162 EXPORT_SYMBOL_GPL(backport_thermal_zone_device_register
);
164 void backport_thermal_zone_device_unregister(struct thermal_zone_device
*dev
)
166 struct backport_thermal_ops_wrapper
*wrapper
=
167 container_of(dev
->ops
, struct backport_thermal_ops_wrapper
, ops
);
169 old_thermal_zone_device_unregister(dev
);
172 EXPORT_SYMBOL_GPL(backport_thermal_zone_device_unregister
);
174 #endif /* >= 3.8.0 */
175 #endif /* CONFIG_THERMAL */
177 static void seq_set_overflow(struct seq_file
*m
)
182 /* A complete analogue of print_hex_dump() */
183 void seq_hex_dump(struct seq_file
*m
, const char *prefix_str
, int prefix_type
,
184 int rowsize
, int groupsize
, const void *buf
, size_t len
,
188 int i
, linelen
, remaining
= len
;
191 if (rowsize
!= 16 && rowsize
!= 32)
194 for (i
= 0; i
< len
&& !seq_has_overflowed(m
); i
+= rowsize
) {
195 linelen
= min(remaining
, rowsize
);
196 remaining
-= rowsize
;
198 switch (prefix_type
) {
199 case DUMP_PREFIX_ADDRESS
:
200 seq_printf(m
, "%s%p: ", prefix_str
, ptr
+ i
);
202 case DUMP_PREFIX_OFFSET
:
203 seq_printf(m
, "%s%.8x: ", prefix_str
, i
);
206 seq_printf(m
, "%s", prefix_str
);
210 ret
= hex_dump_to_buffer(ptr
+ i
, linelen
, rowsize
, groupsize
,
211 m
->buf
+ m
->count
, m
->size
- m
->count
,
213 if (ret
>= m
->size
- m
->count
) {
221 EXPORT_SYMBOL_GPL(seq_hex_dump
);
223 ssize_t
strscpy(char *dest
, const char *src
, size_t count
)
241 /* Hit buffer length without finding a NUL; force NUL-termination. */
247 EXPORT_SYMBOL_GPL(strscpy
);