[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