aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-02-22 09:19:48 -0500
committerRalf Baechle <ralf@linux-mips.org>2007-02-26 18:06:05 -0500
commit67e2cccec6d230165345fdf6c0fe4c8761f9d1ba (patch)
tree13b46b0eb5726d1b4011e5e52fbcfc0197240e73
parentcc39cb15a62c7e515557edcc3aea20cc62ffb13b (diff)
[MIPS] RTLX: Handle signals when sleeping.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/rtlx.c122
1 files changed, 42 insertions, 80 deletions
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index d92c48e0d7a6..766db51ab69e 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -146,9 +146,9 @@ static void stopping(int vpe)
146 146
147int rtlx_open(int index, int can_sleep) 147int rtlx_open(int index, int can_sleep)
148{ 148{
149 int ret;
150 struct rtlx_channel *chan;
151 volatile struct rtlx_info **p; 149 volatile struct rtlx_info **p;
150 struct rtlx_channel *chan;
151 int ret = 0;
152 152
153 if (index >= RTLX_CHANNELS) { 153 if (index >= RTLX_CHANNELS) {
154 printk(KERN_DEBUG "rtlx_open index out of range\n"); 154 printk(KERN_DEBUG "rtlx_open index out of range\n");
@@ -165,65 +165,37 @@ int rtlx_open(int index, int can_sleep)
165 if (rtlx == NULL) { 165 if (rtlx == NULL) {
166 if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { 166 if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
167 if (can_sleep) { 167 if (can_sleep) {
168 DECLARE_WAITQUEUE(wait, current); 168 int ret = 0;
169
170 /* go to sleep */
171 add_wait_queue(&channel_wqs[index].lx_queue, &wait);
172 169
173 set_current_state(TASK_INTERRUPTIBLE); 170 __wait_event_interruptible(channel_wqs[index].lx_queue,
174 while ((p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { 171 (p = vpe_get_shared(RTLX_TARG_VPE)),
175 schedule(); 172 ret);
176 set_current_state(TASK_INTERRUPTIBLE); 173 if (ret)
177 } 174 goto out_fail;
178
179 set_current_state(TASK_RUNNING);
180 remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
181
182 /* back running */
183 } else { 175 } else {
184 printk( KERN_DEBUG "No SP program loaded, and device " 176 printk( KERN_DEBUG "No SP program loaded, and device "
185 "opened with O_NONBLOCK\n"); 177 "opened with O_NONBLOCK\n");
186 channel_wqs[index].in_open = 0; 178 channel_wqs[index].in_open = 0;
187 return -ENOSYS; 179 ret = -ENOSYS;
180 goto out_fail;
188 } 181 }
189 } 182 }
190 183
191 if (*p == NULL) { 184 if (*p == NULL) {
192 if (can_sleep) { 185 if (can_sleep) {
193 DECLARE_WAITQUEUE(wait, current); 186 int ret = 0;
194
195 /* go to sleep */
196 add_wait_queue(&channel_wqs[index].lx_queue, &wait);
197 187
198 set_current_state(TASK_INTERRUPTIBLE); 188 __wait_event_interruptible(channel_wqs[index].lx_queue,
199 while (*p == NULL) { 189 *p != NULL,
200 schedule(); 190 ret);
201 191 if (ret)
202 /* reset task state to interruptable otherwise 192 goto out_fail;
203 we'll whizz round here like a very fast loopy 193 } else {
204 thing. schedule() appears to return with state
205 set to TASK_RUNNING.
206
207 If the loaded SP program, for whatever reason,
208 doesn't set up the shared structure *p will never
209 become true. So whoever connected to either /dev/rt?
210 or if it was kspd, will then take up rather a lot of
211 processor cycles.
212 */
213
214 set_current_state(TASK_INTERRUPTIBLE);
215 }
216
217 set_current_state(TASK_RUNNING);
218 remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
219
220 /* back running */
221 }
222 else {
223 printk(" *vpe_get_shared is NULL. " 194 printk(" *vpe_get_shared is NULL. "
224 "Has an SP program been loaded?\n"); 195 "Has an SP program been loaded?\n");
225 channel_wqs[index].in_open = 0; 196 channel_wqs[index].in_open = 0;
226 return -ENOSYS; 197 ret = -ENOSYS;
198 goto out_fail;
227 } 199 }
228 } 200 }
229 201
@@ -231,10 +203,11 @@ int rtlx_open(int index, int can_sleep)
231 printk(KERN_WARNING "vpe_get_shared returned an invalid pointer " 203 printk(KERN_WARNING "vpe_get_shared returned an invalid pointer "
232 "maybe an error code %d\n", (int)*p); 204 "maybe an error code %d\n", (int)*p);
233 channel_wqs[index].in_open = 0; 205 channel_wqs[index].in_open = 0;
234 return -ENOSYS; 206 ret = -ENOSYS;
207 goto out_fail;
235 } 208 }
236 209
237 if ((ret = rtlx_init(*p)) < 0) { 210 if ((ret = rtlx_init(*p)) < 0) {
238 channel_wqs[index].in_open = 0; 211 channel_wqs[index].in_open = 0;
239 return ret; 212 return ret;
240 } 213 }
@@ -250,6 +223,11 @@ int rtlx_open(int index, int can_sleep)
250 chan->lx_state = RTLX_STATE_OPENED; 223 chan->lx_state = RTLX_STATE_OPENED;
251 channel_wqs[index].in_open = 0; 224 channel_wqs[index].in_open = 0;
252 return 0; 225 return 0;
226
227out_fail:
228 channel_wqs[index].in_open--;
229
230 return ret;
253} 231}
254 232
255int rtlx_release(int index) 233int rtlx_release(int index)
@@ -270,30 +248,17 @@ unsigned int rtlx_read_poll(int index, int can_sleep)
270 /* data available to read? */ 248 /* data available to read? */
271 if (chan->lx_read == chan->lx_write) { 249 if (chan->lx_read == chan->lx_write) {
272 if (can_sleep) { 250 if (can_sleep) {
273 DECLARE_WAITQUEUE(wait, current); 251 int ret = 0;
274 252
275 /* go to sleep */ 253 __wait_event_interruptible(channel_wqs[index].lx_queue,
276 add_wait_queue(&channel_wqs[index].lx_queue, &wait); 254 chan->lx_read != chan->lx_write || sp_stopping,
255 ret);
256 if (ret)
257 return ret;
277 258
278 set_current_state(TASK_INTERRUPTIBLE); 259 if (sp_stopping)
279 while (chan->lx_read == chan->lx_write) { 260 return 0;
280 schedule(); 261 } else
281
282 set_current_state(TASK_INTERRUPTIBLE);
283
284 if (sp_stopping) {
285 set_current_state(TASK_RUNNING);
286 remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
287 return 0;
288 }
289 }
290
291 set_current_state(TASK_RUNNING);
292 remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
293
294 /* back running */
295 }
296 else
297 return 0; 262 return 0;
298 } 263 }
299 264
@@ -454,25 +419,22 @@ static ssize_t file_write(struct file *file, const char __user * buffer,
454{ 419{
455 int minor; 420 int minor;
456 struct rtlx_channel *rt; 421 struct rtlx_channel *rt;
457 DECLARE_WAITQUEUE(wait, current);
458 422
459 minor = iminor(file->f_path.dentry->d_inode); 423 minor = iminor(file->f_path.dentry->d_inode);
460 rt = &rtlx->channel[minor]; 424 rt = &rtlx->channel[minor];
461 425
462 /* any space left... */ 426 /* any space left... */
463 if (!rtlx_write_poll(minor)) { 427 if (!rtlx_write_poll(minor)) {
428 int ret = 0;
464 429
465 if (file->f_flags & O_NONBLOCK) 430 if (file->f_flags & O_NONBLOCK)
466 return -EAGAIN; 431 return -EAGAIN;
467 432
468 add_wait_queue(&channel_wqs[minor].rt_queue, &wait); 433 __wait_event_interruptible(channel_wqs[minor].rt_queue,
469 set_current_state(TASK_INTERRUPTIBLE); 434 rtlx_write_poll(minor),
470 435 ret);
471 while (!rtlx_write_poll(minor)) 436 if (ret)
472 schedule(); 437 return ret;
473
474 set_current_state(TASK_RUNNING);
475 remove_wait_queue(&channel_wqs[minor].rt_queue, &wait);
476 } 438 }
477 439
478 return rtlx_write(minor, (void *)buffer, count, 1); 440 return rtlx_write(minor, (void *)buffer, count, 1);