]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
adma: tegra: report precise dma position
authorRavindra Lokhande <rlokhande@nvidia.com>
Tue, 23 Feb 2016 11:49:53 +0000 (17:19 +0530)
committermobile promotions <svcmobile_promotions@nvidia.com>
Mon, 29 Feb 2016 14:38:16 +0000 (06:38 -0800)
Earlier dma position is reported for buffers for which interrupt is
received. Current buffer transfered bytes are ignored. This change
adds current buffer transferred data to report more precise dma
position.

Change-Id: I5d246d44f6f572951918aebbd31121c83188dfdd
Signed-off-by: Ravindra Lokhande <rlokhande@nvidia.com>
Reviewed-on: http://git-master/r/1018161
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Sumit Bhattacharya <sumitb@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Dara Ramesh <dramesh@nvidia.com>
drivers/dma/tegra210-adma.c

index 48fab6824a8ed554d1a712562bd7bc4ed7252962..9c70d0566153ae16eeee1c8ec8f961d1af62a749 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ADMA driver for Nvidia's Tegra210 ADMA controller.
  *
- * Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -488,6 +488,7 @@ static void tegra_adma_abort_all(struct tegra_adma_chan *tdc)
 /* Returns bytes transferred with period size granularity */
 static inline uint64_t tegra_adma_get_position(struct tegra_adma_chan *tdc)
 {
+       unsigned long cur_tc = 0;
        uint64_t tx_done_max = (ADMA_CH_TRANSFER_DONE_COUNT_MASK >>
                ADMA_CH_TRANSFER_DONE_COUNT_SHIFT) + 1;
        uint64_t tx_done = channel_read(tdc, ADMA_CH_TRANSFER_STATUS) &
@@ -501,7 +502,13 @@ static inline uint64_t tegra_adma_get_position(struct tegra_adma_chan *tdc)
        else
                tdc->total_tx_done += (tx_done - tdc->channel_reg.tx_done);
        tdc->channel_reg.tx_done = tx_done;
-       return tdc->total_tx_done * tdc->channel_reg.tc;
+
+       /* read TC_STATUS register to get current transfer status */
+       cur_tc = channel_read(tdc, ADMA_CH_TC_STATUS);
+       /* get transferred data count */
+       cur_tc = tdc->channel_reg.tc - cur_tc;
+
+       return (tdc->total_tx_done * tdc->channel_reg.tc) + cur_tc;
 }
 
 static bool handle_continuous_head_request(struct tegra_adma_chan *tdc,
@@ -760,7 +767,7 @@ static enum dma_status tegra_adma_tx_status(struct dma_chan *dc,
        list_for_each_entry(dma_desc, &tdc->free_dma_desc, node) {
                if (dma_desc->txd.cookie == cookie) {
                        residual =  dma_desc->bytes_requested -
-                                       (dma_desc->bytes_transferred %
+                                       (tegra_adma_get_position(tdc) %
                                                dma_desc->bytes_requested);
                        dma_set_residue(txstate, residual);
                        ret = dma_desc->dma_status;
@@ -774,7 +781,7 @@ static enum dma_status tegra_adma_tx_status(struct dma_chan *dc,
                dma_desc = sg_req->dma_desc;
                if (dma_desc->txd.cookie == cookie) {
                        residual =  dma_desc->bytes_requested -
-                                       (dma_desc->bytes_transferred %
+                                       (tegra_adma_get_position(tdc) %
                                                dma_desc->bytes_requested);
                        dma_set_residue(txstate, residual);
                        ret = dma_desc->dma_status;