Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2102d31 authored by Himanshu Chauhan's avatar Himanshu Chauhan Committed by Greg Kroah-Hartman
Browse files

staging: usbip: usbip_common: kill rx thread on tx thread creation error.

parent 93416253
Loading
Loading
Loading
Loading
+33 −13
Original line number Diff line number Diff line
@@ -378,47 +378,67 @@ int usbip_thread(void *param)
	complete_and_exit(&ut->thread_done, 0);
}

static void stop_rx_thread(struct usbip_device *ud)
{
	if (ud->tcp_rx.thread != NULL) {
		send_sig(SIGKILL, ud->tcp_rx.thread, 1);
		wait_for_completion(&ud->tcp_rx.thread_done);
		usbip_udbg("rx_thread for ud %p has finished\n", ud);
	}
}

static void stop_tx_thread(struct usbip_device *ud)
{
	if (ud->tcp_tx.thread != NULL) {
		send_sig(SIGKILL, ud->tcp_tx.thread, 1);
		wait_for_completion(&ud->tcp_tx.thread_done);
		usbip_udbg("tx_thread for ud %p has finished\n", ud);
	}
}

int usbip_start_threads(struct usbip_device *ud)
{
	/*
	 * threads are invoked per one device (per one connection).
	 */
	struct task_struct *th;
	int err = 0;

	th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip");
	if (IS_ERR(th)) {
		printk(KERN_WARNING
			"Unable to start control thread\n");
		return PTR_ERR(th);
		err = PTR_ERR(th);
		goto ust_exit;
	}

	th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip");
	if (IS_ERR(th)) {
		printk(KERN_WARNING
			"Unable to start control thread\n");
		return PTR_ERR(th);
		err = PTR_ERR(th);
		goto tx_thread_err;
	}

	/* confirm threads are starting */
	wait_for_completion(&ud->tcp_rx.thread_done);
	wait_for_completion(&ud->tcp_tx.thread_done);

	return 0;

tx_thread_err:
	stop_rx_thread(ud);

ust_exit:
	return err;
}
EXPORT_SYMBOL_GPL(usbip_start_threads);

void usbip_stop_threads(struct usbip_device *ud)
{
	/* kill threads related to this sdev, if v.c. exists */
	if (ud->tcp_rx.thread != NULL) {
		send_sig(SIGKILL, ud->tcp_rx.thread, 1);
		wait_for_completion(&ud->tcp_rx.thread_done);
		usbip_udbg("rx_thread for ud %p has finished\n", ud);
	}

	if (ud->tcp_tx.thread != NULL) {
		send_sig(SIGKILL, ud->tcp_tx.thread, 1);
		wait_for_completion(&ud->tcp_tx.thread_done);
		usbip_udbg("tx_thread for ud %p has finished\n", ud);
	}
	stop_rx_thread(ud);
	stop_tx_thread(ud);
}
EXPORT_SYMBOL_GPL(usbip_stop_threads);