drivers/platform/x86/amd/dptc.c | 259 ++++++++++++++-------------------------- 1 file changed, 91 insertions(+), 168 deletions(-) diff --git a/drivers/platform/x86/amd/dptc.c b/drivers/platform/x86/amd/dptc.c index a3d582e48cd3..f54f4fca63f6 100644 --- a/drivers/platform/x86/amd/dptc.c +++ b/drivers/platform/x86/amd/dptc.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include "../firmware_attributes_class.h" @@ -67,7 +69,6 @@ struct dptc_device_limits { }; struct dptc_param_desc { - const char *name; const char *display_name; u16 scale; /* sysfs-to-ALIB multiplier (e.g. 1000 for W->mW) */ u8 param_id; @@ -75,14 +76,14 @@ struct dptc_param_desc { }; static const struct dptc_param_desc dptc_params[DPTC_NUM_PARAMS] = { - [DPTC_PPT_PL1_SPL] = { "ppt_pl1_spl", "Sustained power limit (W)", - 1000, ALIB_ID_STAPM_LIMIT, ALIB_ID_SKIN_LIMIT }, - [DPTC_PPT_PL2_SPPT] = { "ppt_pl2_sppt", "Slow PPT limit (W)", - 1000, ALIB_ID_SLOW_LIMIT }, - [DPTC_PPT_PL3_FPPT] = { "ppt_pl3_fppt", "Fast PPT limit (W)", - 1000, ALIB_ID_FAST_LIMIT }, - [DPTC_CPU_TEMP] = { "cpu_temp", "Thermal control limit (C)", - 1, ALIB_ID_TEMP_TARGET }, + [DPTC_PPT_PL1_SPL] = { "Sustained power limit (W)", 1000, + ALIB_ID_STAPM_LIMIT, ALIB_ID_SKIN_LIMIT }, + [DPTC_PPT_PL2_SPPT] = { "Slow PPT limit (W)", 1000, + ALIB_ID_SLOW_LIMIT }, + [DPTC_PPT_PL3_FPPT] = { "Fast PPT limit (W)", 1000, + ALIB_ID_FAST_LIMIT }, + [DPTC_CPU_TEMP] = { "Thermal control limit (C)", 1, + ALIB_ID_TEMP_TARGET }, }; /* 15W class: AYANEO AIR (Ryzen 5 5560U) */ @@ -529,22 +530,6 @@ static const struct dmi_system_id dptc_dmi_table[] = { }; MODULE_DEVICE_TABLE(dmi, dptc_dmi_table); -struct dptc_priv; - -struct dptc_attr_sysfs { - struct dptc_priv *priv; - struct kobj_attribute current_value; - struct kobj_attribute default_value; - struct kobj_attribute min_value; - struct kobj_attribute max_value; - struct kobj_attribute scalar_increment; - struct kobj_attribute display_name; - struct kobj_attribute type; - struct attribute *attrs[8]; - struct attribute_group group; - int idx; -}; - struct dptc_priv { struct device *fw_attr_dev; struct kset *fw_attr_kset; @@ -563,10 +548,6 @@ struct dptc_priv { /* Protects mutable driver state */ struct mutex lock; - - struct dptc_attr_sysfs params[DPTC_NUM_PARAMS]; - struct dptc_attr_sysfs expanded_attr; - struct kobj_attribute save_settings_attr; }; static struct platform_device *dptc_pdev; @@ -682,12 +663,23 @@ static int dptc_alib_save(struct dptc_priv *dptc) /* Sysfs callbacks */ +struct dptc_attr_sysfs { + struct kobj_attribute current_value; + struct kobj_attribute default_value; + struct kobj_attribute min_value; + struct kobj_attribute max_value; + struct kobj_attribute scalar_increment; + struct kobj_attribute display_name; + struct kobj_attribute type; + int idx; +}; + static ssize_t dptc_current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { struct dptc_attr_sysfs *ps = container_of(attr, struct dptc_attr_sysfs, current_value); - struct dptc_priv *dptc = ps->priv; + struct dptc_priv *dptc = dev_get_drvdata(kobj_to_dev(kobj->parent)); guard(mutex)(&dptc->lock); @@ -710,7 +702,7 @@ static ssize_t dptc_current_value_store(struct kobject *kobj, { struct dptc_attr_sysfs *ps = container_of(attr, struct dptc_attr_sysfs, current_value); - struct dptc_priv *dptc = ps->priv; + struct dptc_priv *dptc = dev_get_drvdata(kobj_to_dev(kobj->parent)); u32 val, min, max; int ret; @@ -748,8 +740,9 @@ static ssize_t dptc_default_value_show(struct kobject *kobj, { struct dptc_attr_sysfs *ps = container_of(attr, struct dptc_attr_sysfs, default_value); + struct dptc_priv *dptc = dev_get_drvdata(kobj_to_dev(kobj->parent)); - return sysfs_emit(buf, "%u\n", dptc_get_default(ps->priv, ps->idx)); + return sysfs_emit(buf, "%u\n", dptc_get_default(dptc, ps->idx)); } static ssize_t dptc_min_value_show(struct kobject *kobj, @@ -757,7 +750,7 @@ static ssize_t dptc_min_value_show(struct kobject *kobj, { struct dptc_attr_sysfs *ps = container_of(attr, struct dptc_attr_sysfs, min_value); - struct dptc_priv *dptc = ps->priv; + struct dptc_priv *dptc = dev_get_drvdata(kobj_to_dev(kobj->parent)); guard(mutex)(&dptc->lock); @@ -769,7 +762,7 @@ static ssize_t dptc_max_value_show(struct kobject *kobj, { struct dptc_attr_sysfs *ps = container_of(attr, struct dptc_attr_sysfs, max_value); - struct dptc_priv *dptc = ps->priv; + struct dptc_priv *dptc = dev_get_drvdata(kobj_to_dev(kobj->parent)); guard(mutex)(&dptc->lock); @@ -799,8 +792,7 @@ static ssize_t dptc_type_show(struct kobject *kobj, static ssize_t dptc_save_settings_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - struct dptc_priv *dptc = - container_of(attr, struct dptc_priv, save_settings_attr); + struct dptc_priv *dptc = dev_get_drvdata(kobj_to_dev(kobj->parent)); guard(mutex)(&dptc->lock); @@ -813,8 +805,7 @@ static ssize_t dptc_save_settings_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { - struct dptc_priv *dptc = - container_of(attr, struct dptc_priv, save_settings_attr); + struct dptc_priv *dptc = dev_get_drvdata(kobj_to_dev(kobj->parent)); int ret = 0; guard(mutex)(&dptc->lock); @@ -835,9 +826,7 @@ static ssize_t dptc_expanded_current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - struct dptc_attr_sysfs *ps = - container_of(attr, struct dptc_attr_sysfs, current_value); - struct dptc_priv *dptc = ps->priv; + struct dptc_priv *dptc = dev_get_drvdata(kobj_to_dev(kobj->parent)); guard(mutex)(&dptc->lock); @@ -848,9 +837,7 @@ static ssize_t dptc_expanded_current_value_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { - struct dptc_attr_sysfs *ps = - container_of(attr, struct dptc_attr_sysfs, current_value); - struct dptc_priv *dptc = ps->priv; + struct dptc_priv *dptc = dev_get_drvdata(kobj_to_dev(kobj->parent)); bool val; int ret; @@ -912,113 +899,62 @@ static ssize_t dptc_expanded_type_show(struct kobject *kobj, /* Sysfs setup */ -static void dptc_setup_param_sysfs(struct dptc_priv *dptc, - struct dptc_attr_sysfs *ps, int idx) -{ - ps->priv = dptc; - ps->idx = idx; - - sysfs_attr_init(&ps->current_value.attr); - ps->current_value.attr.name = "current_value"; - ps->current_value.attr.mode = 0644; - ps->current_value.show = dptc_current_value_show; - ps->current_value.store = dptc_current_value_store; - - sysfs_attr_init(&ps->default_value.attr); - ps->default_value.attr.name = "default_value"; - ps->default_value.attr.mode = 0444; - ps->default_value.show = dptc_default_value_show; - - sysfs_attr_init(&ps->min_value.attr); - ps->min_value.attr.name = "min_value"; - ps->min_value.attr.mode = 0444; - ps->min_value.show = dptc_min_value_show; - - sysfs_attr_init(&ps->max_value.attr); - ps->max_value.attr.name = "max_value"; - ps->max_value.attr.mode = 0444; - ps->max_value.show = dptc_max_value_show; - - sysfs_attr_init(&ps->scalar_increment.attr); - ps->scalar_increment.attr.name = "scalar_increment"; - ps->scalar_increment.attr.mode = 0444; - ps->scalar_increment.show = dptc_scalar_increment_show; - - sysfs_attr_init(&ps->display_name.attr); - ps->display_name.attr.name = "display_name"; - ps->display_name.attr.mode = 0444; - ps->display_name.show = dptc_display_name_show; - - sysfs_attr_init(&ps->type.attr); - ps->type.attr.name = "type"; - ps->type.attr.mode = 0444; - ps->type.show = dptc_type_show; - - ps->attrs[0] = &ps->current_value.attr; - ps->attrs[1] = &ps->default_value.attr; - ps->attrs[2] = &ps->min_value.attr; - ps->attrs[3] = &ps->max_value.attr; - ps->attrs[4] = &ps->scalar_increment.attr; - ps->attrs[5] = &ps->display_name.attr; - ps->attrs[6] = &ps->type.attr; - ps->attrs[7] = NULL; - - ps->group.name = dptc_params[idx].name; - ps->group.attrs = ps->attrs; -} +#define __DPTC_ATTR_RO(_func, _name) \ + __ATTR(_name, 0444, _func##_##_name##_show, NULL) + +#define __DPTC_ATTR_RW(_func, _name) \ + __ATTR(_name, 0644, _func##_##_name##_show, _func##_##_name##_store) + +#define DPTC_ATTR_RO(_func, _name) \ + ._name = __DPTC_ATTR_RO(_func, _name) + +#define DPTC_ATTR_RW(_func, _name) \ + ._name = __DPTC_ATTR_RW(_func, _name) + +#define DPTC_ATTR_GROUP(_func, _idx, _grpname) \ + static struct dptc_attr_sysfs dptc_##_grpname##_sysfs = { \ + DPTC_ATTR_RW(_func, current_value), \ + DPTC_ATTR_RO(_func, default_value), \ + DPTC_ATTR_RO(_func, min_value), \ + DPTC_ATTR_RO(_func, max_value), \ + DPTC_ATTR_RO(_func, scalar_increment), \ + DPTC_ATTR_RO(_func, display_name), \ + DPTC_ATTR_RO(_func, type), \ + .idx = _idx, \ + }; \ + static struct attribute *dptc_##_grpname##_attrs[] = { \ + &dptc_##_grpname##_sysfs.current_value.attr, \ + &dptc_##_grpname##_sysfs.default_value.attr, \ + &dptc_##_grpname##_sysfs.min_value.attr, \ + &dptc_##_grpname##_sysfs.max_value.attr, \ + &dptc_##_grpname##_sysfs.scalar_increment.attr, \ + &dptc_##_grpname##_sysfs.display_name.attr, \ + &dptc_##_grpname##_sysfs.type.attr, \ + NULL, \ + }; \ + static const struct attribute_group dptc_##_grpname##_group = { \ + .name = __stringify(_grpname), \ + .attrs = dptc_##_grpname##_attrs, \ + } -static void dptc_setup_expanded_sysfs(struct dptc_priv *dptc, - struct dptc_attr_sysfs *ps) -{ - ps->priv = dptc; - sysfs_attr_init(&ps->current_value.attr); - ps->current_value.attr.name = "current_value"; - ps->current_value.attr.mode = 0644; - ps->current_value.show = dptc_expanded_current_value_show; - ps->current_value.store = dptc_expanded_current_value_store; - - sysfs_attr_init(&ps->default_value.attr); - ps->default_value.attr.name = "default_value"; - ps->default_value.attr.mode = 0444; - ps->default_value.show = dptc_expanded_default_value_show; - - sysfs_attr_init(&ps->min_value.attr); - ps->min_value.attr.name = "min_value"; - ps->min_value.attr.mode = 0444; - ps->min_value.show = dptc_expanded_min_value_show; - - sysfs_attr_init(&ps->max_value.attr); - ps->max_value.attr.name = "max_value"; - ps->max_value.attr.mode = 0444; - ps->max_value.show = dptc_expanded_max_value_show; - - sysfs_attr_init(&ps->scalar_increment.attr); - ps->scalar_increment.attr.name = "scalar_increment"; - ps->scalar_increment.attr.mode = 0444; - ps->scalar_increment.show = dptc_expanded_scalar_increment_show; - - sysfs_attr_init(&ps->display_name.attr); - ps->display_name.attr.name = "display_name"; - ps->display_name.attr.mode = 0444; - ps->display_name.show = dptc_expanded_display_name_show; - - sysfs_attr_init(&ps->type.attr); - ps->type.attr.name = "type"; - ps->type.attr.mode = 0444; - ps->type.show = dptc_expanded_type_show; - - ps->attrs[0] = &ps->current_value.attr; - ps->attrs[1] = &ps->default_value.attr; - ps->attrs[2] = &ps->min_value.attr; - ps->attrs[3] = &ps->max_value.attr; - ps->attrs[4] = &ps->scalar_increment.attr; - ps->attrs[5] = &ps->display_name.attr; - ps->attrs[6] = &ps->type.attr; - ps->attrs[7] = NULL; - - ps->group.name = "expanded_limits"; - ps->group.attrs = ps->attrs; -} +DPTC_ATTR_GROUP(dptc, DPTC_PPT_PL1_SPL, ppt_pl1_spl); +DPTC_ATTR_GROUP(dptc, DPTC_PPT_PL2_SPPT, ppt_pl2_sppt); +DPTC_ATTR_GROUP(dptc, DPTC_PPT_PL3_FPPT, ppt_pl3_fppt); +DPTC_ATTR_GROUP(dptc, DPTC_CPU_TEMP, cpu_temp); + +DPTC_ATTR_GROUP(dptc_expanded, 0, expanded); + +static const struct attribute_group *dptc_attr_groups[] = { + &dptc_ppt_pl1_spl_group, + &dptc_ppt_pl2_sppt_group, + &dptc_ppt_pl3_fppt_group, + &dptc_cpu_temp_group, + &dptc_expanded_group, + NULL, +}; + +static const struct kobj_attribute save_settings_attr = + __DPTC_ATTR_RW(dptc, save_settings); static void dptc_fw_dev_unregister(void *data) { @@ -1131,7 +1067,7 @@ static int dptc_probe(struct platform_device *pdev) const struct dmi_system_id *dmi_match = dev_get_platdata(&pdev->dev); struct device *dev = &pdev->dev; struct dptc_priv *dptc; - int i, ret; + int ret; dptc = devm_kzalloc(dev, sizeof(*dptc), GFP_KERNEL); if (!dptc) @@ -1152,6 +1088,8 @@ static int dptc_probe(struct platform_device *pdev) if (IS_ERR(dptc->fw_attr_dev)) return PTR_ERR(dptc->fw_attr_dev); + dev_set_drvdata(dptc->fw_attr_dev, dptc); + ret = devm_add_action_or_reset(dev, dptc_fw_dev_unregister, dptc->fw_attr_dev); if (ret) @@ -1167,27 +1105,12 @@ static int dptc_probe(struct platform_device *pdev) if (ret) return ret; - for (i = 0; i < DPTC_NUM_PARAMS; i++) { - dptc_setup_param_sysfs(dptc, &dptc->params[i], i); - ret = sysfs_create_group(&dptc->fw_attr_kset->kobj, - &dptc->params[i].group); - if (ret) - return ret; - } - - dptc_setup_expanded_sysfs(dptc, &dptc->expanded_attr); - ret = sysfs_create_group(&dptc->fw_attr_kset->kobj, - &dptc->expanded_attr.group); + ret = sysfs_create_groups(&dptc->fw_attr_kset->kobj, dptc_attr_groups); if (ret) return ret; - sysfs_attr_init(&dptc->save_settings_attr.attr); - dptc->save_settings_attr.attr.name = "save_settings"; - dptc->save_settings_attr.attr.mode = 0644; - dptc->save_settings_attr.show = dptc_save_settings_show; - dptc->save_settings_attr.store = dptc_save_settings_store; ret = sysfs_create_file(&dptc->fw_attr_kset->kobj, - &dptc->save_settings_attr.attr); + &save_settings_attr.attr); if (ret) return ret;