Simplifies allocations by using a flexible array member in this struct. Remove hsu_dma_alloc_desc. It now offers no readability advantages in this single usage.
Add __counted_by to get extra runtime analysis. Apply the exact same treatment to struct hsu_dma and devm_kzalloc. Signed-off-by: Rosen Penev <[email protected]> --- drivers/dma/hsu/hsu.c | 37 ++++++++----------------------------- drivers/dma/hsu/hsu.h | 4 ++-- 2 files changed, 10 insertions(+), 31 deletions(-) diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c index f62d60d7bc6b..150c6567eede 100644 --- a/drivers/dma/hsu/hsu.c +++ b/drivers/dma/hsu/hsu.c @@ -241,28 +241,10 @@ int hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, u32 status) } EXPORT_SYMBOL_GPL(hsu_dma_do_irq); -static struct hsu_dma_desc *hsu_dma_alloc_desc(unsigned int nents) -{ - struct hsu_dma_desc *desc; - - desc = kzalloc_obj(*desc, GFP_NOWAIT); - if (!desc) - return NULL; - - desc->sg = kzalloc_objs(*desc->sg, nents, GFP_NOWAIT); - if (!desc->sg) { - kfree(desc); - return NULL; - } - - return desc; -} - static void hsu_dma_desc_free(struct virt_dma_desc *vdesc) { struct hsu_dma_desc *desc = to_hsu_dma_desc(vdesc); - kfree(desc->sg); kfree(desc); } @@ -276,10 +258,12 @@ static struct dma_async_tx_descriptor *hsu_dma_prep_slave_sg( struct scatterlist *sg; unsigned int i; - desc = hsu_dma_alloc_desc(sg_len); + desc = kzalloc_flex(*desc, sg, sg_len, GFP_NOWAIT); if (!desc) return NULL; + desc->nents = sg_len; + for_each_sg(sgl, sg, sg_len, i) { desc->sg[i].addr = sg_dma_address(sg); desc->sg[i].len = sg_dma_len(sg); @@ -287,7 +271,6 @@ static struct dma_async_tx_descriptor *hsu_dma_prep_slave_sg( desc->length += sg_dma_len(sg); } - desc->nents = sg_len; desc->direction = direction; /* desc->active = 0 by kzalloc */ desc->status = DMA_IN_PROGRESS; @@ -430,21 +413,17 @@ int hsu_dma_probe(struct hsu_dma_chip *chip) void __iomem *addr = chip->regs + chip->offset; unsigned short i; int ret; + unsigned short nr_channels; - hsu = devm_kzalloc(chip->dev, sizeof(*hsu), GFP_KERNEL); + /* Calculate nr_channels from the IO space length */ + nr_channels = (chip->length - chip->offset) / HSU_DMA_CHAN_LENGTH; + hsu = devm_kzalloc(chip->dev, struct_size(hsu, chan, nr_channels), GFP_KERNEL); if (!hsu) return -ENOMEM; + hsu->nr_channels = nr_channels; chip->hsu = hsu; - /* Calculate nr_channels from the IO space length */ - hsu->nr_channels = (chip->length - chip->offset) / HSU_DMA_CHAN_LENGTH; - - hsu->chan = devm_kcalloc(chip->dev, hsu->nr_channels, - sizeof(*hsu->chan), GFP_KERNEL); - if (!hsu->chan) - return -ENOMEM; - INIT_LIST_HEAD(&hsu->dma.channels); for (i = 0; i < hsu->nr_channels; i++) { struct hsu_dma_chan *hsuc = &hsu->chan[i]; diff --git a/drivers/dma/hsu/hsu.h b/drivers/dma/hsu/hsu.h index 3bca577b98a1..f6ca1014bccf 100644 --- a/drivers/dma/hsu/hsu.h +++ b/drivers/dma/hsu/hsu.h @@ -71,11 +71,11 @@ struct hsu_dma_sg { struct hsu_dma_desc { struct virt_dma_desc vdesc; enum dma_transfer_direction direction; - struct hsu_dma_sg *sg; unsigned int nents; size_t length; unsigned int active; enum dma_status status; + struct hsu_dma_sg sg[] __counted_by(nents); }; static inline struct hsu_dma_desc *to_hsu_dma_desc(struct virt_dma_desc *vdesc) @@ -115,8 +115,8 @@ struct hsu_dma { struct dma_device dma; /* channels */ - struct hsu_dma_chan *chan; unsigned short nr_channels; + struct hsu_dma_chan chan[] __counted_by(nr_channels); }; static inline struct hsu_dma *to_hsu_dma(struct dma_device *ddev) -- 2.53.0

