drivers/thermal/devfreq_cooling.c

Source file repositories/reference/linux-study-clean/drivers/thermal/devfreq_cooling.c

File Facts

System
Linux kernel
Corpus path
drivers/thermal/devfreq_cooling.c
Extension
.c
Size
15024 bytes
Lines
577
Domain
Driver Families
Bucket
drivers/thermal
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct devfreq_cooling_device {
	struct thermal_cooling_device *cdev;
	struct thermal_cooling_device_ops cooling_ops;
	struct devfreq *devfreq;
	unsigned long cooling_state;
	u32 *freq_table;
	size_t max_state;
	struct devfreq_cooling_power *power_ops;
	u32 res_util;
	int capped_state;
	struct dev_pm_qos_request req_max_freq;
	struct em_perf_domain *em_pd;
};

static int devfreq_cooling_get_max_state(struct thermal_cooling_device *cdev,
					 unsigned long *state)
{
	struct devfreq_cooling_device *dfc = cdev->devdata;

	*state = dfc->max_state;

	return 0;
}

static int devfreq_cooling_get_cur_state(struct thermal_cooling_device *cdev,
					 unsigned long *state)
{
	struct devfreq_cooling_device *dfc = cdev->devdata;

	*state = dfc->cooling_state;

	return 0;
}

static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev,
					 unsigned long state)
{
	struct devfreq_cooling_device *dfc = cdev->devdata;
	struct devfreq *df = dfc->devfreq;
	struct device *dev = df->dev.parent;
	struct em_perf_state *table;
	unsigned long freq;
	int perf_idx;

	if (state == dfc->cooling_state)
		return 0;

	dev_dbg(dev, "Setting cooling state %lu\n", state);

	if (state > dfc->max_state)
		return -EINVAL;

	if (dfc->em_pd) {
		perf_idx = dfc->max_state - state;

		rcu_read_lock();
		table = em_perf_state_from_pd(dfc->em_pd);
		freq = table[perf_idx].frequency * 1000;
		rcu_read_unlock();
	} else {
		freq = dfc->freq_table[state];
	}

	dev_pm_qos_update_request(&dfc->req_max_freq,
				  DIV_ROUND_UP(freq, HZ_PER_KHZ));

	dfc->cooling_state = state;

	return 0;
}

/**
 * get_perf_idx() - get the performance index corresponding to a frequency
 * @em_pd:	Pointer to device's Energy Model
 * @freq:	frequency in kHz
 *
 * Return: the performance index associated with the @freq, or
 * -EINVAL if it wasn't found.
 */
static int get_perf_idx(struct em_perf_domain *em_pd, unsigned long freq)
{
	struct em_perf_state *table;
	int i, idx = -EINVAL;

	rcu_read_lock();
	table = em_perf_state_from_pd(em_pd);
	for (i = 0; i < em_pd->nr_perf_states; i++) {
		if (table[i].frequency != freq)
			continue;

Annotation

Implementation Notes