[MIPS] RTLX: Handle signals when sleeping.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

+42 -80
+42 -80
arch/mips/kernel/rtlx.c
··· 146 146 147 147 int rtlx_open(int index, int can_sleep) 148 148 { 149 - int ret; 150 - struct rtlx_channel *chan; 151 149 volatile struct rtlx_info **p; 150 + struct rtlx_channel *chan; 151 + int ret = 0; 152 152 153 153 if (index >= RTLX_CHANNELS) { 154 154 printk(KERN_DEBUG "rtlx_open index out of range\n"); ··· 165 165 if (rtlx == NULL) { 166 166 if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { 167 167 if (can_sleep) { 168 - DECLARE_WAITQUEUE(wait, current); 168 + int ret = 0; 169 169 170 - /* go to sleep */ 171 - add_wait_queue(&channel_wqs[index].lx_queue, &wait); 172 - 173 - set_current_state(TASK_INTERRUPTIBLE); 174 - while ((p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { 175 - schedule(); 176 - set_current_state(TASK_INTERRUPTIBLE); 177 - } 178 - 179 - set_current_state(TASK_RUNNING); 180 - remove_wait_queue(&channel_wqs[index].lx_queue, &wait); 181 - 182 - /* back running */ 170 + __wait_event_interruptible(channel_wqs[index].lx_queue, 171 + (p = vpe_get_shared(RTLX_TARG_VPE)), 172 + ret); 173 + if (ret) 174 + goto out_fail; 183 175 } else { 184 176 printk( KERN_DEBUG "No SP program loaded, and device " 185 177 "opened with O_NONBLOCK\n"); 186 178 channel_wqs[index].in_open = 0; 187 - return -ENOSYS; 179 + ret = -ENOSYS; 180 + goto out_fail; 188 181 } 189 182 } 190 183 191 184 if (*p == NULL) { 192 185 if (can_sleep) { 193 - DECLARE_WAITQUEUE(wait, current); 186 + int ret = 0; 194 187 195 - /* go to sleep */ 196 - add_wait_queue(&channel_wqs[index].lx_queue, &wait); 197 - 198 - set_current_state(TASK_INTERRUPTIBLE); 199 - while (*p == NULL) { 200 - schedule(); 201 - 202 - /* reset task state to interruptable otherwise 203 - we'll whizz round here like a very fast loopy 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 { 188 + __wait_event_interruptible(channel_wqs[index].lx_queue, 189 + *p != NULL, 190 + ret); 191 + if (ret) 192 + goto out_fail; 193 + } else { 223 194 printk(" *vpe_get_shared is NULL. " 224 195 "Has an SP program been loaded?\n"); 225 196 channel_wqs[index].in_open = 0; 226 - return -ENOSYS; 197 + ret = -ENOSYS; 198 + goto out_fail; 227 199 } 228 200 } 229 201 ··· 203 231 printk(KERN_WARNING "vpe_get_shared returned an invalid pointer " 204 232 "maybe an error code %d\n", (int)*p); 205 233 channel_wqs[index].in_open = 0; 206 - return -ENOSYS; 234 + ret = -ENOSYS; 235 + goto out_fail; 207 236 } 208 237 209 - if ((ret = rtlx_init(*p)) < 0) { 238 + if ((ret = rtlx_init(*p)) < 0) { 210 239 channel_wqs[index].in_open = 0; 211 240 return ret; 212 241 } ··· 223 250 chan->lx_state = RTLX_STATE_OPENED; 224 251 channel_wqs[index].in_open = 0; 225 252 return 0; 253 + 254 + out_fail: 255 + channel_wqs[index].in_open--; 256 + 257 + return ret; 226 258 } 227 259 228 260 int rtlx_release(int index) ··· 248 270 /* data available to read? */ 249 271 if (chan->lx_read == chan->lx_write) { 250 272 if (can_sleep) { 251 - DECLARE_WAITQUEUE(wait, current); 273 + int ret = 0; 252 274 253 - /* go to sleep */ 254 - add_wait_queue(&channel_wqs[index].lx_queue, &wait); 275 + __wait_event_interruptible(channel_wqs[index].lx_queue, 276 + chan->lx_read != chan->lx_write || sp_stopping, 277 + ret); 278 + if (ret) 279 + return ret; 255 280 256 - set_current_state(TASK_INTERRUPTIBLE); 257 - while (chan->lx_read == chan->lx_write) { 258 - schedule(); 259 - 260 - set_current_state(TASK_INTERRUPTIBLE); 261 - 262 - if (sp_stopping) { 263 - set_current_state(TASK_RUNNING); 264 - remove_wait_queue(&channel_wqs[index].lx_queue, &wait); 265 - return 0; 266 - } 267 - } 268 - 269 - set_current_state(TASK_RUNNING); 270 - remove_wait_queue(&channel_wqs[index].lx_queue, &wait); 271 - 272 - /* back running */ 273 - } 274 - else 281 + if (sp_stopping) 282 + return 0; 283 + } else 275 284 return 0; 276 285 } 277 286 ··· 419 454 { 420 455 int minor; 421 456 struct rtlx_channel *rt; 422 - DECLARE_WAITQUEUE(wait, current); 423 457 424 458 minor = iminor(file->f_path.dentry->d_inode); 425 459 rt = &rtlx->channel[minor]; 426 460 427 461 /* any space left... */ 428 462 if (!rtlx_write_poll(minor)) { 463 + int ret = 0; 429 464 430 465 if (file->f_flags & O_NONBLOCK) 431 466 return -EAGAIN; 432 467 433 - add_wait_queue(&channel_wqs[minor].rt_queue, &wait); 434 - set_current_state(TASK_INTERRUPTIBLE); 435 - 436 - while (!rtlx_write_poll(minor)) 437 - schedule(); 438 - 439 - set_current_state(TASK_RUNNING); 440 - remove_wait_queue(&channel_wqs[minor].rt_queue, &wait); 468 + __wait_event_interruptible(channel_wqs[minor].rt_queue, 469 + rtlx_write_poll(minor), 470 + ret); 471 + if (ret) 472 + return ret; 441 473 } 442 474 443 475 return rtlx_write(minor, (void *)buffer, count, 1);