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

Merge branch 'thermal-core'

Merge thermal core updates for 6.12 which, among other things, rework
the thermal driver interface for binding cooling devices to thermal
zones and add a thermal core testing module:

 - Update some thermal drivers to eliminate thermal_zone_get_trip()
   calls from them and get rid of that function (Rafael Wysocki).

 - Update the thermal sysfs code to store trip point attributes in trip
   descriptors and get to trip points via attribute pointers (Rafael
   Wysocki).

 - Move the computation of the low and high boundaries for
   thermal_zone_set_trips() to __thermal_zone_device_update() (Daniel
   Lezcano).

 - Introduce a debugfs-based facility for thermal core testing (Rafael
   Wysocki).

 - Replace the thermal zone .bind() and .unbind() callbacks for binding
   cooling devices to thermal zones with one .should_bind() callback
   used for deciding whether or not a given cooling devices should be
   bound to a given trip point in a given thermal zone (Rafael Wysocki).

 - Eliminate code that has no more users after the other changes, drop
   some redundant checks from the thermal core and clean it up (Rafael
   Wysocki).

 - Fix rounding of delay jiffies in the thermal core (Rafael Wysocki).

* thermal-core: (31 commits)
  thermal: core: Drop tz field from struct thermal_instance
  thermal: core: Drop redundant checks from thermal_bind_cdev_to_trip()
  thermal: core: Rename cdev-to-thermal-zone bind/unbind functions
  thermal: core: Fix rounding of delay jiffies
  thermal: core: Clean up trip bind/unbind functions
  thermal: core: Drop unused bind/unbind functions and callbacks
  thermal/of: Use the .should_bind() thermal zone callback
  thermal: imx: Use the .should_bind() thermal zone callback
  mlxsw: core_thermal: Use the .should_bind() thermal zone callback
  platform/x86: acerhdf: Use the .should_bind() thermal zone callback
  thermal: core: Unexport thermal_bind_cdev_to_trip() and thermal_unbind_cdev_from_trip()
  thermal: ACPI: Use the .should_bind() thermal zone callback
  thermal: core: Introduce .should_bind() thermal zone callback
  thermal: core: Move thermal zone locking out of bind/unbind functions
  thermal: sysfs: Use the dev argument in instance-related show/store
  thermal: core: Drop redundant thermal instance checks
  thermal: core: Rearrange checks in thermal_bind_cdev_to_trip()
  thermal: core: Fold two functions into their respective callers
  thermal: Introduce a debugfs-based testing facility
  thermal/core: Compute low and high boundaries in thermal_zone_device_update()
  ...
parents c0a1ef9c e9654659
Loading
Loading
Loading
Loading
+4 −64
Original line number Diff line number Diff line
@@ -58,10 +58,9 @@ temperature) and throttle appropriate devices.
    ops:
	thermal zone device call-backs.

	.bind:
		bind the thermal zone device with a thermal cooling device.
	.unbind:
		unbind the thermal zone device with a thermal cooling device.
	.should_bind:
		check whether or not a given cooling device should be bound to
		a given trip point in this thermal zone.
	.get_temp:
		get the current temperature of the thermal zone.
	.set_trips:
@@ -246,56 +245,6 @@ temperature) and throttle appropriate devices.
    It deletes the corresponding entry from /sys/class/thermal folder and
    unbinds itself from all the thermal zone devices using it.

1.3 interface for binding a thermal zone device with a thermal cooling device
-----------------------------------------------------------------------------

    ::

	int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
		int trip, struct thermal_cooling_device *cdev,
		unsigned long upper, unsigned long lower, unsigned int weight);

    This interface function binds a thermal cooling device to a particular trip
    point of a thermal zone device.

    This function is usually called in the thermal zone device .bind callback.

    tz:
	  the thermal zone device
    cdev:
	  thermal cooling device
    trip:
	  indicates which trip point in this thermal zone the cooling device
	  is associated with.
    upper:
	  the Maximum cooling state for this trip point.
	  THERMAL_NO_LIMIT means no upper limit,
	  and the cooling device can be in max_state.
    lower:
	  the Minimum cooling state can be used for this trip point.
	  THERMAL_NO_LIMIT means no lower limit,
	  and the cooling device can be in cooling state 0.
    weight:
	  the influence of this cooling device in this thermal
	  zone.  See 1.4.1 below for more information.

    ::

	int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
				int trip, struct thermal_cooling_device *cdev);

    This interface function unbinds a thermal cooling device from a particular
    trip point of a thermal zone device. This function is usually called in
    the thermal zone device .unbind callback.

    tz:
	the thermal zone device
    cdev:
	thermal cooling device
    trip:
	indicates which trip point in this thermal zone the cooling device
	is associated with.

1.4 Thermal Zone Parameters
---------------------------

@@ -366,8 +315,6 @@ Thermal cooling device sys I/F, created once it's registered::

Then next two dynamic attributes are created/removed in pairs. They represent
the relationship between a thermal zone and its associated cooling device.
They are created/removed for each successful execution of
thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device.

::

@@ -459,14 +406,7 @@ are supposed to implement the callback. If they don't, the thermal
framework calculated the trend by comparing the previous and the current
temperature values.

4.2. get_thermal_instance
-------------------------

This function returns the thermal_instance corresponding to a given
{thermal_zone, cooling_device, trip_point} combination. Returns NULL
if such an instance does not exist.

4.3. thermal_cdev_update
4.2. thermal_cdev_update
------------------------

This function serves as an arbitrator to set the state of a cooling
+10 −56
Original line number Diff line number Diff line
@@ -558,77 +558,31 @@ static void acpi_thermal_zone_device_critical(struct thermal_zone_device *therma
	thermal_zone_device_critical(thermal);
}

struct acpi_thermal_bind_data {
	struct thermal_zone_device *thermal;
	struct thermal_cooling_device *cdev;
	bool bind;
};

static int bind_unbind_cdev_cb(struct thermal_trip *trip, void *arg)
static bool acpi_thermal_should_bind_cdev(struct thermal_zone_device *thermal,
					  const struct thermal_trip *trip,
					  struct thermal_cooling_device *cdev,
					  struct cooling_spec *c)
{
	struct acpi_thermal_trip *acpi_trip = trip->priv;
	struct acpi_thermal_bind_data *bd = arg;
	struct thermal_zone_device *thermal = bd->thermal;
	struct thermal_cooling_device *cdev = bd->cdev;
	struct acpi_device *cdev_adev = cdev->devdata;
	int i;

	/* Skip critical and hot trips. */
	if (!acpi_trip)
		return 0;
		return false;

	for (i = 0; i < acpi_trip->devices.count; i++) {
		acpi_handle handle = acpi_trip->devices.handles[i];
		struct acpi_device *adev = acpi_fetch_acpi_dev(handle);

		if (adev != cdev_adev)
			continue;

		if (bd->bind) {
			int ret;

			ret = thermal_bind_cdev_to_trip(thermal, trip, cdev,
							THERMAL_NO_LIMIT,
							THERMAL_NO_LIMIT,
							THERMAL_WEIGHT_DEFAULT);
			if (ret)
				return ret;
		} else {
			thermal_unbind_cdev_from_trip(thermal, trip, cdev);
		}
	}

	return 0;
}

static int acpi_thermal_bind_unbind_cdev(struct thermal_zone_device *thermal,
					 struct thermal_cooling_device *cdev,
					 bool bind)
{
	struct acpi_thermal_bind_data bd = {
		.thermal = thermal, .cdev = cdev, .bind = bind
	};

	return for_each_thermal_trip(thermal, bind_unbind_cdev_cb, &bd);
}

static int
acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
				 struct thermal_cooling_device *cdev)
{
	return acpi_thermal_bind_unbind_cdev(thermal, cdev, true);
		if (acpi_fetch_acpi_dev(handle) == cdev_adev)
			return true;
	}

static int
acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
				   struct thermal_cooling_device *cdev)
{
	return acpi_thermal_bind_unbind_cdev(thermal, cdev, false);
	return false;
}

static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
	.bind = acpi_thermal_bind_cooling_device,
	.unbind	= acpi_thermal_unbind_cooling_device,
	.should_bind = acpi_thermal_should_bind_cdev,
	.get_temp = thermal_get_temp,
	.get_trend = thermal_get_trend,
	.hot = acpi_thermal_zone_device_hot,
+31 −84
Original line number Diff line number Diff line
@@ -165,52 +165,22 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
	return -ENODEV;
}

static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
			      struct thermal_cooling_device *cdev)
static bool mlxsw_thermal_should_bind(struct thermal_zone_device *tzdev,
				      const struct thermal_trip *trip,
				      struct thermal_cooling_device *cdev,
				      struct cooling_spec *c)
{
	struct mlxsw_thermal *thermal = thermal_zone_device_priv(tzdev);
	struct device *dev = thermal->bus_info->dev;
	int i, err;
	const struct mlxsw_cooling_states *state = trip->priv;

	/* If the cooling device is one of ours bind it */
	if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
		return 0;

	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
		const struct mlxsw_cooling_states *state = &thermal->cooling_states[i];

		err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
						       state->max_state,
						       state->min_state,
						       THERMAL_WEIGHT_DEFAULT);
		if (err < 0) {
			dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
			return err;
		}
	}
	return 0;
}

static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
				struct thermal_cooling_device *cdev)
{
	struct mlxsw_thermal *thermal = thermal_zone_device_priv(tzdev);
	struct device *dev = thermal->bus_info->dev;
	int i;
	int err;
		return false;

	/* If the cooling device is our one unbind it */
	if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
		return 0;
	c->upper = state->max_state;
	c->lower = state->min_state;

	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
		err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
		if (err < 0) {
			dev_err(dev, "Failed to unbind cooling device\n");
			return err;
		}
	}
	return 0;
	return true;
}

static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
@@ -240,57 +210,27 @@ static struct thermal_zone_params mlxsw_thermal_params = {
};

static struct thermal_zone_device_ops mlxsw_thermal_ops = {
	.bind = mlxsw_thermal_bind,
	.unbind = mlxsw_thermal_unbind,
	.should_bind = mlxsw_thermal_should_bind,
	.get_temp = mlxsw_thermal_get_temp,
};

static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
				     struct thermal_cooling_device *cdev)
static bool mlxsw_thermal_module_should_bind(struct thermal_zone_device *tzdev,
					     const struct thermal_trip *trip,
					     struct thermal_cooling_device *cdev,
					     struct cooling_spec *c)
{
	struct mlxsw_thermal_module *tz = thermal_zone_device_priv(tzdev);
	const struct mlxsw_cooling_states *state = trip->priv;
	struct mlxsw_thermal *thermal = tz->parent;
	int i, j, err;

	/* If the cooling device is one of ours bind it */
	if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
		return 0;

	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
		const struct mlxsw_cooling_states *state = &tz->cooling_states[i];

		err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
						       state->max_state,
						       state->min_state,
						       THERMAL_WEIGHT_DEFAULT);
		if (err < 0)
			goto err_thermal_zone_bind_cooling_device;
	}
	return 0;

err_thermal_zone_bind_cooling_device:
	for (j = i - 1; j >= 0; j--)
		thermal_zone_unbind_cooling_device(tzdev, j, cdev);
	return err;
}

static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
				       struct thermal_cooling_device *cdev)
{
	struct mlxsw_thermal_module *tz = thermal_zone_device_priv(tzdev);
	struct mlxsw_thermal *thermal = tz->parent;
	int i;
	int err;
		return false;

	/* If the cooling device is one of ours unbind it */
	if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
		return 0;
	c->upper = state->max_state;
	c->lower = state->min_state;

	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
		err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
		WARN_ON(err);
	}
	return err;
	return true;
}

static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
@@ -313,8 +253,7 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
}

static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
	.bind		= mlxsw_thermal_module_bind,
	.unbind		= mlxsw_thermal_module_unbind,
	.should_bind	= mlxsw_thermal_module_should_bind,
	.get_temp	= mlxsw_thermal_module_temp_get,
};

@@ -342,8 +281,7 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
}

static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
	.bind		= mlxsw_thermal_module_bind,
	.unbind		= mlxsw_thermal_module_unbind,
	.should_bind	= mlxsw_thermal_module_should_bind,
	.get_temp	= mlxsw_thermal_gearbox_temp_get,
};

@@ -451,6 +389,7 @@ mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
			  struct mlxsw_thermal_area *area, u8 module)
{
	struct mlxsw_thermal_module *module_tz;
	int i;

	module_tz = &area->tz_module_arr[module];
	/* Skip if parent is already set (case of port split). */
@@ -465,6 +404,8 @@ mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
	       sizeof(thermal->trips));
	memcpy(module_tz->cooling_states, default_cooling_states,
	       sizeof(thermal->cooling_states));
	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++)
		module_tz->trips[i].priv = &module_tz->cooling_states[i];
}

static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
@@ -579,7 +520,7 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
	struct mlxsw_thermal_module *gearbox_tz;
	char mgpir_pl[MLXSW_REG_MGPIR_LEN];
	u8 gbox_num;
	int i;
	int i, j;
	int err;

	mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
@@ -606,6 +547,9 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
		       sizeof(thermal->trips));
		memcpy(gearbox_tz->cooling_states, default_cooling_states,
		       sizeof(thermal->cooling_states));
		for (j = 0; j < MLXSW_THERMAL_NUM_TRIPS; j++)
			gearbox_tz->trips[j].priv = &gearbox_tz->cooling_states[j];

		gearbox_tz->module = i;
		gearbox_tz->parent = thermal;
		gearbox_tz->slot_index = area->slot_index;
@@ -722,6 +666,9 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
	thermal->bus_info = bus_info;
	memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
	memcpy(thermal->cooling_states, default_cooling_states, sizeof(thermal->cooling_states));
	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++)
		thermal->trips[i].priv = &thermal->cooling_states[i];

	thermal->line_cards[0].slot_index = 0;

	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
+6 −27
Original line number Diff line number Diff line
@@ -378,33 +378,13 @@ static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal, int *t)
	return 0;
}

static int acerhdf_bind(struct thermal_zone_device *thermal,
			struct thermal_cooling_device *cdev)
static bool acerhdf_should_bind(struct thermal_zone_device *thermal,
				const struct thermal_trip *trip,
				struct thermal_cooling_device *cdev,
				struct cooling_spec *c)
{
	/* if the cooling device is the one from acerhdf bind it */
	if (cdev != cl_dev)
		return 0;

	if (thermal_zone_bind_cooling_device(thermal, 0, cdev,
			THERMAL_NO_LIMIT, THERMAL_NO_LIMIT,
			THERMAL_WEIGHT_DEFAULT)) {
		pr_err("error binding cooling dev\n");
		return -EINVAL;
	}
	return 0;
}

static int acerhdf_unbind(struct thermal_zone_device *thermal,
			  struct thermal_cooling_device *cdev)
{
	if (cdev != cl_dev)
		return 0;

	if (thermal_zone_unbind_cooling_device(thermal, 0, cdev)) {
		pr_err("error unbinding cooling dev\n");
		return -EINVAL;
	}
	return 0;
	return cdev == cl_dev && trip->type == THERMAL_TRIP_ACTIVE;
}

static inline void acerhdf_revert_to_bios_mode(void)
@@ -447,8 +427,7 @@ static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal,

/* bind callback functions to thermalzone */
static struct thermal_zone_device_ops acerhdf_dev_ops = {
	.bind = acerhdf_bind,
	.unbind = acerhdf_unbind,
	.should_bind = acerhdf_should_bind,
	.get_temp = acerhdf_get_ec_temp,
	.change_mode = acerhdf_change_mode,
	.get_crit_temp = acerhdf_get_crit_temp,
+9 −0
Original line number Diff line number Diff line
@@ -40,6 +40,15 @@ config THERMAL_DEBUGFS
	  Say Y to allow the thermal subsystem to collect diagnostic
	  information that can be accessed via debugfs.

config THERMAL_CORE_TESTING
	tristate "Thermal core testing facility"
	depends on DEBUG_FS
	help
	  Say Y to add a debugfs-based thermal core testing facility.
	  It allows test thermal zones to be created and populated
	  with trip points in order to exercise the thermal core
	  functionality in a controlled way.

config THERMAL_EMERGENCY_POWEROFF_DELAY_MS
	int "Emergency poweroff delay in milli-seconds"
	default 0
Loading