diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2007-02-22 09:19:48 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-02-26 18:06:05 -0500 |
commit | 67e2cccec6d230165345fdf6c0fe4c8761f9d1ba (patch) | |
tree | 13b46b0eb5726d1b4011e5e52fbcfc0197240e73 | |
parent | cc39cb15a62c7e515557edcc3aea20cc62ffb13b (diff) |
[MIPS] RTLX: Handle signals when sleeping.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/kernel/rtlx.c | 122 |
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 | ||
147 | int rtlx_open(int index, int can_sleep) | 147 | int 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 | |||
227 | out_fail: | ||
228 | channel_wqs[index].in_open--; | ||
229 | |||
230 | return ret; | ||
253 | } | 231 | } |
254 | 232 | ||
255 | int rtlx_release(int index) | 233 | int 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); |