diff options
| author | Vinod Koul <vkoul@kernel.org> | 2019-02-04 02:27:56 -0500 |
|---|---|---|
| committer | Vinod Koul <vkoul@kernel.org> | 2019-02-04 02:27:56 -0500 |
| commit | 6d66c8d1a034eeb1bbf4a0a8dd99fa6f33a8db5d (patch) | |
| tree | 7e3cd8b94a7f4779168950dbb3c0f4361e0891b8 | |
| parent | 341198eda723c8c1cddbb006a89ad9e362502ea2 (diff) | |
| parent | 9e528c799d17a4ac37d788c81440b50377dd592d (diff) | |
Merge branch 'fix/brcm' into fixes
| -rw-r--r-- | drivers/dma/bcm2835-dma.c | 70 |
1 files changed, 25 insertions, 45 deletions
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 1a44c8086d77..ae10f5614f95 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c | |||
| @@ -406,38 +406,32 @@ static void bcm2835_dma_fill_cb_chain_with_sg( | |||
| 406 | } | 406 | } |
| 407 | } | 407 | } |
| 408 | 408 | ||
| 409 | static int bcm2835_dma_abort(void __iomem *chan_base) | 409 | static int bcm2835_dma_abort(struct bcm2835_chan *c) |
| 410 | { | 410 | { |
| 411 | unsigned long cs; | 411 | void __iomem *chan_base = c->chan_base; |
| 412 | long int timeout = 10000; | 412 | long int timeout = 10000; |
| 413 | 413 | ||
| 414 | cs = readl(chan_base + BCM2835_DMA_CS); | 414 | /* |
| 415 | if (!(cs & BCM2835_DMA_ACTIVE)) | 415 | * A zero control block address means the channel is idle. |
| 416 | * (The ACTIVE flag in the CS register is not a reliable indicator.) | ||
| 417 | */ | ||
| 418 | if (!readl(chan_base + BCM2835_DMA_ADDR)) | ||
| 416 | return 0; | 419 | return 0; |
| 417 | 420 | ||
| 418 | /* Write 0 to the active bit - Pause the DMA */ | 421 | /* Write 0 to the active bit - Pause the DMA */ |
| 419 | writel(0, chan_base + BCM2835_DMA_CS); | 422 | writel(0, chan_base + BCM2835_DMA_CS); |
| 420 | 423 | ||
| 421 | /* Wait for any current AXI transfer to complete */ | 424 | /* Wait for any current AXI transfer to complete */ |
| 422 | while ((cs & BCM2835_DMA_ISPAUSED) && --timeout) { | 425 | while ((readl(chan_base + BCM2835_DMA_CS) & |
| 426 | BCM2835_DMA_WAITING_FOR_WRITES) && --timeout) | ||
| 423 | cpu_relax(); | 427 | cpu_relax(); |
| 424 | cs = readl(chan_base + BCM2835_DMA_CS); | ||
| 425 | } | ||
| 426 | 428 | ||
| 427 | /* We'll un-pause when we set of our next DMA */ | 429 | /* Peripheral might be stuck and fail to signal AXI write responses */ |
| 428 | if (!timeout) | 430 | if (!timeout) |
| 429 | return -ETIMEDOUT; | 431 | dev_err(c->vc.chan.device->dev, |
| 430 | 432 | "failed to complete outstanding writes\n"); | |
| 431 | if (!(cs & BCM2835_DMA_ACTIVE)) | ||
| 432 | return 0; | ||
| 433 | |||
| 434 | /* Terminate the control block chain */ | ||
| 435 | writel(0, chan_base + BCM2835_DMA_NEXTCB); | ||
| 436 | |||
| 437 | /* Abort the whole DMA */ | ||
| 438 | writel(BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE, | ||
| 439 | chan_base + BCM2835_DMA_CS); | ||
| 440 | 433 | ||
| 434 | writel(BCM2835_DMA_RESET, chan_base + BCM2835_DMA_CS); | ||
| 441 | return 0; | 435 | return 0; |
| 442 | } | 436 | } |
| 443 | 437 | ||
| @@ -476,8 +470,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) | |||
| 476 | 470 | ||
| 477 | spin_lock_irqsave(&c->vc.lock, flags); | 471 | spin_lock_irqsave(&c->vc.lock, flags); |
| 478 | 472 | ||
| 479 | /* Acknowledge interrupt */ | 473 | /* |
| 480 | writel(BCM2835_DMA_INT, c->chan_base + BCM2835_DMA_CS); | 474 | * Clear the INT flag to receive further interrupts. Keep the channel |
| 475 | * active in case the descriptor is cyclic or in case the client has | ||
| 476 | * already terminated the descriptor and issued a new one. (May happen | ||
| 477 | * if this IRQ handler is threaded.) If the channel is finished, it | ||
| 478 | * will remain idle despite the ACTIVE flag being set. | ||
| 479 | */ | ||
| 480 | writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE, | ||
| 481 | c->chan_base + BCM2835_DMA_CS); | ||
| 481 | 482 | ||
| 482 | d = c->desc; | 483 | d = c->desc; |
| 483 | 484 | ||
| @@ -485,11 +486,7 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) | |||
| 485 | if (d->cyclic) { | 486 | if (d->cyclic) { |
| 486 | /* call the cyclic callback */ | 487 | /* call the cyclic callback */ |
| 487 | vchan_cyclic_callback(&d->vd); | 488 | vchan_cyclic_callback(&d->vd); |
| 488 | 489 | } else if (!readl(c->chan_base + BCM2835_DMA_ADDR)) { | |
| 489 | /* Keep the DMA engine running */ | ||
| 490 | writel(BCM2835_DMA_ACTIVE, | ||
| 491 | c->chan_base + BCM2835_DMA_CS); | ||
| 492 | } else { | ||
| 493 | vchan_cookie_complete(&c->desc->vd); | 490 | vchan_cookie_complete(&c->desc->vd); |
| 494 | bcm2835_dma_start_desc(c); | 491 | bcm2835_dma_start_desc(c); |
| 495 | } | 492 | } |
| @@ -779,7 +776,6 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan) | |||
| 779 | struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); | 776 | struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); |
| 780 | struct bcm2835_dmadev *d = to_bcm2835_dma_dev(c->vc.chan.device); | 777 | struct bcm2835_dmadev *d = to_bcm2835_dma_dev(c->vc.chan.device); |
| 781 | unsigned long flags; | 778 | unsigned long flags; |
| 782 | int timeout = 10000; | ||
| 783 | LIST_HEAD(head); | 779 | LIST_HEAD(head); |
| 784 | 780 | ||
| 785 | spin_lock_irqsave(&c->vc.lock, flags); | 781 | spin_lock_irqsave(&c->vc.lock, flags); |
| @@ -789,27 +785,11 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan) | |||
| 789 | list_del_init(&c->node); | 785 | list_del_init(&c->node); |
| 790 | spin_unlock(&d->lock); | 786 | spin_unlock(&d->lock); |
| 791 | 787 | ||
| 792 | /* | 788 | /* stop DMA activity */ |
| 793 | * Stop DMA activity: we assume the callback will not be called | ||
| 794 | * after bcm_dma_abort() returns (even if it does, it will see | ||
| 795 | * c->desc is NULL and exit.) | ||
| 796 | */ | ||
| 797 | if (c->desc) { | 789 | if (c->desc) { |
| 798 | vchan_terminate_vdesc(&c->desc->vd); | 790 | vchan_terminate_vdesc(&c->desc->vd); |
| 799 | c->desc = NULL; | 791 | c->desc = NULL; |
| 800 | bcm2835_dma_abort(c->chan_base); | 792 | bcm2835_dma_abort(c); |
| 801 | |||
| 802 | /* Wait for stopping */ | ||
| 803 | while (--timeout) { | ||
| 804 | if (!(readl(c->chan_base + BCM2835_DMA_CS) & | ||
| 805 | BCM2835_DMA_ACTIVE)) | ||
| 806 | break; | ||
| 807 | |||
| 808 | cpu_relax(); | ||
| 809 | } | ||
| 810 | |||
| 811 | if (!timeout) | ||
| 812 | dev_err(d->ddev.dev, "DMA transfer could not be terminated\n"); | ||
| 813 | } | 793 | } |
| 814 | 794 | ||
| 815 | vchan_get_all_descriptors(&c->vc, &head); | 795 | vchan_get_all_descriptors(&c->vc, &head); |
