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

Merge branch 'thermal-core'

Merge thermal control core changes for 6.3-rc1:

 - Clean up thermal device unregistration code (Viresh Kumar).

 - Fix and clean up thermal control core initialization error code
   paths (Daniel Lezcano).

 - Relocate the trip points handling code into a separate file (Daniel
   Lezcano).

 - Make the thermal core fail registration of thermal zones and cooling
   devices if the thermal class has not been registered (Rafael Wysocki).

 - Make the core thermal control code use sysfs_emit_at() instead of
   scnprintf() where applicable (ye xingchen).

* thermal-core:
  thermal: core: Use sysfs_emit_at() instead of scnprintf()
  thermal: Fail object registration if thermal class is not registered
  thermal/core: Move the thermal trip code to a dedicated file
  thermal/core: Remove unneeded ida_destroy()
  thermal/core: Fix unregistering netlink at thermal init time
  thermal: core: Use device_unregister() instead of device_del/put()
  thermal: core: Move cdev cleanup to thermal_release()
parents f364beb5 5bbafd43
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -4,8 +4,8 @@
#

obj-$(CONFIG_THERMAL)		+= thermal_sys.o
thermal_sys-y			+= thermal_core.o thermal_sysfs.o \
					thermal_helpers.o
thermal_sys-y			+= thermal_core.o thermal_sysfs.o
thermal_sys-y			+= thermal_trip.o thermal_helpers.o

# netlink interface to manage the thermal framework
thermal_sys-$(CONFIG_THERMAL_NETLINK)		+= thermal_netlink.o
+43 −122
Original line number Diff line number Diff line
@@ -229,10 +229,9 @@ int thermal_build_list_of_policies(char *buf)
	mutex_lock(&thermal_governor_lock);

	list_for_each_entry(pos, &thermal_governor_list, governor_list) {
		count += scnprintf(buf + count, PAGE_SIZE - count, "%s ",
				   pos->name);
		count += sysfs_emit_at(buf, count, "%s ", pos->name);
	}
	count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
	count += sysfs_emit_at(buf, count, "\n");

	mutex_unlock(&thermal_governor_lock);

@@ -770,14 +769,14 @@ static void thermal_release(struct device *dev)
	} else if (!strncmp(dev_name(dev), "cooling_device",
			    sizeof("cooling_device") - 1)) {
		cdev = to_cooling_device(dev);
		thermal_cooling_device_destroy_sysfs(cdev);
		kfree(cdev->type);
		ida_free(&thermal_cdev_ida, cdev->id);
		kfree(cdev);
	}
}

static struct class thermal_class = {
	.name = "thermal",
	.dev_release = thermal_release,
};
static struct class *thermal_class;

static inline
void print_bind_err_msg(struct thermal_zone_device *tz,
@@ -880,6 +879,9 @@ __thermal_cooling_device_register(struct device_node *np,
	    !ops->set_cur_state)
		return ERR_PTR(-EINVAL);

	if (!thermal_class)
		return ERR_PTR(-ENODEV);

	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
	if (!cdev)
		return ERR_PTR(-ENOMEM);
@@ -901,27 +903,25 @@ __thermal_cooling_device_register(struct device_node *np,
	cdev->np = np;
	cdev->ops = ops;
	cdev->updated = false;
	cdev->device.class = &thermal_class;
	cdev->device.class = thermal_class;
	cdev->devdata = devdata;

	ret = cdev->ops->get_max_state(cdev, &cdev->max_state);
	if (ret) {
		kfree(cdev->type);
		goto out_ida_remove;
	}
	if (ret)
		goto out_cdev_type;

	thermal_cooling_device_setup_sysfs(cdev);

	ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
	if (ret) {
		kfree(cdev->type);
		thermal_cooling_device_destroy_sysfs(cdev);
		goto out_ida_remove;
	}
	if (ret)
		goto out_cooling_dev;

	ret = device_register(&cdev->device);
	if (ret)
		goto out_kfree_type;
	if (ret) {
		/* thermal_release() handles rest of the cleanup */
		put_device(&cdev->device);
		return ERR_PTR(ret);
	}

	/* Add 'this' new cdev to the global cdev list */
	mutex_lock(&thermal_list_lock);
@@ -940,13 +940,10 @@ __thermal_cooling_device_register(struct device_node *np,

	return cdev;

out_kfree_type:
out_cooling_dev:
	thermal_cooling_device_destroy_sysfs(cdev);
out_cdev_type:
	kfree(cdev->type);
	put_device(&cdev->device);

	/* thermal_release() takes care of the rest */
	cdev = NULL;
out_ida_remove:
	ida_free(&thermal_cdev_ida, id);
out_kfree_cdev:
@@ -1107,11 +1104,7 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)

	mutex_unlock(&thermal_list_lock);

	ida_free(&thermal_cdev_ida, cdev->id);
	device_del(&cdev->device);
	thermal_cooling_device_destroy_sysfs(cdev);
	kfree(cdev->type);
	put_device(&cdev->device);
	device_unregister(&cdev->device);
}
EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister);

@@ -1162,12 +1155,6 @@ static void thermal_set_delay_jiffies(unsigned long *delay_jiffies, int delay_ms
		*delay_jiffies = round_jiffies(*delay_jiffies);
}

int thermal_zone_get_num_trips(struct thermal_zone_device *tz)
{
	return tz->num_trips;
}
EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips);

int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp)
{
	int i, ret = -EINVAL;
@@ -1194,87 +1181,6 @@ int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp)
}
EXPORT_SYMBOL_GPL(thermal_zone_get_crit_temp);

int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
			    struct thermal_trip *trip)
{
	int ret;

	if (!tz || trip_id < 0 || trip_id >= tz->num_trips || !trip)
		return -EINVAL;

	if (tz->trips) {
		*trip = tz->trips[trip_id];
		return 0;
	}

	if (tz->ops->get_trip_hyst) {
		ret = tz->ops->get_trip_hyst(tz, trip_id, &trip->hysteresis);
		if (ret)
			return ret;
	} else {
		trip->hysteresis = 0;
	}

	ret = tz->ops->get_trip_temp(tz, trip_id, &trip->temperature);
	if (ret)
		return ret;

	return tz->ops->get_trip_type(tz, trip_id, &trip->type);
}
EXPORT_SYMBOL_GPL(__thermal_zone_get_trip);

int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
			  struct thermal_trip *trip)
{
	int ret;

	mutex_lock(&tz->lock);
	ret = __thermal_zone_get_trip(tz, trip_id, trip);
	mutex_unlock(&tz->lock);

	return ret;
}
EXPORT_SYMBOL_GPL(thermal_zone_get_trip);

int thermal_zone_set_trip(struct thermal_zone_device *tz, int trip_id,
			  const struct thermal_trip *trip)
{
	struct thermal_trip t;
	int ret;

	if (!tz->ops->set_trip_temp && !tz->ops->set_trip_hyst && !tz->trips)
		return -EINVAL;

	ret = __thermal_zone_get_trip(tz, trip_id, &t);
	if (ret)
		return ret;

	if (t.type != trip->type)
		return -EINVAL;

	if (t.temperature != trip->temperature && tz->ops->set_trip_temp) {
		ret = tz->ops->set_trip_temp(tz, trip_id, trip->temperature);
		if (ret)
			return ret;
	}

	if (t.hysteresis != trip->hysteresis && tz->ops->set_trip_hyst) {
		ret = tz->ops->set_trip_hyst(tz, trip_id, trip->hysteresis);
		if (ret)
			return ret;
	}

	if (tz->trips && (t.temperature != trip->temperature || t.hysteresis != trip->hysteresis))
		tz->trips[trip_id] = *trip;

	thermal_notify_tz_trip_change(tz->id, trip_id, trip->type,
				      trip->temperature, trip->hysteresis);

	__thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
	
	return 0;
}

/**
 * thermal_zone_device_register_with_trips() - register a new thermal zone device
 * @type:	the thermal zone device type
@@ -1349,6 +1255,9 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
	if (num_trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp) && !trips)
		return ERR_PTR(-EINVAL);

	if (!thermal_class)
		return ERR_PTR(-ENODEV);

	tz = kzalloc(sizeof(*tz), GFP_KERNEL);
	if (!tz)
		return ERR_PTR(-ENOMEM);
@@ -1370,7 +1279,7 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t

	tz->ops = ops;
	tz->tzp = tzp;
	tz->device.class = &thermal_class;
	tz->device.class = thermal_class;
	tz->devdata = devdata;
	tz->trips = trips;
	tz->num_trips = num_trips;
@@ -1613,11 +1522,23 @@ static int __init thermal_init(void)

	result = thermal_register_governors();
	if (result)
		goto error;
		goto unregister_netlink;

	result = class_register(&thermal_class);
	if (result)
	thermal_class = kzalloc(sizeof(*thermal_class), GFP_KERNEL);
	if (!thermal_class) {
		result = -ENOMEM;
		goto unregister_governors;
	}

	thermal_class->name = "thermal";
	thermal_class->dev_release = thermal_release;

	result = class_register(thermal_class);
	if (result) {
		kfree(thermal_class);
		thermal_class = NULL;
		goto unregister_governors;
	}

	result = register_pm_notifier(&thermal_pm_nb);
	if (result)
@@ -1628,9 +1549,9 @@ static int __init thermal_init(void)

unregister_governors:
	thermal_unregister_governors();
unregister_netlink:
	thermal_netlink_exit();
error:
	ida_destroy(&thermal_tz_ida);
	ida_destroy(&thermal_cdev_ida);
	mutex_destroy(&thermal_list_lock);
	mutex_destroy(&thermal_governor_lock);
	return result;
+4 −0
Original line number Diff line number Diff line
@@ -52,6 +52,10 @@ int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *,
int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *),
			      void *thermal_governor);

int __for_each_thermal_trip(struct thermal_zone_device *,
			    int (*cb)(struct thermal_trip *, void *),
			    void *);

struct thermal_zone_device *thermal_zone_get_by_id(int id);

struct thermal_attr {
+0 −62
Original line number Diff line number Diff line
@@ -146,68 +146,6 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
}
EXPORT_SYMBOL_GPL(thermal_zone_get_temp);

/**
 * __thermal_zone_set_trips - Computes the next trip points for the driver
 * @tz: a pointer to a thermal zone device structure
 *
 * The function computes the next temperature boundaries by browsing
 * the trip points. The result is the closer low and high trip points
 * to the current temperature. These values are passed to the backend
 * driver to let it set its own notification mechanism (usually an
 * interrupt).
 *
 * This function must be called with tz->lock held. Both tz and tz->ops
 * must be valid pointers.
 *
 * It does not return a value
 */
void __thermal_zone_set_trips(struct thermal_zone_device *tz)
{
	struct thermal_trip trip;
	int low = -INT_MAX, high = INT_MAX;
	int i, ret;

	lockdep_assert_held(&tz->lock);

	if (!tz->ops->set_trips)
		return;

	for (i = 0; i < tz->num_trips; i++) {
		int trip_low;

		ret = __thermal_zone_get_trip(tz, i , &trip);
		if (ret)
			return;

		trip_low = trip.temperature - trip.hysteresis;

		if (trip_low < tz->temperature && trip_low > low)
			low = trip_low;

		if (trip.temperature > tz->temperature &&
		    trip.temperature < high)
			high = trip.temperature;
	}

	/* No need to change trip points */
	if (tz->prev_low_trip == low && tz->prev_high_trip == high)
		return;

	tz->prev_low_trip = low;
	tz->prev_high_trip = high;

	dev_dbg(&tz->device,
		"new temperature boundaries: %d < x < %d\n", low, high);

	/*
	 * Set a temperature window. When this window is left the driver
	 * must inform the thermal core via thermal_zone_device_update.
	 */
	ret = tz->ops->set_trips(tz, low, high);
	if (ret)
		dev_err(&tz->device, "Failed to set trips: %d\n", ret);
}

static void thermal_cdev_set_cur_state(struct thermal_cooling_device *cdev,
				       int target)
{
+5 −0
Original line number Diff line number Diff line
@@ -699,3 +699,8 @@ int __init thermal_netlink_init(void)
{
	return genl_register_family(&thermal_gnl_family);
}

void __init thermal_netlink_exit(void)
{
	genl_unregister_family(&thermal_gnl_family);
}
Loading