Commit a68cf983 authored by Mark Nutter's avatar Mark Nutter Committed by Paul Mackerras

[POWERPC] spufs: scheduler support for NUMA.

This patch adds NUMA support to the the spufs scheduler.

The new arch/powerpc/platforms/cell/spufs/sched.c is greatly
simplified, in an attempt to reduce complexity while adding
support for NUMA scheduler domains.  SPUs are allocated starting
from the calling thread's node, moving to others as supported by
current->cpus_allowed.  Preemption is gone as it was buggy, but
should be re-enabled in another patch when stable.

The new arch/powerpc/platforms/cell/spu_base.c maintains idle
lists on a per-node basis, and allows caller to specify which
node(s) an SPU should be allocated from, while passing -1 tells
spu_alloc() that any node is allowed.

Since the patch removes the currently implemented preemptive
scheduling, it is technically a regression, but practically
all users have since migrated to this version, as it is
part of the IBM SDK and the yellowdog distribution, so there
is not much point holding it back while the new preemptive
scheduling patch gets delayed further.
Signed-off-by: default avatarArnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 27d5bf2a
...@@ -317,7 +317,7 @@ static void spu_free_irqs(struct spu *spu) ...@@ -317,7 +317,7 @@ static void spu_free_irqs(struct spu *spu)
free_irq(spu->irqs[2], spu); free_irq(spu->irqs[2], spu);
} }
static LIST_HEAD(spu_list); static struct list_head spu_list[MAX_NUMNODES];
static DEFINE_MUTEX(spu_mutex); static DEFINE_MUTEX(spu_mutex);
static void spu_init_channels(struct spu *spu) static void spu_init_channels(struct spu *spu)
...@@ -354,32 +354,42 @@ static void spu_init_channels(struct spu *spu) ...@@ -354,32 +354,42 @@ static void spu_init_channels(struct spu *spu)
} }
} }
struct spu *spu_alloc(void) struct spu *spu_alloc_node(int node)
{ {
struct spu *spu; struct spu *spu = NULL;
mutex_lock(&spu_mutex); mutex_lock(&spu_mutex);
if (!list_empty(&spu_list)) { if (!list_empty(&spu_list[node])) {
spu = list_entry(spu_list.next, struct spu, list); spu = list_entry(spu_list[node].next, struct spu, list);
list_del_init(&spu->list); list_del_init(&spu->list);
pr_debug("Got SPU %x %d\n", spu->isrc, spu->number); pr_debug("Got SPU %x %d %d\n",
} else { spu->isrc, spu->number, spu->node);
pr_debug("No SPU left\n"); spu_init_channels(spu);
spu = NULL;
} }
mutex_unlock(&spu_mutex); mutex_unlock(&spu_mutex);
if (spu) return spu;
spu_init_channels(spu); }
EXPORT_SYMBOL_GPL(spu_alloc_node);
struct spu *spu_alloc(void)
{
struct spu *spu = NULL;
int node;
for (node = 0; node < MAX_NUMNODES; node++) {
spu = spu_alloc_node(node);
if (spu)
break;
}
return spu; return spu;
} }
EXPORT_SYMBOL_GPL(spu_alloc);
void spu_free(struct spu *spu) void spu_free(struct spu *spu)
{ {
mutex_lock(&spu_mutex); mutex_lock(&spu_mutex);
list_add_tail(&spu->list, &spu_list); list_add_tail(&spu->list, &spu_list[spu->node]);
mutex_unlock(&spu_mutex); mutex_unlock(&spu_mutex);
} }
EXPORT_SYMBOL_GPL(spu_free); EXPORT_SYMBOL_GPL(spu_free);
...@@ -712,7 +722,7 @@ static int __init create_spu(struct device_node *spe) ...@@ -712,7 +722,7 @@ static int __init create_spu(struct device_node *spe)
if (ret) if (ret)
goto out_free_irqs; goto out_free_irqs;
list_add(&spu->list, &spu_list); list_add(&spu->list, &spu_list[spu->node]);
mutex_unlock(&spu_mutex); mutex_unlock(&spu_mutex);
pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n", pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n",
...@@ -745,9 +755,13 @@ static void destroy_spu(struct spu *spu) ...@@ -745,9 +755,13 @@ static void destroy_spu(struct spu *spu)
static void cleanup_spu_base(void) static void cleanup_spu_base(void)
{ {
struct spu *spu, *tmp; struct spu *spu, *tmp;
int node;
mutex_lock(&spu_mutex); mutex_lock(&spu_mutex);
list_for_each_entry_safe(spu, tmp, &spu_list, list) for (node = 0; node < MAX_NUMNODES; node++) {
destroy_spu(spu); list_for_each_entry_safe(spu, tmp, &spu_list[node], list)
destroy_spu(spu);
}
mutex_unlock(&spu_mutex); mutex_unlock(&spu_mutex);
sysdev_class_unregister(&spu_sysdev_class); sysdev_class_unregister(&spu_sysdev_class);
} }
...@@ -756,13 +770,16 @@ module_exit(cleanup_spu_base); ...@@ -756,13 +770,16 @@ module_exit(cleanup_spu_base);
static int __init init_spu_base(void) static int __init init_spu_base(void)
{ {
struct device_node *node; struct device_node *node;
int ret; int i, ret;
/* create sysdev class for spus */ /* create sysdev class for spus */
ret = sysdev_class_register(&spu_sysdev_class); ret = sysdev_class_register(&spu_sysdev_class);
if (ret) if (ret)
return ret; return ret;
for (i = 0; i < MAX_NUMNODES; i++)
INIT_LIST_HEAD(&spu_list[i]);
ret = -ENODEV; ret = -ENODEV;
for (node = of_find_node_by_type(NULL, "spe"); for (node = of_find_node_by_type(NULL, "spe");
node; node = of_find_node_by_type(node, "spe")) { node; node = of_find_node_by_type(node, "spe")) {
......
This diff is collapsed.
...@@ -147,6 +147,7 @@ struct spu { ...@@ -147,6 +147,7 @@ struct spu {
}; };
struct spu *spu_alloc(void); struct spu *spu_alloc(void);
struct spu *spu_alloc_node(int node);
void spu_free(struct spu *spu); void spu_free(struct spu *spu);
int spu_irq_class_0_bottom(struct spu *spu); int spu_irq_class_0_bottom(struct spu *spu);
int spu_irq_class_1_bottom(struct spu *spu); int spu_irq_class_1_bottom(struct spu *spu);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment