From: Rusty Russell <rusty@rustcorp.com.au>

The cpu handling in net/core/flow.c is complex: it tries to allocate flow
cache as each CPU comes up.  It might as well allocate them for each
possible CPU at boot.



---

 net/core/flow.c |   81 ++++++++++----------------------------------------------
 1 files changed, 15 insertions(+), 66 deletions(-)

diff -puN net/core/flow.c~simplify-flow_c-cpu-handling net/core/flow.c
--- 25/net/core/flow.c~simplify-flow_c-cpu-handling	2004-01-22 00:43:59.000000000 -0800
+++ 25-akpm/net/core/flow.c	2004-01-22 00:43:59.000000000 -0800
@@ -66,24 +66,18 @@ static struct timer_list flow_hash_rnd_t
 
 struct flow_flush_info {
 	atomic_t cpuleft;
-	cpumask_t cpumap;
 	struct completion completion;
 };
 static DEFINE_PER_CPU(struct tasklet_struct, flow_flush_tasklets) = { NULL };
 
 #define flow_flush_tasklet(cpu) (&per_cpu(flow_flush_tasklets, cpu))
 
-static DECLARE_MUTEX(flow_cache_cpu_sem);
-static cpumask_t flow_cache_cpu_map;
-static unsigned int flow_cache_cpu_count;
-
 static void flow_cache_new_hashrnd(unsigned long arg)
 {
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_isset(i, flow_cache_cpu_map))
-			flow_hash_rnd_recalc(i) = 1;
+	for_each_cpu(i)
+		flow_hash_rnd_recalc(i) = 1;
 
 	flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
 	add_timer(&flow_hash_rnd_timer);
@@ -179,7 +173,9 @@ void *flow_cache_lookup(struct flowi *ke
 	cpu = smp_processor_id();
 
 	fle = NULL;
-	if (!cpu_isset(cpu, flow_cache_cpu_map))
+	/* Packet really early in init?  Making flow_cache_init a
+	 * pre-smp initcall would solve this.  --RR */
+	if (!flow_table(cpu))
 		goto nocache;
 
 	if (flow_hash_rnd_recalc(cpu))
@@ -278,8 +274,6 @@ static void flow_cache_flush_per_cpu(voi
 	struct tasklet_struct *tasklet;
 
 	cpu = smp_processor_id();
-	if (!cpu_isset(cpu, info->cpumap))
-		return;
 
 	tasklet = flow_flush_tasklet(cpu);
 	tasklet->data = (unsigned long)info;
@@ -289,29 +283,23 @@ static void flow_cache_flush_per_cpu(voi
 void flow_cache_flush(void)
 {
 	struct flow_flush_info info;
-	static DECLARE_MUTEX(flow_flush_sem);
-
-	down(&flow_cache_cpu_sem);
-	info.cpumap = flow_cache_cpu_map;
-	atomic_set(&info.cpuleft, flow_cache_cpu_count);
-	up(&flow_cache_cpu_sem);
 
+	/* Don't want cpus going down or up during this, also protects
+	 * against multiple callers. */
+	down(&cpucontrol);
+	atomic_set(&info.cpuleft, num_online_cpus());
 	init_completion(&info.completion);
 
-	down(&flow_flush_sem);
-
 	local_bh_disable();
 	smp_call_function(flow_cache_flush_per_cpu, &info, 1, 0);
-	if (cpu_isset(smp_processor_id(), info.cpumap))
-		flow_cache_flush_tasklet((unsigned long)&info);
+	flow_cache_flush_tasklet((unsigned long)&info);
 	local_bh_enable();
 
 	wait_for_completion(&info.completion);
-
-	up(&flow_flush_sem);
+	up(&cpucontrol);
 }
 
-static int __devinit flow_cache_cpu_prepare(int cpu)
+static void __devinit flow_cache_cpu_prepare(int cpu)
 {
 	struct tasklet_struct *tasklet;
 	unsigned long order;
@@ -324,9 +312,8 @@ static int __devinit flow_cache_cpu_prep
 
 	flow_table(cpu) = (struct flow_cache_entry **)
 		__get_free_pages(GFP_KERNEL, order);
-
 	if (!flow_table(cpu))
-		return NOTIFY_BAD;
+		panic("NET: failed to allocate flow cache order %lu\n", order);
 
 	memset(flow_table(cpu), 0, PAGE_SIZE << order);
 
@@ -335,39 +322,8 @@ static int __devinit flow_cache_cpu_prep
 
 	tasklet = flow_flush_tasklet(cpu);
 	tasklet_init(tasklet, flow_cache_flush_tasklet, 0);
-
-	return NOTIFY_OK;
-}
-
-static int __devinit flow_cache_cpu_online(int cpu)
-{
-	down(&flow_cache_cpu_sem);
-	cpu_set(cpu, flow_cache_cpu_map);
-	flow_cache_cpu_count++;
-	up(&flow_cache_cpu_sem);
-
-	return NOTIFY_OK;
 }
 
-static int __devinit flow_cache_cpu_notify(struct notifier_block *self,
-					   unsigned long action, void *hcpu)
-{
-	unsigned long cpu = (unsigned long)cpu;
-	switch (action) {
-	case CPU_UP_PREPARE:
-		return flow_cache_cpu_prepare(cpu);
-		break;
-	case CPU_ONLINE:
-		return flow_cache_cpu_online(cpu);
-		break;
-	}
-	return NOTIFY_OK;
-}
-
-static struct notifier_block __devinitdata flow_cache_cpu_nb = {
-	.notifier_call = flow_cache_cpu_notify,
-};
-
 static int __init flow_cache_init(void)
 {
 	int i;
@@ -389,15 +345,8 @@ static int __init flow_cache_init(void)
 	flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
 	add_timer(&flow_hash_rnd_timer);
 
-	register_cpu_notifier(&flow_cache_cpu_nb);
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_online(i))
-			continue;
-		if (flow_cache_cpu_prepare(i) == NOTIFY_OK &&
-		    flow_cache_cpu_online(i) == NOTIFY_OK)
-			continue;
-		panic("NET: failed to initialise flow cache hash table\n");
-	}
+	for_each_cpu(i)
+		flow_cache_cpu_prepare(i);
 
 	return 0;
 }

_