ENGR00308442-1 usb: chipidea: otg: revert thread solution to restore work queue
authorLi Jun <b47624@freescale.com>
Mon, 14 Apr 2014 06:35:20 +0000 (14:35 +0800)
committerNitin Garg <nitin.garg@freescale.com>
Wed, 16 Apr 2014 16:02:31 +0000 (11:02 -0500)
Revert "ENGR00286962-2 usb: chipidea: fix the system will be deadlock with ID
wakeup" since dedicated thread solution is some expensive, and for otg fsm
extension, work queue is requred.

This reverts commit 7d6fa1243c29562461752c2115a25cb54dc49217.

Signed-off-by: Li Jun <b47624@freescale.com>
drivers/usb/chipidea/ci.h
drivers/usb/chipidea/core.c
drivers/usb/chipidea/otg.c

index eb4d9879acacd8db50c20dbd3942e501f7f2abdc..30f13b414ecf1020bbbe3847ee09eb3d73eedadc 100644 (file)
@@ -110,8 +110,8 @@ struct hw_bank {
  * @roles: array of supported roles for this controller
  * @role: current role
  * @is_otg: if the device is otg-capable
- * @otg_task: the thread for handling otg task
- * @otg_wait: the otg event waitqueue head
+ * @work: work for role changing
+ * @wq: workqueue thread
  * @qh_pool: allocation pool for queue heads
  * @td_pool: allocation pool for transfer descriptors
  * @gadget: device side representation for peripheral controller
@@ -149,8 +149,8 @@ struct ci_hdrc {
        struct ci_role_driver           *roles[CI_ROLE_END];
        enum ci_role                    role;
        bool                            is_otg;
-       struct task_struct              *otg_task;
-       wait_queue_head_t               otg_wait;
+       struct work_struct              work;
+       struct workqueue_struct         *wq;
 
        struct dma_pool                 *qh_pool;
        struct dma_pool                 *td_pool;
index c3bea69cd775c37b3351d7d87a0f5909c26e7be7..572403932fc419200e0edd1bc02f3a606578809c 100644 (file)
@@ -446,7 +446,7 @@ static irqreturn_t ci_irq(int irq, void *data)
                ci->id_event = true;
                hw_write_otgsc(ci, OTGSC_IDIS, OTGSC_IDIS);
                disable_irq_nosync(ci->irq);
-               wake_up(&ci->otg_wait);
+               queue_work(ci->wq, &ci->work);
                return IRQ_HANDLED;
        }
 
@@ -458,7 +458,7 @@ static irqreturn_t ci_irq(int irq, void *data)
                ci->b_sess_valid_event = true;
                hw_write_otgsc(ci, OTGSC_BSVIS, OTGSC_BSVIS);
                disable_irq_nosync(ci->irq);
-               wake_up(&ci->otg_wait);
+               queue_work(ci->wq, &ci->work);
                return IRQ_HANDLED;
        }
 
index e6767e9cb1e8c1626ffe1a47cc38e21134c5a849..0e2b2d8bcb58e84f3c0a6270347377dfb92d810c 100644 (file)
@@ -18,8 +18,6 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/chipidea.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
 
 #include "ci.h"
 #include "bits.h"
@@ -102,19 +100,14 @@ static void ci_handle_id_switch(struct ci_hdrc *ci)
                ci_role_start(ci, role);
        }
 }
-
-/* If there is pending otg event */
-static inline bool ci_otg_event_is_pending(struct ci_hdrc *ci)
-{
-       return ci->id_event || ci->b_sess_valid_event;
-}
-
 /**
- * ci_otg_event - perform otg (vbus/id) event handle
- * @ci: ci_hdrc struct
+ * ci_otg_work - perform otg (vbus/id) event handle
+ * @work: work struct
  */
-static void ci_otg_event(struct ci_hdrc *ci)
+static void ci_otg_work(struct work_struct *work)
 {
+       struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work);
+
        if (ci->id_event) {
                ci->id_event = false;
                /* Keep controller active during id switch */
@@ -132,23 +125,6 @@ static void ci_otg_event(struct ci_hdrc *ci)
        enable_irq(ci->irq);
 }
 
-static int ci_otg_thread(void *ptr)
-{
-       struct ci_hdrc *ci = ptr;
-
-       set_freezable();
-
-       do {
-               wait_event_freezable(ci->otg_wait,
-                               ci_otg_event_is_pending(ci) ||
-                               kthread_should_stop());
-               ci_otg_event(ci);
-       } while (!kthread_should_stop());
-
-       dev_warn(ci->dev, "ci_otg_thread quits\n");
-
-       return 0;
-}
 
 /**
  * ci_hdrc_otg_init - initialize otg struct
@@ -156,11 +132,11 @@ static int ci_otg_thread(void *ptr)
  */
 int ci_hdrc_otg_init(struct ci_hdrc *ci)
 {
-       init_waitqueue_head(&ci->otg_wait);
-       ci->otg_task = kthread_run(ci_otg_thread, ci, "ci otg thread");
-       if (IS_ERR(ci->otg_task)) {
-               dev_err(ci->dev, "error to create otg thread\n");
-               return PTR_ERR(ci->otg_task);
+       INIT_WORK(&ci->work, ci_otg_work);
+       ci->wq = create_singlethread_workqueue("ci_otg");
+       if (!ci->wq) {
+               dev_err(ci->dev, "can't create workqueue\n");
+               return -ENODEV;
        }
 
        return 0;
@@ -172,7 +148,11 @@ int ci_hdrc_otg_init(struct ci_hdrc *ci)
  */
 void ci_hdrc_otg_destroy(struct ci_hdrc *ci)
 {
-       kthread_stop(ci->otg_task);
+       if (ci->wq) {
+               flush_workqueue(ci->wq);
+               destroy_workqueue(ci->wq);
+       }
+
        hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS,
                                                OTGSC_INT_STATUS_BITS);
 }