aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/musb_cppi41.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/musb/musb_cppi41.c')
-rw-r--r--drivers/usb/musb/musb_cppi41.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c
index 39ee516c8cbf..5b0f2a58f8ce 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -39,6 +39,7 @@ struct cppi41_dma_channel {
39 u32 transferred; 39 u32 transferred;
40 u32 packet_sz; 40 u32 packet_sz;
41 struct list_head tx_check; 41 struct list_head tx_check;
42 struct work_struct dma_completion;
42}; 43};
43 44
44#define MUSB_DMA_NUM_CHANNELS 15 45#define MUSB_DMA_NUM_CHANNELS 15
@@ -112,6 +113,18 @@ static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep)
112 return true; 113 return true;
113} 114}
114 115
116static bool is_isoc(struct musb_hw_ep *hw_ep, bool in)
117{
118 if (in && hw_ep->in_qh) {
119 if (hw_ep->in_qh->type == USB_ENDPOINT_XFER_ISOC)
120 return true;
121 } else if (hw_ep->out_qh) {
122 if (hw_ep->out_qh->type == USB_ENDPOINT_XFER_ISOC)
123 return true;
124 }
125 return false;
126}
127
115static void cppi41_dma_callback(void *private_data); 128static void cppi41_dma_callback(void *private_data);
116 129
117static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel) 130static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
@@ -165,6 +178,32 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
165 } 178 }
166} 179}
167 180
181static void cppi_trans_done_work(struct work_struct *work)
182{
183 unsigned long flags;
184 struct cppi41_dma_channel *cppi41_channel =
185 container_of(work, struct cppi41_dma_channel, dma_completion);
186 struct cppi41_dma_controller *controller = cppi41_channel->controller;
187 struct musb *musb = controller->musb;
188 struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
189 bool empty;
190
191 if (!cppi41_channel->is_tx && is_isoc(hw_ep, 1)) {
192 spin_lock_irqsave(&musb->lock, flags);
193 cppi41_trans_done(cppi41_channel);
194 spin_unlock_irqrestore(&musb->lock, flags);
195 } else {
196 empty = musb_is_tx_fifo_empty(hw_ep);
197 if (empty) {
198 spin_lock_irqsave(&musb->lock, flags);
199 cppi41_trans_done(cppi41_channel);
200 spin_unlock_irqrestore(&musb->lock, flags);
201 } else {
202 schedule_work(&cppi41_channel->dma_completion);
203 }
204 }
205}
206
168static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer) 207static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
169{ 208{
170 struct cppi41_dma_controller *controller; 209 struct cppi41_dma_controller *controller;
@@ -228,6 +267,14 @@ static void cppi41_dma_callback(void *private_data)
228 transferred < cppi41_channel->packet_sz) 267 transferred < cppi41_channel->packet_sz)
229 cppi41_channel->prog_len = 0; 268 cppi41_channel->prog_len = 0;
230 269
270 if (!cppi41_channel->is_tx) {
271 if (is_isoc(hw_ep, 1))
272 schedule_work(&cppi41_channel->dma_completion);
273 else
274 cppi41_trans_done(cppi41_channel);
275 goto out;
276 }
277
231 empty = musb_is_tx_fifo_empty(hw_ep); 278 empty = musb_is_tx_fifo_empty(hw_ep);
232 if (empty) { 279 if (empty) {
233 cppi41_trans_done(cppi41_channel); 280 cppi41_trans_done(cppi41_channel);
@@ -264,6 +311,10 @@ static void cppi41_dma_callback(void *private_data)
264 goto out; 311 goto out;
265 } 312 }
266 } 313 }
314 if (is_isoc(hw_ep, 0)) {
315 schedule_work(&cppi41_channel->dma_completion);
316 goto out;
317 }
267 list_add_tail(&cppi41_channel->tx_check, 318 list_add_tail(&cppi41_channel->tx_check,
268 &controller->early_tx_list); 319 &controller->early_tx_list);
269 if (!hrtimer_active(&controller->early_tx)) { 320 if (!hrtimer_active(&controller->early_tx)) {
@@ -620,6 +671,8 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
620 cppi41_channel->port_num = port; 671 cppi41_channel->port_num = port;
621 cppi41_channel->is_tx = is_tx; 672 cppi41_channel->is_tx = is_tx;
622 INIT_LIST_HEAD(&cppi41_channel->tx_check); 673 INIT_LIST_HEAD(&cppi41_channel->tx_check);
674 INIT_WORK(&cppi41_channel->dma_completion,
675 cppi_trans_done_work);
623 676
624 musb_dma = &cppi41_channel->channel; 677 musb_dma = &cppi41_channel->channel;
625 musb_dma->private_data = cppi41_channel; 678 musb_dma->private_data = cppi41_channel;