[POWERPC] spufs: scheduler support for NUMA.
[platform/kernel/linux-starfive.git] / arch / powerpc / platforms / cell / spu_base.c
index 3bd36d4..5931973 100644 (file)
@@ -317,7 +317,7 @@ static void spu_free_irqs(struct spu *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 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);
-       if (!list_empty(&spu_list)) {
-               spu = list_entry(spu_list.next, struct spu, list);
+       if (!list_empty(&spu_list[node])) {
+               spu = list_entry(spu_list[node].next, struct spu, list);
                list_del_init(&spu->list);
-               pr_debug("Got SPU %x %d\n", spu->isrc, spu->number);
-       } else {
-               pr_debug("No SPU left\n");
-               spu = NULL;
+               pr_debug("Got SPU %x %d %d\n",
+                        spu->isrc, spu->number, spu->node);
+               spu_init_channels(spu);
        }
        mutex_unlock(&spu_mutex);
 
-       if (spu)
-               spu_init_channels(spu);
+       return 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;
 }
-EXPORT_SYMBOL_GPL(spu_alloc);
 
 void spu_free(struct spu *spu)
 {
        mutex_lock(&spu_mutex);
-       list_add_tail(&spu->list, &spu_list);
+       list_add_tail(&spu->list, &spu_list[spu->node]);
        mutex_unlock(&spu_mutex);
 }
 EXPORT_SYMBOL_GPL(spu_free);
@@ -538,7 +548,7 @@ static void __iomem * __init map_spe_prop(struct spu *spu,
 
        const void *p;
        int proplen;
-       voidret = NULL;
+       void __iomem *ret = NULL;
        int err = 0;
 
        p = get_property(n, name, &proplen);
@@ -562,30 +572,29 @@ static void spu_unmap(struct spu *spu)
        iounmap(spu->priv2);
        iounmap(spu->priv1);
        iounmap(spu->problem);
-       iounmap((u8 __iomem *)spu->local_store);
+       iounmap((__force u8 __iomem *)spu->local_store);
 }
 
 /* This function shall be abstracted for HV platforms */
 static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
 {
-       struct irq_host *host;
        unsigned int isrc;
        const u32 *tmp;
 
-       host = iic_get_irq_host(spu->node);
-       if (host == NULL)
-               return -ENODEV;
-
-       /* Get the interrupt source from the device-tree */
+       /* Get the interrupt source unit from the device-tree */
        tmp = get_property(np, "isrc", NULL);
        if (!tmp)
                return -ENODEV;
-       spu->isrc = isrc = tmp[0];
+       isrc = tmp[0];
+
+       /* Add the node number */
+       isrc |= spu->node << IIC_IRQ_NODE_SHIFT;
+       spu->isrc = isrc;
 
        /* Now map interrupts of all 3 classes */
-       spu->irqs[0] = irq_create_mapping(host, 0x00 | isrc);
-       spu->irqs[1] = irq_create_mapping(host, 0x10 | isrc);
-       spu->irqs[2] = irq_create_mapping(host, 0x20 | isrc);
+       spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc);
+       spu->irqs[1] = irq_create_mapping(NULL, IIC_IRQ_CLASS_1 | isrc);
+       spu->irqs[2] = irq_create_mapping(NULL, IIC_IRQ_CLASS_2 | isrc);
 
        /* Right now, we only fail if class 2 failed */
        return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;
@@ -713,7 +722,7 @@ static int __init create_spu(struct device_node *spe)
        if (ret)
                goto out_free_irqs;
 
-       list_add(&spu->list, &spu_list);
+       list_add(&spu->list, &spu_list[spu->node]);
        mutex_unlock(&spu_mutex);
 
        pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n",
@@ -746,9 +755,13 @@ static void destroy_spu(struct spu *spu)
 static void cleanup_spu_base(void)
 {
        struct spu *spu, *tmp;
+       int node;
+
        mutex_lock(&spu_mutex);
-       list_for_each_entry_safe(spu, tmp, &spu_list, list)
-               destroy_spu(spu);
+       for (node = 0; node < MAX_NUMNODES; node++) {
+               list_for_each_entry_safe(spu, tmp, &spu_list[node], list)
+                       destroy_spu(spu);
+       }
        mutex_unlock(&spu_mutex);
        sysdev_class_unregister(&spu_sysdev_class);
 }
@@ -757,13 +770,16 @@ module_exit(cleanup_spu_base);
 static int __init init_spu_base(void)
 {
        struct device_node *node;
-       int ret;
+       int i, ret;
 
        /* create sysdev class for spus */
        ret = sysdev_class_register(&spu_sysdev_class);
        if (ret)
                return ret;
 
+       for (i = 0; i < MAX_NUMNODES; i++)
+               INIT_LIST_HEAD(&spu_list[i]);
+
        ret = -ENODEV;
        for (node = of_find_node_by_type(NULL, "spe");
                        node; node = of_find_node_by_type(node, "spe")) {