static int detect_cache_attributes(unsigned int cpu)
{
	int ret;

	if (init_cache_level(cpu) || !cache_leaves(cpu))
		return -ENOENT;

	per_cpu_cacheinfo(cpu) = kcalloc(cache_leaves(cpu),
					 sizeof(struct cacheinfo), GFP_KERNEL);
	if (per_cpu_cacheinfo(cpu) == NULL)
		return -ENOMEM;

	/*
	 * populate_cache_leaves() may completely setup the cache leaves and
	 * shared_cpu_map or it may leave it partially setup.
	 */
	ret = populate_cache_leaves(cpu);
	if (ret)
		goto free_ci;
	/*
	 * For systems using DT for cache hierarchy, fw_token
	 * and shared_cpu_map will be set up here only if they are
	 * not populated already
	 */
	ret = cache_shared_cpu_map_setup(cpu);
	if (ret) {
		pr_warn("Unable to detect cache hierarchy for CPU %d\n", cpu);
		goto free_ci;
	}

	return 0;

free_ci:
	free_cache_attributes(cpu);
	return ret;
}
static int detect_cache_attributes(unsigned int cpu)
{
	int ret;

	if (init_cache_level(cpu) || !cache_leaves(cpu))
		return -ENOENT;

	per_cpu_cacheinfo(cpu) = kcalloc(cache_leaves(cpu),
					 sizeof(struct cacheinfo), GFP_KERNEL);
	if (per_cpu_cacheinfo(cpu) == NULL)
		return -ENOMEM;

	 
	ret = populate_cache_leaves(cpu);
	if (ret)
		goto free_ci;
	 
	ret = cache_shared_cpu_map_setup(cpu);
	if (ret) {
		pr_warn("Unable to detect cache hierarchy for CPU %d\n", cpu);
		goto free_ci;
	}

	return 0;

free_ci:
	free_cache_attributes(cpu);
	return ret;
}