v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli);
if (!v_lli) {
dev_err(sdev->slave.dev, "Failed to alloc lli memory\n");
- kfree(txd);
- return NULL;
+ goto err_txd_free;
}
ret = sun6i_dma_cfg_lli(v_lli, src, dest, len, sconfig);
err_dma_free:
dma_pool_free(sdev->pool, v_lli, p_lli);
+err_txd_free:
+ kfree(txd);
return NULL;
}
for_each_sg(sgl, sg, sg_len, i) {
v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli);
- if (!v_lli) {
- kfree(txd);
- return NULL;
- }
+ if (!v_lli)
+ goto err_lli_free;
if (dir == DMA_MEM_TO_DEV) {
ret = sun6i_dma_cfg_lli(v_lli, sg_dma_address(sg),
sconfig->dst_addr, sg_dma_len(sg),
sconfig);
if (ret)
- goto err_dma_free;
+ goto err_cur_lli_free;
v_lli->cfg |= DMA_CHAN_CFG_DST_IO_MODE |
DMA_CHAN_CFG_SRC_LINEAR_MODE |
sg_dma_address(sg), sg_dma_len(sg),
sconfig);
if (ret)
- goto err_dma_free;
+ goto err_cur_lli_free;
v_lli->cfg |= DMA_CHAN_CFG_DST_LINEAR_MODE |
DMA_CHAN_CFG_SRC_IO_MODE |
return vchan_tx_prep(&vchan->vc, &txd->vd, flags);
-err_dma_free:
+err_cur_lli_free:
dma_pool_free(sdev->pool, v_lli, p_lli);
+err_lli_free:
+ for (prev = txd->v_lli; prev; prev = prev->v_lli_next)
+ dma_pool_free(sdev->pool, prev, virt_to_phys(prev));
+ kfree(txd);
return NULL;
}