Skip to content

Commit

Permalink
staging/usbip: convert to kthread
Browse files Browse the repository at this point in the history
usbip has its own infrastructure for managing kernel
threads, similar to kthread. By changing it to use
the standard functions, we can simplify the code
and get rid of one of the last BKL users at the
same time.

Includes changes suggested by Max Vozeler.

Signed-off-by: Arnd Bergmann <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Takahiro Hirofuchi <[email protected]>
Cc: Max Vozeler <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
arndb authored and gregkh committed Mar 2, 2011
1 parent 8c81161 commit 9720b4b
Show file tree
Hide file tree
Showing 13 changed files with 64 additions and 203 deletions.
2 changes: 1 addition & 1 deletion drivers/staging/usbip/Kconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
config USB_IP_COMMON
tristate "USB IP support (EXPERIMENTAL)"
depends on USB && NET && EXPERIMENTAL && BKL
depends on USB && NET && EXPERIMENTAL
default N
---help---
This enables pushing USB packets over IP to allow remote
Expand Down
4 changes: 2 additions & 2 deletions drivers/staging/usbip/stub.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@ extern struct kmem_cache *stub_priv_cache;

/* stub_tx.c */
void stub_complete(struct urb *);
void stub_tx_loop(struct usbip_task *);
int stub_tx_loop(void *data);

/* stub_dev.c */
extern struct usb_driver stub_driver;

/* stub_rx.c */
void stub_rx_loop(struct usbip_task *);
int stub_rx_loop(void *data);
void stub_enqueue_ret_unlink(struct stub_device *, __u32, __u32);

/* stub_main.c */
Expand Down
12 changes: 6 additions & 6 deletions drivers/staging/usbip/stub_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

#include <linux/slab.h>
#include <linux/kthread.h>

#include "usbip_common.h"
#include "stub.h"
Expand Down Expand Up @@ -138,7 +139,8 @@ static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr,

spin_unlock(&sdev->ud.lock);

usbip_start_threads(&sdev->ud);
sdev->ud.tcp_rx = kthread_run(stub_rx_loop, &sdev->ud, "stub_rx");
sdev->ud.tcp_tx = kthread_run(stub_tx_loop, &sdev->ud, "stub_tx");

spin_lock(&sdev->ud.lock);
sdev->ud.status = SDEV_ST_USED;
Expand Down Expand Up @@ -218,7 +220,8 @@ static void stub_shutdown_connection(struct usbip_device *ud)
}

/* 1. stop threads */
usbip_stop_threads(ud);
kthread_stop(ud->tcp_rx);
kthread_stop(ud->tcp_tx);

/* 2. close the socket */
/*
Expand Down Expand Up @@ -336,9 +339,6 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev,
*/
sdev->devid = (busnum << 16) | devnum;

usbip_task_init(&sdev->ud.tcp_rx, "stub_rx", stub_rx_loop);
usbip_task_init(&sdev->ud.tcp_tx, "stub_tx", stub_tx_loop);

sdev->ud.side = USBIP_STUB;
sdev->ud.status = SDEV_ST_AVAILABLE;
/* sdev->ud.lock = SPIN_LOCK_UNLOCKED; */
Expand Down Expand Up @@ -543,7 +543,7 @@ static void stub_disconnect(struct usb_interface *interface)
stub_remove_files(&interface->dev);

/*If usb reset called from event handler*/
if (busid_priv->sdev->ud.eh.thread == current) {
if (busid_priv->sdev->ud.eh == current) {
busid_priv->interf_count--;
return;
}
Expand Down
13 changes: 5 additions & 8 deletions drivers/staging/usbip/stub_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

#include <linux/slab.h>
#include <linux/kthread.h>

#include "usbip_common.h"
#include "stub.h"
Expand Down Expand Up @@ -616,19 +617,15 @@ static void stub_rx_pdu(struct usbip_device *ud)

}

void stub_rx_loop(struct usbip_task *ut)
int stub_rx_loop(void *data)
{
struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx);

while (1) {
if (signal_pending(current)) {
usbip_dbg_stub_rx("signal caught!\n");
break;
}
struct usbip_device *ud = data;

while (!kthread_should_stop()) {
if (usbip_event_happened(ud))
break;

stub_rx_pdu(ud);
}
return 0;
}
17 changes: 8 additions & 9 deletions drivers/staging/usbip/stub_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

#include <linux/slab.h>
#include <linux/kthread.h>

#include "usbip_common.h"
#include "stub.h"
Expand Down Expand Up @@ -333,17 +334,12 @@ static int stub_send_ret_unlink(struct stub_device *sdev)

/*-------------------------------------------------------------------------*/

void stub_tx_loop(struct usbip_task *ut)
int stub_tx_loop(void *data)
{
struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx);
struct usbip_device *ud = data;
struct stub_device *sdev = container_of(ud, struct stub_device, ud);

while (1) {
if (signal_pending(current)) {
usbip_dbg_stub_tx("signal catched\n");
break;
}

while (!kthread_should_stop()) {
if (usbip_event_happened(ud))
break;

Expand All @@ -369,6 +365,9 @@ void stub_tx_loop(struct usbip_task *ut)

wait_event_interruptible(sdev->tx_waitq,
(!list_empty(&sdev->priv_tx) ||
!list_empty(&sdev->unlink_tx)));
!list_empty(&sdev->unlink_tx) ||
kthread_should_stop()));
}

return 0;
}
105 changes: 0 additions & 105 deletions drivers/staging/usbip/usbip_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*/

#include <linux/kernel.h>
#include <linux/smp_lock.h>
#include <linux/file.h>
#include <linux/tcp.h>
#include <linux/in.h>
Expand Down Expand Up @@ -349,110 +348,6 @@ void usbip_dump_header(struct usbip_header *pdu)
}
EXPORT_SYMBOL_GPL(usbip_dump_header);


/*-------------------------------------------------------------------------*/
/* thread routines */

int usbip_thread(void *param)
{
struct usbip_task *ut = param;

if (!ut)
return -EINVAL;

lock_kernel();
daemonize(ut->name);
allow_signal(SIGKILL);
ut->thread = current;
unlock_kernel();

/* srv.rb must wait for rx_thread starting */
complete(&ut->thread_done);

/* start of while loop */
ut->loop_ops(ut);

/* end of loop */
ut->thread = NULL;

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");
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");
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 */
stop_rx_thread(ud);
stop_tx_thread(ud);
}
EXPORT_SYMBOL_GPL(usbip_stop_threads);

void usbip_task_init(struct usbip_task *ut, char *name,
void (*loop_ops)(struct usbip_task *))
{
ut->thread = NULL;
init_completion(&ut->thread_done);
ut->name = name;
ut->loop_ops = loop_ops;
}
EXPORT_SYMBOL_GPL(usbip_task_init);


/*-------------------------------------------------------------------------*/
/* socket routines */

Expand Down
20 changes: 3 additions & 17 deletions drivers/staging/usbip/usbip_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,6 @@ void usbip_dump_header(struct usbip_header *pdu);

struct usbip_device;

struct usbip_task {
struct task_struct *thread;
struct completion thread_done;
char *name;
void (*loop_ops)(struct usbip_task *);
};

enum usbip_side {
USBIP_VHCI,
USBIP_STUB,
Expand Down Expand Up @@ -346,8 +339,8 @@ struct usbip_device {

struct socket *tcp_socket;

struct usbip_task tcp_rx;
struct usbip_task tcp_tx;
struct task_struct *tcp_rx;
struct task_struct *tcp_tx;

/* event handler */
#define USBIP_EH_SHUTDOWN (1 << 0)
Expand All @@ -367,7 +360,7 @@ struct usbip_device {
#define VDEV_EVENT_ERROR_MALLOC (USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE)

unsigned long event;
struct usbip_task eh;
struct task_struct *eh;
wait_queue_head_t eh_waitq;

struct eh_ops {
Expand All @@ -378,13 +371,6 @@ struct usbip_device {
};


void usbip_task_init(struct usbip_task *ut, char *,
void (*loop_ops)(struct usbip_task *));

int usbip_start_threads(struct usbip_device *ud);
void usbip_stop_threads(struct usbip_device *ud);
int usbip_thread(void *param);

void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
int pack);

Expand Down
38 changes: 13 additions & 25 deletions drivers/staging/usbip/usbip_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,55 +62,43 @@ static int event_handler(struct usbip_device *ud)
return 0;
}

static void event_handler_loop(struct usbip_task *ut)
static int event_handler_loop(void *data)
{
struct usbip_device *ud = container_of(ut, struct usbip_device, eh);
struct usbip_device *ud = data;

while (1) {
if (signal_pending(current)) {
usbip_dbg_eh("signal catched!\n");
break;
}
while (!kthread_should_stop()) {
wait_event_interruptible(ud->eh_waitq,
usbip_event_happened(ud) ||
kthread_should_stop());
usbip_dbg_eh("wakeup\n");

if (event_handler(ud) < 0)
break;

wait_event_interruptible(ud->eh_waitq,
usbip_event_happened(ud));
usbip_dbg_eh("wakeup\n");
}
return 0;
}

int usbip_start_eh(struct usbip_device *ud)
{
struct usbip_task *eh = &ud->eh;
struct task_struct *th;

init_waitqueue_head(&ud->eh_waitq);
ud->event = 0;

usbip_task_init(eh, "usbip_eh", event_handler_loop);

th = kthread_run(usbip_thread, (void *)eh, "usbip");
if (IS_ERR(th)) {
ud->eh = kthread_run(event_handler_loop, ud, "usbip_eh");
if (IS_ERR(ud->eh)) {
printk(KERN_WARNING
"Unable to start control thread\n");
return PTR_ERR(th);
return PTR_ERR(ud->eh);
}

wait_for_completion(&eh->thread_done);
return 0;
}
EXPORT_SYMBOL_GPL(usbip_start_eh);

void usbip_stop_eh(struct usbip_device *ud)
{
struct usbip_task *eh = &ud->eh;

if (eh->thread == current)
if (ud->eh == current)
return; /* do not wait for myself */

wait_for_completion(&eh->thread_done);
kthread_stop(ud->eh);
usbip_dbg_eh("usbip_eh has finished\n");
}
EXPORT_SYMBOL_GPL(usbip_stop_eh);
Expand Down
4 changes: 2 additions & 2 deletions drivers/staging/usbip/vhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ extern struct attribute_group dev_attr_group;
/* vhci_hcd.c */
void rh_port_connect(int rhport, enum usb_device_speed speed);
void rh_port_disconnect(int rhport);
void vhci_rx_loop(struct usbip_task *ut);
void vhci_tx_loop(struct usbip_task *ut);
int vhci_rx_loop(void *data);
int vhci_tx_loop(void *data);

struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev,
__u32 seqnum);
Expand Down
Loading

0 comments on commit 9720b4b

Please sign in to comment.