aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLi Jun <b47624@freescale.com>2014-04-14 02:35:20 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 12:02:31 -0400
commitcf09d8ce34d752891ef9203097d1e8cf48a5fe85 (patch)
tree06acc5ad6e97771d094070cd4c8ec6f1ab0908e9
parenta09fde0d4aba9da26a579cc5751cc3c39fda4ca1 (diff)
ENGR00308442-1 usb: chipidea: otg: revert thread solution to restore work queue
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>
-rw-r--r--drivers/usb/chipidea/ci.h8
-rw-r--r--drivers/usb/chipidea/core.c4
-rw-r--r--drivers/usb/chipidea/otg.c50
3 files changed, 21 insertions, 41 deletions
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index eb4d9879acac..30f13b414ecf 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -110,8 +110,8 @@ struct hw_bank {
110 * @roles: array of supported roles for this controller 110 * @roles: array of supported roles for this controller
111 * @role: current role 111 * @role: current role
112 * @is_otg: if the device is otg-capable 112 * @is_otg: if the device is otg-capable
113 * @otg_task: the thread for handling otg task 113 * @work: work for role changing
114 * @otg_wait: the otg event waitqueue head 114 * @wq: workqueue thread
115 * @qh_pool: allocation pool for queue heads 115 * @qh_pool: allocation pool for queue heads
116 * @td_pool: allocation pool for transfer descriptors 116 * @td_pool: allocation pool for transfer descriptors
117 * @gadget: device side representation for peripheral controller 117 * @gadget: device side representation for peripheral controller
@@ -149,8 +149,8 @@ struct ci_hdrc {
149 struct ci_role_driver *roles[CI_ROLE_END]; 149 struct ci_role_driver *roles[CI_ROLE_END];
150 enum ci_role role; 150 enum ci_role role;
151 bool is_otg; 151 bool is_otg;
152 struct task_struct *otg_task; 152 struct work_struct work;
153 wait_queue_head_t otg_wait; 153 struct workqueue_struct *wq;
154 154
155 struct dma_pool *qh_pool; 155 struct dma_pool *qh_pool;
156 struct dma_pool *td_pool; 156 struct dma_pool *td_pool;
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index c3bea69cd775..572403932fc4 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -446,7 +446,7 @@ static irqreturn_t ci_irq(int irq, void *data)
446 ci->id_event = true; 446 ci->id_event = true;
447 hw_write_otgsc(ci, OTGSC_IDIS, OTGSC_IDIS); 447 hw_write_otgsc(ci, OTGSC_IDIS, OTGSC_IDIS);
448 disable_irq_nosync(ci->irq); 448 disable_irq_nosync(ci->irq);
449 wake_up(&ci->otg_wait); 449 queue_work(ci->wq, &ci->work);
450 return IRQ_HANDLED; 450 return IRQ_HANDLED;
451 } 451 }
452 452
@@ -458,7 +458,7 @@ static irqreturn_t ci_irq(int irq, void *data)
458 ci->b_sess_valid_event = true; 458 ci->b_sess_valid_event = true;
459 hw_write_otgsc(ci, OTGSC_BSVIS, OTGSC_BSVIS); 459 hw_write_otgsc(ci, OTGSC_BSVIS, OTGSC_BSVIS);
460 disable_irq_nosync(ci->irq); 460 disable_irq_nosync(ci->irq);
461 wake_up(&ci->otg_wait); 461 queue_work(ci->wq, &ci->work);
462 return IRQ_HANDLED; 462 return IRQ_HANDLED;
463 } 463 }
464 464
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index e6767e9cb1e8..0e2b2d8bcb58 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -18,8 +18,6 @@
18#include <linux/usb/otg.h> 18#include <linux/usb/otg.h>
19#include <linux/usb/gadget.h> 19#include <linux/usb/gadget.h>
20#include <linux/usb/chipidea.h> 20#include <linux/usb/chipidea.h>
21#include <linux/kthread.h>
22#include <linux/freezer.h>
23 21
24#include "ci.h" 22#include "ci.h"
25#include "bits.h" 23#include "bits.h"
@@ -102,19 +100,14 @@ static void ci_handle_id_switch(struct ci_hdrc *ci)
102 ci_role_start(ci, role); 100 ci_role_start(ci, role);
103 } 101 }
104} 102}
105
106/* If there is pending otg event */
107static inline bool ci_otg_event_is_pending(struct ci_hdrc *ci)
108{
109 return ci->id_event || ci->b_sess_valid_event;
110}
111
112/** 103/**
113 * ci_otg_event - perform otg (vbus/id) event handle 104 * ci_otg_work - perform otg (vbus/id) event handle
114 * @ci: ci_hdrc struct 105 * @work: work struct
115 */ 106 */
116static void ci_otg_event(struct ci_hdrc *ci) 107static void ci_otg_work(struct work_struct *work)
117{ 108{
109 struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work);
110
118 if (ci->id_event) { 111 if (ci->id_event) {
119 ci->id_event = false; 112 ci->id_event = false;
120 /* Keep controller active during id switch */ 113 /* Keep controller active during id switch */
@@ -132,23 +125,6 @@ static void ci_otg_event(struct ci_hdrc *ci)
132 enable_irq(ci->irq); 125 enable_irq(ci->irq);
133} 126}
134 127
135static int ci_otg_thread(void *ptr)
136{
137 struct ci_hdrc *ci = ptr;
138
139 set_freezable();
140
141 do {
142 wait_event_freezable(ci->otg_wait,
143 ci_otg_event_is_pending(ci) ||
144 kthread_should_stop());
145 ci_otg_event(ci);
146 } while (!kthread_should_stop());
147
148 dev_warn(ci->dev, "ci_otg_thread quits\n");
149
150 return 0;
151}
152 128
153/** 129/**
154 * ci_hdrc_otg_init - initialize otg struct 130 * ci_hdrc_otg_init - initialize otg struct
@@ -156,11 +132,11 @@ static int ci_otg_thread(void *ptr)
156 */ 132 */
157int ci_hdrc_otg_init(struct ci_hdrc *ci) 133int ci_hdrc_otg_init(struct ci_hdrc *ci)
158{ 134{
159 init_waitqueue_head(&ci->otg_wait); 135 INIT_WORK(&ci->work, ci_otg_work);
160 ci->otg_task = kthread_run(ci_otg_thread, ci, "ci otg thread"); 136 ci->wq = create_singlethread_workqueue("ci_otg");
161 if (IS_ERR(ci->otg_task)) { 137 if (!ci->wq) {
162 dev_err(ci->dev, "error to create otg thread\n"); 138 dev_err(ci->dev, "can't create workqueue\n");
163 return PTR_ERR(ci->otg_task); 139 return -ENODEV;
164 } 140 }
165 141
166 return 0; 142 return 0;
@@ -172,7 +148,11 @@ int ci_hdrc_otg_init(struct ci_hdrc *ci)
172 */ 148 */
173void ci_hdrc_otg_destroy(struct ci_hdrc *ci) 149void ci_hdrc_otg_destroy(struct ci_hdrc *ci)
174{ 150{
175 kthread_stop(ci->otg_task); 151 if (ci->wq) {
152 flush_workqueue(ci->wq);
153 destroy_workqueue(ci->wq);
154 }
155
176 hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS, 156 hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS,
177 OTGSC_INT_STATUS_BITS); 157 OTGSC_INT_STATUS_BITS);
178} 158}