diff options
author | Li Jun <b47624@freescale.com> | 2014-04-14 02:35:20 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 12:02:31 -0400 |
commit | cf09d8ce34d752891ef9203097d1e8cf48a5fe85 (patch) | |
tree | 06acc5ad6e97771d094070cd4c8ec6f1ab0908e9 | |
parent | a09fde0d4aba9da26a579cc5751cc3c39fda4ca1 (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.h | 8 | ||||
-rw-r--r-- | drivers/usb/chipidea/core.c | 4 | ||||
-rw-r--r-- | drivers/usb/chipidea/otg.c | 50 |
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 */ | ||
107 | static 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 | */ |
116 | static void ci_otg_event(struct ci_hdrc *ci) | 107 | static 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 | ||
135 | static 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 | */ |
157 | int ci_hdrc_otg_init(struct ci_hdrc *ci) | 133 | int 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 | */ |
173 | void ci_hdrc_otg_destroy(struct ci_hdrc *ci) | 149 | void 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 | } |