diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index a4d427e..cd68f8e 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -53,6 +53,7 @@ MODULE_PARM_DESC(init_nr_desc_per_channel,
 
 /* prototypes */
 static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx);
+static void atc_issue_pending(struct dma_chan *chan);
 
 
 /*----------------------------------------------------------------------*/
@@ -229,6 +230,94 @@ static void atc_dostart(struct at_dma_chan *atchan, struct at_desc *first)
 	vdbg_dump_regs(atchan);
 }
 
+/*
+ * atc_get_current_descriptors -
+ * locate the descriptor which equal to physical address in DSCR
+ * @atchan: the channel we want to start
+ * @dscr_addr: physical descriptor address in DSCR
+ */
+static struct at_desc *atc_get_current_descriptors(struct at_dma_chan *atchan,
+							u32 dscr_addr)
+{
+	struct at_desc  *desc, *_desc, *child, *desc_cur = NULL;
+
+	list_for_each_entry_safe(desc, _desc, &atchan->active_list, desc_node) {
+		if (desc->lli.dscr == dscr_addr) {
+			desc_cur = desc;
+			break;
+		}
+
+		list_for_each_entry(child, &desc->tx_list, desc_node) {
+			if (child->lli.dscr == dscr_addr) {
+				desc_cur = child;
+				break;
+			}
+		}
+	}
+
+	return desc_cur;
+}
+
+/*
+ * atc_get_bytes_left -
+ * Get the number of bytes residue in dma buffer,
+ * @chan: the channel we want to start
+ */
+static int atc_get_bytes_left(struct dma_chan *chan)
+{
+	struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+	struct at_dma           *atdma = to_at_dma(chan->device);
+	int	chan_id = atchan->chan_common.chan_id;
+	struct at_desc *desc_first = atc_first_active(atchan);
+	struct at_desc *desc_cur;
+	int ret = 0, count = 0;
+
+	/*
+	 * Initialize necessary values in the first time.
+	 * remain_desc record remain desc length.
+	 */
+	if (atchan->remain_desc == 0)
+		/* First descriptor embedds the transaction length */
+		atchan->remain_desc = desc_first->len;
+
+	/*
+	 * This happens when current descriptor transfer complete.
+	 * The residual buffer size should reduce current descriptor length.
+	 */
+	if (unlikely(test_bit(ATC_IS_BTC, &atchan->status))) {
+		clear_bit(ATC_IS_BTC, &atchan->status);
+		desc_cur = atc_get_current_descriptors(atchan,
+						channel_readl(atchan, DSCR));
+		if (!desc_cur) {
+			ret = -EINVAL;
+			goto out;
+		}
+		atchan->remain_desc -= (desc_cur->lli.ctrla & ATC_BTSIZE_MAX)
+						<< (desc_first->tx_width);
+		if (atchan->remain_desc < 0) {
+			ret = -EINVAL;
+			goto out;
+		} else
+			ret = atchan->remain_desc;
+	} else {
+		/*
+		 * Get residual bytes when current
+		 * descriptor transfer in progress.
+		 */
+		count = (channel_readl(atchan, CTRLA) & ATC_BTSIZE_MAX)
+				<< (desc_first->tx_width);
+		ret = atchan->remain_desc - count;
+	}
+	/*
+	 * Check fifo empty.
+	 */
+	if (!(dma_readl(atdma, CHSR) & AT_DMA_EMPT(chan_id)))
+		atc_issue_pending(chan);
+
+out:
+	return ret;
+}
+
 /**
  * atc_chain_complete - finish work for one transaction chain
  * @atchan: channel we work on
@@ -494,6 +583,8 @@ static irqreturn_t at_dma_interrupt(int irq, void *dev_id)
 					/* Give information to tasklet */
 					set_bit(ATC_IS_ERROR, &atchan->status);
 				}
+				if (pending & AT_DMA_BTC(i))
+					set_bit(ATC_IS_BTC, &atchan->status);
 				tasklet_schedule(&atchan->tasklet);
 				ret = IRQ_HANDLED;
 			}
@@ -1033,34 +1124,35 @@ atc_tx_status(struct dma_chan *chan,
 		struct dma_tx_state *txstate)
 {
 	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
-	dma_cookie_t		last_used;
-	dma_cookie_t		last_complete;
 	unsigned long		flags;
 	enum dma_status		ret;
-
-	spin_lock_irqsave(&atchan->lock, flags);
+	int bytes = 0;
 
 	ret = dma_cookie_status(chan, cookie, txstate);
-	if (ret != DMA_SUCCESS) {
-		atc_cleanup_descriptors(atchan);
+	if (ret == DMA_SUCCESS)
+		return ret;
+	/*
+	 * There's no point calculating the residue if there's
+	 * no txstate to store the value.
+	 */
+	if (!txstate)
+		return DMA_ERROR;
 
-		ret = dma_cookie_status(chan, cookie, txstate);
-	}
+	spin_lock_irqsave(&atchan->lock, flags);
 
-	last_complete = chan->completed_cookie;
-	last_used = chan->cookie;
+	/*  Get number of bytes left in the active transactions */
+	bytes = atc_get_bytes_left(chan);
 
 	spin_unlock_irqrestore(&atchan->lock, flags);
 
-	if (ret != DMA_SUCCESS)
-		dma_set_residue(txstate, atc_first_active(atchan)->len);
-
-	if (atc_chan_is_paused(atchan))
-		ret = DMA_PAUSED;
+	if (unlikely(bytes < 0)) {
+		dev_vdbg(chan2dev(chan), "get residual bytes error\n");
+		return DMA_ERROR;
+	} else
+		dma_set_residue(txstate, bytes);
 
-	dev_vdbg(chan2dev(chan), "tx_status %d: cookie = %d (d%d, u%d)\n",
-		 ret, cookie, last_complete ? last_complete : 0,
-		 last_used ? last_used : 0);
+	dev_vdbg(chan2dev(chan), "tx_status %d: cookie = %d residue = %d\n",
+		 ret, cookie, bytes);
 
 	return ret;
 }
@@ -1146,6 +1238,7 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
 
 	spin_lock_irqsave(&atchan->lock, flags);
 	atchan->descs_allocated = i;
+	atchan->remain_desc = 0;
 	list_splice(&tmp_list, &atchan->free_list);
 	dma_cookie_init(chan);
 	spin_unlock_irqrestore(&atchan->lock, flags);
@@ -1188,6 +1281,7 @@ static void atc_free_chan_resources(struct dma_chan *chan)
 	list_splice_init(&atchan->free_list, &list);
 	atchan->descs_allocated = 0;
 	atchan->status = 0;
+	atchan->remain_desc = 0;
 
 	dev_vdbg(chan2dev(chan), "free_chan_resources: done\n");
 }
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index d27942f..443d62b 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -213,6 +213,7 @@ txd_to_at_desc(struct dma_async_tx_descriptor *txd)
 enum atc_status {
 	ATC_IS_ERROR = 0,
 	ATC_IS_PAUSED = 1,
+	ATC_IS_BTC = 2,
 	ATC_IS_CYCLIC = 24,
 };
 
@@ -228,6 +229,7 @@ enum atc_status {
  * @save_cfg: configuration register that is saved on suspend/resume cycle
  * @save_dscr: for cyclic operations, preserve next descriptor address in
  *             the cyclic list on suspend/resume cycle
+ * @remain_desc: to save remain desc length
  * @dma_sconfig: configuration for slave transfers, passed via DMA_SLAVE_CONFIG
  * @lock: serializes enqueue/dequeue operations to descriptors lists
  * @active_list: list of descriptors dmaengine is being running on
@@ -244,6 +246,7 @@ struct at_dma_chan {
 	struct tasklet_struct	tasklet;
 	u32			save_cfg;
 	u32			save_dscr;
+	u32			remain_desc;
 	struct dma_slave_config dma_sconfig;
 
 	spinlock_t		lock;
