diff options
Diffstat (limited to 'lib/cpumask.c')
| -rw-r--r-- | lib/cpumask.c | 67 | 
1 files changed, 65 insertions, 2 deletions
diff --git a/lib/cpumask.c b/lib/cpumask.c index d327b87c99b..b6513a9f289 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c @@ -140,7 +140,7 @@ EXPORT_SYMBOL(zalloc_cpumask_var);   */  void __init alloc_bootmem_cpumask_var(cpumask_var_t *mask)  { -	*mask = alloc_bootmem(cpumask_size()); +	*mask = memblock_virt_alloc(cpumask_size(), 0);  }  /** @@ -161,6 +161,69 @@ EXPORT_SYMBOL(free_cpumask_var);   */  void __init free_bootmem_cpumask_var(cpumask_var_t mask)  { -	free_bootmem(__pa(mask), cpumask_size()); +	memblock_free_early(__pa(mask), cpumask_size());  }  #endif + +/** + * cpumask_set_cpu_local_first - set i'th cpu with local numa cpu's first + * + * @i: index number + * @numa_node: local numa_node + * @dstp: cpumask with the relevant cpu bit set according to the policy + * + * This function sets the cpumask according to a numa aware policy. + * cpumask could be used as an affinity hint for the IRQ related to a + * queue. When the policy is to spread queues across cores - local cores + * first. + * + * Returns 0 on success, -ENOMEM for no memory, and -EAGAIN when failed to set + * the cpu bit and need to re-call the function. + */ +int cpumask_set_cpu_local_first(int i, int numa_node, cpumask_t *dstp) +{ +	cpumask_var_t mask; +	int cpu; +	int ret = 0; + +	if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) +		return -ENOMEM; + +	i %= num_online_cpus(); + +	if (numa_node == -1 || !cpumask_of_node(numa_node)) { +		/* Use all online cpu's for non numa aware system */ +		cpumask_copy(mask, cpu_online_mask); +	} else { +		int n; + +		cpumask_and(mask, +			    cpumask_of_node(numa_node), cpu_online_mask); + +		n = cpumask_weight(mask); +		if (i >= n) { +			i -= n; + +			/* If index > number of local cpu's, mask out local +			 * cpu's +			 */ +			cpumask_andnot(mask, cpu_online_mask, mask); +		} +	} + +	for_each_cpu(cpu, mask) { +		if (--i < 0) +			goto out; +	} + +	ret = -EAGAIN; + +out: +	free_cpumask_var(mask); + +	if (!ret) +		cpumask_set_cpu(cpu, dstp); + +	return ret; +} +EXPORT_SYMBOL(cpumask_set_cpu_local_first);  | 
