Add attributes for registers that are supported by the platform. This prevents unsupported optional registers from having sysfs entries created. Signed-off-by: Janakarajan Natarajan <Janakarajan.Natarajan@xxxxxxx> --- drivers/acpi/cppc_acpi.c | 70 ++++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 1b207fca1420..66fad270376c 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -179,22 +179,8 @@ static ssize_t show_feedback_ctrs(struct kobject *kobj, } define_one_cppc_ro(feedback_ctrs); -static struct attribute *cppc_attrs[] = { - &feedback_ctrs.attr, - &reference_perf.attr, - &wraparound_time.attr, - &highest_perf.attr, - &lowest_perf.attr, - &lowest_nonlinear_perf.attr, - &nominal_perf.attr, - &nominal_freq.attr, - &lowest_freq.attr, - NULL -}; - static struct kobj_type cppc_ktype = { .sysfs_ops = &kobj_sysfs_ops, - .default_attrs = cppc_attrs, }; static int check_pcc_chan(int pcc_ss_id, bool chk_err_bit) @@ -709,6 +695,57 @@ static bool is_cppc_supported(int revision, int num_ent) * } */ +int set_cppc_attrs(struct cpc_desc *cpc, int entries) +{ + static struct attribute **cppc_attrs; + int i, attr_i = 0; + + /* Extra for feedback_ctrs to be exposed via sysfs */ + cppc_attrs = kcalloc(entries + 1, sizeof(*cppc_attrs), GFP_KERNEL); + if (!cppc_attrs) + return -ENOMEM; + + for (i = 0; i < MAX_CPC_REG_ENT && attr_i < entries; i++) { + if (!CPC_SUPPORTED(&cpc->cpc_regs[i])) + continue; + + switch (i) { + case HIGHEST_PERF: + cppc_attrs[attr_i++] = &highest_perf.attr; + break; + case NOMINAL_PERF: + cppc_attrs[attr_i++] = &nominal_perf.attr; + break; + case LOW_NON_LINEAR_PERF: + cppc_attrs[attr_i++] = &lowest_nonlinear_perf.attr; + break; + case LOWEST_PERF: + cppc_attrs[attr_i++] = &lowest_perf.attr; + break; + case NOMINAL_FREQ: + cppc_attrs[attr_i++] = &nominal_freq.attr; + break; + case LOWEST_FREQ: + cppc_attrs[attr_i++] = &lowest_freq.attr; + break; + case REFERENCE_PERF: + cppc_attrs[attr_i++] = &reference_perf.attr; + break; + case CTR_WRAP_TIME: + cppc_attrs[attr_i++] = &wraparound_time.attr; + break; + } + } + + /* Set feedback_ctr sysfs entry */ + cppc_attrs[attr_i] = &feedback_ctrs.attr; + + /* Set kobj_type member */ + cppc_ktype.default_attrs = cppc_attrs; + + return 0; +} + /** * acpi_cppc_processor_probe - Search for per CPU _CPC objects. * @pr: Ptr to acpi_processor containing this CPUs logical Id. @@ -863,6 +900,10 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) /* Plug PSD data into this CPUs CPC descriptor. */ per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr; + ret = set_cppc_attrs(cpc_ptr, num_ent - 2); + if (ret) + goto out_free; + ret = kobject_init_and_add(&cpc_ptr->kobj, &cppc_ktype, &cpu_dev->kobj, "acpi_cppc"); if (ret) { @@ -924,6 +965,7 @@ void acpi_cppc_processor_exit(struct acpi_processor *pr) iounmap(addr); } + kfree(cppc_ktype.default_attrs); kobject_put(&cpc_ptr->kobj); kfree(cpc_ptr); } -- 2.17.1