Use a flexible array member to combine allocations. Add __counted_by for extra runtime analysis.
Fixup k3-udma as well since ti_sci_resource is used there as well and needs fixing up to use kzalloc_flex. Signed-off-by: Rosen Penev <[email protected]> --- v2: add k3-udma fixes. drivers/dma/ti/k3-udma.c | 180 +++++++++++++------------ drivers/firmware/ti_sci.c | 7 +- include/linux/soc/ti/ti_sci_protocol.h | 2 +- 3 files changed, 98 insertions(+), 91 deletions(-) diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index c964ebfcf3b6..ad6c50d0b844 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -4584,9 +4584,10 @@ static int udma_setup_resources(struct udma_dev *ud) { int ret, i, j; struct device *dev = ud->dev; - struct ti_sci_resource *rm_res, irq_res; + struct ti_sci_resource *rm_res, *irq_res; struct udma_tisci_rm *tisci_rm = &ud->tisci_rm; u32 cap3; + u16 sets; /* Set up the throughput level start indexes */ cap3 = udma_read(ud->mmrs[MMR_GCFG], 0x2c); @@ -4664,64 +4665,67 @@ static int udma_setup_resources(struct udma_dev *ud) rm_res = tisci_rm->rm_ranges[RM_RANGE_TCHAN]; if (IS_ERR(rm_res)) { bitmap_zero(ud->tchan_map, ud->tchan_cnt); - irq_res.sets = 1; + sets = 1; } else { bitmap_fill(ud->tchan_map, ud->tchan_cnt); for (i = 0; i < rm_res->sets; i++) udma_mark_resource_ranges(ud, ud->tchan_map, &rm_res->desc[i], "tchan"); - irq_res.sets = rm_res->sets; + sets = rm_res->sets; } /* rchan and matching default flow ranges */ rm_res = tisci_rm->rm_ranges[RM_RANGE_RCHAN]; if (IS_ERR(rm_res)) { bitmap_zero(ud->rchan_map, ud->rchan_cnt); - irq_res.sets++; + sets++; } else { bitmap_fill(ud->rchan_map, ud->rchan_cnt); for (i = 0; i < rm_res->sets; i++) udma_mark_resource_ranges(ud, ud->rchan_map, &rm_res->desc[i], "rchan"); - irq_res.sets += rm_res->sets; + sets += rm_res->sets; } - irq_res.desc = kzalloc_objs(*irq_res.desc, irq_res.sets); - if (!irq_res.desc) + irq_res = kzalloc_flex(*irq_res, desc, sets); + if (!irq_res) return -ENOMEM; + + irq_res->sets = sets; + rm_res = tisci_rm->rm_ranges[RM_RANGE_TCHAN]; if (IS_ERR(rm_res)) { - irq_res.desc[0].start = 0; - irq_res.desc[0].num = ud->tchan_cnt; + irq_res->desc[0].start = 0; + irq_res->desc[0].num = ud->tchan_cnt; i = 1; } else { for (i = 0; i < rm_res->sets; i++) { - irq_res.desc[i].start = rm_res->desc[i].start; - irq_res.desc[i].num = rm_res->desc[i].num; - irq_res.desc[i].start_sec = rm_res->desc[i].start_sec; - irq_res.desc[i].num_sec = rm_res->desc[i].num_sec; + irq_res->desc[i].start = rm_res->desc[i].start; + irq_res->desc[i].num = rm_res->desc[i].num; + irq_res->desc[i].start_sec = rm_res->desc[i].start_sec; + irq_res->desc[i].num_sec = rm_res->desc[i].num_sec; } } rm_res = tisci_rm->rm_ranges[RM_RANGE_RCHAN]; if (IS_ERR(rm_res)) { - irq_res.desc[i].start = 0; - irq_res.desc[i].num = ud->rchan_cnt; + irq_res->desc[i].start = 0; + irq_res->desc[i].num = ud->rchan_cnt; } else { for (j = 0; j < rm_res->sets; j++, i++) { if (rm_res->desc[j].num) { - irq_res.desc[i].start = rm_res->desc[j].start + + irq_res->desc[i].start = rm_res->desc[j].start + ud->soc_data->oes.udma_rchan; - irq_res.desc[i].num = rm_res->desc[j].num; + irq_res->desc[i].num = rm_res->desc[j].num; } if (rm_res->desc[j].num_sec) { - irq_res.desc[i].start_sec = rm_res->desc[j].start_sec + + irq_res->desc[i].start_sec = rm_res->desc[j].start_sec + ud->soc_data->oes.udma_rchan; - irq_res.desc[i].num_sec = rm_res->desc[j].num_sec; + irq_res->desc[i].num_sec = rm_res->desc[j].num_sec; } } } - ret = ti_sci_inta_msi_domain_alloc_irqs(ud->dev, &irq_res); - kfree(irq_res.desc); + ret = ti_sci_inta_msi_domain_alloc_irqs(ud->dev, irq_res); + kfree(irq_res); if (ret) { dev_err(ud->dev, "Failed to allocate MSI interrupts\n"); return ret; @@ -4746,9 +4750,10 @@ static int bcdma_setup_resources(struct udma_dev *ud) { int ret, i, j; struct device *dev = ud->dev; - struct ti_sci_resource *rm_res, irq_res; + struct ti_sci_resource *rm_res, *irq_res; struct udma_tisci_rm *tisci_rm = &ud->tisci_rm; const struct udma_oes_offsets *oes = &ud->soc_data->oes; + u16 sets; u32 cap; /* Set up the throughput level start indexes */ @@ -4828,21 +4833,21 @@ static int bcdma_setup_resources(struct udma_dev *ud) (char *)range_names[i]); } - irq_res.sets = 0; + sets = 0; /* bchan ranges */ if (ud->bchan_cnt) { rm_res = tisci_rm->rm_ranges[RM_RANGE_BCHAN]; if (IS_ERR(rm_res)) { bitmap_zero(ud->bchan_map, ud->bchan_cnt); - irq_res.sets++; + sets++; } else { bitmap_fill(ud->bchan_map, ud->bchan_cnt); for (i = 0; i < rm_res->sets; i++) udma_mark_resource_ranges(ud, ud->bchan_map, &rm_res->desc[i], "bchan"); - irq_res.sets += rm_res->sets; + sets += rm_res->sets; } } @@ -4851,14 +4856,14 @@ static int bcdma_setup_resources(struct udma_dev *ud) rm_res = tisci_rm->rm_ranges[RM_RANGE_TCHAN]; if (IS_ERR(rm_res)) { bitmap_zero(ud->tchan_map, ud->tchan_cnt); - irq_res.sets += 2; + sets += 2; } else { bitmap_fill(ud->tchan_map, ud->tchan_cnt); for (i = 0; i < rm_res->sets; i++) udma_mark_resource_ranges(ud, ud->tchan_map, &rm_res->desc[i], "tchan"); - irq_res.sets += rm_res->sets * 2; + sets += rm_res->sets * 2; } } @@ -4867,36 +4872,39 @@ static int bcdma_setup_resources(struct udma_dev *ud) rm_res = tisci_rm->rm_ranges[RM_RANGE_RCHAN]; if (IS_ERR(rm_res)) { bitmap_zero(ud->rchan_map, ud->rchan_cnt); - irq_res.sets += 2; + sets += 2; } else { bitmap_fill(ud->rchan_map, ud->rchan_cnt); for (i = 0; i < rm_res->sets; i++) udma_mark_resource_ranges(ud, ud->rchan_map, &rm_res->desc[i], "rchan"); - irq_res.sets += rm_res->sets * 2; + sets += rm_res->sets * 2; } } - irq_res.desc = kzalloc_objs(*irq_res.desc, irq_res.sets); - if (!irq_res.desc) + irq_res = kzalloc_flex(*irq_res, desc, sets); + if (!irq_res) return -ENOMEM; + + irq_res->sets = sets; + if (ud->bchan_cnt) { rm_res = tisci_rm->rm_ranges[RM_RANGE_BCHAN]; if (IS_ERR(rm_res)) { - irq_res.desc[0].start = oes->bcdma_bchan_ring; - irq_res.desc[0].num = ud->bchan_cnt; + irq_res->desc[0].start = oes->bcdma_bchan_ring; + irq_res->desc[0].num = ud->bchan_cnt; i = 1; } else { for (i = 0; i < rm_res->sets; i++) { - irq_res.desc[i].start = rm_res->desc[i].start + + irq_res->desc[i].start = rm_res->desc[i].start + oes->bcdma_bchan_ring; - irq_res.desc[i].num = rm_res->desc[i].num; + irq_res->desc[i].num = rm_res->desc[i].num; if (rm_res->desc[i].num_sec) { - irq_res.desc[i].start_sec = rm_res->desc[i].start_sec + + irq_res->desc[i].start_sec = rm_res->desc[i].start_sec + oes->bcdma_bchan_ring; - irq_res.desc[i].num_sec = rm_res->desc[i].num_sec; + irq_res->desc[i].num_sec = rm_res->desc[i].num_sec; } } } @@ -4907,28 +4915,28 @@ static int bcdma_setup_resources(struct udma_dev *ud) if (ud->tchan_cnt) { rm_res = tisci_rm->rm_ranges[RM_RANGE_TCHAN]; if (IS_ERR(rm_res)) { - irq_res.desc[i].start = oes->bcdma_tchan_data; - irq_res.desc[i].num = ud->tchan_cnt; - irq_res.desc[i + 1].start = oes->bcdma_tchan_ring; - irq_res.desc[i + 1].num = ud->tchan_cnt; + irq_res->desc[i].start = oes->bcdma_tchan_data; + irq_res->desc[i].num = ud->tchan_cnt; + irq_res->desc[i + 1].start = oes->bcdma_tchan_ring; + irq_res->desc[i + 1].num = ud->tchan_cnt; i += 2; } else { for (j = 0; j < rm_res->sets; j++, i += 2) { - irq_res.desc[i].start = rm_res->desc[j].start + + irq_res->desc[i].start = rm_res->desc[j].start + oes->bcdma_tchan_data; - irq_res.desc[i].num = rm_res->desc[j].num; + irq_res->desc[i].num = rm_res->desc[j].num; - irq_res.desc[i + 1].start = rm_res->desc[j].start + + irq_res->desc[i + 1].start = rm_res->desc[j].start + oes->bcdma_tchan_ring; - irq_res.desc[i + 1].num = rm_res->desc[j].num; + irq_res->desc[i + 1].num = rm_res->desc[j].num; if (rm_res->desc[j].num_sec) { - irq_res.desc[i].start_sec = rm_res->desc[j].start_sec + + irq_res->desc[i].start_sec = rm_res->desc[j].start_sec + oes->bcdma_tchan_data; - irq_res.desc[i].num_sec = rm_res->desc[j].num_sec; - irq_res.desc[i + 1].start_sec = rm_res->desc[j].start_sec + + irq_res->desc[i].num_sec = rm_res->desc[j].num_sec; + irq_res->desc[i + 1].start_sec = rm_res->desc[j].start_sec + oes->bcdma_tchan_ring; - irq_res.desc[i + 1].num_sec = rm_res->desc[j].num_sec; + irq_res->desc[i + 1].num_sec = rm_res->desc[j].num_sec; } } } @@ -4936,35 +4944,35 @@ static int bcdma_setup_resources(struct udma_dev *ud) if (ud->rchan_cnt) { rm_res = tisci_rm->rm_ranges[RM_RANGE_RCHAN]; if (IS_ERR(rm_res)) { - irq_res.desc[i].start = oes->bcdma_rchan_data; - irq_res.desc[i].num = ud->rchan_cnt; - irq_res.desc[i + 1].start = oes->bcdma_rchan_ring; - irq_res.desc[i + 1].num = ud->rchan_cnt; + irq_res->desc[i].start = oes->bcdma_rchan_data; + irq_res->desc[i].num = ud->rchan_cnt; + irq_res->desc[i + 1].start = oes->bcdma_rchan_ring; + irq_res->desc[i + 1].num = ud->rchan_cnt; i += 2; } else { for (j = 0; j < rm_res->sets; j++, i += 2) { - irq_res.desc[i].start = rm_res->desc[j].start + + irq_res->desc[i].start = rm_res->desc[j].start + oes->bcdma_rchan_data; - irq_res.desc[i].num = rm_res->desc[j].num; + irq_res->desc[i].num = rm_res->desc[j].num; - irq_res.desc[i + 1].start = rm_res->desc[j].start + + irq_res->desc[i + 1].start = rm_res->desc[j].start + oes->bcdma_rchan_ring; - irq_res.desc[i + 1].num = rm_res->desc[j].num; + irq_res->desc[i + 1].num = rm_res->desc[j].num; if (rm_res->desc[j].num_sec) { - irq_res.desc[i].start_sec = rm_res->desc[j].start_sec + + irq_res->desc[i].start_sec = rm_res->desc[j].start_sec + oes->bcdma_rchan_data; - irq_res.desc[i].num_sec = rm_res->desc[j].num_sec; - irq_res.desc[i + 1].start_sec = rm_res->desc[j].start_sec + + irq_res->desc[i].num_sec = rm_res->desc[j].num_sec; + irq_res->desc[i + 1].start_sec = rm_res->desc[j].start_sec + oes->bcdma_rchan_ring; - irq_res.desc[i + 1].num_sec = rm_res->desc[j].num_sec; + irq_res->desc[i + 1].num_sec = rm_res->desc[j].num_sec; } } } } - ret = ti_sci_inta_msi_domain_alloc_irqs(ud->dev, &irq_res); - kfree(irq_res.desc); + ret = ti_sci_inta_msi_domain_alloc_irqs(ud->dev, irq_res); + kfree(irq_res); if (ret) { dev_err(ud->dev, "Failed to allocate MSI interrupts\n"); return ret; @@ -4977,10 +4985,11 @@ static int pktdma_setup_resources(struct udma_dev *ud) { int ret, i, j; struct device *dev = ud->dev; - struct ti_sci_resource *rm_res, irq_res; + struct ti_sci_resource *rm_res, *irq_res; struct udma_tisci_rm *tisci_rm = &ud->tisci_rm; const struct udma_oes_offsets *oes = &ud->soc_data->oes; u32 cap3; + u16 sets; /* Set up the throughput level start indexes */ cap3 = udma_read(ud->mmrs[MMR_GCFG], 0x2c); @@ -5057,13 +5066,13 @@ static int pktdma_setup_resources(struct udma_dev *ud) if (IS_ERR(rm_res)) { /* all rflows are assigned exclusively to Linux */ bitmap_zero(ud->rflow_in_use, ud->rflow_cnt); - irq_res.sets = 1; + sets = 1; } else { bitmap_fill(ud->rflow_in_use, ud->rflow_cnt); for (i = 0; i < rm_res->sets; i++) udma_mark_resource_ranges(ud, ud->rflow_in_use, &rm_res->desc[i], "rflow"); - irq_res.sets = rm_res->sets; + sets = rm_res->sets; } /* tflow ranges */ @@ -5071,55 +5080,58 @@ static int pktdma_setup_resources(struct udma_dev *ud) if (IS_ERR(rm_res)) { /* all tflows are assigned exclusively to Linux */ bitmap_zero(ud->tflow_map, ud->tflow_cnt); - irq_res.sets++; + sets++; } else { bitmap_fill(ud->tflow_map, ud->tflow_cnt); for (i = 0; i < rm_res->sets; i++) udma_mark_resource_ranges(ud, ud->tflow_map, &rm_res->desc[i], "tflow"); - irq_res.sets += rm_res->sets; + sets += rm_res->sets; } - irq_res.desc = kzalloc_objs(*irq_res.desc, irq_res.sets); - if (!irq_res.desc) + irq_res = kzalloc_flex(*irq_res, desc, sets); + if (!irq_res) return -ENOMEM; + + irq_res->sets = sets; + rm_res = tisci_rm->rm_ranges[RM_RANGE_TFLOW]; if (IS_ERR(rm_res)) { - irq_res.desc[0].start = oes->pktdma_tchan_flow; - irq_res.desc[0].num = ud->tflow_cnt; + irq_res->desc[0].start = oes->pktdma_tchan_flow; + irq_res->desc[0].num = ud->tflow_cnt; i = 1; } else { for (i = 0; i < rm_res->sets; i++) { - irq_res.desc[i].start = rm_res->desc[i].start + + irq_res->desc[i].start = rm_res->desc[i].start + oes->pktdma_tchan_flow; - irq_res.desc[i].num = rm_res->desc[i].num; + irq_res->desc[i].num = rm_res->desc[i].num; if (rm_res->desc[i].num_sec) { - irq_res.desc[i].start_sec = rm_res->desc[i].start_sec + + irq_res->desc[i].start_sec = rm_res->desc[i].start_sec + oes->pktdma_tchan_flow; - irq_res.desc[i].num_sec = rm_res->desc[i].num_sec; + irq_res->desc[i].num_sec = rm_res->desc[i].num_sec; } } } rm_res = tisci_rm->rm_ranges[RM_RANGE_RFLOW]; if (IS_ERR(rm_res)) { - irq_res.desc[i].start = oes->pktdma_rchan_flow; - irq_res.desc[i].num = ud->rflow_cnt; + irq_res->desc[i].start = oes->pktdma_rchan_flow; + irq_res->desc[i].num = ud->rflow_cnt; } else { for (j = 0; j < rm_res->sets; j++, i++) { - irq_res.desc[i].start = rm_res->desc[j].start + + irq_res->desc[i].start = rm_res->desc[j].start + oes->pktdma_rchan_flow; - irq_res.desc[i].num = rm_res->desc[j].num; + irq_res->desc[i].num = rm_res->desc[j].num; if (rm_res->desc[j].num_sec) { - irq_res.desc[i].start_sec = rm_res->desc[j].start_sec + + irq_res->desc[i].start_sec = rm_res->desc[j].start_sec + oes->pktdma_rchan_flow; - irq_res.desc[i].num_sec = rm_res->desc[j].num_sec; + irq_res->desc[i].num_sec = rm_res->desc[j].num_sec; } } } - ret = ti_sci_inta_msi_domain_alloc_irqs(ud->dev, &irq_res); - kfree(irq_res.desc); + ret = ti_sci_inta_msi_domain_alloc_irqs(ud->dev, irq_res); + kfree(irq_res); if (ret) { dev_err(ud->dev, "Failed to allocate MSI interrupts\n"); return ret; diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index e027a2bd8f26..04d99c1fafa1 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -3574,16 +3574,11 @@ devm_ti_sci_get_resource_sets(const struct ti_sci_handle *handle, bool valid_set = false; int i, ret, res_count; - res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL); + res = devm_kzalloc(dev, struct_size(res, desc, sets), GFP_KERNEL); if (!res) return ERR_PTR(-ENOMEM); res->sets = sets; - res->desc = devm_kcalloc(dev, res->sets, sizeof(*res->desc), - GFP_KERNEL); - if (!res->desc) - return ERR_PTR(-ENOMEM); - for (i = 0; i < res->sets; i++) { ret = handle->ops.rm_core_ops.get_range(handle, dev_id, sub_types[i], diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index fd104b666836..7632bb11c862 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -599,7 +599,7 @@ struct ti_sci_handle { struct ti_sci_resource { u16 sets; raw_spinlock_t lock; - struct ti_sci_resource_desc *desc; + struct ti_sci_resource_desc desc[] __counted_by(sets); }; #if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL) -- 2.54.0

