aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-02-23 08:40:45 -0500
committerRalf Baechle <ralf@linux-mips.org>2007-02-26 18:06:06 -0500
commitc4c4018b04f9b7993e3800dc1f391ac8947764a5 (patch)
tree346c9a4aa9c46eee6df883f89553e43b9d7033fc /arch
parentcbc841356702ccf4f16e760c84006ed3ddd4b1fd (diff)
[MIPS] RTLX, VPE: Make open actually atomic.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/kernel/rtlx.c44
-rw-r--r--arch/mips/kernel/vpe.c7
2 files changed, 23 insertions, 28 deletions
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 766db51ab69e..7a8683ab6fde 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -53,7 +53,7 @@ static char module_name[] = "rtlx";
53static struct chan_waitqueues { 53static struct chan_waitqueues {
54 wait_queue_head_t rt_queue; 54 wait_queue_head_t rt_queue;
55 wait_queue_head_t lx_queue; 55 wait_queue_head_t lx_queue;
56 int in_open; 56 atomic_t in_open;
57} channel_wqs[RTLX_CHANNELS]; 57} channel_wqs[RTLX_CHANNELS];
58 58
59static struct irqaction irq; 59static struct irqaction irq;
@@ -148,6 +148,7 @@ int rtlx_open(int index, int can_sleep)
148{ 148{
149 volatile struct rtlx_info **p; 149 volatile struct rtlx_info **p;
150 struct rtlx_channel *chan; 150 struct rtlx_channel *chan;
151 enum rtlx_state state;
151 int ret = 0; 152 int ret = 0;
152 153
153 if (index >= RTLX_CHANNELS) { 154 if (index >= RTLX_CHANNELS) {
@@ -155,13 +156,13 @@ int rtlx_open(int index, int can_sleep)
155 return -ENOSYS; 156 return -ENOSYS;
156 } 157 }
157 158
158 if (channel_wqs[index].in_open) { 159 if (atomic_inc_return(&channel_wqs[index].in_open) > 1) {
159 printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index); 160 printk(KERN_DEBUG "rtlx_open channel %d already opened\n",
160 return -EBUSY; 161 index);
162 ret = -EBUSY;
163 goto out_fail;
161 } 164 }
162 165
163 channel_wqs[index].in_open++;
164
165 if (rtlx == NULL) { 166 if (rtlx == NULL) {
166 if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { 167 if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
167 if (can_sleep) { 168 if (can_sleep) {
@@ -173,9 +174,8 @@ int rtlx_open(int index, int can_sleep)
173 if (ret) 174 if (ret)
174 goto out_fail; 175 goto out_fail;
175 } else { 176 } else {
176 printk( KERN_DEBUG "No SP program loaded, and device " 177 printk(KERN_DEBUG "No SP program loaded, and device "
177 "opened with O_NONBLOCK\n"); 178 "opened with O_NONBLOCK\n");
178 channel_wqs[index].in_open = 0;
179 ret = -ENOSYS; 179 ret = -ENOSYS;
180 goto out_fail; 180 goto out_fail;
181 } 181 }
@@ -193,7 +193,6 @@ int rtlx_open(int index, int can_sleep)
193 } else { 193 } else {
194 printk(" *vpe_get_shared is NULL. " 194 printk(" *vpe_get_shared is NULL. "
195 "Has an SP program been loaded?\n"); 195 "Has an SP program been loaded?\n");
196 channel_wqs[index].in_open = 0;
197 ret = -ENOSYS; 196 ret = -ENOSYS;
198 goto out_fail; 197 goto out_fail;
199 } 198 }
@@ -202,31 +201,28 @@ int rtlx_open(int index, int can_sleep)
202 if ((unsigned int)*p < KSEG0) { 201 if ((unsigned int)*p < KSEG0) {
203 printk(KERN_WARNING "vpe_get_shared returned an invalid pointer " 202 printk(KERN_WARNING "vpe_get_shared returned an invalid pointer "
204 "maybe an error code %d\n", (int)*p); 203 "maybe an error code %d\n", (int)*p);
205 channel_wqs[index].in_open = 0;
206 ret = -ENOSYS; 204 ret = -ENOSYS;
207 goto out_fail; 205 goto out_fail;
208 } 206 }
209 207
210 if ((ret = rtlx_init(*p)) < 0) { 208 if ((ret = rtlx_init(*p)) < 0)
211 channel_wqs[index].in_open = 0; 209 goto out_ret;
212 return ret;
213 }
214 } 210 }
215 211
216 chan = &rtlx->channel[index]; 212 chan = &rtlx->channel[index];
217 213
218 if (chan->lx_state == RTLX_STATE_OPENED) { 214 state = xchg(&chan->lx_state, RTLX_STATE_OPENED);
219 channel_wqs[index].in_open = 0; 215 if (state == RTLX_STATE_OPENED) {
220 return -EBUSY; 216 ret = -EBUSY;
221 } 217 goto out_fail;
222 218 }
223 chan->lx_state = RTLX_STATE_OPENED;
224 channel_wqs[index].in_open = 0;
225 return 0;
226 219
227out_fail: 220out_fail:
228 channel_wqs[index].in_open--; 221 smp_mb();
222 atomic_dec(&channel_wqs[index].in_open);
223 smp_mb();
229 224
225out_ret:
230 return ret; 226 return ret;
231} 227}
232 228
@@ -475,7 +471,7 @@ static int rtlx_module_init(void)
475 for (i = 0; i < RTLX_CHANNELS; i++) { 471 for (i = 0; i < RTLX_CHANNELS; i++) {
476 init_waitqueue_head(&channel_wqs[i].rt_queue); 472 init_waitqueue_head(&channel_wqs[i].rt_queue);
477 init_waitqueue_head(&channel_wqs[i].lx_queue); 473 init_waitqueue_head(&channel_wqs[i].lx_queue);
478 channel_wqs[i].in_open = 0; 474 atomic_set(&channel_wqs[i].in_open, 0);
479 475
480 dev = device_create(mt_class, NULL, MKDEV(major, i), 476 dev = device_create(mt_class, NULL, MKDEV(major, i),
481 "%s%d", module_name, i); 477 "%s%d", module_name, i);
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 9aca871a307f..c9ee9d2d5856 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1079,6 +1079,7 @@ static int getcwd(char *buff, int size)
1079static int vpe_open(struct inode *inode, struct file *filp) 1079static int vpe_open(struct inode *inode, struct file *filp)
1080{ 1080{
1081 int minor, ret; 1081 int minor, ret;
1082 enum vpe_state state;
1082 struct vpe *v; 1083 struct vpe *v;
1083 struct vpe_notifications *not; 1084 struct vpe_notifications *not;
1084 1085
@@ -1093,7 +1094,8 @@ static int vpe_open(struct inode *inode, struct file *filp)
1093 return -ENODEV; 1094 return -ENODEV;
1094 } 1095 }
1095 1096
1096 if (v->state != VPE_STATE_UNUSED) { 1097 state = xchg(&v->state, VPE_STATE_INUSE);
1098 if (state != VPE_STATE_UNUSED) {
1097 dvpe(); 1099 dvpe();
1098 1100
1099 printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n"); 1101 printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n");
@@ -1108,9 +1110,6 @@ static int vpe_open(struct inode *inode, struct file *filp)
1108 cleanup_tc(get_tc(minor)); 1110 cleanup_tc(get_tc(minor));
1109 } 1111 }
1110 1112
1111 // allocate it so when we get write ops we know it's expected.
1112 v->state = VPE_STATE_INUSE;
1113
1114 /* this of-course trashes what was there before... */ 1113 /* this of-course trashes what was there before... */
1115 v->pbuffer = vmalloc(P_SIZE); 1114 v->pbuffer = vmalloc(P_SIZE);
1116 v->plen = P_SIZE; 1115 v->plen = P_SIZE;