aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/cell/spu_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/cell/spu_base.c')
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c110
1 files changed, 85 insertions, 25 deletions
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index 7aa809d5a24..d5aeb3c6dd4 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -38,6 +38,7 @@
#include <asm/spu.h>
#include <asm/spu_priv1.h>
#include <asm/mmu_context.h>
+#include <asm/xmon.h>
#include "interrupt.h"
@@ -89,7 +90,30 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
printk("%s: invalid access during switch!\n", __func__);
return 1;
}
- if (!mm || (REGION_ID(ea) != USER_REGION_ID)) {
+ esid = (ea & ESID_MASK) | SLB_ESID_V;
+
+ switch(REGION_ID(ea)) {
+ case USER_REGION_ID:
+#ifdef CONFIG_HUGETLB_PAGE
+ if (in_hugepage_area(mm->context, ea))
+ llp = mmu_psize_defs[mmu_huge_psize].sllp;
+ else
+#endif
+ llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+ vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
+ SLB_VSID_USER | llp;
+ break;
+ case VMALLOC_REGION_ID:
+ llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+ vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) |
+ SLB_VSID_KERNEL | llp;
+ break;
+ case KERNEL_REGION_ID:
+ llp = mmu_psize_defs[mmu_linear_psize].sllp;
+ vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) |
+ SLB_VSID_KERNEL | llp;
+ break;
+ default:
/* Future: support kernel segments so that drivers
* can use SPUs.
*/
@@ -97,16 +121,6 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
return 1;
}
- esid = (ea & ESID_MASK) | SLB_ESID_V;
-#ifdef CONFIG_HUGETLB_PAGE
- if (in_hugepage_area(mm->context, ea))
- llp = mmu_psize_defs[mmu_huge_psize].sllp;
- else
-#endif
- llp = mmu_psize_defs[mmu_virtual_psize].sllp;
- vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
- SLB_VSID_USER | llp;
-
out_be64(&priv2->slb_index_W, spu->slb_replace);
out_be64(&priv2->slb_vsid_RW, vsid);
out_be64(&priv2->slb_esid_RW, esid);
@@ -320,6 +334,7 @@ static void spu_free_irqs(struct spu *spu)
}
static struct list_head spu_list[MAX_NUMNODES];
+static LIST_HEAD(spu_full_list);
static DEFINE_MUTEX(spu_mutex);
static void spu_init_channels(struct spu *spu)
@@ -364,8 +379,7 @@ struct spu *spu_alloc_node(int node)
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 %d\n",
- spu->isrc, spu->number, spu->node);
+ pr_debug("Got SPU %d %d\n", spu->number, spu->node);
spu_init_channels(spu);
}
mutex_unlock(&spu_mutex);
@@ -591,7 +605,6 @@ static int __init spu_map_interrupts_old(struct spu *spu, struct device_node *np
/* 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(NULL, IIC_IRQ_CLASS_0 | isrc);
@@ -758,15 +771,56 @@ struct sysdev_class spu_sysdev_class = {
set_kset_name("spu")
};
-static ssize_t spu_show_isrc(struct sys_device *sysdev, char *buf)
+int spu_add_sysdev_attr(struct sysdev_attribute *attr)
{
- struct spu *spu = container_of(sysdev, struct spu, sysdev);
- return sprintf(buf, "%d\n", spu->isrc);
+ struct spu *spu;
+ mutex_lock(&spu_mutex);
+
+ list_for_each_entry(spu, &spu_full_list, full_list)
+ sysdev_create_file(&spu->sysdev, attr);
+ mutex_unlock(&spu_mutex);
+ return 0;
}
-static SYSDEV_ATTR(isrc, 0400, spu_show_isrc, NULL);
+EXPORT_SYMBOL_GPL(spu_add_sysdev_attr);
+
+int spu_add_sysdev_attr_group(struct attribute_group *attrs)
+{
+ struct spu *spu;
+ mutex_lock(&spu_mutex);
-extern int attach_sysdev_to_node(struct sys_device *dev, int nid);
+ list_for_each_entry(spu, &spu_full_list, full_list)
+ sysfs_create_group(&spu->sysdev.kobj, attrs);
+
+ mutex_unlock(&spu_mutex);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group);
+
+
+void spu_remove_sysdev_attr(struct sysdev_attribute *attr)
+{
+ struct spu *spu;
+ mutex_lock(&spu_mutex);
+
+ list_for_each_entry(spu, &spu_full_list, full_list)
+ sysdev_remove_file(&spu->sysdev, attr);
+
+ mutex_unlock(&spu_mutex);
+}
+EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr);
+
+void spu_remove_sysdev_attr_group(struct attribute_group *attrs)
+{
+ struct spu *spu;
+ mutex_lock(&spu_mutex);
+
+ list_for_each_entry(spu, &spu_full_list, full_list)
+ sysfs_remove_group(&spu->sysdev.kobj, attrs);
+
+ mutex_unlock(&spu_mutex);
+}
+EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr_group);
static int spu_create_sysdev(struct spu *spu)
{
@@ -781,8 +835,6 @@ static int spu_create_sysdev(struct spu *spu)
return ret;
}
- if (spu->isrc != 0)
- sysdev_create_file(&spu->sysdev, &attr_isrc);
sysfs_add_device_to_node(&spu->sysdev, spu->nid);
return 0;
@@ -790,7 +842,6 @@ static int spu_create_sysdev(struct spu *spu)
static void spu_destroy_sysdev(struct spu *spu)
{
- sysdev_remove_file(&spu->sysdev, &attr_isrc);
sysfs_remove_device_from_node(&spu->sysdev, spu->nid);
sysdev_unregister(&spu->sysdev);
}
@@ -830,7 +881,7 @@ static int __init create_spu(struct device_node *spe)
if (ret)
goto out_unmap;
spin_lock_init(&spu->register_lock);
- spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1));
+ spu_mfc_sdr_setup(spu);
spu_mfc_sr1_set(spu, 0x33);
mutex_lock(&spu_mutex);
@@ -844,10 +895,13 @@ static int __init create_spu(struct device_node *spe)
goto out_free_irqs;
list_add(&spu->list, &spu_list[spu->node]);
+ list_add(&spu->full_list, &spu_full_list);
+ spu->devnode = of_node_get(spe);
+
mutex_unlock(&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 %d\n",
+ spu->name, spu->local_store,
spu->problem, spu->priv1, spu->priv2, spu->number);
goto out;
@@ -866,6 +920,9 @@ out:
static void destroy_spu(struct spu *spu)
{
list_del_init(&spu->list);
+ list_del_init(&spu->full_list);
+
+ of_node_put(spu->devnode);
spu_destroy_sysdev(spu);
spu_free_irqs(spu);
@@ -912,6 +969,9 @@ static int __init init_spu_base(void)
break;
}
}
+
+ xmon_register_spus(&spu_full_list);
+
return ret;
}
module_init(init_spu_base);