Merge branch 'linux-2.6' into for-linus
[linux-2.6-block.git] / arch / powerpc / platforms / cell / spu_base.c
index 7aa809d5a244230f14ce6a9042efc918063409cf..d5aeb3c6dd457a234045d2c174fb97eeb012b559 100644 (file)
@@ -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);