[PATCH] spufs split off platform code
Geoff Levand
geoffrey.levand at am.sony.com
Sat Jan 28 10:51:36 EST 2006
spufs-split-off-platform-code.patch:
This patch moves the platform dependent code from
spu_base.c to spu_priv1.c.
Signed-off-by: Masato Noguchi <Masato.Noguchi at jp.sony.com>
Signed-off-by: Geoff Levand <geoffrey.levand at am.sony.com>
--
Index: alp-linux--dev--10/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- alp-linux--dev--10.orig/arch/powerpc/platforms/cell/spu_base.c 2006-01-27 10:45:30.000000000 -0800
+++ alp-linux--dev--10/arch/powerpc/platforms/cell/spu_base.c 2006-01-27 11:27:34.000000000 -0800
@@ -31,13 +31,10 @@
#include <linux/wait.h>
#include <asm/io.h>
-#include <asm/prom.h>
#include <asm/semaphore.h>
#include <asm/spu.h>
#include <asm/mmu_context.h>
-#include "interrupt.h"
-
static int __spu_trap_invalid_dma(struct spu *spu)
{
pr_debug("%s\n", __FUNCTION__);
@@ -296,53 +293,6 @@
return stat ? IRQ_HANDLED : IRQ_NONE;
}
-static int
-spu_request_irqs(struct spu *spu)
-{
- int ret;
- int irq_base;
-
- irq_base = IIC_NODE_STRIDE * spu->node + IIC_SPE_OFFSET;
-
- snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0", spu->number);
- ret = request_irq(irq_base + spu->isrc,
- spu_irq_class_0, 0, spu->irq_c0, spu);
- if (ret)
- goto out;
-
- snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1", spu->number);
- ret = request_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc,
- spu_irq_class_1, 0, spu->irq_c1, spu);
- if (ret)
- goto out1;
-
- snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2", spu->number);
- ret = request_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->isrc,
- spu_irq_class_2, 0, spu->irq_c2, spu);
- if (ret)
- goto out2;
- goto out;
-
-out2:
- free_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc, spu);
-out1:
- free_irq(irq_base + spu->isrc, spu);
-out:
- return ret;
-}
-
-static void
-spu_free_irqs(struct spu *spu)
-{
- int irq_base;
-
- irq_base = IIC_NODE_STRIDE * spu->node + IIC_SPE_OFFSET;
-
- free_irq(irq_base + spu->isrc, spu);
- free_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc, spu);
- free_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->isrc, spu);
-}
-
static LIST_HEAD(spu_list);
static DECLARE_MUTEX(spu_mutex);
@@ -388,7 +338,7 @@
if (!list_empty(&spu_list)) {
spu = list_entry(spu_list.next, struct spu, list);
list_del_init(&spu->list);
- pr_debug("Got SPU %x %d\n", spu->isrc, spu->number);
+ pr_debug("Got SPU %d\n", spu->number);
} else {
pr_debug("No SPU left\n");
spu = NULL;
@@ -509,103 +459,37 @@
return ret;
}
-void spu_irq_setaffinity(struct spu *spu, int cpu)
-{
- u64 target = iic_get_target_id(cpu);
- u64 route = target << 48 | target << 32 | target << 16;
- spu_int_route_set(spu, route);
-}
-EXPORT_SYMBOL_GPL(spu_irq_setaffinity);
-
-static void __iomem * __init map_spe_prop(struct device_node *n,
- const char *name)
-{
- struct address_prop {
- unsigned long address;
- unsigned int len;
- } __attribute__((packed)) *prop;
-
- void *p;
- int proplen;
-
- p = get_property(n, name, &proplen);
- if (proplen != sizeof (struct address_prop))
- return NULL;
-
- prop = p;
-
- return ioremap(prop->address, prop->len);
-}
-
static void spu_unmap(struct spu *spu)
{
- iounmap(spu->priv2);
iounmap(spu->priv1);
+ iounmap(spu->priv2);
iounmap(spu->problem);
iounmap((u8 __iomem *)spu->local_store);
}
-static int __init spu_map_device(struct spu *spu, struct device_node *spe)
+static int __init spu_map(struct spu *spu)
{
- char *prop;
- int ret;
-
- ret = -ENODEV;
- prop = get_property(spe, "isrc", NULL);
- if (!prop)
- goto out;
- spu->isrc = *(unsigned int *)prop;
-
- spu->name = get_property(spe, "name", NULL);
- if (!spu->name)
- goto out;
-
- prop = get_property(spe, "local-store", NULL);
- if (!prop)
- goto out;
- spu->local_store_phys = *(unsigned long *)prop;
-
- /* we use local store as ram, not io memory */
- spu->local_store = (void __force *)map_spe_prop(spe, "local-store");
- if (!spu->local_store)
- goto out;
-
- prop = get_property(spe, "problem", NULL);
- if (!prop)
- goto out_unmap;
- spu->problem_phys = *(unsigned long *)prop;
-
- spu->problem= map_spe_prop(spe, "problem");
- if (!spu->problem)
- goto out_unmap;
-
- spu->priv1= map_spe_prop(spe, "priv1");
- /* priv1 is not available on a hypervisor */
-
- spu->priv2= map_spe_prop(spe, "priv2");
- if (!spu->priv2)
- goto out_unmap;
- ret = 0;
- goto out;
-
-out_unmap:
- spu_unmap(spu);
-out:
- return ret;
-}
-
-static int __init find_spu_node_id(struct device_node *spe)
-{
- unsigned int *id;
- struct device_node *cpu;
-
- cpu = spe->parent->parent;
- id = (unsigned int *)get_property(cpu, "node-id", NULL);
-
- return id ? *id : 0;
+ spu->local_store = ioremap(spu->local_store_phys.addr,
+ spu->local_store_phys.size);
+ spu->problem = ioremap(spu->problem_phys.addr,
+ spu->problem_phys.size);
+ spu->priv2 = ioremap(spu->priv2_phys.addr, spu->priv2_phys.size);
+ spu->priv1 = spu->priv1_phys.addr
+ ? ioremap(spu->priv1_phys.addr, spu->priv1_phys.size)
+ : NULL;
+
+ if (!spu->local_store || !spu->problem || !spu->priv2
+ || (!spu->priv1_phys.addr != !spu->priv1)) {
+ pr_debug("%s failed: %p %p %p %p\n", __func__, spu->local_store,
+ spu->problem, spu->priv2, spu->priv1);
+ spu_unmap(spu);
+ return -ENODEV;
+ }
+
+ return 0;
}
-static int __init create_spu(struct device_node *spe)
+int create_spu(void *spu_setup_data)
{
struct spu *spu;
int ret;
@@ -616,11 +500,14 @@
if (!spu)
goto out;
- ret = spu_map_device(spu, spe);
+ ret = spu_setup(spu, spu_setup_data);
+ if (ret)
+ goto out_free;
+
+ ret = spu_map(spu);
if (ret)
goto out_free;
- spu->node = find_spu_node_id(spe);
spu->stop_code = 0;
spu->slb_replace = 0;
spu->mm = NULL;
@@ -643,15 +530,16 @@
down(&spu_mutex);
spu->number = number++;
- ret = spu_request_irqs(spu);
+ ret = spu_request_irqs(spu, spu_irq_class_0, spu_irq_class_1,
+ spu_irq_class_2);
if (ret)
goto out_unmap;
list_add(&spu->list, &spu_list);
up(&spu_mutex);
- pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n",
- spu->name, spu->isrc, spu->local_store,
+ pr_debug(KERN_DEBUG "Using SPE %s (%p) %p %p %p %p %d\n",
+ spu->name, spu, spu->local_store,
spu->problem, spu->priv1, spu->priv2, spu->number);
goto out;
@@ -663,6 +551,7 @@
out:
return ret;
}
+EXPORT_SYMBOL_GPL(create_spu);
static void destroy_spu(struct spu *spu)
{
@@ -685,31 +574,11 @@
static int __init init_spu_base(void)
{
- struct device_node *node;
- int ret;
-
- ret = -ENODEV;
- for (node = of_find_node_by_type(NULL, "spe");
- node; node = of_find_node_by_type(node, "spe")) {
- ret = create_spu(node);
- if (ret) {
- printk(KERN_WARNING "%s: Error initializing %s\n",
- __FUNCTION__, node->name);
- cleanup_spu_base();
- break;
- }
- }
- /* in some old firmware versions, the spe is called 'spc', so we
- look for that as well */
- for (node = of_find_node_by_type(NULL, "spc");
- node; node = of_find_node_by_type(node, "spc")) {
- ret = create_spu(node);
- if (ret) {
- printk(KERN_WARNING "%s: Error initializing %s\n",
- __FUNCTION__, node->name);
- cleanup_spu_base();
- break;
- }
+ int ret = enum_and_create_spu();
+ if (ret) {
+ printk(KERN_WARNING "%s: Error initializing spu-base\n",
+ __FUNCTION__);
+ cleanup_spu_base();
}
return ret;
}
Index: alp-linux--dev--10/arch/powerpc/platforms/cell/spu_priv1.c
===================================================================
--- alp-linux--dev--10.orig/arch/powerpc/platforms/cell/spu_priv1.c 2006-01-27 10:45:30.000000000 -0800
+++ alp-linux--dev--10/arch/powerpc/platforms/cell/spu_priv1.c 2006-01-27 11:31:06.000000000 -0800
@@ -5,6 +5,202 @@
#include <asm/io.h>
#include <asm/spu.h>
+#include <asm/prom.h>
+#include "interrupt.h"
+
+struct spu_priv_data {
+ u32 isrc;
+ u32 node;
+};
+
+static int __init find_spu_node_id(struct device_node *spe)
+{
+ unsigned int *id;
+ struct device_node *cpu;
+
+ cpu = spe->parent->parent;
+ id = (unsigned int *)get_property(cpu, "node-id", NULL);
+
+ return id ? *id : 0;
+}
+
+static void __init get_spe_property(struct device_node *n, const char *name,
+ struct spu_phys* phys)
+{
+ struct address_prop {
+ unsigned long address;
+ unsigned int len;
+ } __attribute__((packed)) *prop;
+
+ void *p;
+ int proplen;
+
+ p = get_property(n, name, &proplen);
+ if (proplen != sizeof (struct address_prop)) {
+ phys->addr = phys->size = 0;
+ return;
+ }
+ prop = p;
+
+ phys->addr = prop->address;
+ phys->size = prop->len;
+}
+
+int __init enum_and_create_spu(void)
+{
+ struct device_node *node;
+ int ret;
+
+ ret = -ENODEV;
+ for (node = of_find_node_by_type(NULL, "spe");
+ node; node = of_find_node_by_type(node, "spe")) {
+ ret = create_spu(node);
+ if (ret)
+ break;
+ }
+ /* in some old firmware versions, the spe is called 'spc', so we
+ look for that as well */
+ for (node = of_find_node_by_type(NULL, "spc");
+ node; node = of_find_node_by_type(node, "spc")) {
+ ret = create_spu(node);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(enum_and_create_spu);
+
+int __init spu_setup(struct spu *spu, void *spu_setup_data)
+{
+ struct device_node *spe = spu_setup_data;
+ char *prop;
+
+ spu->priv_data = kmalloc(sizeof(struct spu_priv_data), GFP_KERNEL);
+ if (!spu->priv_data)
+ return -ENOMEM;
+
+ spu->priv_data->node = find_spu_node_id(spe);
+
+ prop = get_property(spe, "isrc", NULL);
+ if (!prop)
+ goto out_free;
+ spu->priv_data->isrc = *(unsigned int *)prop;
+
+ spu->name = get_property(spe, "name", NULL);
+ if (!spu->name)
+ goto out_free;
+
+ get_spe_property(spe, "local-store", &spu->local_store_phys);
+ if (!spu->local_store_phys.addr)
+ goto out_free;
+
+ get_spe_property(spe, "problem", &spu->problem_phys);
+ if (!spu->problem_phys.addr)
+ goto out_free;
+
+ get_spe_property(spe, "priv1", &spu->priv1_phys);
+
+ get_spe_property(spe, "priv2", &spu->priv2_phys);
+ if (!spu->priv2_phys.addr)
+ goto out_free;
+
+ return 0;
+
+out_free:
+ printk(KERN_WARNING "%s: no spu device found\n", __func__);
+ pr_debug("%s: error (%p)\n", __func__, spu);
+ kfree(spu->priv_data);
+ spu->priv_data = NULL;
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(spu_setup);
+
+void spu_free_priv_data(struct spu *spu)
+{
+ if (spu->priv_data) {
+ kfree(spu->priv_data);
+ spu->priv_data = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(spu_free_priv_data);
+
+int spu_request_irqs(struct spu *spu,
+ irqreturn_t (*cls0)(int, void *, struct pt_regs *),
+ irqreturn_t (*cls1)(int, void *, struct pt_regs *),
+ irqreturn_t (*cls2)(int, void *, struct pt_regs *))
+{
+ int ret;
+ int irq_base;
+
+ BUG_ON(spu->priv_data);
+
+ if(!spu->priv_data) {
+ spu->priv_data = kmalloc(sizeof(struct spu_priv_data),
+ GFP_KERNEL);
+
+ if(!spu->priv_data) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+
+ irq_base = IIC_NODE_STRIDE * spu->priv_data->node + IIC_SPE_OFFSET;
+
+ snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0", spu->number);
+ ret = request_irq(irq_base + spu->priv_data->isrc,
+ cls0, 0, spu->irq_c0, spu);
+ if (ret)
+ goto out;
+
+ snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1", spu->number);
+ ret = request_irq(irq_base + IIC_CLASS_STRIDE + spu->priv_data->isrc,
+ cls1, 0, spu->irq_c1, spu);
+ if (ret)
+ goto out1;
+
+ snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2", spu->number);
+ ret = request_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->priv_data->isrc,
+ cls2, 0, spu->irq_c2, spu);
+ if (ret)
+ goto out2;
+ goto out;
+
+out2:
+ free_irq(irq_base + IIC_CLASS_STRIDE + spu->priv_data->isrc, spu);
+out1:
+ free_irq(irq_base + spu->priv_data->isrc, spu);
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(spu_request_irqs);
+
+void spu_free_irqs(struct spu *spu)
+{
+ int irq_base;
+
+ if(!spu->priv_data) {
+ pr_debug("null priv_data in %p\n", spu);
+ return;
+ }
+
+ irq_base = IIC_NODE_STRIDE * spu->priv_data->node + IIC_SPE_OFFSET;
+
+ free_irq(irq_base + spu->priv_data->isrc, spu);
+ free_irq(irq_base + IIC_CLASS_STRIDE + spu->priv_data->isrc, spu);
+ free_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->priv_data->isrc, spu);
+
+ kfree(spu->priv_data);
+ spu->priv_data = NULL;
+}
+EXPORT_SYMBOL_GPL(spu_free_irqs);
+
+void spu_irq_setaffinity(struct spu *spu, int cpu)
+{
+ u64 target = iic_get_target_id(cpu);
+ u64 route = target << 48 | target << 32 | target << 16;
+ spu_int_route_set(spu, route);
+}
+EXPORT_SYMBOL_GPL(spu_irq_setaffinity);
void spu_int_mask_and(struct spu *spu, int class, u64 mask)
{
Index: alp-linux--dev--10/include/asm-powerpc/spu.h
===================================================================
--- alp-linux--dev--10.orig/include/asm-powerpc/spu.h 2006-01-27 10:45:30.000000000 -0800
+++ alp-linux--dev--10/include/asm-powerpc/spu.h 2006-01-27 11:02:29.000000000 -0800
@@ -25,6 +25,7 @@
#include <linux/config.h>
#include <linux/kref.h>
#include <linux/workqueue.h>
+#include <linux/interrupt.h>
#define LS_SIZE (256 * 1024)
#define LS_ADDR_MASK (LS_SIZE - 1)
@@ -103,20 +104,26 @@
struct spu_context;
struct spu_runqueue;
+struct spu_priv_data;
+struct spu_phys {
+ unsigned long addr;
+ unsigned long size;
+};
struct spu {
+ struct spu_priv_data *priv_data; /* opaque */
char *name;
- unsigned long local_store_phys;
+ struct spu_phys local_store_phys;
u8 *local_store;
- unsigned long problem_phys;
+ struct spu_phys problem_phys;
struct spu_problem __iomem *problem;
+ struct spu_phys priv1_phys;
struct spu_priv1 __iomem *priv1;
+ struct spu_phys priv2_phys;
struct spu_priv2 __iomem *priv2;
struct list_head list;
struct list_head sched_list;
int number;
- u32 isrc;
- u32 node;
u64 flags;
u64 dar;
u64 dsisr;
@@ -178,7 +185,19 @@
}
#endif
-/* access to priv1 registers */
+/* base setup routines */
+int create_spu(void *spu_setup_data);
+
+/* platform setup routines */
+int enum_and_create_spu(void);
+int spu_setup(struct spu *spu, void *spu_setup_data);
+int spu_request_irqs(struct spu *spu,
+ irqreturn_t (*cls0)(int, void *, struct pt_regs *),
+ irqreturn_t (*cls1)(int, void *, struct pt_regs *),
+ irqreturn_t (*cls2)(int, void *, struct pt_regs *));
+void spu_free_irqs(struct spu *spu);
+
+/* platform priv1 register access */
void spu_int_mask_and(struct spu *spu, int class, u64 mask);
void spu_int_mask_or(struct spu *spu, int class, u64 mask);
void spu_int_mask_set(struct spu *spu, int class, u64 mask);
More information about the Linuxppc64-dev
mailing list