Commit 5c897a9a authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge back earlier thermal control material for v6.10.

parents b552f63c 0dbf6087
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -17,10 +17,13 @@

static int get_trip_level(struct thermal_zone_device *tz)
{
	const struct thermal_trip *trip, *level_trip = NULL;
	const struct thermal_trip *level_trip = NULL;
	const struct thermal_trip_desc *td;
	int trip_level = -1;

	for_each_trip(tz, trip) {
	for_each_trip_desc(tz, td) {
		const struct thermal_trip *trip = &td->trip;

		if (trip->temperature >= tz->temperature)
			continue;

+4 −2
Original line number Diff line number Diff line
@@ -496,9 +496,11 @@ static void get_governor_trips(struct thermal_zone_device *tz,
	const struct thermal_trip *first_passive = NULL;
	const struct thermal_trip *last_passive = NULL;
	const struct thermal_trip *last_active = NULL;
	const struct thermal_trip *trip;
	const struct thermal_trip_desc *td;

	for_each_trip_desc(tz, td) {
		const struct thermal_trip *trip = &td->trip;

	for_each_trip(tz, trip) {
		switch (trip->type) {
		case THERMAL_TRIP_PASSIVE:
			if (!first_passive) {
+16 −25
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@ static unsigned long get_target_state(struct thermal_instance *instance,
{
	struct thermal_cooling_device *cdev = instance->cdev;
	unsigned long cur_state;
	unsigned long next_target;

	/*
	 * We keep this instance the way it is by default.
@@ -40,32 +39,26 @@ static unsigned long get_target_state(struct thermal_instance *instance,
	 * cdev in use to determine the next_target.
	 */
	cdev->ops->get_cur_state(cdev, &cur_state);
	next_target = instance->target;
	dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);

	if (!instance->initialized) {
		if (throttle) {
			next_target = clamp((cur_state + 1), instance->lower, instance->upper);
		} else {
			next_target = THERMAL_NO_TARGET;
		}
		if (throttle)
			return clamp(cur_state + 1, instance->lower, instance->upper);

		return next_target;
		return THERMAL_NO_TARGET;
	}

	if (throttle) {
		if (trend == THERMAL_TREND_RAISING)
			next_target = clamp((cur_state + 1), instance->lower, instance->upper);
	} else {
		if (trend == THERMAL_TREND_DROPPING) {
			return clamp(cur_state + 1, instance->lower, instance->upper);
	} else if (trend == THERMAL_TREND_DROPPING) {
		if (cur_state <= instance->lower)
				next_target = THERMAL_NO_TARGET;
			else
				next_target = clamp((cur_state - 1), instance->lower, instance->upper);
		}
			return THERMAL_NO_TARGET;

		return clamp(cur_state - 1, instance->lower, instance->upper);
	}

	return next_target;
	return instance->target;
}

static void thermal_zone_trip_update(struct thermal_zone_device *tz,
@@ -99,15 +92,13 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
		if (instance->initialized && old_target == instance->target)
			continue;

		if (trip->type == THERMAL_TRIP_PASSIVE) {
			/* If needed, update the status of passive polling. */
			if (old_target == THERMAL_NO_TARGET &&
		    instance->target != THERMAL_NO_TARGET) {
			/* Activate a passive thermal instance */
			if (trip->type == THERMAL_TRIP_PASSIVE)
			    instance->target != THERMAL_NO_TARGET)
				tz->passive++;
		} else if (old_target != THERMAL_NO_TARGET &&
			   instance->target == THERMAL_NO_TARGET) {
			/* Deactivate a passive thermal instance */
			if (trip->type == THERMAL_TRIP_PASSIVE)
			else if (old_target != THERMAL_NO_TARGET &&
				 instance->target == THERMAL_NO_TARGET)
				tz->passive--;
		}

+2 −2
Original line number Diff line number Diff line
@@ -309,7 +309,7 @@ static int acpi_parse_psvt(acpi_handle handle, int *psvt_count, struct psvt **ps

		if (knob->type == ACPI_TYPE_STRING) {
			memset(&psvt->limit, 0, sizeof(u64));
			strncpy(psvt->limit.string, psvt_ptr->limit.str_ptr, knob->string.length);
			strscpy(psvt->limit.string, psvt_ptr->limit.str_ptr, ACPI_LIMIT_STR_MAX_LEN);
		} else {
			psvt->limit.integer = psvt_ptr->limit.integer;
		}
@@ -468,7 +468,7 @@ static int fill_psvt(char __user *ubuf)
		psvt_user[i].unlimit_coeff = psvts[i].unlimit_coeff;
		psvt_user[i].control_knob_type = psvts[i].control_knob_type;
		if (psvt_user[i].control_knob_type == ACPI_TYPE_STRING)
			strncpy(psvt_user[i].limit.string, psvts[i].limit.string,
			strscpy(psvt_user[i].limit.string, psvts[i].limit.string,
				ACPI_LIMIT_STR_MAX_LEN);
		else
			psvt_user[i].limit.integer = psvts[i].limit.integer;
+89 −8
Original line number Diff line number Diff line
@@ -159,6 +159,7 @@ struct hfi_cpu_info {
static DEFINE_PER_CPU(struct hfi_cpu_info, hfi_cpu_info) = { .index = -1 };

static int max_hfi_instances;
static int hfi_clients_nr;
static struct hfi_instance *hfi_instances;

static struct hfi_features hfi_features;
@@ -477,8 +478,11 @@ void intel_hfi_online(unsigned int cpu)
enable:
	cpumask_set_cpu(cpu, hfi_instance->cpus);

	/* Enable this HFI instance if this is its first online CPU. */
	if (cpumask_weight(hfi_instance->cpus) == 1) {
	/*
	 * Enable this HFI instance if this is its first online CPU and
	 * there are user-space clients of thermal events.
	 */
	if (cpumask_weight(hfi_instance->cpus) == 1 && hfi_clients_nr > 0) {
		hfi_set_hw_table(hfi_instance);
		hfi_enable();
	}
@@ -573,18 +577,33 @@ static __init int hfi_parse_features(void)
	return 0;
}

static void hfi_do_enable(void)
/*
 * If concurrency is not prevented by other means, the HFI enable/disable
 * routines must be called under hfi_instance_lock."
 */
static void hfi_enable_instance(void *ptr)
{
	hfi_set_hw_table(ptr);
	hfi_enable();
}

static void hfi_disable_instance(void *ptr)
{
	hfi_disable();
}

static void hfi_syscore_resume(void)
{
	/* This code runs only on the boot CPU. */
	struct hfi_cpu_info *info = &per_cpu(hfi_cpu_info, 0);
	struct hfi_instance *hfi_instance = info->hfi_instance;

	/* No locking needed. There is no concurrency with CPU online. */
	hfi_set_hw_table(hfi_instance);
	hfi_enable();
	if (hfi_clients_nr > 0)
		hfi_enable_instance(hfi_instance);
}

static int hfi_do_disable(void)
static int hfi_syscore_suspend(void)
{
	/* No locking needed. There is no concurrency with CPU offline. */
	hfi_disable();
@@ -593,8 +612,58 @@ static int hfi_do_disable(void)
}

static struct syscore_ops hfi_pm_ops = {
	.resume = hfi_do_enable,
	.suspend = hfi_do_disable,
	.resume = hfi_syscore_resume,
	.suspend = hfi_syscore_suspend,
};

static int hfi_thermal_notify(struct notifier_block *nb, unsigned long state,
			      void *_notify)
{
	struct thermal_genl_notify *notify = _notify;
	struct hfi_instance *hfi_instance;
	smp_call_func_t func = NULL;
	unsigned int cpu;
	int i;

	if (notify->mcgrp != THERMAL_GENL_EVENT_GROUP)
		return NOTIFY_DONE;

	if (state != THERMAL_NOTIFY_BIND && state != THERMAL_NOTIFY_UNBIND)
		return NOTIFY_DONE;

	mutex_lock(&hfi_instance_lock);

	switch (state) {
	case THERMAL_NOTIFY_BIND:
		if (++hfi_clients_nr == 1)
			func = hfi_enable_instance;
		break;
	case THERMAL_NOTIFY_UNBIND:
		if (--hfi_clients_nr == 0)
			func = hfi_disable_instance;
		break;
	}

	if (!func)
		goto out;

	for (i = 0; i < max_hfi_instances; i++) {
		hfi_instance = &hfi_instances[i];
		if (cpumask_empty(hfi_instance->cpus))
			continue;

		cpu = cpumask_any(hfi_instance->cpus);
		smp_call_function_single(cpu, func, hfi_instance, true);
	}

out:
	mutex_unlock(&hfi_instance_lock);

	return NOTIFY_OK;
}

static struct notifier_block hfi_thermal_nb = {
	.notifier_call = hfi_thermal_notify,
};

void __init intel_hfi_init(void)
@@ -628,10 +697,22 @@ void __init intel_hfi_init(void)
	if (!hfi_updates_wq)
		goto err_nomem;

	/*
	 * Both thermal core and Intel HFI can not be build as modules.
	 * As kernel build-in drivers they are initialized before user-space
	 * starts, hence we can not miss BIND/UNBIND events when applications
	 * add/remove thermal multicast group to/from a netlink socket.
	 */
	if (thermal_genl_register_notifier(&hfi_thermal_nb))
		goto err_nl_notif;

	register_syscore_ops(&hfi_pm_ops);

	return;

err_nl_notif:
	destroy_workqueue(hfi_updates_wq);

err_nomem:
	for (j = 0; j < i; ++j) {
		hfi_instance = &hfi_instances[j];
Loading