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