aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2007-12-20 02:39:59 -0500
committerPaul Mackerras <paulus@samba.org>2007-12-21 03:46:21 -0500
commit197b1a8263bf365d2ca8aba532352036ff95e04d (patch)
tree0eb09da9579f4cc047e195a2bfd8cd20ae2cb9f9 /arch/powerpc/platforms
parente65c2f6fcebb9af0c3f53c796aff730dd657f5e7 (diff)
[POWERPC] spufs: add enchanced simple attr macros
The simple attr macros currently used by spufs can't deal with the handlers returning errors, which is required to make the state_mutex interruptible. This adds a local copy that allows for an error return from the get/set handlers. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jeremy Kerr <jk@ozlabs.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c178
1 files changed, 154 insertions, 24 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 78df905743b3..510adc57af90 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -40,6 +40,120 @@
40 40
41#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) 41#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
42 42
43/* Simple attribute files */
44struct spufs_attr {
45 int (*get)(void *, u64 *);
46 int (*set)(void *, u64);
47 char get_buf[24]; /* enough to store a u64 and "\n\0" */
48 char set_buf[24];
49 void *data;
50 const char *fmt; /* format for read operation */
51 struct mutex mutex; /* protects access to these buffers */
52};
53
54static int spufs_attr_open(struct inode *inode, struct file *file,
55 int (*get)(void *, u64 *), int (*set)(void *, u64),
56 const char *fmt)
57{
58 struct spufs_attr *attr;
59
60 attr = kmalloc(sizeof(*attr), GFP_KERNEL);
61 if (!attr)
62 return -ENOMEM;
63
64 attr->get = get;
65 attr->set = set;
66 attr->data = inode->i_private;
67 attr->fmt = fmt;
68 mutex_init(&attr->mutex);
69 file->private_data = attr;
70
71 return nonseekable_open(inode, file);
72}
73
74static int spufs_attr_release(struct inode *inode, struct file *file)
75{
76 kfree(file->private_data);
77 return 0;
78}
79
80static ssize_t spufs_attr_read(struct file *file, char __user *buf,
81 size_t len, loff_t *ppos)
82{
83 struct spufs_attr *attr;
84 size_t size;
85 ssize_t ret;
86
87 attr = file->private_data;
88 if (!attr->get)
89 return -EACCES;
90
91 ret = mutex_lock_interruptible(&attr->mutex);
92 if (ret)
93 return ret;
94
95 if (*ppos) { /* continued read */
96 size = strlen(attr->get_buf);
97 } else { /* first read */
98 u64 val;
99 ret = attr->get(attr->data, &val);
100 if (ret)
101 goto out;
102
103 size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
104 attr->fmt, (unsigned long long)val);
105 }
106
107 ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
108out:
109 mutex_unlock(&attr->mutex);
110 return ret;
111}
112
113static ssize_t spufs_attr_write(struct file *file, const char __user *buf,
114 size_t len, loff_t *ppos)
115{
116 struct spufs_attr *attr;
117 u64 val;
118 size_t size;
119 ssize_t ret;
120
121 attr = file->private_data;
122 if (!attr->set)
123 return -EACCES;
124
125 ret = mutex_lock_interruptible(&attr->mutex);
126 if (ret)
127 return ret;
128
129 ret = -EFAULT;
130 size = min(sizeof(attr->set_buf) - 1, len);
131 if (copy_from_user(attr->set_buf, buf, size))
132 goto out;
133
134 ret = len; /* claim we got the whole input */
135 attr->set_buf[size] = '\0';
136 val = simple_strtol(attr->set_buf, NULL, 0);
137 attr->set(attr->data, val);
138out:
139 mutex_unlock(&attr->mutex);
140 return ret;
141}
142
143#define DEFINE_SPUFS_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \
144static int __fops ## _open(struct inode *inode, struct file *file) \
145{ \
146 __simple_attr_check_format(__fmt, 0ull); \
147 return spufs_attr_open(inode, file, __get, __set, __fmt); \
148} \
149static struct file_operations __fops = { \
150 .owner = THIS_MODULE, \
151 .open = __fops ## _open, \
152 .release = spufs_attr_release, \
153 .read = spufs_attr_read, \
154 .write = spufs_attr_write, \
155};
156
43 157
44static int 158static int
45spufs_mem_open(struct inode *inode, struct file *file) 159spufs_mem_open(struct inode *inode, struct file *file)
@@ -296,25 +410,26 @@ static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
296#define spufs_cntl_mmap NULL 410#define spufs_cntl_mmap NULL
297#endif /* !SPUFS_MMAP_4K */ 411#endif /* !SPUFS_MMAP_4K */
298 412
299static u64 spufs_cntl_get(void *data) 413static int spufs_cntl_get(void *data, u64 *val)
300{ 414{
301 struct spu_context *ctx = data; 415 struct spu_context *ctx = data;
302 u64 val;
303 416
304 spu_acquire(ctx); 417 spu_acquire(ctx);
305 val = ctx->ops->status_read(ctx); 418 *val = ctx->ops->status_read(ctx);
306 spu_release(ctx); 419 spu_release(ctx);
307 420
308 return val; 421 return 0;
309} 422}
310 423
311static void spufs_cntl_set(void *data, u64 val) 424static int spufs_cntl_set(void *data, u64 val)
312{ 425{
313 struct spu_context *ctx = data; 426 struct spu_context *ctx = data;
314 427
315 spu_acquire(ctx); 428 spu_acquire(ctx);
316 ctx->ops->runcntl_write(ctx, val); 429 ctx->ops->runcntl_write(ctx, val);
317 spu_release(ctx); 430 spu_release(ctx);
431
432 return 0;
318} 433}
319 434
320static int spufs_cntl_open(struct inode *inode, struct file *file) 435static int spufs_cntl_open(struct inode *inode, struct file *file)
@@ -327,7 +442,7 @@ static int spufs_cntl_open(struct inode *inode, struct file *file)
327 if (!i->i_openers++) 442 if (!i->i_openers++)
328 ctx->cntl = inode->i_mapping; 443 ctx->cntl = inode->i_mapping;
329 mutex_unlock(&ctx->mapping_lock); 444 mutex_unlock(&ctx->mapping_lock);
330 return simple_attr_open(inode, file, spufs_cntl_get, 445 return spufs_attr_open(inode, file, spufs_cntl_get,
331 spufs_cntl_set, "0x%08lx"); 446 spufs_cntl_set, "0x%08lx");
332} 447}
333 448
@@ -337,7 +452,7 @@ spufs_cntl_release(struct inode *inode, struct file *file)
337 struct spufs_inode_info *i = SPUFS_I(inode); 452 struct spufs_inode_info *i = SPUFS_I(inode);
338 struct spu_context *ctx = i->i_ctx; 453 struct spu_context *ctx = i->i_ctx;
339 454
340 simple_attr_close(inode, file); 455 spufs_attr_release(inode, file);
341 456
342 mutex_lock(&ctx->mapping_lock); 457 mutex_lock(&ctx->mapping_lock);
343 if (!--i->i_openers) 458 if (!--i->i_openers)
@@ -349,8 +464,8 @@ spufs_cntl_release(struct inode *inode, struct file *file)
349static const struct file_operations spufs_cntl_fops = { 464static const struct file_operations spufs_cntl_fops = {
350 .open = spufs_cntl_open, 465 .open = spufs_cntl_open,
351 .release = spufs_cntl_release, 466 .release = spufs_cntl_release,
352 .read = simple_attr_read, 467 .read = spufs_attr_read,
353 .write = simple_attr_write, 468 .write = spufs_attr_write,
354 .mmap = spufs_cntl_mmap, 469 .mmap = spufs_cntl_mmap,
355}; 470};
356 471
@@ -1102,33 +1217,34 @@ static const struct file_operations spufs_signal2_nosched_fops = {
1102#define SPU_ATTR_ACQUIRE_SAVED 2 1217#define SPU_ATTR_ACQUIRE_SAVED 2
1103 1218
1104#define DEFINE_SPUFS_ATTRIBUTE(__name, __get, __set, __fmt, __acquire) \ 1219#define DEFINE_SPUFS_ATTRIBUTE(__name, __get, __set, __fmt, __acquire) \
1105static u64 __##__get(void *data) \ 1220static int __##__get(void *data, u64 *val) \
1106{ \ 1221{ \
1107 struct spu_context *ctx = data; \ 1222 struct spu_context *ctx = data; \
1108 u64 ret; \
1109 \ 1223 \
1110 if (__acquire == SPU_ATTR_ACQUIRE) { \ 1224 if (__acquire == SPU_ATTR_ACQUIRE) { \
1111 spu_acquire(ctx); \ 1225 spu_acquire(ctx); \
1112 ret = __get(ctx); \ 1226 *val = __get(ctx); \
1113 spu_release(ctx); \ 1227 spu_release(ctx); \
1114 } else if (__acquire == SPU_ATTR_ACQUIRE_SAVED) { \ 1228 } else if (__acquire == SPU_ATTR_ACQUIRE_SAVED) { \
1115 spu_acquire_saved(ctx); \ 1229 spu_acquire_saved(ctx); \
1116 ret = __get(ctx); \ 1230 *val = __get(ctx); \
1117 spu_release_saved(ctx); \ 1231 spu_release_saved(ctx); \
1118 } else \ 1232 } else \
1119 ret = __get(ctx); \ 1233 *val = __get(ctx); \
1120 \ 1234 \
1121 return ret; \ 1235 return 0; \
1122} \ 1236} \
1123DEFINE_SIMPLE_ATTRIBUTE(__name, __##__get, __set, __fmt); 1237DEFINE_SPUFS_SIMPLE_ATTRIBUTE(__name, __##__get, __set, __fmt);
1124 1238
1125static void spufs_signal1_type_set(void *data, u64 val) 1239static int spufs_signal1_type_set(void *data, u64 val)
1126{ 1240{
1127 struct spu_context *ctx = data; 1241 struct spu_context *ctx = data;
1128 1242
1129 spu_acquire(ctx); 1243 spu_acquire(ctx);
1130 ctx->ops->signal1_type_set(ctx, val); 1244 ctx->ops->signal1_type_set(ctx, val);
1131 spu_release(ctx); 1245 spu_release(ctx);
1246
1247 return 0;
1132} 1248}
1133 1249
1134static u64 spufs_signal1_type_get(struct spu_context *ctx) 1250static u64 spufs_signal1_type_get(struct spu_context *ctx)
@@ -1139,13 +1255,15 @@ DEFINE_SPUFS_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
1139 spufs_signal1_type_set, "%llu", SPU_ATTR_ACQUIRE); 1255 spufs_signal1_type_set, "%llu", SPU_ATTR_ACQUIRE);
1140 1256
1141 1257
1142static void spufs_signal2_type_set(void *data, u64 val) 1258static int spufs_signal2_type_set(void *data, u64 val)
1143{ 1259{
1144 struct spu_context *ctx = data; 1260 struct spu_context *ctx = data;
1145 1261
1146 spu_acquire(ctx); 1262 spu_acquire(ctx);
1147 ctx->ops->signal2_type_set(ctx, val); 1263 ctx->ops->signal2_type_set(ctx, val);
1148 spu_release(ctx); 1264 spu_release(ctx);
1265
1266 return 0;
1149} 1267}
1150 1268
1151static u64 spufs_signal2_type_get(struct spu_context *ctx) 1269static u64 spufs_signal2_type_get(struct spu_context *ctx)
@@ -1625,12 +1743,14 @@ static const struct file_operations spufs_mfc_fops = {
1625 .mmap = spufs_mfc_mmap, 1743 .mmap = spufs_mfc_mmap,
1626}; 1744};
1627 1745
1628static void spufs_npc_set(void *data, u64 val) 1746static int spufs_npc_set(void *data, u64 val)
1629{ 1747{
1630 struct spu_context *ctx = data; 1748 struct spu_context *ctx = data;
1631 spu_acquire(ctx); 1749 spu_acquire(ctx);
1632 ctx->ops->npc_write(ctx, val); 1750 ctx->ops->npc_write(ctx, val);
1633 spu_release(ctx); 1751 spu_release(ctx);
1752
1753 return 0;
1634} 1754}
1635 1755
1636static u64 spufs_npc_get(struct spu_context *ctx) 1756static u64 spufs_npc_get(struct spu_context *ctx)
@@ -1640,13 +1760,15 @@ static u64 spufs_npc_get(struct spu_context *ctx)
1640DEFINE_SPUFS_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, 1760DEFINE_SPUFS_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set,
1641 "0x%llx\n", SPU_ATTR_ACQUIRE); 1761 "0x%llx\n", SPU_ATTR_ACQUIRE);
1642 1762
1643static void spufs_decr_set(void *data, u64 val) 1763static int spufs_decr_set(void *data, u64 val)
1644{ 1764{
1645 struct spu_context *ctx = data; 1765 struct spu_context *ctx = data;
1646 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1766 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1647 spu_acquire_saved(ctx); 1767 spu_acquire_saved(ctx);
1648 lscsa->decr.slot[0] = (u32) val; 1768 lscsa->decr.slot[0] = (u32) val;
1649 spu_release_saved(ctx); 1769 spu_release_saved(ctx);
1770
1771 return 0;
1650} 1772}
1651 1773
1652static u64 spufs_decr_get(struct spu_context *ctx) 1774static u64 spufs_decr_get(struct spu_context *ctx)
@@ -1657,7 +1779,7 @@ static u64 spufs_decr_get(struct spu_context *ctx)
1657DEFINE_SPUFS_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set, 1779DEFINE_SPUFS_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
1658 "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED); 1780 "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED);
1659 1781
1660static void spufs_decr_status_set(void *data, u64 val) 1782static int spufs_decr_status_set(void *data, u64 val)
1661{ 1783{
1662 struct spu_context *ctx = data; 1784 struct spu_context *ctx = data;
1663 spu_acquire_saved(ctx); 1785 spu_acquire_saved(ctx);
@@ -1666,6 +1788,8 @@ static void spufs_decr_status_set(void *data, u64 val)
1666 else 1788 else
1667 ctx->csa.priv2.mfc_control_RW &= ~MFC_CNTL_DECREMENTER_RUNNING; 1789 ctx->csa.priv2.mfc_control_RW &= ~MFC_CNTL_DECREMENTER_RUNNING;
1668 spu_release_saved(ctx); 1790 spu_release_saved(ctx);
1791
1792 return 0;
1669} 1793}
1670 1794
1671static u64 spufs_decr_status_get(struct spu_context *ctx) 1795static u64 spufs_decr_status_get(struct spu_context *ctx)
@@ -1679,13 +1803,15 @@ DEFINE_SPUFS_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
1679 spufs_decr_status_set, "0x%llx\n", 1803 spufs_decr_status_set, "0x%llx\n",
1680 SPU_ATTR_ACQUIRE_SAVED); 1804 SPU_ATTR_ACQUIRE_SAVED);
1681 1805
1682static void spufs_event_mask_set(void *data, u64 val) 1806static int spufs_event_mask_set(void *data, u64 val)
1683{ 1807{
1684 struct spu_context *ctx = data; 1808 struct spu_context *ctx = data;
1685 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1809 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1686 spu_acquire_saved(ctx); 1810 spu_acquire_saved(ctx);
1687 lscsa->event_mask.slot[0] = (u32) val; 1811 lscsa->event_mask.slot[0] = (u32) val;
1688 spu_release_saved(ctx); 1812 spu_release_saved(ctx);
1813
1814 return 0;
1689} 1815}
1690 1816
1691static u64 spufs_event_mask_get(struct spu_context *ctx) 1817static u64 spufs_event_mask_get(struct spu_context *ctx)
@@ -1710,13 +1836,15 @@ static u64 spufs_event_status_get(struct spu_context *ctx)
1710DEFINE_SPUFS_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get, 1836DEFINE_SPUFS_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get,
1711 NULL, "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED) 1837 NULL, "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED)
1712 1838
1713static void spufs_srr0_set(void *data, u64 val) 1839static int spufs_srr0_set(void *data, u64 val)
1714{ 1840{
1715 struct spu_context *ctx = data; 1841 struct spu_context *ctx = data;
1716 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1842 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1717 spu_acquire_saved(ctx); 1843 spu_acquire_saved(ctx);
1718 lscsa->srr0.slot[0] = (u32) val; 1844 lscsa->srr0.slot[0] = (u32) val;
1719 spu_release_saved(ctx); 1845 spu_release_saved(ctx);
1846
1847 return 0;
1720} 1848}
1721 1849
1722static u64 spufs_srr0_get(struct spu_context *ctx) 1850static u64 spufs_srr0_get(struct spu_context *ctx)
@@ -1747,10 +1875,12 @@ static u64 spufs_object_id_get(struct spu_context *ctx)
1747 return ctx->object_id; 1875 return ctx->object_id;
1748} 1876}
1749 1877
1750static void spufs_object_id_set(void *data, u64 id) 1878static int spufs_object_id_set(void *data, u64 id)
1751{ 1879{
1752 struct spu_context *ctx = data; 1880 struct spu_context *ctx = data;
1753 ctx->object_id = id; 1881 ctx->object_id = id;
1882
1883 return 0;
1754} 1884}
1755 1885
1756DEFINE_SPUFS_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get, 1886DEFINE_SPUFS_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,