Commit 255b721c authored by Liang Jie's avatar Liang Jie Committed by Linus Walleij
Browse files

pinctrl: mediatek: make devm allocations safer and clearer in mtk_eint_do_init()



mtk_eint_do_init() allocates several pointer arrays which are then
populated in a per-instance loop and freed on error. The arrays are
currently allocated with devm_kmalloc(), so their entries are left
uninitialised until the per-instance allocations succeed.

On a failure in the middle of the loop, the error path iterates over
the full nbase range and calls devm_kfree() on each element. For
indices which were never initialised, the corresponding array entries
contain stack garbage. If any of those happen to be non-zero,
devm_kfree() will pass them to devres_destroy(), which will WARN
because there is no matching devm_kmalloc() resource for such bogus
pointers.

Improve the robustness and readability by:

  - Using devm_kcalloc() for the pointer arrays so that all entries
    start as NULL, ensuring that only genuinely initialised elements
    may be freed and preventing spurious WARN_ON()s in the error path.
  - Switching the allocations to sizeof(*ptr) / sizeof(**ptr) forms,
    avoiding hard-coded element types and making the code more resilient
    to future type changes.
  - Dropping the redundant NULL checks before devm_kfree(), as
    devm_kfree() safely handles NULL pointers.

The functional behaviour in the successful initialisation path remains
unchanged, while the error handling becomes simpler and less
error-prone.

Reviewed-by: default avatarfanggeng <fanggeng@lixiang.com>
Signed-off-by: default avatarLiang Jie <liangjie@lixiang.com>
Signed-off-by: default avatarLinus Walleij <linusw@kernel.org>
parent a035b23b
Loading
Loading
Loading
Loading
+17 −12
Original line number Diff line number Diff line
@@ -544,24 +544,32 @@ int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin)
		}
	}

	eint->pin_list = devm_kmalloc(eint->dev, eint->nbase * sizeof(u16 *), GFP_KERNEL);
	eint->pin_list = devm_kcalloc(eint->dev, eint->nbase,
				      sizeof(*eint->pin_list), GFP_KERNEL);
	if (!eint->pin_list)
		goto err_pin_list;

	eint->wake_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL);
	eint->wake_mask = devm_kcalloc(eint->dev, eint->nbase,
				       sizeof(*eint->wake_mask), GFP_KERNEL);
	if (!eint->wake_mask)
		goto err_wake_mask;

	eint->cur_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL);
	eint->cur_mask = devm_kcalloc(eint->dev, eint->nbase,
				      sizeof(*eint->cur_mask), GFP_KERNEL);
	if (!eint->cur_mask)
		goto err_cur_mask;

	for (i = 0; i < eint->nbase; i++) {
		eint->pin_list[i] = devm_kzalloc(eint->dev, eint->base_pin_num[i] * sizeof(u16),
		eint->pin_list[i] = devm_kzalloc(eint->dev,
						 eint->base_pin_num[i] * sizeof(**eint->pin_list),
						 GFP_KERNEL);
		port = DIV_ROUND_UP(eint->base_pin_num[i], 32);
		eint->wake_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL);
		eint->cur_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL);
		eint->wake_mask[i] = devm_kzalloc(eint->dev,
						  port * sizeof(**eint->wake_mask),
						  GFP_KERNEL);
		eint->cur_mask[i] = devm_kzalloc(eint->dev,
						 port * sizeof(**eint->cur_mask),
						 GFP_KERNEL);
		if (!eint->pin_list[i] || !eint->wake_mask[i] || !eint->cur_mask[i])
			goto err_eint;
	}
@@ -597,11 +605,8 @@ int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin)

err_eint:
	for (i = 0; i < eint->nbase; i++) {
		if (eint->cur_mask[i])
		devm_kfree(eint->dev, eint->cur_mask[i]);
		if (eint->wake_mask[i])
		devm_kfree(eint->dev, eint->wake_mask[i]);
		if (eint->pin_list[i])
		devm_kfree(eint->dev, eint->pin_list[i]);
	}
	devm_kfree(eint->dev, eint->cur_mask);