[POWERPC] spufs: restore mapping of mssync register
authorarnd@arndb.de <arnd@arndb.de>
Mon, 19 Jun 2006 18:33:21 +0000 (20:33 +0200)
committerPaul Mackerras <paulus@samba.org>
Wed, 21 Jun 2006 05:01:30 +0000 (15:01 +1000)
A recent change to the way that the mfc file gets mapped made it
impossible to map the SPE Multi-Source Synchronization register
into user space, but that may be needed by some applications.

This restores the missing functionality.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/platforms/cell/spufs/file.c

index 366185e926672729ed9025618977d447790ed815..3bc00913fe184d32d3e2b6cc3210d9c32e807d59 100644 (file)
@@ -824,6 +824,55 @@ static u64 spufs_signal2_type_get(void *data)
 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
                                        spufs_signal2_type_set, "%llu");
 
+#ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma,
+                                          unsigned long address, int *type)
+{
+       return spufs_ps_nopage(vma, address, type, 0x0000);
+}
+
+static struct vm_operations_struct spufs_mss_mmap_vmops = {
+       .nopage = spufs_mss_mmap_nopage,
+};
+
+/*
+ * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
+ * Mapping this area requires that the application have CAP_SYS_RAWIO,
+ * as these registers require special care when read/writing.
+ */
+static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       if (!(vma->vm_flags & VM_SHARED))
+               return -EINVAL;
+
+       if (!capable(CAP_SYS_RAWIO))
+               return -EPERM;
+
+       vma->vm_flags |= VM_RESERVED;
+       vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+                                    | _PAGE_NO_CACHE);
+
+       vma->vm_ops = &spufs_mss_mmap_vmops;
+       return 0;
+}
+#endif
+
+static int spufs_mss_open(struct inode *inode, struct file *file)
+{
+       struct spufs_inode_info *i = SPUFS_I(inode);
+
+       file->private_data = i->i_ctx;
+       return nonseekable_open(inode, file);
+}
+
+static struct file_operations spufs_mss_fops = {
+       .open    = spufs_mss_open,
+#ifdef CONFIG_SPUFS_MMAP
+       .mmap    = spufs_mss_mmap,
+#endif
+};
+
+
 #ifdef CONFIG_SPUFS_MMAP
 static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma,
                                           unsigned long address, int *type)
@@ -1292,6 +1341,7 @@ struct tree_descr spufs_dir_contents[] = {
        { "signal2", &spufs_signal2_fops, 0666, },
        { "signal1_type", &spufs_signal1_type, 0666, },
        { "signal2_type", &spufs_signal2_type, 0666, },
+       { "mss", &spufs_mss_fops, 0666, },
        { "mfc", &spufs_mfc_fops, 0666, },
        { "cntl", &spufs_cntl_fops,  0666, },
        { "npc", &spufs_npc_ops, 0666, },