]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/mips/kernel/vpe.c
[MIPS] i8253: Cleanup.
[linux-2.6-omap-h63xx.git] / arch / mips / kernel / vpe.c
index c726c47cd2c359f38080ecdb455348a603742ec7..436a64ff3989485feebd20b388212b832738f37f 100644 (file)
@@ -64,6 +64,10 @@ typedef void *vpe_handle;
 /* If this is set, the section belongs in the init part of the module */
 #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
 
+/*
+ * The number of TCs and VPEs physically available on the core
+ */
+static int hw_tcs, hw_vpes;
 static char module_name[] = "vpe";
 static int major;
 static const int minor = 1;    /* fixed for now  */
@@ -126,6 +130,8 @@ struct vpe {
 
        /* the list of who wants to know when something major happens */
        struct list_head notify;
+
+       unsigned int ntcs;
 };
 
 struct tc {
@@ -738,6 +744,7 @@ static int vpe_run(struct vpe * v)
         * here...  Or set $a3 to zero and define DFLT_STACK_SIZE and
         * DFLT_HEAP_SIZE when you compile your program
         */
+       mttgpr(6, v->ntcs);
        mttgpr(7, physical_memsize);
 
        /* set up VPE1 */
@@ -929,8 +936,18 @@ static int vpe_elfload(struct vpe * v)
 
                }
        } else {
-               for (i = 0; i < hdr->e_shnum; i++) {
+               struct elf_phdr *phdr = (struct elf_phdr *) ((char *)hdr + hdr->e_phoff);
 
+               for (i = 0; i < hdr->e_phnum; i++) {
+                       if (phdr->p_type != PT_LOAD)
+                               continue;
+
+                       memcpy((void *)phdr->p_paddr, (char *)hdr + phdr->p_offset, phdr->p_filesz);
+                       memset((void *)phdr->p_paddr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
+                       phdr++;
+               }
+
+               for (i = 0; i < hdr->e_shnum; i++) {
                        /* Internal symbols and strings. */
                        if (sechdrs[i].sh_type == SHT_SYMTAB) {
                                symindex = i;
@@ -941,39 +958,6 @@ static int vpe_elfload(struct vpe * v)
                                   magic symbols */
                                sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
                        }
-
-                       /* filter sections we dont want in the final image */
-                       if (!(sechdrs[i].sh_flags & SHF_ALLOC) ||
-                           (sechdrs[i].sh_type == SHT_MIPS_REGINFO)) {
-                               printk( KERN_DEBUG " ignoring section, "
-                                       "name %s type %x address 0x%x \n",
-                                       secstrings + sechdrs[i].sh_name,
-                                       sechdrs[i].sh_type, sechdrs[i].sh_addr);
-                               continue;
-                       }
-
-                       if (sechdrs[i].sh_addr < (unsigned int)v->load_addr) {
-                               printk( KERN_WARNING "VPE loader: "
-                                       "fully linked image has invalid section, "
-                                       "name %s type %x address 0x%x, before load "
-                                       "address of 0x%x\n",
-                                       secstrings + sechdrs[i].sh_name,
-                                       sechdrs[i].sh_type, sechdrs[i].sh_addr,
-                                       (unsigned int)v->load_addr);
-                               return -ENOEXEC;
-                       }
-
-                       printk(KERN_DEBUG " copying section sh_name %s, sh_addr 0x%x "
-                              "size 0x%x0 from x%p\n",
-                              secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr,
-                              sechdrs[i].sh_size, hdr + sechdrs[i].sh_offset);
-
-                       if (sechdrs[i].sh_type != SHT_NOBITS)
-                               memcpy((void *)sechdrs[i].sh_addr,
-                                      (char *)hdr + sechdrs[i].sh_offset,
-                                      sechdrs[i].sh_size);
-                       else
-                               memset((void *)sechdrs[i].sh_addr, 0, sechdrs[i].sh_size);
                }
        }
 
@@ -1037,7 +1021,7 @@ static int getcwd(char *buff, int size)
        old_fs = get_fs();
        set_fs(KERNEL_DS);
 
-       ret = sys_getcwd(buff,size);
+       ret = sys_getcwd(buff, size);
 
        set_fs(old_fs);
 
@@ -1333,16 +1317,81 @@ static void kspd_sp_exit( int sp_id)
 }
 #endif
 
-static struct device *vpe_dev;
+static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
+                         const char *buf, size_t len)
+{
+       struct vpe *vpe = get_vpe(tclimit);
+       struct vpe_notifications *not;
+
+       list_for_each_entry(not, &vpe->notify, list) {
+               not->stop(tclimit);
+       }
+
+       release_progmem(vpe->load_addr);
+       cleanup_tc(get_tc(tclimit));
+       vpe_stop(vpe);
+       vpe_free(vpe);
+
+       return len;
+}
+
+static ssize_t show_ntcs(struct device *cd, struct device_attribute *attr,
+                        char *buf)
+{
+       struct vpe *vpe = get_vpe(tclimit);
+
+       return sprintf(buf, "%d\n", vpe->ntcs);
+}
+
+static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr,
+                         const char *buf, size_t len)
+{
+       struct vpe *vpe = get_vpe(tclimit);
+       unsigned long new;
+       char *endp;
+
+       new = simple_strtoul(buf, &endp, 0);
+       if (endp == buf)
+               goto out_einval;
+
+       if (new == 0 || new > (hw_tcs - tclimit))
+               goto out_einval;
+
+       vpe->ntcs = new;
+
+       return len;
+
+out_einval:
+       return -EINVAL;;
+}
+
+static struct device_attribute vpe_class_attributes[] = {
+       __ATTR(kill, S_IWUSR, NULL, store_kill),
+       __ATTR(ntcs, S_IRUGO | S_IWUSR, show_ntcs, store_ntcs),
+       {}
+};
+
+static void vpe_device_release(struct device *cd)
+{
+       kfree(cd);
+}
+
+struct class vpe_class = {
+       .name = "vpe",
+       .owner = THIS_MODULE,
+       .dev_release = vpe_device_release,
+       .dev_attrs = vpe_class_attributes,
+};
+
+struct device vpe_device;
 
 static int __init vpe_module_init(void)
 {
        unsigned int mtflags, vpflags;
-       int hw_tcs, hw_vpes, tc, err = 0;
        unsigned long flags, val;
        struct vpe *v = NULL;
-       struct device *dev;
        struct tc *t;
+       int tc, err;
 
        if (!cpu_has_mipsmt) {
                printk("VPE loader: not a MIPS MT capable processor\n");
@@ -1371,13 +1420,22 @@ static int __init vpe_module_init(void)
                return major;
        }
 
-       dev = device_create(mt_class, NULL, MKDEV(major, minor),
-                           "vpe%d", minor);
-       if (IS_ERR(dev)) {
-               err = PTR_ERR(dev);
+       err = class_register(&vpe_class);
+       if (err) {
+               printk(KERN_ERR "vpe_class registration failed\n");
                goto out_chrdev;
        }
-       vpe_dev = dev;
+
+       device_initialize(&vpe_device);
+       vpe_device.class        = &vpe_class,
+       vpe_device.parent       = NULL,
+       strlcpy(vpe_device.bus_id, "vpe1", BUS_ID_SIZE);
+       vpe_device.devt = MKDEV(major, minor);
+       err = device_add(&vpe_device);
+       if (err) {
+               printk(KERN_ERR "Adding vpe_device failed\n");
+               goto out_class;
+       }
 
        local_irq_save(flags);
        mtflags = dmt();
@@ -1422,6 +1480,8 @@ static int __init vpe_module_init(void)
                                goto out_reenable;
                        }
 
+                       v->ntcs = hw_tcs - tclimit;
+
                        /* add the tc to the list of this vpe's tc's. */
                        list_add(&t->tc, &v->tc);
 
@@ -1497,6 +1557,8 @@ out_reenable:
 #endif
        return 0;
 
+out_class:
+       class_unregister(&vpe_class);
 out_chrdev:
        unregister_chrdev(major, module_name);
 
@@ -1514,7 +1576,7 @@ static void __exit vpe_module_exit(void)
                }
        }
 
-       device_destroy(mt_class, MKDEV(major, minor));
+       device_del(&vpe_device);
        unregister_chrdev(major, module_name);
 }