drivers/powercap/intel_rapl_common.c

Source file repositories/reference/linux-study-clean/drivers/powercap/intel_rapl_common.c

File Facts

System
Linux kernel
Corpus path
drivers/powercap/intel_rapl_common.c
Extension
.c
Size
49491 bytes
Lines
1894
Domain
Driver Families
Bucket
drivers/powercap
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 rapl_pmu {
	struct pmu pmu;			/* Perf PMU structure */
	u64 timer_ms;			/* Maximum expiration time to avoid counter overflow */
	unsigned long domain_map;	/* Events supported by current registered PMU */
	bool registered;		/* Whether the PMU has been registered or not */
};

static struct rapl_pmu rapl_pmu;

/* PMU helpers */

static void set_pmu_cpumask(struct rapl_package *rp, cpumask_var_t mask)
{
	int cpu;

	if (!rp->has_pmu)
		return;

	/* Only TPMI & MSR RAPL are supported for now */
	if (rp->priv->type != RAPL_IF_TPMI && rp->priv->type != RAPL_IF_MSR)
		return;

	/* TPMI/MSR RAPL uses any CPU in the package for PMU */
	for_each_online_cpu(cpu)
		if (topology_physical_package_id(cpu) == rp->id)
			cpumask_set_cpu(cpu, mask);
}

static bool is_rp_pmu_cpu(struct rapl_package *rp, int cpu)
{
	if (!rp->has_pmu)
		return false;

	/* Only TPMI & MSR RAPL are supported for now */
	if (rp->priv->type != RAPL_IF_TPMI && rp->priv->type != RAPL_IF_MSR)
		return false;

	/* TPMI/MSR RAPL uses any CPU in the package for PMU */
	return topology_physical_package_id(cpu) == rp->id;
}

static struct rapl_package_pmu_data *event_to_pmu_data(struct perf_event *event)
{
	struct rapl_package *rp = event->pmu_private;

	return &rp->pmu_data;
}

/* PMU event callbacks */

static u64 event_read_counter(struct perf_event *event)
{
	struct rapl_package *rp = event->pmu_private;
	u64 val;
	int ret;

	/* Return 0 for unsupported events */
	if (event->hw.idx < 0)
		return 0;

	ret = rapl_read_data_raw(&rp->domains[event->hw.idx], ENERGY_COUNTER, false, &val, true);

	/* Return 0 for failed read */
	if (ret)
		return 0;

	return val;
}

static void __rapl_pmu_event_start(struct perf_event *event)
{
	struct rapl_package_pmu_data *data = event_to_pmu_data(event);

	if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
		return;

	event->hw.state = 0;

	list_add_tail(&event->active_entry, &data->active_list);

	local64_set(&event->hw.prev_count, event_read_counter(event));
	if (++data->n_active == 1)
		hrtimer_start(&data->hrtimer, data->timer_interval,
			      HRTIMER_MODE_REL_PINNED);
}

static void rapl_pmu_event_start(struct perf_event *event, int mode)
{
	struct rapl_package_pmu_data *data = event_to_pmu_data(event);
	unsigned long flags;

Annotation

Implementation Notes