In order to determine the number of L2 cache ways enabled at runtime, implement a private attribute using cache_get_priv_group() in cacheinfo framework. Reading this attribute ("number_of_ways_enabled") will return the number of enabled L2 cache ways at runtime. Signed-off-by: Yash Shah <yash.shah@xxxxxxxxxx> --- arch/riscv/include/asm/sifive_l2_cache.h | 2 ++ arch/riscv/kernel/cacheinfo.c | 31 +++++++++++++++++++++++++++++++ drivers/soc/sifive/sifive_l2_cache.c | 5 +++++ 3 files changed, 38 insertions(+) diff --git a/arch/riscv/include/asm/sifive_l2_cache.h b/arch/riscv/include/asm/sifive_l2_cache.h index 04f6748..217a42f 100644 --- a/arch/riscv/include/asm/sifive_l2_cache.h +++ b/arch/riscv/include/asm/sifive_l2_cache.h @@ -10,6 +10,8 @@ extern int register_sifive_l2_error_notifier(struct notifier_block *nb); extern int unregister_sifive_l2_error_notifier(struct notifier_block *nb); +int sifive_l2_largest_wayenabled(void); + #define SIFIVE_L2_ERR_TYPE_CE 0 #define SIFIVE_L2_ERR_TYPE_UE 1 diff --git a/arch/riscv/kernel/cacheinfo.c b/arch/riscv/kernel/cacheinfo.c index 4c90c07..29bdb21 100644 --- a/arch/riscv/kernel/cacheinfo.c +++ b/arch/riscv/kernel/cacheinfo.c @@ -7,6 +7,7 @@ #include <linux/cpu.h> #include <linux/of.h> #include <linux/of_device.h> +#include <asm/sifive_l2_cache.h> static void ci_leaf_init(struct cacheinfo *this_leaf, struct device_node *node, @@ -16,6 +17,36 @@ static void ci_leaf_init(struct cacheinfo *this_leaf, this_leaf->type = type; } +#ifdef CONFIG_SIFIVE_L2 +static ssize_t number_of_ways_enabled_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", sifive_l2_largest_wayenabled()); +} + +static DEVICE_ATTR_RO(number_of_ways_enabled); + +static struct attribute *priv_attrs[] = { + &dev_attr_number_of_ways_enabled.attr, + NULL, +}; + +static const struct attribute_group priv_attr_group = { + .attrs = priv_attrs, +}; + +const struct attribute_group * +cache_get_priv_group(struct cacheinfo *this_leaf) +{ + /* We want to use private group for L2 cache only */ + if (this_leaf->level == 2) + return &priv_attr_group; + else + return NULL; +} +#endif /* CONFIG_SIFIVE_L2 */ + static int __init_cache_level(unsigned int cpu) { struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); diff --git a/drivers/soc/sifive/sifive_l2_cache.c b/drivers/soc/sifive/sifive_l2_cache.c index a9ffff3..f1a5f2c 100644 --- a/drivers/soc/sifive/sifive_l2_cache.c +++ b/drivers/soc/sifive/sifive_l2_cache.c @@ -107,6 +107,11 @@ int unregister_sifive_l2_error_notifier(struct notifier_block *nb) } EXPORT_SYMBOL_GPL(unregister_sifive_l2_error_notifier); +int sifive_l2_largest_wayenabled(void) +{ + return readl(l2_base + SIFIVE_L2_WAYENABLE); +} + static irqreturn_t l2_int_handler(int irq, void *device) { unsigned int add_h, add_l; -- 2.7.4