Changing descs to a flexible array member allows one fewer allocation. Aadded __counted_by for extra runtime analysis.
Changed error path to a simple kfree. descs in all paths are not allocated. No reason to call xdma_free_desc. A single kfree is enough. Signed-off-by: Rosen Penev <[email protected]> --- drivers/dma/xilinx/xdma.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/dma/xilinx/xdma.c b/drivers/dma/xilinx/xdma.c index d02a4dac2291..14fbc7200a6d 100644 --- a/drivers/dma/xilinx/xdma.c +++ b/drivers/dma/xilinx/xdma.c @@ -80,7 +80,6 @@ struct xdma_chan { * @vdesc: Virtual DMA descriptor * @chan: DMA channel pointer * @dir: Transferring direction of the request - * @desc_blocks: Hardware descriptor blocks * @dblk_num: Number of hardware descriptor blocks * @desc_num: Number of hardware descriptors * @completed_desc_num: Completed hardware descriptors @@ -90,12 +89,12 @@ struct xdma_chan { * @period_size: Size of a period in bytes in cyclic transfers * @frames_left: Number of frames left in interleaved DMA transfer * @error: tx error flag + * @desc_blocks: Hardware descriptor blocks */ struct xdma_desc { struct virt_dma_desc vdesc; struct xdma_chan *chan; enum dma_transfer_direction dir; - struct xdma_desc_block *desc_blocks; u32 dblk_num; u32 desc_num; u32 completed_desc_num; @@ -105,6 +104,7 @@ struct xdma_desc { u32 period_size; u32 frames_left; bool error; + struct xdma_desc_block desc_blocks[] __counted_by(dblk_num); }; #define XDMA_DEV_STATUS_REG_DMA BIT(0) @@ -254,7 +254,6 @@ static void xdma_free_desc(struct virt_dma_desc *vdesc) sw_desc->desc_blocks[i].virt_addr, sw_desc->desc_blocks[i].dma_addr); } - kfree(sw_desc->desc_blocks); kfree(sw_desc); } @@ -275,26 +274,22 @@ xdma_alloc_desc(struct xdma_chan *chan, u32 desc_num, bool cyclic) void *addr; int i, j; - sw_desc = kzalloc_obj(*sw_desc, GFP_NOWAIT); + dblk_num = DIV_ROUND_UP(desc_num, XDMA_DESC_ADJACENT); + sw_desc = kzalloc_flex(*sw_desc, desc_blocks, dblk_num, GFP_NOWAIT); if (!sw_desc) return NULL; + sw_desc->dblk_num = dblk_num; sw_desc->chan = chan; sw_desc->desc_num = desc_num; sw_desc->cyclic = cyclic; sw_desc->error = false; - dblk_num = DIV_ROUND_UP(desc_num, XDMA_DESC_ADJACENT); - sw_desc->desc_blocks = kzalloc_objs(*sw_desc->desc_blocks, dblk_num, - GFP_NOWAIT); - if (!sw_desc->desc_blocks) - goto failed; if (cyclic) control = XDMA_DESC_CONTROL_CYCLIC; else control = XDMA_DESC_CONTROL(1, 0); - sw_desc->dblk_num = dblk_num; for (i = 0; i < sw_desc->dblk_num; i++) { addr = dma_pool_alloc(chan->desc_pool, GFP_NOWAIT, &dma_addr); if (!addr) @@ -314,7 +309,7 @@ xdma_alloc_desc(struct xdma_chan *chan, u32 desc_num, bool cyclic) return sw_desc; failed: - xdma_free_desc(&sw_desc->vdesc); + kfree(desc); return NULL; } -- 2.53.0

