* [PATCH 10/15] celleb: SPU support routines
@ 2006-12-12 3:49 Ishizaki Kou
2006-12-12 12:59 ` Arnd Bergmann
0 siblings, 1 reply; 5+ messages in thread
From: Ishizaki Kou @ 2006-12-12 3:49 UTC (permalink / raw)
To: paulus, linuxppc-dev
SPU support routines for Celleb platform.
Signed-off-by: Kou Ishizaki <kou.ishizaki.co.jp>
---
Index: linux-powerpc-git/include/asm-powerpc/spu_priv1.h
diff -u linux-powerpc-git/include/asm-powerpc/spu_priv1.h:1.1.1.1 linux-powerpc-git/include/asm-powerpc/spu_priv1.h:1.2
--- linux-powerpc-git/include/asm-powerpc/spu_priv1.h:1.1.1.1 Wed Dec 6 08:24:04 2006
+++ linux-powerpc-git/include/asm-powerpc/spu_priv1.h Wed Dec 6 08:43:16 2006
@@ -207,6 +207,8 @@
extern const struct spu_priv1_ops spu_priv1_mmio_ops;
extern const struct spu_management_ops spu_management_of_ops;
+extern const struct spu_priv1_ops spu_priv1_beat_ops;
+extern const struct spu_management_ops spu_management_beat_ops;
#endif /* __KERNEL__ */
#endif
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/spu.h
diff -u /dev/null linux-powerpc-git/arch/powerpc/platforms/celleb/spu.h:1.2
--- /dev/null Mon Dec 11 20:37:36 2006
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/spu.h Thu Dec 7 16:41:39 2006
@@ -0,0 +1,36 @@
+/*
+ * spu hypervisor abstraction for Beat
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CELLEB_SPU_H
+#define _CELLEB_SPU_H
+
+struct spu_pdata {
+ int nid;
+ u64 unit_number;
+ u64 shadow_int_mask_RW[3];
+};
+
+static inline struct spu_pdata *spu_get_pdata(struct spu *spu)
+{
+ BUG_ON(!spu->pdata);
+ return spu->pdata;
+}
+
+#endif /* _CELLEB_SPU_H */
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/spu_manage.c
diff -u /dev/null linux-powerpc-git/arch/powerpc/platforms/celleb/spu_manage.c:1.4
--- /dev/null Mon Dec 11 20:37:36 2006
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/spu_manage.c Mon Dec 11 15:52:35 2006
@@ -0,0 +1,282 @@
+/*
+ * spu management operations for Beat
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This code is based on arch/powerpc/platforms/cell/spu_priv1_mmio.c:
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ * Copyright 2006 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+
+#include <asm/spu.h>
+#include <asm/spu_priv1.h>
+#include <asm/firmware.h>
+#include <asm/prom.h>
+
+#include "spu.h"
+
+static int __init find_spu_node_id(struct device_node *spe)
+{
+ const unsigned int *id;
+ struct device_node *cpu;
+ cpu = spe->parent->parent;
+ id = get_property(cpu, "node-id", NULL);
+ return id ? *id : 0;
+}
+
+static u64 __init find_spu_unit_number(struct device_node *spe)
+{
+ const unsigned int *reg;
+ reg = get_property(spe, "reg", NULL);
+ return reg ? (u64)*reg : 0ul;
+}
+
+static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe,
+ const char *prop)
+{
+ static DEFINE_MUTEX(add_spumem_mutex);
+
+ const struct address_prop {
+ unsigned long address;
+ unsigned int len;
+ } __attribute__((packed)) *p;
+ int proplen;
+
+ unsigned long start_pfn, nr_pages;
+ struct pglist_data *pgdata;
+ struct zone *zone;
+ int ret;
+
+ p = get_property(spe, prop, &proplen);
+ WARN_ON(proplen != sizeof (*p));
+
+ start_pfn = p->address >> PAGE_SHIFT;
+ nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ pgdata = NODE_DATA(spu_get_pdata(spu)->nid);
+ zone = pgdata->node_zones;
+
+ /* XXX rethink locking here */
+ mutex_lock(&add_spumem_mutex);
+ ret = __add_pages(zone, start_pfn, nr_pages);
+ mutex_unlock(&add_spumem_mutex);
+
+ return ret;
+}
+
+static void __iomem * __init map_spe_prop(struct spu *spu,
+ struct device_node *n, const char *name)
+{
+ const struct address_prop {
+ unsigned long address;
+ unsigned int len;
+ } __attribute__((packed)) *prop;
+
+ const void *p;
+ int proplen;
+ void __iomem *ret = NULL;
+ int err = 0;
+
+ p = get_property(n, name, &proplen);
+ if (proplen != sizeof (struct address_prop))
+ return NULL;
+
+ prop = p;
+
+ err = cell_spuprop_present(spu, n, name);
+ if (err && (err != -EEXIST))
+ goto out;
+
+ ret = ioremap(prop->address, prop->len);
+
+ out:
+ return ret;
+}
+
+static void spu_unmap(struct spu *spu)
+{
+ iounmap(spu->priv2);
+ iounmap(spu->problem);
+ iounmap((__force u8 __iomem *)spu->local_store);
+}
+
+static int __init spu_map_device(struct spu *spu, struct device_node *node)
+{
+ const char *prop;
+ int ret;
+
+ ret = -ENODEV;
+ spu->name = get_property(node, "name", NULL);
+ if (!spu->name)
+ goto out;
+
+ prop = get_property(node, "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(spu, node, "local-store");
+ if (!spu->local_store)
+ goto out;
+
+ prop = get_property(node, "problem", NULL);
+ if (!prop)
+ goto out_unmap;
+ spu->problem_phys = *(unsigned long *)prop;
+
+ spu->problem= map_spe_prop(spu, node, "problem");
+ if (!spu->problem)
+ goto out_unmap;
+
+ spu->priv2= map_spe_prop(spu, node, "priv2");
+ if (!spu->priv2)
+ goto out_unmap;
+ ret = 0;
+ goto out;
+
+out_unmap:
+ spu_unmap(spu);
+out:
+ return ret;
+}
+
+static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
+{
+ struct of_irq oirq;
+ int ret;
+ int i;
+
+ for (i=0; i < 3; i++) {
+ ret = of_irq_map_one(np, i, &oirq);
+ if (ret) {
+ pr_debug("spu_new: failed to get irq %d\n", i);
+ goto err;
+ }
+ ret = -EINVAL;
+ pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0],
+ oirq.controller->full_name);
+ spu->irqs[i] = irq_create_of_mapping(oirq.controller,
+ oirq.specifier, oirq.size);
+ if (spu->irqs[i] == NO_IRQ) {
+ pr_debug("spu_new: failed to map it !\n");
+ goto err;
+ }
+ }
+ return 0;
+
+err:
+ pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier,
+ spu->name);
+ for (; i >= 0; i--) {
+ if (spu->irqs[i] != NO_IRQ)
+ irq_dispose_mapping(spu->irqs[i]);
+ }
+ return ret;
+}
+
+static int __init of_enumerate_spus(int (*fn)(void *data))
+{
+ int ret;
+ struct device_node *node;
+
+ ret = -ENODEV;
+ for (node = of_find_node_by_type(NULL, "spe");
+ node; node = of_find_node_by_type(node, "spe")) {
+ ret = fn(node);
+ if (ret) {
+ printk(KERN_WARNING "%s: Error initializing %s\n",
+ __FUNCTION__, node->name);
+ break;
+ }
+ }
+ return ret;
+}
+
+static int __init beat_create_spu(struct spu *spu, void *data)
+{
+ int ret;
+ struct device_node *spe = (struct device_node *)data;
+
+ spu->pdata = kzalloc(sizeof(struct spu_pdata),
+ GFP_KERNEL);
+ if (!spu->pdata) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ spu->node = find_spu_node_id(spe);
+ if (spu->node >= MAX_NUMNODES) {
+ printk(KERN_WARNING "SPE %s on node %d ignored,"
+ " node number too big\n", spe->full_name, spu->node);
+ printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n");
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+ spu_get_pdata(spu)->nid = of_node_to_nid(spe);
+ if (spu_get_pdata(spu)->nid == -1)
+ spu_get_pdata(spu)->nid = 0;
+
+ spu_get_pdata(spu)->unit_number = find_spu_unit_number(spe);
+
+ ret = spu_map_device(spu, spe);
+ if (ret)
+ goto out_free;
+
+ ret = spu_map_interrupts(spu, spe);
+ if (ret)
+ goto out_unmap;
+
+ pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %d\n", spu->name,
+ spu->local_store, spu->problem, spu->priv2, spu->number);
+ goto out;
+
+out_unmap:
+ spu_unmap(spu);
+out_free:
+ kfree(spu->pdata);
+ spu->pdata = NULL;
+out:
+ return ret;
+}
+
+static int beat_destroy_spu(struct spu *spu)
+{
+ spu_unmap(spu);
+ kfree(spu->pdata);
+ spu->pdata = NULL;
+ return 0;
+}
+
+const struct spu_management_ops spu_management_beat_ops = {
+ .enumerate_spus = of_enumerate_spus,
+ .create_spu = beat_create_spu,
+ .destroy_spu = beat_destroy_spu,
+};
Index: linux-powerpc-git/arch/powerpc/platforms/celleb/spu_priv1.c
diff -u /dev/null linux-powerpc-git/arch/powerpc/platforms/celleb/spu_priv1.c:1.2
--- /dev/null Mon Dec 11 20:37:36 2006
+++ linux-powerpc-git/arch/powerpc/platforms/celleb/spu_priv1.c Thu Dec 7 16:43:32 2006
@@ -0,0 +1,210 @@
+/*
+ * spu hypervisor abstraction for Beat
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+
+#include <asm/spu.h>
+#include <asm/spu_priv1.h>
+
+#include "beat.h"
+#include "spu.h"
+
+static inline void _int_mask_set(struct spu *spu, int class, u64 mask)
+{
+ spu_get_pdata(spu)->shadow_int_mask_RW[class] = mask;
+ beat_set_irq_mask_for_spe(spu_get_pdata(spu)->unit_number, class, mask);
+}
+
+static inline u64 _int_mask_get(struct spu *spu, int class)
+{
+ return spu_get_pdata(spu)->shadow_int_mask_RW[class];
+}
+
+static void int_mask_set(struct spu *spu, int class, u64 mask)
+{
+ _int_mask_set(spu, class, mask);
+}
+
+static u64 int_mask_get(struct spu *spu, int class)
+{
+ return _int_mask_get(spu, class);
+}
+
+static void int_mask_and(struct spu *spu, int class, u64 mask)
+{
+ u64 old_mask;
+ old_mask = _int_mask_get(spu, class);
+ _int_mask_set(spu, class, old_mask & mask);
+}
+
+static void int_mask_or(struct spu *spu, int class, u64 mask)
+{
+ u64 old_mask;
+ old_mask = _int_mask_get(spu, class);
+ _int_mask_set(spu, class, old_mask | mask);
+}
+
+static void int_stat_clear(struct spu *spu, int class, u64 stat)
+{
+ beat_clear_interrupt_status_of_spe(spu_get_pdata(spu)->unit_number,
+ class, stat);
+}
+
+static u64 int_stat_get(struct spu *spu, int class)
+{
+ u64 int_stat;
+ beat_get_interrupt_status_of_spe(spu_get_pdata(spu)->unit_number,
+ class, &int_stat);
+ return int_stat;
+}
+
+static void cpu_affinity_set(struct spu *spu, int cpu)
+{
+ return;
+}
+
+static u64 mfc_dar_get(struct spu *spu)
+{
+ u64 dar;
+ beat_get_spe_privileged_state_1_registers(
+ spu_get_pdata(spu)->unit_number,
+ offsetof(struct spu_priv1, mfc_dar_RW), &dar);
+ return dar;
+}
+
+static u64 mfc_dsisr_get(struct spu *spu)
+{
+ u64 dsisr;
+ beat_get_spe_privileged_state_1_registers(
+ spu_get_pdata(spu)->unit_number,
+ offsetof(struct spu_priv1, mfc_dsisr_RW), &dsisr);
+ return dsisr;
+}
+
+static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
+{
+ beat_set_spe_privileged_state_1_registers(
+ spu_get_pdata(spu)->unit_number,
+ offsetof(struct spu_priv1, mfc_dsisr_RW), dsisr);
+}
+
+static void mfc_sdr_setup(struct spu *spu)
+{
+ return;
+}
+
+static void mfc_sr1_set(struct spu *spu, u64 sr1)
+{
+ beat_set_spe_privileged_state_1_registers(
+ spu_get_pdata(spu)->unit_number,
+ offsetof(struct spu_priv1, mfc_sr1_RW), sr1);
+}
+
+static u64 mfc_sr1_get(struct spu *spu)
+{
+ u64 sr1;
+ beat_get_spe_privileged_state_1_registers(
+ spu_get_pdata(spu)->unit_number,
+ offsetof(struct spu_priv1, mfc_sr1_RW), &sr1);
+ return sr1;
+}
+
+static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
+{
+ beat_set_spe_privileged_state_1_registers(
+ spu_get_pdata(spu)->unit_number,
+ offsetof(struct spu_priv1, mfc_tclass_id_RW), tclass_id);
+}
+
+static u64 mfc_tclass_id_get(struct spu *spu)
+{
+ u64 tclass_id;
+ beat_get_spe_privileged_state_1_registers(
+ spu_get_pdata(spu)->unit_number,
+ offsetof(struct spu_priv1, mfc_tclass_id_RW), &tclass_id);
+ return tclass_id;
+}
+
+static void tlb_invalidate(struct spu *spu)
+{
+ beat_set_spe_privileged_state_1_registers(
+ spu_get_pdata(spu)->unit_number,
+ offsetof(struct spu_priv1, tlb_invalidate_entry_W), 0ul);
+}
+
+static void resource_allocation_groupID_set(struct spu *spu, u64 id)
+{
+ beat_set_spe_privileged_state_1_registers(
+ spu_get_pdata(spu)->unit_number,
+ offsetof(struct spu_priv1, resource_allocation_groupID_RW),
+ id);
+}
+
+static u64 resource_allocation_groupID_get(struct spu *spu)
+{
+ u64 id;
+ beat_get_spe_privileged_state_1_registers(
+ spu_get_pdata(spu)->unit_number,
+ offsetof(struct spu_priv1, resource_allocation_groupID_RW),
+ &id);
+ return id;
+}
+
+static void resource_allocation_enable_set(struct spu *spu, u64 enable)
+{
+ beat_set_spe_privileged_state_1_registers(
+ spu_get_pdata(spu)->unit_number,
+ offsetof(struct spu_priv1, resource_allocation_enable_RW),
+ enable);
+}
+
+static u64 resource_allocation_enable_get(struct spu *spu)
+{
+ u64 enable;
+ beat_get_spe_privileged_state_1_registers(
+ spu_get_pdata(spu)->unit_number,
+ offsetof(struct spu_priv1, resource_allocation_enable_RW),
+ &enable);
+ return enable;
+}
+
+const struct spu_priv1_ops spu_priv1_beat_ops =
+{
+ .int_mask_and = int_mask_and,
+ .int_mask_or = int_mask_or,
+ .int_mask_set = int_mask_set,
+ .int_mask_get = int_mask_get,
+ .int_stat_clear = int_stat_clear,
+ .int_stat_get = int_stat_get,
+ .cpu_affinity_set = cpu_affinity_set,
+ .mfc_dar_get = mfc_dar_get,
+ .mfc_dsisr_get = mfc_dsisr_get,
+ .mfc_dsisr_set = mfc_dsisr_set,
+ .mfc_sdr_setup = mfc_sdr_setup,
+ .mfc_sr1_set = mfc_sr1_set,
+ .mfc_sr1_get = mfc_sr1_get,
+ .mfc_tclass_id_set = mfc_tclass_id_set,
+ .mfc_tclass_id_get = mfc_tclass_id_get,
+ .tlb_invalidate = tlb_invalidate,
+ .resource_allocation_groupID_set = resource_allocation_groupID_set,
+ .resource_allocation_groupID_get = resource_allocation_groupID_get,
+ .resource_allocation_enable_set = resource_allocation_enable_set,
+ .resource_allocation_enable_get = resource_allocation_enable_get,
+};
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH 10/15] celleb: SPU support routines
2006-12-12 3:49 [PATCH 10/15] celleb: SPU support routines Ishizaki Kou
@ 2006-12-12 12:59 ` Arnd Bergmann
2006-12-14 1:48 ` Ishizaki Kou
0 siblings, 1 reply; 5+ messages in thread
From: Arnd Bergmann @ 2006-12-12 12:59 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
On Tuesday 12 December 2006 04:49, Ishizaki Kou wrote:
> +static int __init find_spu_node_id(struct device_node *spe)
> +{
> + const unsigned int *id;
> + struct device_node *cpu;
> + cpu = spe->parent->parent;
> + id = get_property(cpu, "node-id", NULL);
> + return id ? *id : 0;
> +}
> +
> +static u64 __init find_spu_unit_number(struct device_node *spe)
> +{
> + const unsigned int *reg;
> + reg = get_property(spe, "reg", NULL);
> + return reg ? (u64)*reg : 0ul;
> +}
> +
> +static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe,
> + const char *prop)
> +{
> + static DEFINE_MUTEX(add_spumem_mutex);
> +
> + const struct address_prop {
> + unsigned long address;
> + unsigned int len;
> + } __attribute__((packed)) *p;
> + int proplen;
> +
> + unsigned long start_pfn, nr_pages;
> + struct pglist_data *pgdata;
> + struct zone *zone;
> + int ret;
> +
> + p = get_property(spe, prop, &proplen);
> + WARN_ON(proplen != sizeof (*p));
> +
> + start_pfn = p->address >> PAGE_SHIFT;
> + nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
> +
> + pgdata = NODE_DATA(spu_get_pdata(spu)->nid);
> + zone = pgdata->node_zones;
> +
> + /* XXX rethink locking here */
> + mutex_lock(&add_spumem_mutex);
> + ret = __add_pages(zone, start_pfn, nr_pages);
> + mutex_unlock(&add_spumem_mutex);
> +
> + return ret;
> +}
> +
> +static void __iomem * __init map_spe_prop(struct spu *spu,
> + struct device_node *n, const char *name)
> +{
> + const struct address_prop {
> + unsigned long address;
> + unsigned int len;
> + } __attribute__((packed)) *prop;
> +
> + const void *p;
> + int proplen;
> + void __iomem *ret = NULL;
> + int err = 0;
> +
> + p = get_property(n, name, &proplen);
> + if (proplen != sizeof (struct address_prop))
> + return NULL;
> +
> + prop = p;
> +
> + err = cell_spuprop_present(spu, n, name);
> + if (err && (err != -EEXIST))
> + goto out;
> +
> + ret = ioremap(prop->address, prop->len);
> +
> + out:
> + return ret;
> +}
> +
> +static void spu_unmap(struct spu *spu)
> +{
> + iounmap(spu->priv2);
> + iounmap(spu->problem);
> + iounmap((__force u8 __iomem *)spu->local_store);
> +}
> +
> +static int __init spu_map_device(struct spu *spu, struct device_node *node)
> +{
> + const char *prop;
> + int ret;
> +
> + ret = -ENODEV;
> + spu->name = get_property(node, "name", NULL);
> + if (!spu->name)
> + goto out;
> +
> + prop = get_property(node, "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(spu, node, "local-store");
> + if (!spu->local_store)
> + goto out;
> +
> + prop = get_property(node, "problem", NULL);
> + if (!prop)
> + goto out_unmap;
> + spu->problem_phys = *(unsigned long *)prop;
> +
> + spu->problem= map_spe_prop(spu, node, "problem");
> + if (!spu->problem)
> + goto out_unmap;
> +
> + spu->priv2= map_spe_prop(spu, node, "priv2");
> + if (!spu->priv2)
> + goto out_unmap;
> + ret = 0;
> + goto out;
> +
> +out_unmap:
> + spu_unmap(spu);
> +out:
> + return ret;
> +}
> +
> +static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
> +{
> + struct of_irq oirq;
> + int ret;
> + int i;
> +
> + for (i=0; i < 3; i++) {
> + ret = of_irq_map_one(np, i, &oirq);
> + if (ret) {
> + pr_debug("spu_new: failed to get irq %d\n", i);
> + goto err;
> + }
> + ret = -EINVAL;
> + pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0],
> + oirq.controller->full_name);
> + spu->irqs[i] = irq_create_of_mapping(oirq.controller,
> + oirq.specifier, oirq.size);
> + if (spu->irqs[i] == NO_IRQ) {
> + pr_debug("spu_new: failed to map it !\n");
> + goto err;
> + }
> + }
> + return 0;
> +
> +err:
> + pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier,
> + spu->name);
> + for (; i >= 0; i--) {
> + if (spu->irqs[i] != NO_IRQ)
> + irq_dispose_mapping(spu->irqs[i]);
> + }
> + return ret;
> +}
> +
> +static int __init of_enumerate_spus(int (*fn)(void *data))
> +{
> + int ret;
> + struct device_node *node;
> +
> + ret = -ENODEV;
> + for (node = of_find_node_by_type(NULL, "spe");
> + node; node = of_find_node_by_type(node, "spe")) {
> + ret = fn(node);
> + if (ret) {
> + printk(KERN_WARNING "%s: Error initializing %s\n",
> + __FUNCTION__, node->name);
> + break;
> + }
> + }
> + return ret;
> +}
> +
> +static int __init beat_create_spu(struct spu *spu, void *data)
> +{
> + int ret;
> + struct device_node *spe = (struct device_node *)data;
> +
> + spu->pdata = kzalloc(sizeof(struct spu_pdata),
> + GFP_KERNEL);
> + if (!spu->pdata) {
> + ret = -ENOMEM;
> + goto out;
> + }
> +
> + spu->node = find_spu_node_id(spe);
> + if (spu->node >= MAX_NUMNODES) {
> + printk(KERN_WARNING "SPE %s on node %d ignored,"
> + " node number too big\n", spe->full_name, spu->node);
> + printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n");
> + ret = -ENODEV;
> + goto out_free;
> + }
> +
> + spu_get_pdata(spu)->nid = of_node_to_nid(spe);
> + if (spu_get_pdata(spu)->nid == -1)
> + spu_get_pdata(spu)->nid = 0;
> +
> + spu_get_pdata(spu)->unit_number = find_spu_unit_number(spe);
> +
> + ret = spu_map_device(spu, spe);
> + if (ret)
> + goto out_free;
> +
> + ret = spu_map_interrupts(spu, spe);
> + if (ret)
> + goto out_unmap;
> +
> + pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %d\n", spu->name,
> + spu->local_store, spu->problem, spu->priv2, spu->number);
> + goto out;
> +
> +out_unmap:
> + spu_unmap(spu);
> +out_free:
> + kfree(spu->pdata);
> + spu->pdata = NULL;
> +out:
> + return ret;
> +}
> +
All this code is just the same as the one from
platforms/cell/spu_priv1_mmio.c, right? I guess it should really be a separate
file then that is used by both platforms in that case, in particular since
I have a few bug fixes for it that may easily get out of sync. I should
have probably noticed that when Geoff moved this code around in the ps3
merge, but it looks like we need to move it again.
The rest of this patch looks good.
Arnd <><
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH 10/15] celleb: SPU support routines
2006-12-12 12:59 ` Arnd Bergmann
@ 2006-12-14 1:48 ` Ishizaki Kou
2006-12-14 5:34 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 5+ messages in thread
From: Ishizaki Kou @ 2006-12-14 1:48 UTC (permalink / raw)
To: arnd; +Cc: linuxppc-dev, paulus
Arnd-san,
Thank you for your comment.
> On Tuesday 12 December 2006 04:49, Ishizaki Kou wrote:
>
> > +static int __init find_spu_node_id(struct device_node *spe)
> > +{
> > + const unsigned int *id;
> > + struct device_node *cpu;
> > + cpu = spe->parent->parent;
> > + id = get_property(cpu, "node-id", NULL);
> > + return id ? *id : 0;
> > +}
> > +
> > +static u64 __init find_spu_unit_number(struct device_node *spe)
> > +{
> > + const unsigned int *reg;
> > + reg = get_property(spe, "reg", NULL);
> > + return reg ? (u64)*reg : 0ul;
> > +}
> > +
> > +static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe,
> > + const char *prop)
> > +{
> > + static DEFINE_MUTEX(add_spumem_mutex);
> > +
> > + const struct address_prop {
> > + unsigned long address;
> > + unsigned int len;
> > + } __attribute__((packed)) *p;
> > + int proplen;
> > +
> > + unsigned long start_pfn, nr_pages;
> > + struct pglist_data *pgdata;
> > + struct zone *zone;
> > + int ret;
> > +
> > + p = get_property(spe, prop, &proplen);
> > + WARN_ON(proplen != sizeof (*p));
> > +
> > + start_pfn = p->address >> PAGE_SHIFT;
> > + nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
> > +
> > + pgdata = NODE_DATA(spu_get_pdata(spu)->nid);
> > + zone = pgdata->node_zones;
> > +
> > + /* XXX rethink locking here */
> > + mutex_lock(&add_spumem_mutex);
> > + ret = __add_pages(zone, start_pfn, nr_pages);
> > + mutex_unlock(&add_spumem_mutex);
> > +
> > + return ret;
> > +}
> > +
> > +static void __iomem * __init map_spe_prop(struct spu *spu,
> > + struct device_node *n, const char *name)
> > +{
> > + const struct address_prop {
> > + unsigned long address;
> > + unsigned int len;
> > + } __attribute__((packed)) *prop;
> > +
> > + const void *p;
> > + int proplen;
> > + void __iomem *ret = NULL;
> > + int err = 0;
> > +
> > + p = get_property(n, name, &proplen);
> > + if (proplen != sizeof (struct address_prop))
> > + return NULL;
> > +
> > + prop = p;
> > +
> > + err = cell_spuprop_present(spu, n, name);
> > + if (err && (err != -EEXIST))
> > + goto out;
> > +
> > + ret = ioremap(prop->address, prop->len);
> > +
> > + out:
> > + return ret;
> > +}
> > +
> > +static void spu_unmap(struct spu *spu)
> > +{
> > + iounmap(spu->priv2);
> > + iounmap(spu->problem);
> > + iounmap((__force u8 __iomem *)spu->local_store);
> > +}
> > +
> > +static int __init spu_map_device(struct spu *spu, struct device_node *node)
> > +{
> > + const char *prop;
> > + int ret;
> > +
> > + ret = -ENODEV;
> > + spu->name = get_property(node, "name", NULL);
> > + if (!spu->name)
> > + goto out;
> > +
> > + prop = get_property(node, "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(spu, node, "local-store");
> > + if (!spu->local_store)
> > + goto out;
> > +
> > + prop = get_property(node, "problem", NULL);
> > + if (!prop)
> > + goto out_unmap;
> > + spu->problem_phys = *(unsigned long *)prop;
> > +
> > + spu->problem= map_spe_prop(spu, node, "problem");
> > + if (!spu->problem)
> > + goto out_unmap;
> > +
> > + spu->priv2= map_spe_prop(spu, node, "priv2");
> > + if (!spu->priv2)
> > + goto out_unmap;
> > + ret = 0;
> > + goto out;
> > +
> > +out_unmap:
> > + spu_unmap(spu);
> > +out:
> > + return ret;
> > +}
> > +
> > +static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
> > +{
> > + struct of_irq oirq;
> > + int ret;
> > + int i;
> > +
> > + for (i=0; i < 3; i++) {
> > + ret = of_irq_map_one(np, i, &oirq);
> > + if (ret) {
> > + pr_debug("spu_new: failed to get irq %d\n", i);
> > + goto err;
> > + }
> > + ret = -EINVAL;
> > + pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0],
> > + oirq.controller->full_name);
> > + spu->irqs[i] = irq_create_of_mapping(oirq.controller,
> > + oirq.specifier, oirq.size);
> > + if (spu->irqs[i] == NO_IRQ) {
> > + pr_debug("spu_new: failed to map it !\n");
> > + goto err;
> > + }
> > + }
> > + return 0;
> > +
> > +err:
> > + pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier,
> > + spu->name);
> > + for (; i >= 0; i--) {
> > + if (spu->irqs[i] != NO_IRQ)
> > + irq_dispose_mapping(spu->irqs[i]);
> > + }
> > + return ret;
> > +}
> > +
> > +static int __init of_enumerate_spus(int (*fn)(void *data))
> > +{
> > + int ret;
> > + struct device_node *node;
> > +
> > + ret = -ENODEV;
> > + for (node = of_find_node_by_type(NULL, "spe");
> > + node; node = of_find_node_by_type(node, "spe")) {
> > + ret = fn(node);
> > + if (ret) {
> > + printk(KERN_WARNING "%s: Error initializing %s\n",
> > + __FUNCTION__, node->name);
> > + break;
> > + }
> > + }
> > + return ret;
> > +}
> > +> > +static int __init beat_create_spu(struct spu *spu, void *data)
> > +{
> > + int ret;
> > + struct device_node *spe = (struct device_node *)data;
> > +
> > + spu->pdata = kzalloc(sizeof(struct spu_pdata),
> > + GFP_KERNEL);
> > + if (!spu->pdata) {
> > + ret = -ENOMEM;
> > + goto out;
> > + }
> > +
> > + spu->node = find_spu_node_id(spe);
> > + if (spu->node >= MAX_NUMNODES) {
> > + printk(KERN_WARNING "SPE %s on node %d ignored,"
> > + " node number too big\n", spe->full_name, spu->node);
> > + printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n");
> > + ret = -ENODEV;
> > + goto out_free;
> > + }
> > +
> > + spu_get_pdata(spu)->nid = of_node_to_nid(spe);
> > + if (spu_get_pdata(spu)->nid == -1)
> > + spu_get_pdata(spu)->nid = 0;
> > +
> > + spu_get_pdata(spu)->unit_number = find_spu_unit_number(spe);
> > +
> > + ret = spu_map_device(spu, spe);
> > + if (ret)
> > + goto out_free;
> > +
> > + ret = spu_map_interrupts(spu, spe);
> > + if (ret)
> > + goto out_unmap;
> > +
> > + pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %d\n", spu->name,
> > + spu->local_store, spu->problem, spu->priv2, spu->number);
> > + goto out;
> > +
> > +out_unmap:
> > + spu_unmap(spu);
> > +out_free:
> > + kfree(spu->pdata);
> > + spu->pdata = NULL;
> > +out:
> > + return ret;
> > +}
> > +
>
> All this code is just the same as the one from
> platforms/cell/spu_priv1_mmio.c, right? I guess it should really be a separate
> file then that is used by both platforms in that case, in particular since
> I have a few bug fixes for it that may easily get out of sync. I should
> have probably noticed that when Geoff moved this code around in the ps3
> merge, but it looks like we need to move it again.
Most of our SPU management routines are imported from
platforms/cell/spu_priv1_mmio.c and some functions are modified for
Beat.
There are two differences with Cell Blade.
- platform private data
Beat requires some private members and initailizing.
- device-tree
Standard binding doesn't exist. Our DT is similar to 'old' style of
Cell Blade but not identical.
We think the integration of codes is preferable, but this is our first code
for public and we need time to modify them. So, this time we hope they are
merged into as it is. We'd like to discuss and modify our codes toward
integrated codes after this first merge.
Best regards,
Kou Ishizaki
Toshiba
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH 10/15] celleb: SPU support routines
2006-12-14 1:48 ` Ishizaki Kou
@ 2006-12-14 5:34 ` Benjamin Herrenschmidt
2006-12-15 6:03 ` Akira Iguchi
0 siblings, 1 reply; 5+ messages in thread
From: Benjamin Herrenschmidt @ 2006-12-14 5:34 UTC (permalink / raw)
To: Ishizaki Kou; +Cc: linuxppc-dev, paulus, arnd
> We think the integration of codes is preferable, but this is our first code
> for public and we need time to modify them. So, this time we hope they are
> merged into as it is. We'd like to discuss and modify our codes toward
> integrated codes after this first merge.
As much as I would have liked to integrate your code in 2.6.20, it seems
that it won't be possible (as I told you privately earlier today). Linus
is getting fairly strict about the 2 weeks window which closed... today.
We'll merge the code in powerpc.git in the meantime, not in it's current
form but after you have addresses some of the remaning comments. That
way, it will be in -mm at least, and in the powerpc tree which means
that from there, you won't have to rebase it every time we change
something and it will get in first thing in 2.6.21 merge window.
That will also give us more time to address some of the remaining issues
that I'm not too happy with, like some of the PCI bits.
In general, code should be ready to merge -before- the merge window open
or at worst during the first week, the second week being mostly to flush
out bits that collided or needed rebasing etc...
In a similar vein, while some of the PS3 code was actually merged, a lot
of it wasn't yet (drivers etc...) are they are not ready, so it looks
like 2.6.20 won't be the "big cell relase" but 2.6.21 will be instead.
Cheers,
Ben.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 10/15] celleb: SPU support routines
2006-12-14 5:34 ` Benjamin Herrenschmidt
@ 2006-12-15 6:03 ` Akira Iguchi
0 siblings, 0 replies; 5+ messages in thread
From: Akira Iguchi @ 2006-12-15 6:03 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, paulus, arnd
>As much as I would have liked to integrate your code in 2.6.20, it seems
>that it won't be possible (as I told you privately earlier today). Linus
>is getting fairly strict about the 2 weeks window which closed... today.
>
>We'll merge the code in powerpc.git in the meantime, not in it's current
>form but after you have addresses some of the remaning comments. That
>way, it will be in -mm at least, and in the powerpc tree which means
>that from there, you won't have to rebase it every time we change
>something and it will get in first thing in 2.6.21 merge window.
>
>That will also give us more time to address some of the remaining issues
>that I'm not too happy with, like some of the PCI bits.
Then we will make efforts to merge our code in powerpc.git tree.
Next time, we will send patches and fix some problems in our code
as timely as possible.
>In general, code should be ready to merge -before- the merge window open
>or at worst during the first week, the second week being mostly to flush
>out bits that collided or needed rebasing etc...
>
>In a similar vein, while some of the PS3 code was actually merged, a lot
>of it wasn't yet (drivers etc...) are they are not ready, so it looks
>like 2.6.20 won't be the "big cell relase" but 2.6.21 will be instead.
We hope 2.6.21 will be the "big cell release", too.
To realize that, we will do the best.
Best regards,
Akira Iguchi
Toshiba
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2006-12-15 6:02 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-12-12 3:49 [PATCH 10/15] celleb: SPU support routines Ishizaki Kou
2006-12-12 12:59 ` Arnd Bergmann
2006-12-14 1:48 ` Ishizaki Kou
2006-12-14 5:34 ` Benjamin Herrenschmidt
2006-12-15 6:03 ` Akira Iguchi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox