staging/usbip: convert to kthread
authorArnd Bergmann <arnd@arndb.de>
Tue, 1 Mar 2011 23:13:05 +0000 (00:13 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 2 Mar 2011 21:03:59 +0000 (16:03 -0500)
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 <arnd@arndb.de>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Takahiro Hirofuchi <hirofuchi@users.sourceforge.net>
Cc: Max Vozeler <max@vozeler.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
13 files changed:
drivers/staging/usbip/Kconfig
drivers/staging/usbip/stub.h
drivers/staging/usbip/stub_dev.c
drivers/staging/usbip/stub_rx.c
drivers/staging/usbip/stub_tx.c
drivers/staging/usbip/usbip_common.c
drivers/staging/usbip/usbip_common.h
drivers/staging/usbip/usbip_event.c
drivers/staging/usbip/vhci.h
drivers/staging/usbip/vhci_hcd.c
drivers/staging/usbip/vhci_rx.c
drivers/staging/usbip/vhci_sysfs.c
drivers/staging/usbip/vhci_tx.c

index b11ec379b5c248ea75e7bed01c0d5aef6b23ce01..2c1d10acb8b52c6022461d9babb48c521f4bb93b 100644 (file)
@@ -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
index d73267961ef48774cbd8583fbdb1ec0daf7a25e3..6004fcdbc1a4bd2b8d71fa4d7c54c6621e4af3c9 100644 (file)
@@ -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 */
index a7ce51cc89099bfc26a8c777d604e1dc623d164e..8214c353d9f5224921c9d6d6962c4b31f2a979ff 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include "usbip_common.h"
 #include "stub.h"
@@ -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;
@@ -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 */
        /*
@@ -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; */
@@ -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;
        }
index ae6ac82754a4dd1296071037dac674f713de618f..6445f12cb4fd40cefacf77252fcfbf22eb7b3ff2 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include "usbip_common.h"
 #include "stub.h"
@@ -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;
 }
index d7136e2c86faa16a1e64638047dc0109dca0d533..5523f25998e6fcbae42de8490a7cee68f47506ca 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include "usbip_common.h"
 #include "stub.h"
@@ -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;
 
@@ -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;
 }
index 210ef16bab8d271a52e5d36cd1994aad57ad99e1..337abc48f714d11786402288258af4d38ca5636b 100644 (file)
@@ -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>
@@ -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 */
 
index d280e234e0670bca4220095c295c999e03213ade..9f809c315d92fc15f62ac94e2b63f07c74147bfa 100644 (file)
@@ -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,
@@ -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)
@@ -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 {
@@ -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);
 
index af3832b03e4b95cb12394ea0ed6b5232d091c9ac..f4b287ef71d0c97b92d45940ea3aae66cf87f65d 100644 (file)
@@ -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);
index afc3b1a7188199bf29496fbb6e9933d6f3d37952..d3f1e5f8a96023c2d45d52abf7740b80191f6ae6 100644 (file)
@@ -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);
index a35fe61268de3e974f8ece7f2edb0bd1e28b0468..36ae9fbd20a6796ef2d64cd97200d444c61e514a 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include "usbip_common.h"
 #include "vhci.h"
@@ -874,7 +875,10 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
                kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
        }
 
-       usbip_stop_threads(&vdev->ud);
+       /* kill threads related to this sdev, if v.c. exists */
+       kthread_stop(vdev->ud.tcp_rx);
+       kthread_stop(vdev->ud.tcp_tx);
+
        usbip_uinfo("stop threads\n");
 
        /* active connection is closed */
@@ -945,8 +949,8 @@ static void vhci_device_init(struct vhci_device *vdev)
 {
        memset(vdev, 0, sizeof(*vdev));
 
-       usbip_task_init(&vdev->ud.tcp_rx, "vhci_rx", vhci_rx_loop);
-       usbip_task_init(&vdev->ud.tcp_tx, "vhci_tx", vhci_tx_loop);
+       vdev->ud.tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx");
+       vdev->ud.tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx");
 
        vdev->ud.side   = USBIP_VHCI;
        vdev->ud.status = VDEV_ST_NULL;
index bf69914709410cf054825933a638b7dd7060180a..09bf2355934bb6834e67641ab679faec43e88818 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include "usbip_common.h"
 #include "vhci.h"
@@ -269,22 +270,17 @@ static void vhci_rx_pdu(struct usbip_device *ud)
 
 /*-------------------------------------------------------------------------*/
 
-void vhci_rx_loop(struct usbip_task *ut)
+int vhci_rx_loop(void *data)
 {
-       struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx);
-
-
-       while (1) {
-               if (signal_pending(current)) {
-                       usbip_dbg_vhci_rx("signal catched!\n");
-                       break;
-               }
+       struct usbip_device *ud = data;
 
 
+       while (!kthread_should_stop()) {
                if (usbip_event_happened(ud))
                        break;
 
                vhci_rx_pdu(ud);
        }
-}
 
+       return 0;
+}
index f6e34e03c8e47afd92ad7416e13fd67658f51031..3f2459f30415ef5ec03e84eedf0417bb712d93e1 100644 (file)
@@ -220,16 +220,13 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
        vdev->ud.tcp_socket = socket;
        vdev->ud.status     = VDEV_ST_NOTASSIGNED;
 
+       wake_up_process(vdev->ud.tcp_rx);
+       wake_up_process(vdev->ud.tcp_tx);
+
        spin_unlock(&vdev->ud.lock);
        spin_unlock(&the_controller->lock);
        /* end the lock */
 
-       /*
-        * this function will sleep, so should be out of the lock. but, it's ok
-        * because we already marked vdev as being used. really?
-        */
-       usbip_start_threads(&vdev->ud);
-
        rh_port_connect(rhport, speed);
 
        return count;
index e1c1f716a1c2822a9bacb138af03e05fb1c64e6b..d9ab49d6769734870514924a065e7a2b2b5f53a0 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include "usbip_common.h"
 #include "vhci.h"
@@ -215,17 +216,12 @@ static int vhci_send_cmd_unlink(struct vhci_device *vdev)
 
 /*-------------------------------------------------------------------------*/
 
-void vhci_tx_loop(struct usbip_task *ut)
+int vhci_tx_loop(void *data)
 {
-       struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx);
+       struct usbip_device *ud = data;
        struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
 
-       while (1) {
-               if (signal_pending(current)) {
-                       usbip_uinfo("vhci_tx signal catched\n");
-                       break;
-               }
-
+       while (!kthread_should_stop()) {
                if (vhci_send_cmd_submit(vdev) < 0)
                        break;
 
@@ -234,8 +230,11 @@ void vhci_tx_loop(struct usbip_task *ut)
 
                wait_event_interruptible(vdev->waitq_tx,
                                (!list_empty(&vdev->priv_tx) ||
-                                !list_empty(&vdev->unlink_tx)));
+                                !list_empty(&vdev->unlink_tx) ||
+                                kthread_should_stop()));
 
                usbip_dbg_vhci_tx("pending urbs ?, now wake up\n");
        }
+
+       return 0;
 }