aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/cell/spufs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs/file.c')
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c130
1 files changed, 84 insertions, 46 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 51fd197ab5d..64f8b0a9b9e 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -36,6 +36,8 @@
36 36
37#include "spufs.h" 37#include "spufs.h"
38 38
39#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
40
39 41
40static int 42static int
41spufs_mem_open(struct inode *inode, struct file *file) 43spufs_mem_open(struct inode *inode, struct file *file)
@@ -88,7 +90,6 @@ spufs_mem_write(struct file *file, const char __user *buffer,
88 return ret; 90 return ret;
89} 91}
90 92
91#ifdef CONFIG_SPUFS_MMAP
92static struct page * 93static struct page *
93spufs_mem_mmap_nopage(struct vm_area_struct *vma, 94spufs_mem_mmap_nopage(struct vm_area_struct *vma,
94 unsigned long address, int *type) 95 unsigned long address, int *type)
@@ -133,22 +134,19 @@ spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
133 vma->vm_ops = &spufs_mem_mmap_vmops; 134 vma->vm_ops = &spufs_mem_mmap_vmops;
134 return 0; 135 return 0;
135} 136}
136#endif
137 137
138static struct file_operations spufs_mem_fops = { 138static struct file_operations spufs_mem_fops = {
139 .open = spufs_mem_open, 139 .open = spufs_mem_open,
140 .read = spufs_mem_read, 140 .read = spufs_mem_read,
141 .write = spufs_mem_write, 141 .write = spufs_mem_write,
142 .llseek = generic_file_llseek, 142 .llseek = generic_file_llseek,
143#ifdef CONFIG_SPUFS_MMAP
144 .mmap = spufs_mem_mmap, 143 .mmap = spufs_mem_mmap,
145#endif
146}; 144};
147 145
148#ifdef CONFIG_SPUFS_MMAP
149static struct page *spufs_ps_nopage(struct vm_area_struct *vma, 146static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
150 unsigned long address, 147 unsigned long address,
151 int *type, unsigned long ps_offs) 148 int *type, unsigned long ps_offs,
149 unsigned long ps_size)
152{ 150{
153 struct page *page = NOPAGE_SIGBUS; 151 struct page *page = NOPAGE_SIGBUS;
154 int fault_type = VM_FAULT_SIGBUS; 152 int fault_type = VM_FAULT_SIGBUS;
@@ -158,7 +156,7 @@ static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
158 int ret; 156 int ret;
159 157
160 offset += vma->vm_pgoff << PAGE_SHIFT; 158 offset += vma->vm_pgoff << PAGE_SHIFT;
161 if (offset >= 0x4000) 159 if (offset >= ps_size)
162 goto out; 160 goto out;
163 161
164 ret = spu_acquire_runnable(ctx); 162 ret = spu_acquire_runnable(ctx);
@@ -179,10 +177,11 @@ static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
179 return page; 177 return page;
180} 178}
181 179
180#if SPUFS_MMAP_4K
182static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma, 181static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma,
183 unsigned long address, int *type) 182 unsigned long address, int *type)
184{ 183{
185 return spufs_ps_nopage(vma, address, type, 0x4000); 184 return spufs_ps_nopage(vma, address, type, 0x4000, 0x1000);
186} 185}
187 186
188static struct vm_operations_struct spufs_cntl_mmap_vmops = { 187static struct vm_operations_struct spufs_cntl_mmap_vmops = {
@@ -191,17 +190,12 @@ static struct vm_operations_struct spufs_cntl_mmap_vmops = {
191 190
192/* 191/*
193 * mmap support for problem state control area [0x4000 - 0x4fff]. 192 * mmap support for problem state control area [0x4000 - 0x4fff].
194 * Mapping this area requires that the application have CAP_SYS_RAWIO,
195 * as these registers require special care when read/writing.
196 */ 193 */
197static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma) 194static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
198{ 195{
199 if (!(vma->vm_flags & VM_SHARED)) 196 if (!(vma->vm_flags & VM_SHARED))
200 return -EINVAL; 197 return -EINVAL;
201 198
202 if (!capable(CAP_SYS_RAWIO))
203 return -EPERM;
204
205 vma->vm_flags |= VM_RESERVED; 199 vma->vm_flags |= VM_RESERVED;
206 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 200 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
207 | _PAGE_NO_CACHE | _PAGE_GUARDED); 201 | _PAGE_NO_CACHE | _PAGE_GUARDED);
@@ -209,7 +203,9 @@ static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
209 vma->vm_ops = &spufs_cntl_mmap_vmops; 203 vma->vm_ops = &spufs_cntl_mmap_vmops;
210 return 0; 204 return 0;
211} 205}
212#endif 206#else /* SPUFS_MMAP_4K */
207#define spufs_cntl_mmap NULL
208#endif /* !SPUFS_MMAP_4K */
213 209
214static int spufs_cntl_open(struct inode *inode, struct file *file) 210static int spufs_cntl_open(struct inode *inode, struct file *file)
215{ 211{
@@ -242,9 +238,7 @@ static struct file_operations spufs_cntl_fops = {
242 .open = spufs_cntl_open, 238 .open = spufs_cntl_open,
243 .read = spufs_cntl_read, 239 .read = spufs_cntl_read,
244 .write = spufs_cntl_write, 240 .write = spufs_cntl_write,
245#ifdef CONFIG_SPUFS_MMAP
246 .mmap = spufs_cntl_mmap, 241 .mmap = spufs_cntl_mmap,
247#endif
248}; 242};
249 243
250static int 244static int
@@ -657,11 +651,19 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
657 return 4; 651 return 4;
658} 652}
659 653
660#ifdef CONFIG_SPUFS_MMAP
661static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma, 654static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma,
662 unsigned long address, int *type) 655 unsigned long address, int *type)
663{ 656{
664 return spufs_ps_nopage(vma, address, type, 0x14000); 657#if PAGE_SIZE == 0x1000
658 return spufs_ps_nopage(vma, address, type, 0x14000, 0x1000);
659#elif PAGE_SIZE == 0x10000
660 /* For 64k pages, both signal1 and signal2 can be used to mmap the whole
661 * signal 1 and 2 area
662 */
663 return spufs_ps_nopage(vma, address, type, 0x10000, 0x10000);
664#else
665#error unsupported page size
666#endif
665} 667}
666 668
667static struct vm_operations_struct spufs_signal1_mmap_vmops = { 669static struct vm_operations_struct spufs_signal1_mmap_vmops = {
@@ -680,15 +682,12 @@ static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
680 vma->vm_ops = &spufs_signal1_mmap_vmops; 682 vma->vm_ops = &spufs_signal1_mmap_vmops;
681 return 0; 683 return 0;
682} 684}
683#endif
684 685
685static struct file_operations spufs_signal1_fops = { 686static struct file_operations spufs_signal1_fops = {
686 .open = spufs_signal1_open, 687 .open = spufs_signal1_open,
687 .read = spufs_signal1_read, 688 .read = spufs_signal1_read,
688 .write = spufs_signal1_write, 689 .write = spufs_signal1_write,
689#ifdef CONFIG_SPUFS_MMAP
690 .mmap = spufs_signal1_mmap, 690 .mmap = spufs_signal1_mmap,
691#endif
692}; 691};
693 692
694static int spufs_signal2_open(struct inode *inode, struct file *file) 693static int spufs_signal2_open(struct inode *inode, struct file *file)
@@ -743,11 +742,20 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
743 return 4; 742 return 4;
744} 743}
745 744
746#ifdef CONFIG_SPUFS_MMAP 745#if SPUFS_MMAP_4K
747static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma, 746static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma,
748 unsigned long address, int *type) 747 unsigned long address, int *type)
749{ 748{
750 return spufs_ps_nopage(vma, address, type, 0x1c000); 749#if PAGE_SIZE == 0x1000
750 return spufs_ps_nopage(vma, address, type, 0x1c000, 0x1000);
751#elif PAGE_SIZE == 0x10000
752 /* For 64k pages, both signal1 and signal2 can be used to mmap the whole
753 * signal 1 and 2 area
754 */
755 return spufs_ps_nopage(vma, address, type, 0x10000, 0x10000);
756#else
757#error unsupported page size
758#endif
751} 759}
752 760
753static struct vm_operations_struct spufs_signal2_mmap_vmops = { 761static struct vm_operations_struct spufs_signal2_mmap_vmops = {
@@ -767,15 +775,15 @@ static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
767 vma->vm_ops = &spufs_signal2_mmap_vmops; 775 vma->vm_ops = &spufs_signal2_mmap_vmops;
768 return 0; 776 return 0;
769} 777}
770#endif 778#else /* SPUFS_MMAP_4K */
779#define spufs_signal2_mmap NULL
780#endif /* !SPUFS_MMAP_4K */
771 781
772static struct file_operations spufs_signal2_fops = { 782static struct file_operations spufs_signal2_fops = {
773 .open = spufs_signal2_open, 783 .open = spufs_signal2_open,
774 .read = spufs_signal2_read, 784 .read = spufs_signal2_read,
775 .write = spufs_signal2_write, 785 .write = spufs_signal2_write,
776#ifdef CONFIG_SPUFS_MMAP
777 .mmap = spufs_signal2_mmap, 786 .mmap = spufs_signal2_mmap,
778#endif
779}; 787};
780 788
781static void spufs_signal1_type_set(void *data, u64 val) 789static void spufs_signal1_type_set(void *data, u64 val)
@@ -824,11 +832,11 @@ static u64 spufs_signal2_type_get(void *data)
824DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, 832DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
825 spufs_signal2_type_set, "%llu"); 833 spufs_signal2_type_set, "%llu");
826 834
827#ifdef CONFIG_SPUFS_MMAP 835#if SPUFS_MMAP_4K
828static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma, 836static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma,
829 unsigned long address, int *type) 837 unsigned long address, int *type)
830{ 838{
831 return spufs_ps_nopage(vma, address, type, 0x0000); 839 return spufs_ps_nopage(vma, address, type, 0x0000, 0x1000);
832} 840}
833 841
834static struct vm_operations_struct spufs_mss_mmap_vmops = { 842static struct vm_operations_struct spufs_mss_mmap_vmops = {
@@ -837,17 +845,12 @@ static struct vm_operations_struct spufs_mss_mmap_vmops = {
837 845
838/* 846/*
839 * mmap support for problem state MFC DMA area [0x0000 - 0x0fff]. 847 * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
840 * Mapping this area requires that the application have CAP_SYS_RAWIO,
841 * as these registers require special care when read/writing.
842 */ 848 */
843static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma) 849static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
844{ 850{
845 if (!(vma->vm_flags & VM_SHARED)) 851 if (!(vma->vm_flags & VM_SHARED))
846 return -EINVAL; 852 return -EINVAL;
847 853
848 if (!capable(CAP_SYS_RAWIO))
849 return -EPERM;
850
851 vma->vm_flags |= VM_RESERVED; 854 vma->vm_flags |= VM_RESERVED;
852 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 855 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
853 | _PAGE_NO_CACHE | _PAGE_GUARDED); 856 | _PAGE_NO_CACHE | _PAGE_GUARDED);
@@ -855,7 +858,9 @@ static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
855 vma->vm_ops = &spufs_mss_mmap_vmops; 858 vma->vm_ops = &spufs_mss_mmap_vmops;
856 return 0; 859 return 0;
857} 860}
858#endif 861#else /* SPUFS_MMAP_4K */
862#define spufs_mss_mmap NULL
863#endif /* !SPUFS_MMAP_4K */
859 864
860static int spufs_mss_open(struct inode *inode, struct file *file) 865static int spufs_mss_open(struct inode *inode, struct file *file)
861{ 866{
@@ -867,17 +872,54 @@ static int spufs_mss_open(struct inode *inode, struct file *file)
867 872
868static struct file_operations spufs_mss_fops = { 873static struct file_operations spufs_mss_fops = {
869 .open = spufs_mss_open, 874 .open = spufs_mss_open,
870#ifdef CONFIG_SPUFS_MMAP
871 .mmap = spufs_mss_mmap, 875 .mmap = spufs_mss_mmap,
872#endif 876};
877
878static struct page *spufs_psmap_mmap_nopage(struct vm_area_struct *vma,
879 unsigned long address, int *type)
880{
881 return spufs_ps_nopage(vma, address, type, 0x0000, 0x20000);
882}
883
884static struct vm_operations_struct spufs_psmap_mmap_vmops = {
885 .nopage = spufs_psmap_mmap_nopage,
886};
887
888/*
889 * mmap support for full problem state area [0x00000 - 0x1ffff].
890 */
891static int spufs_psmap_mmap(struct file *file, struct vm_area_struct *vma)
892{
893 if (!(vma->vm_flags & VM_SHARED))
894 return -EINVAL;
895
896 vma->vm_flags |= VM_RESERVED;
897 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
898 | _PAGE_NO_CACHE | _PAGE_GUARDED);
899
900 vma->vm_ops = &spufs_psmap_mmap_vmops;
901 return 0;
902}
903
904static int spufs_psmap_open(struct inode *inode, struct file *file)
905{
906 struct spufs_inode_info *i = SPUFS_I(inode);
907
908 file->private_data = i->i_ctx;
909 return nonseekable_open(inode, file);
910}
911
912static struct file_operations spufs_psmap_fops = {
913 .open = spufs_psmap_open,
914 .mmap = spufs_psmap_mmap,
873}; 915};
874 916
875 917
876#ifdef CONFIG_SPUFS_MMAP 918#if SPUFS_MMAP_4K
877static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma, 919static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma,
878 unsigned long address, int *type) 920 unsigned long address, int *type)
879{ 921{
880 return spufs_ps_nopage(vma, address, type, 0x3000); 922 return spufs_ps_nopage(vma, address, type, 0x3000, 0x1000);
881} 923}
882 924
883static struct vm_operations_struct spufs_mfc_mmap_vmops = { 925static struct vm_operations_struct spufs_mfc_mmap_vmops = {
@@ -886,17 +928,12 @@ static struct vm_operations_struct spufs_mfc_mmap_vmops = {
886 928
887/* 929/*
888 * mmap support for problem state MFC DMA area [0x0000 - 0x0fff]. 930 * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
889 * Mapping this area requires that the application have CAP_SYS_RAWIO,
890 * as these registers require special care when read/writing.
891 */ 931 */
892static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma) 932static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
893{ 933{
894 if (!(vma->vm_flags & VM_SHARED)) 934 if (!(vma->vm_flags & VM_SHARED))
895 return -EINVAL; 935 return -EINVAL;
896 936
897 if (!capable(CAP_SYS_RAWIO))
898 return -EPERM;
899
900 vma->vm_flags |= VM_RESERVED; 937 vma->vm_flags |= VM_RESERVED;
901 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 938 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
902 | _PAGE_NO_CACHE | _PAGE_GUARDED); 939 | _PAGE_NO_CACHE | _PAGE_GUARDED);
@@ -904,7 +941,9 @@ static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
904 vma->vm_ops = &spufs_mfc_mmap_vmops; 941 vma->vm_ops = &spufs_mfc_mmap_vmops;
905 return 0; 942 return 0;
906} 943}
907#endif 944#else /* SPUFS_MMAP_4K */
945#define spufs_mfc_mmap NULL
946#endif /* !SPUFS_MMAP_4K */
908 947
909static int spufs_mfc_open(struct inode *inode, struct file *file) 948static int spufs_mfc_open(struct inode *inode, struct file *file)
910{ 949{
@@ -1194,9 +1233,7 @@ static struct file_operations spufs_mfc_fops = {
1194 .flush = spufs_mfc_flush, 1233 .flush = spufs_mfc_flush,
1195 .fsync = spufs_mfc_fsync, 1234 .fsync = spufs_mfc_fsync,
1196 .fasync = spufs_mfc_fasync, 1235 .fasync = spufs_mfc_fasync,
1197#ifdef CONFIG_SPUFS_MMAP
1198 .mmap = spufs_mfc_mmap, 1236 .mmap = spufs_mfc_mmap,
1199#endif
1200}; 1237};
1201 1238
1202static void spufs_npc_set(void *data, u64 val) 1239static void spufs_npc_set(void *data, u64 val)
@@ -1368,5 +1405,6 @@ struct tree_descr spufs_dir_contents[] = {
1368 { "event_mask", &spufs_event_mask_ops, 0666, }, 1405 { "event_mask", &spufs_event_mask_ops, 0666, },
1369 { "srr0", &spufs_srr0_ops, 0666, }, 1406 { "srr0", &spufs_srr0_ops, 0666, },
1370 { "phys-id", &spufs_id_ops, 0666, }, 1407 { "phys-id", &spufs_id_ops, 0666, },
1408 { "psmap", &spufs_psmap_fops, 0666, },
1371 {}, 1409 {},
1372}; 1410};