cpumask: use percpu allocations instead of arrays in net/core/dev.c

Instead of allocating an nr_cpu_ids array, most places should be using
percpu_alloc().  This doesn't waste space if cpu numbers aren't
contiguous.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 net/core/dev.c |   27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff -r d35cbbcc46b2 net/core/dev.c
--- a/net/core/dev.c	Thu Nov 20 00:55:21 2008 +1030
+++ b/net/core/dev.c	Thu Nov 20 00:58:59 2008 +1030
@@ -170,7 +170,7 @@
 	struct dma_client client;
 	spinlock_t lock;
 	cpumask_t channel_mask;
-	struct dma_chan **channels;
+	struct dma_chan **channels_pcpu;
 };
 
 static enum dma_state_client
@@ -2445,7 +2445,8 @@
 	if (!cpus_empty(net_dma.channel_mask)) {
 		int chan_idx;
 		for_each_cpu_mask_nr(chan_idx, net_dma.channel_mask) {
-			struct dma_chan *chan = net_dma.channels[chan_idx];
+			struct dma_chan *chan =
+				*per_cpu_ptr(net_dma.channels_pcpu, chan_idx);
 			if (chan)
 				dma_async_memcpy_issue_pending(chan);
 		}
@@ -4620,7 +4621,7 @@
 	cpu = first_cpu(cpu_online_map);
 
 	for_each_cpu_mask_nr(chan_idx, net_dma->channel_mask) {
-		chan = net_dma->channels[chan_idx];
+		chan = *per_cpu_ptr(net_dma->channels_pcpu, chan_idx);
 
 		n = ((num_online_cpus() / cpus_weight(net_dma->channel_mask))
 		   + (i < (num_online_cpus() %
@@ -4653,23 +4654,24 @@
 	spin_lock(&net_dma->lock);
 	switch (state) {
 	case DMA_RESOURCE_AVAILABLE:
-		for (i = 0; i < nr_cpu_ids; i++)
-			if (net_dma->channels[i] == chan) {
+		for_each_possible_cpu(i)
+			if (*per_cpu_ptr(net_dma->channels_pcpu, i) == chan) {
 				found = 1;
 				break;
-			} else if (net_dma->channels[i] == NULL && pos < 0)
+			} else if (!*per_cpu_ptr(net_dma->channels_pcpu, i) &&
+				   pos < 0)
 				pos = i;
 
 		if (!found && pos >= 0) {
 			ack = DMA_ACK;
-			net_dma->channels[pos] = chan;
+			*per_cpu_ptr(net_dma->channels_pcpu, i) = chan;
 			cpu_set(pos, net_dma->channel_mask);
 			net_dma_rebalance(net_dma);
 		}
 		break;
 	case DMA_RESOURCE_REMOVED:
-		for (i = 0; i < nr_cpu_ids; i++)
-			if (net_dma->channels[i] == chan) {
+		for_each_possible_cpu(i)
+			if (*per_cpu_ptr(net_dma->channels_pcpu, i) == chan) {
 				found = 1;
 				pos = i;
 				break;
@@ -4678,7 +4680,7 @@
 		if (found) {
 			ack = DMA_ACK;
 			cpu_clear(pos, net_dma->channel_mask);
-			net_dma->channels[i] = NULL;
+			*per_cpu_ptr(net_dma->channels_pcpu, i) = NULL;
 			net_dma_rebalance(net_dma);
 		}
 		break;
@@ -4695,9 +4697,8 @@
  */
 static int __init netdev_dma_register(void)
 {
-	net_dma.channels = kzalloc(nr_cpu_ids * sizeof(struct net_dma),
-								GFP_KERNEL);
-	if (unlikely(!net_dma.channels)) {
+	net_dma.channels_pcpu = alloc_percpu(struct dma_chan *);
+	if (unlikely(!net_dma.channels_pcpu)) {
 		printk(KERN_NOTICE
 				"netdev_dma: no memory for net_dma.channels\n");
 		return -ENOMEM;
