Messages in this thread Patch in this message | | | From | Dongliang Mu <> | Subject | [PATCH 3/3] ipack: tpci200: fix memory leak in the tpci200_register | Date | Wed, 21 Jul 2021 19:11:32 +0800 |
| |
The error handling code in tpci200_register does not free interface_regs allocated by ioremap and the current version of error handling code is problematic.
Fix this by refactoring the error handling code and free interface_regs when necessary.
Reported-by: Dongliang Mu <mudongliangabcd@gmail.com> Fixes: 43986798fd50 ("ipack: add error handling for ioremap_nocache") Signed-off-by: Dongliang Mu <mudongliangabcd@gmail.com> --- drivers/ipack/carriers/tpci200.c | 52 +++++++++++++++++--------------- 1 file changed, 28 insertions(+), 24 deletions(-)
diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c index 7fbfb17c341b..a4e5883321df 100644 --- a/drivers/ipack/carriers/tpci200.c +++ b/drivers/ipack/carriers/tpci200.c @@ -84,20 +84,6 @@ static void tpci200_set_mask(struct tpci200_board *tpci200, spin_unlock_irqrestore(&tpci200->regs_lock, flags); } -static void tpci200_unregister(struct tpci200_board *tpci200) -{ - free_irq(tpci200->info->pdev->irq, (void *) tpci200); - - iounmap(tpci200->info->interface_regs); - - pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR); - pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR); - pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR); - pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR); - - pci_disable_device(tpci200->info->pdev); -} - static void tpci200_enable_irq(struct tpci200_board *tpci200, int islot) { @@ -254,7 +240,7 @@ static int tpci200_register(struct tpci200_board *tpci200) "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !", tpci200->info->pdev->bus->number, tpci200->info->pdev->devfn); - goto out_disable_pci; + goto err_enable_device; } /* Request IO ID INT space (Bar 3) */ @@ -266,7 +252,7 @@ static int tpci200_register(struct tpci200_board *tpci200) "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !", tpci200->info->pdev->bus->number, tpci200->info->pdev->devfn); - goto out_release_ip_space; + goto err_ip_interface_bar; } /* Request MEM8 space (Bar 5) */ @@ -277,7 +263,7 @@ static int tpci200_register(struct tpci200_board *tpci200) "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 5!", tpci200->info->pdev->bus->number, tpci200->info->pdev->devfn); - goto out_release_ioid_int_space; + goto err_io_id_int_spaces_bar; } /* Request MEM16 space (Bar 4) */ @@ -288,7 +274,7 @@ static int tpci200_register(struct tpci200_board *tpci200) "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!", tpci200->info->pdev->bus->number, tpci200->info->pdev->devfn); - goto out_release_mem8_space; + goto err_mem8_space_bar; } /* Map internal tpci200 driver user space */ @@ -302,7 +288,7 @@ static int tpci200_register(struct tpci200_board *tpci200) tpci200->info->pdev->bus->number, tpci200->info->pdev->devfn); res = -ENOMEM; - goto out_release_mem8_space; + goto err_mem16_space_bar; } /* Initialize lock that protects interface_regs */ @@ -341,22 +327,40 @@ static int tpci200_register(struct tpci200_board *tpci200) "(bn 0x%X, sn 0x%X) unable to register IRQ !", tpci200->info->pdev->bus->number, tpci200->info->pdev->devfn); - goto out_release_ioid_int_space; + goto err_interface_regs; } return 0; -out_release_mem8_space: +err_interface_regs: + iounmap(tpci200->info->interface_regs); +err_mem16_space_bar: + pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR); +err_mem8_space_bar: pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR); -out_release_ioid_int_space: +err_io_id_int_spaces_bar: pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR); -out_release_ip_space: +err_ip_interface_bar: pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR); -out_disable_pci: +err_enable_device: pci_disable_device(tpci200->info->pdev); return res; } +static void tpci200_unregister(struct tpci200_board *tpci200) +{ + free_irq(tpci200->info->pdev->irq, (void *) tpci200); + + iounmap(tpci200->info->interface_regs); + + pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR); + pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR); + pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR); + pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR); + + pci_disable_device(tpci200->info->pdev); +} + static int tpci200_get_clockrate(struct ipack_device *dev) { struct tpci200_board *tpci200 = check_slot(dev); -- 2.25.1
| |