2019-05-29 14:18:02 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2015-01-16 23:59:03 +00:00
|
|
|
/*
|
|
|
|
* int340x_thermal_zone.c
|
|
|
|
* Copyright (c) 2015, Intel Corporation.
|
|
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/acpi.h>
|
|
|
|
#include <linux/thermal.h>
|
2020-01-31 06:15:44 +00:00
|
|
|
#include <linux/units.h>
|
2015-01-16 23:59:03 +00:00
|
|
|
#include "int340x_thermal_zone.h"
|
|
|
|
|
|
|
|
static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
|
2015-07-24 06:12:54 +00:00
|
|
|
int *temp)
|
2015-01-16 23:59:03 +00:00
|
|
|
{
|
|
|
|
struct int34x_thermal_zone *d = zone->devdata;
|
|
|
|
unsigned long long tmp;
|
|
|
|
acpi_status status;
|
|
|
|
|
|
|
|
status = acpi_evaluate_integer(d->adev->handle, "_TMP", NULL, &tmp);
|
|
|
|
if (ACPI_FAILURE(status))
|
|
|
|
return -EIO;
|
|
|
|
|
2015-01-28 19:56:48 +00:00
|
|
|
if (d->lpat_table) {
|
|
|
|
int conv_temp;
|
|
|
|
|
|
|
|
conv_temp = acpi_lpat_raw_to_temp(d->lpat_table, (int)tmp);
|
|
|
|
if (conv_temp < 0)
|
|
|
|
return conv_temp;
|
|
|
|
|
|
|
|
*temp = (unsigned long)conv_temp * 10;
|
|
|
|
} else
|
|
|
|
/* _TMP returns the temperature in tenths of degrees Kelvin */
|
2020-01-31 06:15:44 +00:00
|
|
|
*temp = deci_kelvin_to_millicelsius(tmp);
|
2015-01-16 23:59:03 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone,
|
2015-07-24 06:12:54 +00:00
|
|
|
int trip, int *temp)
|
2015-01-16 23:59:03 +00:00
|
|
|
{
|
|
|
|
struct int34x_thermal_zone *d = zone->devdata;
|
2023-01-25 14:54:03 +00:00
|
|
|
int i;
|
2023-01-23 17:21:10 +00:00
|
|
|
|
2015-01-16 23:59:03 +00:00
|
|
|
if (trip < d->aux_trip_nr)
|
|
|
|
*temp = d->aux_trips[trip];
|
|
|
|
else if (trip == d->crt_trip_id)
|
|
|
|
*temp = d->crt_temp;
|
|
|
|
else if (trip == d->psv_trip_id)
|
|
|
|
*temp = d->psv_temp;
|
|
|
|
else if (trip == d->hot_trip_id)
|
|
|
|
*temp = d->hot_temp;
|
|
|
|
else {
|
|
|
|
for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) {
|
|
|
|
if (d->act_trips[i].valid &&
|
|
|
|
d->act_trips[i].id == trip) {
|
|
|
|
*temp = d->act_trips[i].temp;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i == INT340X_THERMAL_MAX_ACT_TRIP_COUNT)
|
2023-01-25 14:54:03 +00:00
|
|
|
return -EINVAL;
|
2015-01-16 23:59:03 +00:00
|
|
|
}
|
|
|
|
|
2023-01-25 14:54:03 +00:00
|
|
|
return 0;
|
2015-01-16 23:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone,
|
|
|
|
int trip,
|
|
|
|
enum thermal_trip_type *type)
|
|
|
|
{
|
|
|
|
struct int34x_thermal_zone *d = zone->devdata;
|
2023-01-25 14:54:03 +00:00
|
|
|
int i;
|
2023-01-25 12:17:42 +00:00
|
|
|
|
2015-01-16 23:59:03 +00:00
|
|
|
if (trip < d->aux_trip_nr)
|
|
|
|
*type = THERMAL_TRIP_PASSIVE;
|
|
|
|
else if (trip == d->crt_trip_id)
|
|
|
|
*type = THERMAL_TRIP_CRITICAL;
|
|
|
|
else if (trip == d->hot_trip_id)
|
|
|
|
*type = THERMAL_TRIP_HOT;
|
|
|
|
else if (trip == d->psv_trip_id)
|
|
|
|
*type = THERMAL_TRIP_PASSIVE;
|
|
|
|
else {
|
|
|
|
for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) {
|
|
|
|
if (d->act_trips[i].valid &&
|
|
|
|
d->act_trips[i].id == trip) {
|
|
|
|
*type = THERMAL_TRIP_ACTIVE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i == INT340X_THERMAL_MAX_ACT_TRIP_COUNT)
|
2023-01-25 14:54:03 +00:00
|
|
|
return -EINVAL;
|
2015-01-16 23:59:03 +00:00
|
|
|
}
|
|
|
|
|
2023-01-25 14:54:03 +00:00
|
|
|
return 0;
|
2015-01-16 23:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
|
2015-07-24 06:12:54 +00:00
|
|
|
int trip, int temp)
|
2015-01-16 23:59:03 +00:00
|
|
|
{
|
|
|
|
struct int34x_thermal_zone *d = zone->devdata;
|
|
|
|
acpi_status status;
|
|
|
|
char name[10];
|
|
|
|
|
|
|
|
snprintf(name, sizeof(name), "PAT%d", trip);
|
|
|
|
status = acpi_execute_simple_method(d->adev->handle, name,
|
2020-01-31 06:15:44 +00:00
|
|
|
millicelsius_to_deci_kelvin(temp));
|
2015-01-16 23:59:03 +00:00
|
|
|
if (ACPI_FAILURE(status))
|
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
d->aux_trips[trip] = temp;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone,
|
2015-07-24 06:12:54 +00:00
|
|
|
int trip, int *temp)
|
2015-01-16 23:59:03 +00:00
|
|
|
{
|
|
|
|
struct int34x_thermal_zone *d = zone->devdata;
|
|
|
|
acpi_status status;
|
|
|
|
unsigned long long hyst;
|
|
|
|
|
|
|
|
status = acpi_evaluate_integer(d->adev->handle, "GTSH", NULL, &hyst);
|
|
|
|
if (ACPI_FAILURE(status))
|
2018-05-26 01:10:10 +00:00
|
|
|
*temp = 0;
|
|
|
|
else
|
|
|
|
*temp = hyst * 100;
|
2015-01-16 23:59:03 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
thermal: int340x: Fix unexpected shutdown at critical temperature
We are seeing thermal shutdown on Intel based mobile workstations, the
shutdown happens during the first trip handle in
thermal_zone_device_register():
kernel: thermal thermal_zone15: critical temperature reached (101 C), shutting down
However, we shouldn't do a thermal shutdown here, since
1) We may want to use a dedicated daemon, Intel's thermald in this case,
to handle thermal shutdown.
2) For ACPI based system, _CRT doesn't mean shutdown unless it's inside
ThermalZone namespace. ACPI Spec, 11.4.4 _CRT (Critical Temperature):
"... If this object it present under a device, the device’s driver
evaluates this object to determine the device’s critical cooling
temperature trip point. This value may then be used by the device’s
driver to program an internal device temperature sensor trip point."
So a "critical trip" here merely means we should take a more aggressive
cooling method.
As int340x device isn't present under ACPI ThermalZone, override the
default .critical callback to prevent surprising thermal shutdown.
Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/20201221172345.36976-1-kai.heng.feng@canonical.com
2020-12-21 17:23:43 +00:00
|
|
|
static void int340x_thermal_critical(struct thermal_zone_device *zone)
|
|
|
|
{
|
|
|
|
dev_dbg(&zone->device, "%s: critical temperature reached\n", zone->type);
|
|
|
|
}
|
|
|
|
|
2015-01-16 23:59:03 +00:00
|
|
|
static struct thermal_zone_device_ops int340x_thermal_zone_ops = {
|
|
|
|
.get_temp = int340x_thermal_get_zone_temp,
|
|
|
|
.get_trip_temp = int340x_thermal_get_trip_temp,
|
|
|
|
.get_trip_type = int340x_thermal_get_trip_type,
|
|
|
|
.set_trip_temp = int340x_thermal_set_trip_temp,
|
|
|
|
.get_trip_hyst = int340x_thermal_get_trip_hyst,
|
thermal: int340x: Fix unexpected shutdown at critical temperature
We are seeing thermal shutdown on Intel based mobile workstations, the
shutdown happens during the first trip handle in
thermal_zone_device_register():
kernel: thermal thermal_zone15: critical temperature reached (101 C), shutting down
However, we shouldn't do a thermal shutdown here, since
1) We may want to use a dedicated daemon, Intel's thermald in this case,
to handle thermal shutdown.
2) For ACPI based system, _CRT doesn't mean shutdown unless it's inside
ThermalZone namespace. ACPI Spec, 11.4.4 _CRT (Critical Temperature):
"... If this object it present under a device, the device’s driver
evaluates this object to determine the device’s critical cooling
temperature trip point. This value may then be used by the device’s
driver to program an internal device temperature sensor trip point."
So a "critical trip" here merely means we should take a more aggressive
cooling method.
As int340x device isn't present under ACPI ThermalZone, override the
default .critical callback to prevent surprising thermal shutdown.
Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/20201221172345.36976-1-kai.heng.feng@canonical.com
2020-12-21 17:23:43 +00:00
|
|
|
.critical = int340x_thermal_critical,
|
2015-01-16 23:59:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int int340x_thermal_get_trip_config(acpi_handle handle, char *name,
|
2015-07-24 06:12:54 +00:00
|
|
|
int *temp)
|
2015-01-16 23:59:03 +00:00
|
|
|
{
|
|
|
|
unsigned long long r;
|
|
|
|
acpi_status status;
|
|
|
|
|
|
|
|
status = acpi_evaluate_integer(handle, name, NULL, &r);
|
|
|
|
if (ACPI_FAILURE(status))
|
|
|
|
return -EIO;
|
|
|
|
|
2020-01-31 06:15:44 +00:00
|
|
|
*temp = deci_kelvin_to_millicelsius(r);
|
2015-01-16 23:59:03 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-01-25 14:52:25 +00:00
|
|
|
static int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone)
|
2016-08-26 23:21:18 +00:00
|
|
|
{
|
|
|
|
int trip_cnt = int34x_zone->aux_trip_nr;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
int34x_zone->crt_trip_id = -1;
|
|
|
|
if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_CRT",
|
|
|
|
&int34x_zone->crt_temp))
|
|
|
|
int34x_zone->crt_trip_id = trip_cnt++;
|
|
|
|
|
|
|
|
int34x_zone->hot_trip_id = -1;
|
|
|
|
if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_HOT",
|
|
|
|
&int34x_zone->hot_temp))
|
|
|
|
int34x_zone->hot_trip_id = trip_cnt++;
|
|
|
|
|
|
|
|
int34x_zone->psv_trip_id = -1;
|
|
|
|
if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_PSV",
|
|
|
|
&int34x_zone->psv_temp))
|
|
|
|
int34x_zone->psv_trip_id = trip_cnt++;
|
|
|
|
|
|
|
|
for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) {
|
|
|
|
char name[5] = { '_', 'A', 'C', '0' + i, '\0' };
|
|
|
|
|
|
|
|
if (int340x_thermal_get_trip_config(int34x_zone->adev->handle,
|
|
|
|
name,
|
|
|
|
&int34x_zone->act_trips[i].temp))
|
|
|
|
break;
|
|
|
|
|
|
|
|
int34x_zone->act_trips[i].id = trip_cnt++;
|
|
|
|
int34x_zone->act_trips[i].valid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return trip_cnt;
|
|
|
|
}
|
|
|
|
|
2015-01-16 23:59:03 +00:00
|
|
|
static struct thermal_zone_params int340x_thermal_params = {
|
|
|
|
.governor_name = "user_space",
|
|
|
|
.no_hwmon = true,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
|
2022-10-03 09:26:01 +00:00
|
|
|
int (*get_temp) (struct thermal_zone_device *, int *))
|
2015-01-16 23:59:03 +00:00
|
|
|
{
|
|
|
|
struct int34x_thermal_zone *int34x_thermal_zone;
|
|
|
|
acpi_status status;
|
|
|
|
unsigned long long trip_cnt;
|
2016-08-26 23:21:18 +00:00
|
|
|
int trip_mask = 0;
|
2015-01-16 23:59:03 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
int34x_thermal_zone = kzalloc(sizeof(*int34x_thermal_zone),
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!int34x_thermal_zone)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
|
int34x_thermal_zone->adev = adev;
|
2022-10-03 09:26:01 +00:00
|
|
|
|
|
|
|
int34x_thermal_zone->ops = kmemdup(&int340x_thermal_zone_ops,
|
|
|
|
sizeof(int340x_thermal_zone_ops), GFP_KERNEL);
|
|
|
|
if (!int34x_thermal_zone->ops) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto err_ops_alloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (get_temp)
|
|
|
|
int34x_thermal_zone->ops->get_temp = get_temp;
|
2015-01-16 23:59:03 +00:00
|
|
|
|
|
|
|
status = acpi_evaluate_integer(adev->handle, "PATC", NULL, &trip_cnt);
|
|
|
|
if (ACPI_FAILURE(status))
|
|
|
|
trip_cnt = 0;
|
|
|
|
else {
|
2021-04-30 12:23:43 +00:00
|
|
|
int i;
|
|
|
|
|
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 21:03:40 +00:00
|
|
|
int34x_thermal_zone->aux_trips =
|
|
|
|
kcalloc(trip_cnt,
|
|
|
|
sizeof(*int34x_thermal_zone->aux_trips),
|
|
|
|
GFP_KERNEL);
|
2015-01-16 23:59:03 +00:00
|
|
|
if (!int34x_thermal_zone->aux_trips) {
|
|
|
|
ret = -ENOMEM;
|
2015-03-02 21:12:07 +00:00
|
|
|
goto err_trip_alloc;
|
2015-01-16 23:59:03 +00:00
|
|
|
}
|
|
|
|
trip_mask = BIT(trip_cnt) - 1;
|
|
|
|
int34x_thermal_zone->aux_trip_nr = trip_cnt;
|
2021-04-30 12:23:43 +00:00
|
|
|
for (i = 0; i < trip_cnt; ++i)
|
|
|
|
int34x_thermal_zone->aux_trips[i] = THERMAL_TEMP_INVALID;
|
2015-01-16 23:59:03 +00:00
|
|
|
}
|
|
|
|
|
2016-08-26 23:21:18 +00:00
|
|
|
trip_cnt = int340x_thermal_read_trips(int34x_thermal_zone);
|
2015-01-16 23:59:03 +00:00
|
|
|
|
2015-01-28 19:56:48 +00:00
|
|
|
int34x_thermal_zone->lpat_table = acpi_lpat_get_conversion_table(
|
|
|
|
adev->handle);
|
2015-01-16 23:59:03 +00:00
|
|
|
|
|
|
|
int34x_thermal_zone->zone = thermal_zone_device_register(
|
|
|
|
acpi_device_bid(adev),
|
|
|
|
trip_cnt,
|
|
|
|
trip_mask, int34x_thermal_zone,
|
2022-10-03 09:26:01 +00:00
|
|
|
int34x_thermal_zone->ops,
|
2015-01-16 23:59:03 +00:00
|
|
|
&int340x_thermal_params,
|
|
|
|
0, 0);
|
|
|
|
if (IS_ERR(int34x_thermal_zone->zone)) {
|
|
|
|
ret = PTR_ERR(int34x_thermal_zone->zone);
|
2015-03-02 21:12:07 +00:00
|
|
|
goto err_thermal_zone;
|
2015-01-16 23:59:03 +00:00
|
|
|
}
|
2020-06-29 12:29:22 +00:00
|
|
|
ret = thermal_zone_device_enable(int34x_thermal_zone->zone);
|
|
|
|
if (ret)
|
|
|
|
goto err_enable;
|
2015-01-16 23:59:03 +00:00
|
|
|
|
|
|
|
return int34x_thermal_zone;
|
|
|
|
|
2020-06-29 12:29:22 +00:00
|
|
|
err_enable:
|
|
|
|
thermal_zone_device_unregister(int34x_thermal_zone->zone);
|
2015-03-02 21:12:07 +00:00
|
|
|
err_thermal_zone:
|
2015-01-28 19:56:48 +00:00
|
|
|
acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
|
2015-03-02 21:12:07 +00:00
|
|
|
kfree(int34x_thermal_zone->aux_trips);
|
|
|
|
err_trip_alloc:
|
2022-10-03 09:26:01 +00:00
|
|
|
kfree(int34x_thermal_zone->ops);
|
|
|
|
err_ops_alloc:
|
2015-01-16 23:59:03 +00:00
|
|
|
kfree(int34x_thermal_zone);
|
|
|
|
return ERR_PTR(ret);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(int340x_thermal_zone_add);
|
|
|
|
|
|
|
|
void int340x_thermal_zone_remove(struct int34x_thermal_zone
|
|
|
|
*int34x_thermal_zone)
|
|
|
|
{
|
|
|
|
thermal_zone_device_unregister(int34x_thermal_zone->zone);
|
2015-01-28 19:56:48 +00:00
|
|
|
acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
|
2015-03-02 21:12:07 +00:00
|
|
|
kfree(int34x_thermal_zone->aux_trips);
|
2022-10-03 09:26:01 +00:00
|
|
|
kfree(int34x_thermal_zone->ops);
|
2015-01-16 23:59:03 +00:00
|
|
|
kfree(int34x_thermal_zone);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(int340x_thermal_zone_remove);
|
|
|
|
|
2023-01-25 14:52:25 +00:00
|
|
|
void int340x_thermal_update_trips(struct int34x_thermal_zone *int34x_zone)
|
|
|
|
{
|
|
|
|
acpi_handle zone_handle = int34x_zone->adev->handle;
|
|
|
|
int i, err;
|
|
|
|
|
2023-01-25 14:54:03 +00:00
|
|
|
mutex_lock(&int34x_zone->zone->lock);
|
2023-01-25 14:52:25 +00:00
|
|
|
|
|
|
|
if (int34x_zone->crt_trip_id > 0) {
|
|
|
|
err = int340x_thermal_get_trip_config(zone_handle, "_CRT",
|
|
|
|
&int34x_zone->crt_temp);
|
|
|
|
if (err)
|
|
|
|
int34x_zone->crt_temp = THERMAL_TEMP_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (int34x_zone->hot_trip_id > 0) {
|
|
|
|
err = int340x_thermal_get_trip_config(zone_handle, "_HOT",
|
|
|
|
&int34x_zone->hot_temp);
|
|
|
|
if (err)
|
|
|
|
int34x_zone->hot_temp = THERMAL_TEMP_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (int34x_zone->psv_trip_id > 0) {
|
|
|
|
err = int340x_thermal_get_trip_config(zone_handle, "_PSV",
|
|
|
|
&int34x_zone->psv_temp);
|
|
|
|
if (err)
|
|
|
|
int34x_zone->psv_temp = THERMAL_TEMP_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < INT340X_THERMAL_MAX_ACT_TRIP_COUNT; i++) {
|
|
|
|
char name[5] = { '_', 'A', 'C', '0' + i, '\0' };
|
|
|
|
|
|
|
|
if (!int34x_zone->act_trips[i].valid)
|
|
|
|
break;
|
|
|
|
|
|
|
|
err = int340x_thermal_get_trip_config(zone_handle, name,
|
|
|
|
&int34x_zone->act_trips[i].temp);
|
|
|
|
if (err)
|
|
|
|
int34x_zone->act_trips[i].temp = THERMAL_TEMP_INVALID;
|
|
|
|
}
|
|
|
|
|
2023-01-25 14:54:03 +00:00
|
|
|
mutex_unlock(&int34x_zone->zone->lock);
|
2023-01-25 14:52:25 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(int340x_thermal_update_trips);
|
|
|
|
|
2015-01-16 23:59:03 +00:00
|
|
|
MODULE_AUTHOR("Aaron Lu <aaron.lu@intel.com>");
|
|
|
|
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
|
|
|
|
MODULE_DESCRIPTION("Intel INT340x common thermal zone handler");
|
|
|
|
MODULE_LICENSE("GPL v2");
|