aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/dma.c
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2010-08-18 03:19:12 -0400
committerColin Cross <ccross@android.com>2011-02-10 20:50:41 -0500
commit5789fee934278dd6f4c541db97de229bd4a76424 (patch)
tree15aad9ddf9f423f6350aa6c1a6e49ef652761ad0 /arch/arm/mach-tegra/dma.c
parent699fe145d6e651a814423eeb6125381998f3c077 (diff)
ARM: tegra: dma: Fix critical data corruption bugs
Sometimes, due to high interrupt latency in the continuous mode of DMA transfer, the half buffer complete interrupt is handled after DMA has transferred the full buffer. When this is detected, stop DMA immediately and restart with the next buffer if the next buffer is ready. originally fixed by Victor(Weiguo) Pan <wpan@nvidia.com> In place of using the simple spin_lock()/spi_unlock() in the interrupt thread, using the spin_lock_irqsave() and spin_unlock_irqrestore(). The lock is shared between the normal process context and interrupt context. originally fixed by Laxman Dewangan (ldewangan@nvidia.com) The use of shadow registers caused memory corruption at physical address 0 because the enable bit was not shadowed, and assuming it needed to be set would enable an unconfigured dma block. Most of the register accesses don't need to know the previous state of the registers, and the few places that do need to modify only a few bits in the registers are the same ones that were sometimes incorrectly setting the enable bit. This patch convert tegra_dma_update_hardware to set the entire register, and the other users to read-modify-write, and drops the shadow registers completely. Also fixes missing locking in tegra_dma_allocate_channel Signed-off-by: Colin Cross <ccross@android.com>
Diffstat (limited to 'arch/arm/mach-tegra/dma.c')
-rw-r--r--arch/arm/mach-tegra/dma.c197
1 files changed, 108 insertions, 89 deletions
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c
index a2a252db024..250bc7baa00 100644
--- a/arch/arm/mach-tegra/dma.c
+++ b/arch/arm/mach-tegra/dma.c
@@ -121,17 +121,13 @@ struct tegra_dma_channel {
121 void __iomem *addr; 121 void __iomem *addr;
122 int mode; 122 int mode;
123 int irq; 123 int irq;
124 124 int req_transfer_count;
125 /* Register shadow */
126 u32 csr;
127 u32 ahb_seq;
128 u32 ahb_ptr;
129 u32 apb_seq;
130 u32 apb_ptr;
131}; 125};
132 126
133#define NV_DMA_MAX_CHANNELS 32 127#define NV_DMA_MAX_CHANNELS 32
134 128
129static DEFINE_MUTEX(tegra_dma_lock);
130
135static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS); 131static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS);
136static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS]; 132static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS];
137 133
@@ -139,7 +135,6 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
139 struct tegra_dma_req *req); 135 struct tegra_dma_req *req);
140static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch, 136static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
141 struct tegra_dma_req *req); 137 struct tegra_dma_req *req);
142static void tegra_dma_init_hw(struct tegra_dma_channel *ch);
143static void tegra_dma_stop(struct tegra_dma_channel *ch); 138static void tegra_dma_stop(struct tegra_dma_channel *ch);
144 139
145void tegra_dma_flush(struct tegra_dma_channel *ch) 140void tegra_dma_flush(struct tegra_dma_channel *ch)
@@ -151,6 +146,9 @@ void tegra_dma_dequeue(struct tegra_dma_channel *ch)
151{ 146{
152 struct tegra_dma_req *req; 147 struct tegra_dma_req *req;
153 148
149 if (tegra_dma_is_empty(ch))
150 return;
151
154 req = list_entry(ch->list.next, typeof(*req), node); 152 req = list_entry(ch->list.next, typeof(*req), node);
155 153
156 tegra_dma_dequeue_req(ch, req); 154 tegra_dma_dequeue_req(ch, req);
@@ -159,10 +157,10 @@ void tegra_dma_dequeue(struct tegra_dma_channel *ch)
159 157
160void tegra_dma_stop(struct tegra_dma_channel *ch) 158void tegra_dma_stop(struct tegra_dma_channel *ch)
161{ 159{
162 unsigned int csr; 160 u32 csr;
163 unsigned int status; 161 u32 status;
164 162
165 csr = ch->csr; 163 csr = readl(ch->addr + APB_DMA_CHAN_CSR);
166 csr &= ~CSR_IE_EOC; 164 csr &= ~CSR_IE_EOC;
167 writel(csr, ch->addr + APB_DMA_CHAN_CSR); 165 writel(csr, ch->addr + APB_DMA_CHAN_CSR);
168 166
@@ -176,19 +174,16 @@ void tegra_dma_stop(struct tegra_dma_channel *ch)
176 174
177int tegra_dma_cancel(struct tegra_dma_channel *ch) 175int tegra_dma_cancel(struct tegra_dma_channel *ch)
178{ 176{
179 unsigned int csr; 177 u32 csr;
180 unsigned long irq_flags; 178 unsigned long irq_flags;
181 179
182 spin_lock_irqsave(&ch->lock, irq_flags); 180 spin_lock_irqsave(&ch->lock, irq_flags);
183 while (!list_empty(&ch->list)) 181 while (!list_empty(&ch->list))
184 list_del(ch->list.next); 182 list_del(ch->list.next);
185 183
186 csr = ch->csr; 184 csr = readl(ch->addr + APB_DMA_CHAN_CSR);
187 csr &= ~CSR_REQ_SEL_MASK; 185 csr &= ~CSR_REQ_SEL_MASK;
188 csr |= CSR_REQ_SEL_INVALID; 186 csr |= CSR_REQ_SEL_INVALID;
189
190 /* Set the enable as that is not shadowed */
191 csr |= CSR_ENB;
192 writel(csr, ch->addr + APB_DMA_CHAN_CSR); 187 writel(csr, ch->addr + APB_DMA_CHAN_CSR);
193 188
194 tegra_dma_stop(ch); 189 tegra_dma_stop(ch);
@@ -230,18 +225,15 @@ int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
230 * - Finally stop or program the DMA to the next buffer in the 225 * - Finally stop or program the DMA to the next buffer in the
231 * list. 226 * list.
232 */ 227 */
233 csr = ch->csr; 228 csr = readl(ch->addr + APB_DMA_CHAN_CSR);
234 csr &= ~CSR_REQ_SEL_MASK; 229 csr &= ~CSR_REQ_SEL_MASK;
235 csr |= CSR_REQ_SEL_INVALID; 230 csr |= CSR_REQ_SEL_INVALID;
236
237 /* Set the enable as that is not shadowed */
238 csr |= CSR_ENB;
239 writel(csr, ch->addr + APB_DMA_CHAN_CSR); 231 writel(csr, ch->addr + APB_DMA_CHAN_CSR);
240 232
241 /* Get the transfer count */ 233 /* Get the transfer count */
242 status = readl(ch->addr + APB_DMA_CHAN_STA); 234 status = readl(ch->addr + APB_DMA_CHAN_STA);
243 to_transfer = (status & STA_COUNT_MASK) >> STA_COUNT_SHIFT; 235 to_transfer = (status & STA_COUNT_MASK) >> STA_COUNT_SHIFT;
244 req_transfer_count = (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT; 236 req_transfer_count = ch->req_transfer_count;
245 req_transfer_count += 1; 237 req_transfer_count += 1;
246 to_transfer += 1; 238 to_transfer += 1;
247 239
@@ -349,7 +341,9 @@ EXPORT_SYMBOL(tegra_dma_enqueue_req);
349struct tegra_dma_channel *tegra_dma_allocate_channel(int mode) 341struct tegra_dma_channel *tegra_dma_allocate_channel(int mode)
350{ 342{
351 int channel; 343 int channel;
352 struct tegra_dma_channel *ch; 344 struct tegra_dma_channel *ch = NULL;
345
346 mutex_lock(&tegra_dma_lock);
353 347
354 /* first channel is the shared channel */ 348 /* first channel is the shared channel */
355 if (mode & TEGRA_DMA_SHARED) { 349 if (mode & TEGRA_DMA_SHARED) {
@@ -358,11 +352,14 @@ struct tegra_dma_channel *tegra_dma_allocate_channel(int mode)
358 channel = find_first_zero_bit(channel_usage, 352 channel = find_first_zero_bit(channel_usage,
359 ARRAY_SIZE(dma_channels)); 353 ARRAY_SIZE(dma_channels));
360 if (channel >= ARRAY_SIZE(dma_channels)) 354 if (channel >= ARRAY_SIZE(dma_channels))
361 return NULL; 355 goto out;
362 } 356 }
363 __set_bit(channel, channel_usage); 357 __set_bit(channel, channel_usage);
364 ch = &dma_channels[channel]; 358 ch = &dma_channels[channel];
365 ch->mode = mode; 359 ch->mode = mode;
360
361out:
362 mutex_unlock(&tegra_dma_lock);
366 return ch; 363 return ch;
367} 364}
368EXPORT_SYMBOL(tegra_dma_allocate_channel); 365EXPORT_SYMBOL(tegra_dma_allocate_channel);
@@ -372,22 +369,27 @@ void tegra_dma_free_channel(struct tegra_dma_channel *ch)
372 if (ch->mode & TEGRA_DMA_SHARED) 369 if (ch->mode & TEGRA_DMA_SHARED)
373 return; 370 return;
374 tegra_dma_cancel(ch); 371 tegra_dma_cancel(ch);
372 mutex_lock(&tegra_dma_lock);
375 __clear_bit(ch->id, channel_usage); 373 __clear_bit(ch->id, channel_usage);
374 mutex_unlock(&tegra_dma_lock);
376} 375}
377EXPORT_SYMBOL(tegra_dma_free_channel); 376EXPORT_SYMBOL(tegra_dma_free_channel);
378 377
379static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch, 378static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
380 struct tegra_dma_req *req) 379 struct tegra_dma_req *req)
381{ 380{
381 u32 apb_ptr;
382 u32 ahb_ptr;
383
382 if (req->to_memory) { 384 if (req->to_memory) {
383 ch->apb_ptr = req->source_addr; 385 apb_ptr = req->source_addr;
384 ch->ahb_ptr = req->dest_addr; 386 ahb_ptr = req->dest_addr;
385 } else { 387 } else {
386 ch->apb_ptr = req->dest_addr; 388 apb_ptr = req->dest_addr;
387 ch->ahb_ptr = req->source_addr; 389 ahb_ptr = req->source_addr;
388 } 390 }
389 writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR); 391 writel(apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
390 writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR); 392 writel(ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
391 393
392 req->status = TEGRA_DMA_REQ_INFLIGHT; 394 req->status = TEGRA_DMA_REQ_INFLIGHT;
393 return; 395 return;
@@ -401,38 +403,39 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
401 int ahb_bus_width; 403 int ahb_bus_width;
402 int apb_bus_width; 404 int apb_bus_width;
403 int index; 405 int index;
404 unsigned long csr;
405 406
407 u32 ahb_seq;
408 u32 apb_seq;
409 u32 ahb_ptr;
410 u32 apb_ptr;
411 u32 csr;
412
413 csr = CSR_IE_EOC | CSR_FLOW;
414 ahb_seq = AHB_SEQ_INTR_ENB | AHB_SEQ_BURST_1;
415 apb_seq = 0;
406 416
407 ch->csr |= CSR_FLOW; 417 csr |= req->req_sel << CSR_REQ_SEL_SHIFT;
408 ch->csr &= ~CSR_REQ_SEL_MASK;
409 ch->csr |= req->req_sel << CSR_REQ_SEL_SHIFT;
410 ch->ahb_seq &= ~AHB_SEQ_BURST_MASK;
411 ch->ahb_seq |= AHB_SEQ_BURST_1;
412 418
413 /* One shot mode is always single buffered, 419 /* One shot mode is always single buffered,
414 * continuous mode is always double buffered 420 * continuous mode is always double buffered
415 * */ 421 * */
416 if (ch->mode & TEGRA_DMA_MODE_ONESHOT) { 422 if (ch->mode & TEGRA_DMA_MODE_ONESHOT) {
417 ch->csr |= CSR_ONCE; 423 csr |= CSR_ONCE;
418 ch->ahb_seq &= ~AHB_SEQ_DBL_BUF; 424 ch->req_transfer_count = (req->size >> 2) - 1;
419 ch->csr &= ~CSR_WCOUNT_MASK;
420 ch->csr |= ((req->size>>2) - 1) << CSR_WCOUNT_SHIFT;
421 } else { 425 } else {
422 ch->csr &= ~CSR_ONCE; 426 ahb_seq |= AHB_SEQ_DBL_BUF;
423 ch->ahb_seq |= AHB_SEQ_DBL_BUF;
424 427
425 /* In double buffered mode, we set the size to half the 428 /* In double buffered mode, we set the size to half the
426 * requested size and interrupt when half the buffer 429 * requested size and interrupt when half the buffer
427 * is full */ 430 * is full */
428 ch->csr &= ~CSR_WCOUNT_MASK; 431 ch->req_transfer_count = (req->size >> 3) - 1;
429 ch->csr |= ((req->size>>3) - 1) << CSR_WCOUNT_SHIFT;
430 } 432 }
431 433
434 csr |= ch->req_transfer_count << CSR_WCOUNT_SHIFT;
435
432 if (req->to_memory) { 436 if (req->to_memory) {
433 ch->csr &= ~CSR_DIR; 437 apb_ptr = req->source_addr;
434 ch->apb_ptr = req->source_addr; 438 ahb_ptr = req->dest_addr;
435 ch->ahb_ptr = req->dest_addr;
436 439
437 apb_addr_wrap = req->source_wrap; 440 apb_addr_wrap = req->source_wrap;
438 ahb_addr_wrap = req->dest_wrap; 441 ahb_addr_wrap = req->dest_wrap;
@@ -440,9 +443,9 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
440 ahb_bus_width = req->dest_bus_width; 443 ahb_bus_width = req->dest_bus_width;
441 444
442 } else { 445 } else {
443 ch->csr |= CSR_DIR; 446 csr |= CSR_DIR;
444 ch->apb_ptr = req->dest_addr; 447 apb_ptr = req->dest_addr;
445 ch->ahb_ptr = req->source_addr; 448 ahb_ptr = req->source_addr;
446 449
447 apb_addr_wrap = req->dest_wrap; 450 apb_addr_wrap = req->dest_wrap;
448 ahb_addr_wrap = req->source_wrap; 451 ahb_addr_wrap = req->source_wrap;
@@ -461,8 +464,7 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
461 index++; 464 index++;
462 } while (index < ARRAY_SIZE(apb_addr_wrap_table)); 465 } while (index < ARRAY_SIZE(apb_addr_wrap_table));
463 BUG_ON(index == ARRAY_SIZE(apb_addr_wrap_table)); 466 BUG_ON(index == ARRAY_SIZE(apb_addr_wrap_table));
464 ch->apb_seq &= ~APB_SEQ_WRAP_MASK; 467 apb_seq |= index << APB_SEQ_WRAP_SHIFT;
465 ch->apb_seq |= index << APB_SEQ_WRAP_SHIFT;
466 468
467 /* set address wrap for AHB size */ 469 /* set address wrap for AHB size */
468 index = 0; 470 index = 0;
@@ -472,55 +474,42 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
472 index++; 474 index++;
473 } while (index < ARRAY_SIZE(ahb_addr_wrap_table)); 475 } while (index < ARRAY_SIZE(ahb_addr_wrap_table));
474 BUG_ON(index == ARRAY_SIZE(ahb_addr_wrap_table)); 476 BUG_ON(index == ARRAY_SIZE(ahb_addr_wrap_table));
475 ch->ahb_seq &= ~AHB_SEQ_WRAP_MASK; 477 ahb_seq |= index << AHB_SEQ_WRAP_SHIFT;
476 ch->ahb_seq |= index << AHB_SEQ_WRAP_SHIFT;
477 478
478 for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) { 479 for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
479 if (bus_width_table[index] == ahb_bus_width) 480 if (bus_width_table[index] == ahb_bus_width)
480 break; 481 break;
481 } 482 }
482 BUG_ON(index == ARRAY_SIZE(bus_width_table)); 483 BUG_ON(index == ARRAY_SIZE(bus_width_table));
483 ch->ahb_seq &= ~AHB_SEQ_BUS_WIDTH_MASK; 484 ahb_seq |= index << AHB_SEQ_BUS_WIDTH_SHIFT;
484 ch->ahb_seq |= index << AHB_SEQ_BUS_WIDTH_SHIFT;
485 485
486 for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) { 486 for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
487 if (bus_width_table[index] == apb_bus_width) 487 if (bus_width_table[index] == apb_bus_width)
488 break; 488 break;
489 } 489 }
490 BUG_ON(index == ARRAY_SIZE(bus_width_table)); 490 BUG_ON(index == ARRAY_SIZE(bus_width_table));
491 ch->apb_seq &= ~APB_SEQ_BUS_WIDTH_MASK; 491 apb_seq |= index << APB_SEQ_BUS_WIDTH_SHIFT;
492 ch->apb_seq |= index << APB_SEQ_BUS_WIDTH_SHIFT;
493
494 ch->csr |= CSR_IE_EOC;
495 492
496 /* update hw registers with the shadow */ 493 writel(csr, ch->addr + APB_DMA_CHAN_CSR);
497 writel(ch->csr, ch->addr + APB_DMA_CHAN_CSR); 494 writel(apb_seq, ch->addr + APB_DMA_CHAN_APB_SEQ);
498 writel(ch->apb_seq, ch->addr + APB_DMA_CHAN_APB_SEQ); 495 writel(apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
499 writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR); 496 writel(ahb_seq, ch->addr + APB_DMA_CHAN_AHB_SEQ);
500 writel(ch->ahb_seq, ch->addr + APB_DMA_CHAN_AHB_SEQ); 497 writel(ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
501 writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
502 498
503 csr = ch->csr | CSR_ENB; 499 csr |= CSR_ENB;
504 writel(csr, ch->addr + APB_DMA_CHAN_CSR); 500 writel(csr, ch->addr + APB_DMA_CHAN_CSR);
505 501
506 req->status = TEGRA_DMA_REQ_INFLIGHT; 502 req->status = TEGRA_DMA_REQ_INFLIGHT;
507} 503}
508 504
509static void tegra_dma_init_hw(struct tegra_dma_channel *ch)
510{
511 /* One shot with an interrupt to CPU after transfer */
512 ch->csr = CSR_ONCE | CSR_IE_EOC;
513 ch->ahb_seq = AHB_SEQ_BUS_WIDTH_32 | AHB_SEQ_INTR_ENB;
514 ch->apb_seq = APB_SEQ_BUS_WIDTH_32 | 1 << APB_SEQ_WRAP_SHIFT;
515}
516
517static void handle_oneshot_dma(struct tegra_dma_channel *ch) 505static void handle_oneshot_dma(struct tegra_dma_channel *ch)
518{ 506{
519 struct tegra_dma_req *req; 507 struct tegra_dma_req *req;
508 unsigned long irq_flags;
520 509
521 spin_lock(&ch->lock); 510 spin_lock_irqsave(&ch->lock, irq_flags);
522 if (list_empty(&ch->list)) { 511 if (list_empty(&ch->list)) {
523 spin_unlock(&ch->lock); 512 spin_unlock_irqrestore(&ch->lock, irq_flags);
524 return; 513 return;
525 } 514 }
526 515
@@ -528,8 +517,7 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch)
528 if (req) { 517 if (req) {
529 int bytes_transferred; 518 int bytes_transferred;
530 519
531 bytes_transferred = 520 bytes_transferred = ch->req_transfer_count;
532 (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
533 bytes_transferred += 1; 521 bytes_transferred += 1;
534 bytes_transferred <<= 2; 522 bytes_transferred <<= 2;
535 523
@@ -537,12 +525,12 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch)
537 req->bytes_transferred = bytes_transferred; 525 req->bytes_transferred = bytes_transferred;
538 req->status = TEGRA_DMA_REQ_SUCCESS; 526 req->status = TEGRA_DMA_REQ_SUCCESS;
539 527
540 spin_unlock(&ch->lock); 528 spin_unlock_irqrestore(&ch->lock, irq_flags);
541 /* Callback should be called without any lock */ 529 /* Callback should be called without any lock */
542 pr_debug("%s: transferred %d bytes\n", __func__, 530 pr_debug("%s: transferred %d bytes\n", __func__,
543 req->bytes_transferred); 531 req->bytes_transferred);
544 req->complete(req); 532 req->complete(req);
545 spin_lock(&ch->lock); 533 spin_lock_irqsave(&ch->lock, irq_flags);
546 } 534 }
547 535
548 if (!list_empty(&ch->list)) { 536 if (!list_empty(&ch->list)) {
@@ -552,22 +540,55 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch)
552 if (req->status != TEGRA_DMA_REQ_INFLIGHT) 540 if (req->status != TEGRA_DMA_REQ_INFLIGHT)
553 tegra_dma_update_hw(ch, req); 541 tegra_dma_update_hw(ch, req);
554 } 542 }
555 spin_unlock(&ch->lock); 543 spin_unlock_irqrestore(&ch->lock, irq_flags);
556} 544}
557 545
558static void handle_continuous_dma(struct tegra_dma_channel *ch) 546static void handle_continuous_dma(struct tegra_dma_channel *ch)
559{ 547{
560 struct tegra_dma_req *req; 548 struct tegra_dma_req *req;
549 unsigned long irq_flags;
561 550
562 spin_lock(&ch->lock); 551 spin_lock_irqsave(&ch->lock, irq_flags);
563 if (list_empty(&ch->list)) { 552 if (list_empty(&ch->list)) {
564 spin_unlock(&ch->lock); 553 spin_unlock_irqrestore(&ch->lock, irq_flags);
565 return; 554 return;
566 } 555 }
567 556
568 req = list_entry(ch->list.next, typeof(*req), node); 557 req = list_entry(ch->list.next, typeof(*req), node);
569 if (req) { 558 if (req) {
570 if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_EMPTY) { 559 if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_EMPTY) {
560 bool is_dma_ping_complete;
561 is_dma_ping_complete = (readl(ch->addr + APB_DMA_CHAN_STA)
562 & STA_PING_PONG) ? true : false;
563 if (req->to_memory)
564 is_dma_ping_complete = !is_dma_ping_complete;
565 /* Out of sync - Release current buffer */
566 if (!is_dma_ping_complete) {
567 int bytes_transferred;
568
569 bytes_transferred = ch->req_transfer_count;
570 bytes_transferred += 1;
571 bytes_transferred <<= 3;
572 req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_FULL;
573 req->bytes_transferred = bytes_transferred;
574 req->status = TEGRA_DMA_REQ_SUCCESS;
575 tegra_dma_stop(ch);
576
577 if (!list_is_last(&req->node, &ch->list)) {
578 struct tegra_dma_req *next_req;
579
580 next_req = list_entry(req->node.next,
581 typeof(*next_req), node);
582 tegra_dma_update_hw(ch, next_req);
583 }
584
585 list_del(&req->node);
586
587 /* DMA lock is NOT held when callbak is called */
588 spin_unlock_irqrestore(&ch->lock, irq_flags);
589 req->complete(req);
590 return;
591 }
571 /* Load the next request into the hardware, if available 592 /* Load the next request into the hardware, if available
572 * */ 593 * */
573 if (!list_is_last(&req->node, &ch->list)) { 594 if (!list_is_last(&req->node, &ch->list)) {
@@ -580,7 +601,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)
580 req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL; 601 req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL;
581 req->status = TEGRA_DMA_REQ_SUCCESS; 602 req->status = TEGRA_DMA_REQ_SUCCESS;
582 /* DMA lock is NOT held when callback is called */ 603 /* DMA lock is NOT held when callback is called */
583 spin_unlock(&ch->lock); 604 spin_unlock_irqrestore(&ch->lock, irq_flags);
584 if (likely(req->threshold)) 605 if (likely(req->threshold))
585 req->threshold(req); 606 req->threshold(req);
586 return; 607 return;
@@ -591,8 +612,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)
591 * the second interrupt */ 612 * the second interrupt */
592 int bytes_transferred; 613 int bytes_transferred;
593 614
594 bytes_transferred = 615 bytes_transferred = ch->req_transfer_count;
595 (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
596 bytes_transferred += 1; 616 bytes_transferred += 1;
597 bytes_transferred <<= 3; 617 bytes_transferred <<= 3;
598 618
@@ -602,7 +622,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)
602 list_del(&req->node); 622 list_del(&req->node);
603 623
604 /* DMA lock is NOT held when callbak is called */ 624 /* DMA lock is NOT held when callbak is called */
605 spin_unlock(&ch->lock); 625 spin_unlock_irqrestore(&ch->lock, irq_flags);
606 req->complete(req); 626 req->complete(req);
607 return; 627 return;
608 628
@@ -610,7 +630,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)
610 BUG(); 630 BUG();
611 } 631 }
612 } 632 }
613 spin_unlock(&ch->lock); 633 spin_unlock_irqrestore(&ch->lock, irq_flags);
614} 634}
615 635
616static irqreturn_t dma_isr(int irq, void *data) 636static irqreturn_t dma_isr(int irq, void *data)
@@ -674,7 +694,6 @@ int __init tegra_dma_init(void)
674 694
675 spin_lock_init(&ch->lock); 695 spin_lock_init(&ch->lock);
676 INIT_LIST_HEAD(&ch->list); 696 INIT_LIST_HEAD(&ch->list);
677 tegra_dma_init_hw(ch);
678 697
679 irq = INT_APB_DMA_CH0 + i; 698 irq = INT_APB_DMA_CH0 + i;
680 ret = request_threaded_irq(irq, dma_isr, dma_thread_fn, 0, 699 ret = request_threaded_irq(irq, dma_isr, dma_thread_fn, 0,