cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

powercap_sys.c (18817B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Power capping class
      4 * Copyright (c) 2013, Intel Corporation.
      5 */
      6
      7#include <linux/module.h>
      8#include <linux/device.h>
      9#include <linux/err.h>
     10#include <linux/slab.h>
     11#include <linux/powercap.h>
     12
     13#define to_powercap_zone(n) container_of(n, struct powercap_zone, dev)
     14#define to_powercap_control_type(n) \
     15			container_of(n, struct powercap_control_type, dev)
     16
     17/* Power zone show function */
     18#define define_power_zone_show(_attr)		\
     19static ssize_t _attr##_show(struct device *dev, \
     20					struct device_attribute *dev_attr,\
     21					char *buf) \
     22{ \
     23	u64 value; \
     24	ssize_t len = -EINVAL; \
     25	struct powercap_zone *power_zone = to_powercap_zone(dev); \
     26	\
     27	if (power_zone->ops->get_##_attr) { \
     28		if (!power_zone->ops->get_##_attr(power_zone, &value)) \
     29			len = sprintf(buf, "%lld\n", value); \
     30	} \
     31	\
     32	return len; \
     33}
     34
     35/* The only meaningful input is 0 (reset), others are silently ignored */
     36#define define_power_zone_store(_attr)		\
     37static ssize_t _attr##_store(struct device *dev,\
     38				struct device_attribute *dev_attr, \
     39				const char *buf, size_t count) \
     40{ \
     41	int err; \
     42	struct powercap_zone *power_zone = to_powercap_zone(dev); \
     43	u64 value; \
     44	\
     45	err = kstrtoull(buf, 10, &value); \
     46	if (err) \
     47		return -EINVAL; \
     48	if (value) \
     49		return count; \
     50	if (power_zone->ops->reset_##_attr) { \
     51		if (!power_zone->ops->reset_##_attr(power_zone)) \
     52			return count; \
     53	} \
     54	\
     55	return -EINVAL; \
     56}
     57
     58/* Power zone constraint show function */
     59#define define_power_zone_constraint_show(_attr) \
     60static ssize_t show_constraint_##_attr(struct device *dev, \
     61				struct device_attribute *dev_attr,\
     62				char *buf) \
     63{ \
     64	u64 value; \
     65	ssize_t len = -ENODATA; \
     66	struct powercap_zone *power_zone = to_powercap_zone(dev); \
     67	int id; \
     68	struct powercap_zone_constraint *pconst;\
     69	\
     70	if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \
     71		return -EINVAL; \
     72	if (id >= power_zone->const_id_cnt)	\
     73		return -EINVAL; \
     74	pconst = &power_zone->constraints[id]; \
     75	if (pconst && pconst->ops && pconst->ops->get_##_attr) { \
     76		if (!pconst->ops->get_##_attr(power_zone, id, &value)) \
     77			len = sprintf(buf, "%lld\n", value); \
     78	} \
     79	\
     80	return len; \
     81}
     82
     83/* Power zone constraint store function */
     84#define define_power_zone_constraint_store(_attr) \
     85static ssize_t store_constraint_##_attr(struct device *dev,\
     86				struct device_attribute *dev_attr, \
     87				const char *buf, size_t count) \
     88{ \
     89	int err; \
     90	u64 value; \
     91	struct powercap_zone *power_zone = to_powercap_zone(dev); \
     92	int id; \
     93	struct powercap_zone_constraint *pconst;\
     94	\
     95	if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \
     96		return -EINVAL; \
     97	if (id >= power_zone->const_id_cnt)	\
     98		return -EINVAL; \
     99	pconst = &power_zone->constraints[id]; \
    100	err = kstrtoull(buf, 10, &value); \
    101	if (err) \
    102		return -EINVAL; \
    103	if (pconst && pconst->ops && pconst->ops->set_##_attr) { \
    104		if (!pconst->ops->set_##_attr(power_zone, id, value)) \
    105			return count; \
    106	} \
    107	\
    108	return -ENODATA; \
    109}
    110
    111/* Power zone information callbacks */
    112define_power_zone_show(power_uw);
    113define_power_zone_show(max_power_range_uw);
    114define_power_zone_show(energy_uj);
    115define_power_zone_store(energy_uj);
    116define_power_zone_show(max_energy_range_uj);
    117
    118/* Power zone attributes */
    119static DEVICE_ATTR_RO(max_power_range_uw);
    120static DEVICE_ATTR_RO(power_uw);
    121static DEVICE_ATTR_RO(max_energy_range_uj);
    122static DEVICE_ATTR_RW(energy_uj);
    123
    124/* Power zone constraint attributes callbacks */
    125define_power_zone_constraint_show(power_limit_uw);
    126define_power_zone_constraint_store(power_limit_uw);
    127define_power_zone_constraint_show(time_window_us);
    128define_power_zone_constraint_store(time_window_us);
    129define_power_zone_constraint_show(max_power_uw);
    130define_power_zone_constraint_show(min_power_uw);
    131define_power_zone_constraint_show(max_time_window_us);
    132define_power_zone_constraint_show(min_time_window_us);
    133
    134/* For one time seeding of constraint device attributes */
    135struct powercap_constraint_attr {
    136	struct device_attribute power_limit_attr;
    137	struct device_attribute time_window_attr;
    138	struct device_attribute max_power_attr;
    139	struct device_attribute min_power_attr;
    140	struct device_attribute max_time_window_attr;
    141	struct device_attribute min_time_window_attr;
    142	struct device_attribute name_attr;
    143};
    144
    145static struct powercap_constraint_attr
    146				constraint_attrs[MAX_CONSTRAINTS_PER_ZONE];
    147
    148/* A list of powercap control_types */
    149static LIST_HEAD(powercap_cntrl_list);
    150/* Mutex to protect list of powercap control_types */
    151static DEFINE_MUTEX(powercap_cntrl_list_lock);
    152
    153#define POWERCAP_CONSTRAINT_NAME_LEN	30 /* Some limit to avoid overflow */
    154static ssize_t show_constraint_name(struct device *dev,
    155				struct device_attribute *dev_attr,
    156				char *buf)
    157{
    158	const char *name;
    159	struct powercap_zone *power_zone = to_powercap_zone(dev);
    160	int id;
    161	ssize_t len = -ENODATA;
    162	struct powercap_zone_constraint *pconst;
    163
    164	if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id))
    165		return -EINVAL;
    166	if (id >= power_zone->const_id_cnt)
    167		return -EINVAL;
    168	pconst = &power_zone->constraints[id];
    169
    170	if (pconst && pconst->ops && pconst->ops->get_name) {
    171		name = pconst->ops->get_name(power_zone, id);
    172		if (name) {
    173			sprintf(buf, "%.*s\n", POWERCAP_CONSTRAINT_NAME_LEN - 1,
    174				name);
    175			len = strlen(buf);
    176		}
    177	}
    178
    179	return len;
    180}
    181
    182static int create_constraint_attribute(int id, const char *name,
    183				int mode,
    184				struct device_attribute *dev_attr,
    185				ssize_t (*show)(struct device *,
    186					struct device_attribute *, char *),
    187				ssize_t (*store)(struct device *,
    188					struct device_attribute *,
    189				const char *, size_t)
    190				)
    191{
    192
    193	dev_attr->attr.name = kasprintf(GFP_KERNEL, "constraint_%d_%s",
    194								id, name);
    195	if (!dev_attr->attr.name)
    196		return -ENOMEM;
    197	dev_attr->attr.mode = mode;
    198	dev_attr->show = show;
    199	dev_attr->store = store;
    200
    201	return 0;
    202}
    203
    204static void free_constraint_attributes(void)
    205{
    206	int i;
    207
    208	for (i = 0; i < MAX_CONSTRAINTS_PER_ZONE; ++i) {
    209		kfree(constraint_attrs[i].power_limit_attr.attr.name);
    210		kfree(constraint_attrs[i].time_window_attr.attr.name);
    211		kfree(constraint_attrs[i].name_attr.attr.name);
    212		kfree(constraint_attrs[i].max_power_attr.attr.name);
    213		kfree(constraint_attrs[i].min_power_attr.attr.name);
    214		kfree(constraint_attrs[i].max_time_window_attr.attr.name);
    215		kfree(constraint_attrs[i].min_time_window_attr.attr.name);
    216	}
    217}
    218
    219static int seed_constraint_attributes(void)
    220{
    221	int i;
    222	int ret;
    223
    224	for (i = 0; i < MAX_CONSTRAINTS_PER_ZONE; ++i) {
    225		ret = create_constraint_attribute(i, "power_limit_uw",
    226					S_IWUSR | S_IRUGO,
    227					&constraint_attrs[i].power_limit_attr,
    228					show_constraint_power_limit_uw,
    229					store_constraint_power_limit_uw);
    230		if (ret)
    231			goto err_alloc;
    232		ret = create_constraint_attribute(i, "time_window_us",
    233					S_IWUSR | S_IRUGO,
    234					&constraint_attrs[i].time_window_attr,
    235					show_constraint_time_window_us,
    236					store_constraint_time_window_us);
    237		if (ret)
    238			goto err_alloc;
    239		ret = create_constraint_attribute(i, "name", S_IRUGO,
    240				&constraint_attrs[i].name_attr,
    241				show_constraint_name,
    242				NULL);
    243		if (ret)
    244			goto err_alloc;
    245		ret = create_constraint_attribute(i, "max_power_uw", S_IRUGO,
    246				&constraint_attrs[i].max_power_attr,
    247				show_constraint_max_power_uw,
    248				NULL);
    249		if (ret)
    250			goto err_alloc;
    251		ret = create_constraint_attribute(i, "min_power_uw", S_IRUGO,
    252				&constraint_attrs[i].min_power_attr,
    253				show_constraint_min_power_uw,
    254				NULL);
    255		if (ret)
    256			goto err_alloc;
    257		ret = create_constraint_attribute(i, "max_time_window_us",
    258				S_IRUGO,
    259				&constraint_attrs[i].max_time_window_attr,
    260				show_constraint_max_time_window_us,
    261				NULL);
    262		if (ret)
    263			goto err_alloc;
    264		ret = create_constraint_attribute(i, "min_time_window_us",
    265				S_IRUGO,
    266				&constraint_attrs[i].min_time_window_attr,
    267				show_constraint_min_time_window_us,
    268				NULL);
    269		if (ret)
    270			goto err_alloc;
    271
    272	}
    273
    274	return 0;
    275
    276err_alloc:
    277	free_constraint_attributes();
    278
    279	return ret;
    280}
    281
    282static int create_constraints(struct powercap_zone *power_zone,
    283			int nr_constraints,
    284			const struct powercap_zone_constraint_ops *const_ops)
    285{
    286	int i;
    287	int ret = 0;
    288	int count;
    289	struct powercap_zone_constraint *pconst;
    290
    291	if (!power_zone || !const_ops || !const_ops->get_power_limit_uw ||
    292					!const_ops->set_power_limit_uw ||
    293					!const_ops->get_time_window_us ||
    294					!const_ops->set_time_window_us)
    295		return -EINVAL;
    296
    297	count = power_zone->zone_attr_count;
    298	for (i = 0; i < nr_constraints; ++i) {
    299		pconst = &power_zone->constraints[i];
    300		pconst->ops = const_ops;
    301		pconst->id = power_zone->const_id_cnt;
    302		power_zone->const_id_cnt++;
    303		power_zone->zone_dev_attrs[count++] =
    304				&constraint_attrs[i].power_limit_attr.attr;
    305		power_zone->zone_dev_attrs[count++] =
    306				&constraint_attrs[i].time_window_attr.attr;
    307		if (pconst->ops->get_name)
    308			power_zone->zone_dev_attrs[count++] =
    309				&constraint_attrs[i].name_attr.attr;
    310		if (pconst->ops->get_max_power_uw)
    311			power_zone->zone_dev_attrs[count++] =
    312				&constraint_attrs[i].max_power_attr.attr;
    313		if (pconst->ops->get_min_power_uw)
    314			power_zone->zone_dev_attrs[count++] =
    315				&constraint_attrs[i].min_power_attr.attr;
    316		if (pconst->ops->get_max_time_window_us)
    317			power_zone->zone_dev_attrs[count++] =
    318				&constraint_attrs[i].max_time_window_attr.attr;
    319		if (pconst->ops->get_min_time_window_us)
    320			power_zone->zone_dev_attrs[count++] =
    321				&constraint_attrs[i].min_time_window_attr.attr;
    322	}
    323	power_zone->zone_attr_count = count;
    324
    325	return ret;
    326}
    327
    328static bool control_type_valid(void *control_type)
    329{
    330	struct powercap_control_type *pos = NULL;
    331	bool found = false;
    332
    333	mutex_lock(&powercap_cntrl_list_lock);
    334
    335	list_for_each_entry(pos, &powercap_cntrl_list, node) {
    336		if (pos == control_type) {
    337			found = true;
    338			break;
    339		}
    340	}
    341	mutex_unlock(&powercap_cntrl_list_lock);
    342
    343	return found;
    344}
    345
    346static ssize_t name_show(struct device *dev,
    347				struct device_attribute *attr,
    348				char *buf)
    349{
    350	struct powercap_zone *power_zone = to_powercap_zone(dev);
    351
    352	return sprintf(buf, "%s\n", power_zone->name);
    353}
    354
    355static DEVICE_ATTR_RO(name);
    356
    357/* Create zone and attributes in sysfs */
    358static void create_power_zone_common_attributes(
    359					struct powercap_zone *power_zone)
    360{
    361	int count = 0;
    362
    363	power_zone->zone_dev_attrs[count++] = &dev_attr_name.attr;
    364	if (power_zone->ops->get_max_energy_range_uj)
    365		power_zone->zone_dev_attrs[count++] =
    366					&dev_attr_max_energy_range_uj.attr;
    367	if (power_zone->ops->get_energy_uj) {
    368		if (power_zone->ops->reset_energy_uj)
    369			dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUSR;
    370		else
    371			dev_attr_energy_uj.attr.mode = S_IRUSR;
    372		power_zone->zone_dev_attrs[count++] =
    373					&dev_attr_energy_uj.attr;
    374	}
    375	if (power_zone->ops->get_power_uw)
    376		power_zone->zone_dev_attrs[count++] =
    377					&dev_attr_power_uw.attr;
    378	if (power_zone->ops->get_max_power_range_uw)
    379		power_zone->zone_dev_attrs[count++] =
    380					&dev_attr_max_power_range_uw.attr;
    381	power_zone->zone_dev_attrs[count] = NULL;
    382	power_zone->zone_attr_count = count;
    383}
    384
    385static void powercap_release(struct device *dev)
    386{
    387	bool allocated;
    388
    389	if (dev->parent) {
    390		struct powercap_zone *power_zone = to_powercap_zone(dev);
    391
    392		/* Store flag as the release() may free memory */
    393		allocated = power_zone->allocated;
    394		/* Remove id from parent idr struct */
    395		idr_remove(power_zone->parent_idr, power_zone->id);
    396		/* Destroy idrs allocated for this zone */
    397		idr_destroy(&power_zone->idr);
    398		kfree(power_zone->name);
    399		kfree(power_zone->zone_dev_attrs);
    400		kfree(power_zone->constraints);
    401		if (power_zone->ops->release)
    402			power_zone->ops->release(power_zone);
    403		if (allocated)
    404			kfree(power_zone);
    405	} else {
    406		struct powercap_control_type *control_type =
    407						to_powercap_control_type(dev);
    408
    409		/* Store flag as the release() may free memory */
    410		allocated = control_type->allocated;
    411		idr_destroy(&control_type->idr);
    412		mutex_destroy(&control_type->lock);
    413		if (control_type->ops && control_type->ops->release)
    414			control_type->ops->release(control_type);
    415		if (allocated)
    416			kfree(control_type);
    417	}
    418}
    419
    420static ssize_t enabled_show(struct device *dev,
    421				struct device_attribute *attr,
    422				char *buf)
    423{
    424	bool mode = true;
    425
    426	/* Default is enabled */
    427	if (dev->parent) {
    428		struct powercap_zone *power_zone = to_powercap_zone(dev);
    429		if (power_zone->ops->get_enable)
    430			if (power_zone->ops->get_enable(power_zone, &mode))
    431				mode = false;
    432	} else {
    433		struct powercap_control_type *control_type =
    434						to_powercap_control_type(dev);
    435		if (control_type->ops && control_type->ops->get_enable)
    436			if (control_type->ops->get_enable(control_type, &mode))
    437				mode = false;
    438	}
    439
    440	return sprintf(buf, "%d\n", mode);
    441}
    442
    443static ssize_t enabled_store(struct device *dev,
    444				struct device_attribute *attr,
    445				const char *buf,  size_t len)
    446{
    447	bool mode;
    448
    449	if (strtobool(buf, &mode))
    450		return -EINVAL;
    451	if (dev->parent) {
    452		struct powercap_zone *power_zone = to_powercap_zone(dev);
    453		if (power_zone->ops->set_enable)
    454			if (!power_zone->ops->set_enable(power_zone, mode))
    455				return len;
    456	} else {
    457		struct powercap_control_type *control_type =
    458						to_powercap_control_type(dev);
    459		if (control_type->ops && control_type->ops->set_enable)
    460			if (!control_type->ops->set_enable(control_type, mode))
    461				return len;
    462	}
    463
    464	return -ENOSYS;
    465}
    466
    467static DEVICE_ATTR_RW(enabled);
    468
    469static struct attribute *powercap_attrs[] = {
    470	&dev_attr_enabled.attr,
    471	NULL,
    472};
    473ATTRIBUTE_GROUPS(powercap);
    474
    475static struct class powercap_class = {
    476	.name = "powercap",
    477	.dev_release = powercap_release,
    478	.dev_groups = powercap_groups,
    479};
    480
    481struct powercap_zone *powercap_register_zone(
    482			struct powercap_zone *power_zone,
    483			struct powercap_control_type *control_type,
    484			const char *name,
    485			struct powercap_zone *parent,
    486			const struct powercap_zone_ops *ops,
    487			int nr_constraints,
    488			const struct powercap_zone_constraint_ops *const_ops)
    489{
    490	int result;
    491	int nr_attrs;
    492
    493	if (!name || !control_type || !ops ||
    494			nr_constraints > MAX_CONSTRAINTS_PER_ZONE ||
    495			(!ops->get_energy_uj && !ops->get_power_uw) ||
    496			!control_type_valid(control_type))
    497		return ERR_PTR(-EINVAL);
    498
    499	if (power_zone) {
    500		if (!ops->release)
    501			return ERR_PTR(-EINVAL);
    502		memset(power_zone, 0, sizeof(*power_zone));
    503	} else {
    504		power_zone = kzalloc(sizeof(*power_zone), GFP_KERNEL);
    505		if (!power_zone)
    506			return ERR_PTR(-ENOMEM);
    507		power_zone->allocated = true;
    508	}
    509	power_zone->ops = ops;
    510	power_zone->control_type_inst = control_type;
    511	if (!parent) {
    512		power_zone->dev.parent = &control_type->dev;
    513		power_zone->parent_idr = &control_type->idr;
    514	} else {
    515		power_zone->dev.parent = &parent->dev;
    516		power_zone->parent_idr = &parent->idr;
    517	}
    518	power_zone->dev.class = &powercap_class;
    519
    520	mutex_lock(&control_type->lock);
    521	/* Using idr to get the unique id */
    522	result = idr_alloc(power_zone->parent_idr, NULL, 0, 0, GFP_KERNEL);
    523	if (result < 0)
    524		goto err_idr_alloc;
    525
    526	power_zone->id = result;
    527	idr_init(&power_zone->idr);
    528	result = -ENOMEM;
    529	power_zone->name = kstrdup(name, GFP_KERNEL);
    530	if (!power_zone->name)
    531		goto err_name_alloc;
    532	dev_set_name(&power_zone->dev, "%s:%x",
    533					dev_name(power_zone->dev.parent),
    534					power_zone->id);
    535	power_zone->constraints = kcalloc(nr_constraints,
    536					  sizeof(*power_zone->constraints),
    537					  GFP_KERNEL);
    538	if (!power_zone->constraints)
    539		goto err_const_alloc;
    540
    541	nr_attrs = nr_constraints * POWERCAP_CONSTRAINTS_ATTRS +
    542						POWERCAP_ZONE_MAX_ATTRS + 1;
    543	power_zone->zone_dev_attrs = kcalloc(nr_attrs, sizeof(void *),
    544					     GFP_KERNEL);
    545	if (!power_zone->zone_dev_attrs)
    546		goto err_attr_alloc;
    547	create_power_zone_common_attributes(power_zone);
    548	result = create_constraints(power_zone, nr_constraints, const_ops);
    549	if (result)
    550		goto err_dev_ret;
    551
    552	power_zone->zone_dev_attrs[power_zone->zone_attr_count] = NULL;
    553	power_zone->dev_zone_attr_group.attrs = power_zone->zone_dev_attrs;
    554	power_zone->dev_attr_groups[0] = &power_zone->dev_zone_attr_group;
    555	power_zone->dev_attr_groups[1] = NULL;
    556	power_zone->dev.groups = power_zone->dev_attr_groups;
    557	result = device_register(&power_zone->dev);
    558	if (result)
    559		goto err_dev_ret;
    560
    561	control_type->nr_zones++;
    562	mutex_unlock(&control_type->lock);
    563
    564	return power_zone;
    565
    566err_dev_ret:
    567	kfree(power_zone->zone_dev_attrs);
    568err_attr_alloc:
    569	kfree(power_zone->constraints);
    570err_const_alloc:
    571	kfree(power_zone->name);
    572err_name_alloc:
    573	idr_remove(power_zone->parent_idr, power_zone->id);
    574err_idr_alloc:
    575	if (power_zone->allocated)
    576		kfree(power_zone);
    577	mutex_unlock(&control_type->lock);
    578
    579	return ERR_PTR(result);
    580}
    581EXPORT_SYMBOL_GPL(powercap_register_zone);
    582
    583int powercap_unregister_zone(struct powercap_control_type *control_type,
    584				struct powercap_zone *power_zone)
    585{
    586	if (!power_zone || !control_type)
    587		return -EINVAL;
    588
    589	mutex_lock(&control_type->lock);
    590	control_type->nr_zones--;
    591	mutex_unlock(&control_type->lock);
    592
    593	device_unregister(&power_zone->dev);
    594
    595	return 0;
    596}
    597EXPORT_SYMBOL_GPL(powercap_unregister_zone);
    598
    599struct powercap_control_type *powercap_register_control_type(
    600				struct powercap_control_type *control_type,
    601				const char *name,
    602				const struct powercap_control_type_ops *ops)
    603{
    604	int result;
    605
    606	if (!name)
    607		return ERR_PTR(-EINVAL);
    608	if (control_type) {
    609		if (!ops || !ops->release)
    610			return ERR_PTR(-EINVAL);
    611		memset(control_type, 0, sizeof(*control_type));
    612	} else {
    613		control_type = kzalloc(sizeof(*control_type), GFP_KERNEL);
    614		if (!control_type)
    615			return ERR_PTR(-ENOMEM);
    616		control_type->allocated = true;
    617	}
    618	mutex_init(&control_type->lock);
    619	control_type->ops = ops;
    620	INIT_LIST_HEAD(&control_type->node);
    621	control_type->dev.class = &powercap_class;
    622	dev_set_name(&control_type->dev, "%s", name);
    623	result = device_register(&control_type->dev);
    624	if (result) {
    625		if (control_type->allocated)
    626			kfree(control_type);
    627		return ERR_PTR(result);
    628	}
    629	idr_init(&control_type->idr);
    630
    631	mutex_lock(&powercap_cntrl_list_lock);
    632	list_add_tail(&control_type->node, &powercap_cntrl_list);
    633	mutex_unlock(&powercap_cntrl_list_lock);
    634
    635	return control_type;
    636}
    637EXPORT_SYMBOL_GPL(powercap_register_control_type);
    638
    639int powercap_unregister_control_type(struct powercap_control_type *control_type)
    640{
    641	struct powercap_control_type *pos = NULL;
    642
    643	if (control_type->nr_zones) {
    644		dev_err(&control_type->dev, "Zones of this type still not freed\n");
    645		return -EINVAL;
    646	}
    647	mutex_lock(&powercap_cntrl_list_lock);
    648	list_for_each_entry(pos, &powercap_cntrl_list, node) {
    649		if (pos == control_type) {
    650			list_del(&control_type->node);
    651			mutex_unlock(&powercap_cntrl_list_lock);
    652			device_unregister(&control_type->dev);
    653			return 0;
    654		}
    655	}
    656	mutex_unlock(&powercap_cntrl_list_lock);
    657
    658	return -ENODEV;
    659}
    660EXPORT_SYMBOL_GPL(powercap_unregister_control_type);
    661
    662static int __init powercap_init(void)
    663{
    664	int result;
    665
    666	result = seed_constraint_attributes();
    667	if (result)
    668		return result;
    669
    670	return class_register(&powercap_class);
    671}
    672
    673fs_initcall(powercap_init);
    674
    675MODULE_DESCRIPTION("PowerCap sysfs Driver");
    676MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
    677MODULE_LICENSE("GPL v2");