diff options
author | Dan Carpenter <dan.carpenter@oracle.com> | 2018-08-08 08:03:19 -0400 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2018-08-13 04:03:44 -0400 |
commit | 4096165d55218a6f58b6c2ebc5d2428aa0aa70e4 (patch) | |
tree | d61a2147f8416953173b2ea82ea5d793d917a5ef | |
parent | 0702bc4d2fe793018ad9aa0eb14bff7f526c4095 (diff) |
irqchip/stm32: Fix init error handling
If there are any errors in stm32_exti_host_init() then it leads to a
NULL dereference in the callers. The function should clean up after
itself.
Fixes: f9fc1745501e ("irqchip/stm32: Add host and driver data structures")
Reviewed-by: Ludovic Barre <ludovic.barre@st.com>
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r-- | drivers/irqchip/irq-stm32-exti.c | 25 |
1 files changed, 13 insertions, 12 deletions
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c index 3a7e8905a97e..880e48947576 100644 --- a/drivers/irqchip/irq-stm32-exti.c +++ b/drivers/irqchip/irq-stm32-exti.c | |||
@@ -602,17 +602,24 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd, | |||
602 | sizeof(struct stm32_exti_chip_data), | 602 | sizeof(struct stm32_exti_chip_data), |
603 | GFP_KERNEL); | 603 | GFP_KERNEL); |
604 | if (!host_data->chips_data) | 604 | if (!host_data->chips_data) |
605 | return NULL; | 605 | goto free_host_data; |
606 | 606 | ||
607 | host_data->base = of_iomap(node, 0); | 607 | host_data->base = of_iomap(node, 0); |
608 | if (!host_data->base) { | 608 | if (!host_data->base) { |
609 | pr_err("%pOF: Unable to map registers\n", node); | 609 | pr_err("%pOF: Unable to map registers\n", node); |
610 | return NULL; | 610 | goto free_chips_data; |
611 | } | 611 | } |
612 | 612 | ||
613 | stm32_host_data = host_data; | 613 | stm32_host_data = host_data; |
614 | 614 | ||
615 | return host_data; | 615 | return host_data; |
616 | |||
617 | free_chips_data: | ||
618 | kfree(host_data->chips_data); | ||
619 | free_host_data: | ||
620 | kfree(host_data); | ||
621 | |||
622 | return NULL; | ||
616 | } | 623 | } |
617 | 624 | ||
618 | static struct | 625 | static struct |
@@ -664,10 +671,8 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data, | |||
664 | struct irq_domain *domain; | 671 | struct irq_domain *domain; |
665 | 672 | ||
666 | host_data = stm32_exti_host_init(drv_data, node); | 673 | host_data = stm32_exti_host_init(drv_data, node); |
667 | if (!host_data) { | 674 | if (!host_data) |
668 | ret = -ENOMEM; | 675 | return -ENOMEM; |
669 | goto out_free_mem; | ||
670 | } | ||
671 | 676 | ||
672 | domain = irq_domain_add_linear(node, drv_data->bank_nr * IRQS_PER_BANK, | 677 | domain = irq_domain_add_linear(node, drv_data->bank_nr * IRQS_PER_BANK, |
673 | &irq_exti_domain_ops, NULL); | 678 | &irq_exti_domain_ops, NULL); |
@@ -724,7 +729,6 @@ out_free_domain: | |||
724 | irq_domain_remove(domain); | 729 | irq_domain_remove(domain); |
725 | out_unmap: | 730 | out_unmap: |
726 | iounmap(host_data->base); | 731 | iounmap(host_data->base); |
727 | out_free_mem: | ||
728 | kfree(host_data->chips_data); | 732 | kfree(host_data->chips_data); |
729 | kfree(host_data); | 733 | kfree(host_data); |
730 | return ret; | 734 | return ret; |
@@ -751,10 +755,8 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data, | |||
751 | } | 755 | } |
752 | 756 | ||
753 | host_data = stm32_exti_host_init(drv_data, node); | 757 | host_data = stm32_exti_host_init(drv_data, node); |
754 | if (!host_data) { | 758 | if (!host_data) |
755 | ret = -ENOMEM; | 759 | return -ENOMEM; |
756 | goto out_free_mem; | ||
757 | } | ||
758 | 760 | ||
759 | for (i = 0; i < drv_data->bank_nr; i++) | 761 | for (i = 0; i < drv_data->bank_nr; i++) |
760 | stm32_exti_chip_init(host_data, i, node); | 762 | stm32_exti_chip_init(host_data, i, node); |
@@ -776,7 +778,6 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data, | |||
776 | 778 | ||
777 | out_unmap: | 779 | out_unmap: |
778 | iounmap(host_data->base); | 780 | iounmap(host_data->base); |
779 | out_free_mem: | ||
780 | kfree(host_data->chips_data); | 781 | kfree(host_data->chips_data); |
781 | kfree(host_data); | 782 | kfree(host_data); |
782 | return ret; | 783 | return ret; |