aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorHimanshu Chauhan <hschauhan@nulltrace.org>2010-06-04 13:46:27 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-06-30 11:18:14 -0400
commitf2102d31de1f0ddb9ced62d65d2ed89a5149ea39 (patch)
treeb045f523d4699d735b952fdf7aa4a7f103852247 /drivers/staging
parent93416253073511716f7e70c06e32c3810c3deac4 (diff)
staging: usbip: usbip_common: kill rx thread on tx thread creation error.
Signed-off-by: Himanshu Chauhan <hschauhan@nulltrace.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/usbip/usbip_common.c46
1 files changed, 33 insertions, 13 deletions
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
index 52408164036f..6a499f0eb594 100644
--- a/drivers/staging/usbip/usbip_common.c
+++ b/drivers/staging/usbip/usbip_common.c
@@ -378,47 +378,67 @@ int usbip_thread(void *param)
378 complete_and_exit(&ut->thread_done, 0); 378 complete_and_exit(&ut->thread_done, 0);
379} 379}
380 380
381static void stop_rx_thread(struct usbip_device *ud)
382{
383 if (ud->tcp_rx.thread != NULL) {
384 send_sig(SIGKILL, ud->tcp_rx.thread, 1);
385 wait_for_completion(&ud->tcp_rx.thread_done);
386 usbip_udbg("rx_thread for ud %p has finished\n", ud);
387 }
388}
389
390static void stop_tx_thread(struct usbip_device *ud)
391{
392 if (ud->tcp_tx.thread != NULL) {
393 send_sig(SIGKILL, ud->tcp_tx.thread, 1);
394 wait_for_completion(&ud->tcp_tx.thread_done);
395 usbip_udbg("tx_thread for ud %p has finished\n", ud);
396 }
397}
398
381int usbip_start_threads(struct usbip_device *ud) 399int usbip_start_threads(struct usbip_device *ud)
382{ 400{
383 /* 401 /*
384 * threads are invoked per one device (per one connection). 402 * threads are invoked per one device (per one connection).
385 */ 403 */
386 struct task_struct *th; 404 struct task_struct *th;
405 int err = 0;
387 406
388 th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip"); 407 th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip");
389 if (IS_ERR(th)) { 408 if (IS_ERR(th)) {
390 printk(KERN_WARNING 409 printk(KERN_WARNING
391 "Unable to start control thread\n"); 410 "Unable to start control thread\n");
392 return PTR_ERR(th); 411 err = PTR_ERR(th);
412 goto ust_exit;
393 } 413 }
414
394 th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip"); 415 th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip");
395 if (IS_ERR(th)) { 416 if (IS_ERR(th)) {
396 printk(KERN_WARNING 417 printk(KERN_WARNING
397 "Unable to start control thread\n"); 418 "Unable to start control thread\n");
398 return PTR_ERR(th); 419 err = PTR_ERR(th);
420 goto tx_thread_err;
399 } 421 }
400 422
401 /* confirm threads are starting */ 423 /* confirm threads are starting */
402 wait_for_completion(&ud->tcp_rx.thread_done); 424 wait_for_completion(&ud->tcp_rx.thread_done);
403 wait_for_completion(&ud->tcp_tx.thread_done); 425 wait_for_completion(&ud->tcp_tx.thread_done);
426
404 return 0; 427 return 0;
428
429tx_thread_err:
430 stop_rx_thread(ud);
431
432ust_exit:
433 return err;
405} 434}
406EXPORT_SYMBOL_GPL(usbip_start_threads); 435EXPORT_SYMBOL_GPL(usbip_start_threads);
407 436
408void usbip_stop_threads(struct usbip_device *ud) 437void usbip_stop_threads(struct usbip_device *ud)
409{ 438{
410 /* kill threads related to this sdev, if v.c. exists */ 439 /* kill threads related to this sdev, if v.c. exists */
411 if (ud->tcp_rx.thread != NULL) { 440 stop_rx_thread(ud);
412 send_sig(SIGKILL, ud->tcp_rx.thread, 1); 441 stop_tx_thread(ud);
413 wait_for_completion(&ud->tcp_rx.thread_done);
414 usbip_udbg("rx_thread for ud %p has finished\n", ud);
415 }
416
417 if (ud->tcp_tx.thread != NULL) {
418 send_sig(SIGKILL, ud->tcp_tx.thread, 1);
419 wait_for_completion(&ud->tcp_tx.thread_done);
420 usbip_udbg("tx_thread for ud %p has finished\n", ud);
421 }
422} 442}
423EXPORT_SYMBOL_GPL(usbip_stop_threads); 443EXPORT_SYMBOL_GPL(usbip_stop_threads);
424 444