drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c

Source file repositories/reference/linux-study-clean/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
Extension
.c
Size
11058 bytes
Lines
352
Domain
Driver Families
Bucket
drivers/platform
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

if (data->agent_type_mask) {
			init_attribute_ro(agent_types);
			data->uncore_attrs[index++] = &data->agent_types_kobj_attr.attr;
		}
		if (topology_max_dies_per_package() > 1 &&
		    data->agent_type_mask & AGENT_TYPE_CORE) {
			init_attribute_ro(die_id);
			data->uncore_attrs[index++] = &data->die_id_kobj_attr.attr;
		}
	}

	data->uncore_attrs[index++] = &data->max_freq_khz_kobj_attr.attr;
	data->uncore_attrs[index++] = &data->min_freq_khz_kobj_attr.attr;
	data->uncore_attrs[index++] = &data->initial_min_freq_khz_kobj_attr.attr;
	data->uncore_attrs[index++] = &data->initial_max_freq_khz_kobj_attr.attr;

	ret = uncore_read(data, &val, UNCORE_INDEX_CURRENT_FREQ);
	if (!ret)
		data->uncore_attrs[index++] = &data->current_freq_khz_kobj_attr.attr;

	ret = uncore_read(data, &val, UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD);
	if (!ret) {
		init_attribute_rw(elc_low_threshold_percent);
		init_attribute_rw(elc_high_threshold_percent);
		init_attribute_rw(elc_high_threshold_enable);
		init_attribute_rw(elc_floor_freq_khz);

		data->uncore_attrs[index++] = &data->elc_low_threshold_percent_kobj_attr.attr;
		data->uncore_attrs[index++] = &data->elc_high_threshold_percent_kobj_attr.attr;
		data->uncore_attrs[index++] =
			&data->elc_high_threshold_enable_kobj_attr.attr;
		data->uncore_attrs[index++] = &data->elc_floor_freq_khz_kobj_attr.attr;
	}

	data->uncore_attrs[index] = NULL;

	data->uncore_attr_group.name = name;
	data->uncore_attr_group.attrs = data->uncore_attrs;
	ret = sysfs_create_group(uncore_root_kobj, &data->uncore_attr_group);

	return ret;
}

static void delete_attr_group(struct uncore_data *data, char *name)
{
	sysfs_remove_group(uncore_root_kobj, &data->uncore_attr_group);
}

int uncore_freq_add_entry(struct uncore_data *data, int cpu)
{
	int ret = 0;

	mutex_lock(&uncore_lock);
	if (data->valid) {
		/* control cpu changed */
		data->control_cpu = cpu;
		goto uncore_unlock;
	}

	if (data->domain_id != UNCORE_DOMAIN_ID_INVALID) {
		ret = ida_alloc(&intel_uncore_ida, GFP_KERNEL);
		if (ret < 0)
			goto uncore_unlock;

		data->instance_id = ret;
		scnprintf(data->name, sizeof(data->name), "uncore%02d", ret);
	} else {
		scnprintf(data->name, sizeof(data->name), "package_%02d_die_%02d",
			  data->package_id, data->die_id);
	}

	uncore_read(data, &data->initial_min_freq_khz, UNCORE_INDEX_MIN_FREQ);
	uncore_read(data, &data->initial_max_freq_khz, UNCORE_INDEX_MAX_FREQ);

	ret = create_attr_group(data, data->name);
	if (ret) {
		if (data->domain_id != UNCORE_DOMAIN_ID_INVALID)
			ida_free(&intel_uncore_ida, data->instance_id);
	} else {
		data->control_cpu = cpu;
		data->valid = true;
	}

uncore_unlock:
	mutex_unlock(&uncore_lock);

	return ret;
}
EXPORT_SYMBOL_NS_GPL(uncore_freq_add_entry, "INTEL_UNCORE_FREQUENCY");

Annotation

Implementation Notes