diff options
author | Muli Ben-Yehuda <muli@il.ibm.com> | 2006-09-26 04:52:31 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-09-26 04:52:31 -0400 |
commit | b8f4fe66a560b5ccbb4d4d0d2df356a5d9b98b83 (patch) | |
tree | 71b68a0950e4058dd0a4771d093f4e2a58227820 /arch/x86_64/kernel/pci-calgary.c | |
parent | 9f2dc46d5ec6fd7787182d2232a1003af11879f1 (diff) |
[PATCH] Calgary IOMMU: fix error path memleak in calgary_free_tar
We were freeing the iommu_table and leaking the bitmap pages. Also
rename it to calgary_free_bus, which is more accurate.
Signed-off-by: Muli Ben-Yehuda <muli@il.ibm.com>
Signed-off-by: Jon Mason <jdmason@us.ibm.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/x86_64/kernel/pci-calgary.c')
-rw-r--r-- | arch/x86_64/kernel/pci-calgary.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c index b2182c93630..6c5da1d813f 100644 --- a/arch/x86_64/kernel/pci-calgary.c +++ b/arch/x86_64/kernel/pci-calgary.c | |||
@@ -658,11 +658,12 @@ static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar) | |||
658 | return 0; | 658 | return 0; |
659 | } | 659 | } |
660 | 660 | ||
661 | static void __init calgary_free_tar(struct pci_dev *dev) | 661 | static void __init calgary_free_bus(struct pci_dev *dev) |
662 | { | 662 | { |
663 | u64 val64; | 663 | u64 val64; |
664 | struct iommu_table *tbl = dev->sysdata; | 664 | struct iommu_table *tbl = dev->sysdata; |
665 | void __iomem *target; | 665 | void __iomem *target; |
666 | unsigned int bitmapsz; | ||
666 | 667 | ||
667 | target = calgary_reg(tbl->bbar, tar_offset(dev->bus->number)); | 668 | target = calgary_reg(tbl->bbar, tar_offset(dev->bus->number)); |
668 | val64 = be64_to_cpu(readq(target)); | 669 | val64 = be64_to_cpu(readq(target)); |
@@ -670,8 +671,15 @@ static void __init calgary_free_tar(struct pci_dev *dev) | |||
670 | writeq(cpu_to_be64(val64), target); | 671 | writeq(cpu_to_be64(val64), target); |
671 | readq(target); /* flush */ | 672 | readq(target); /* flush */ |
672 | 673 | ||
674 | bitmapsz = tbl->it_size / BITS_PER_BYTE; | ||
675 | free_pages((unsigned long)tbl->it_map, get_order(bitmapsz)); | ||
676 | tbl->it_map = NULL; | ||
677 | |||
673 | kfree(tbl); | 678 | kfree(tbl); |
674 | dev->sysdata = NULL; | 679 | dev->sysdata = NULL; |
680 | |||
681 | /* Can't free bootmem allocated memory after system is up :-( */ | ||
682 | bus_info[dev->bus->number].tce_space = NULL; | ||
675 | } | 683 | } |
676 | 684 | ||
677 | static void calgary_watchdog(unsigned long data) | 685 | static void calgary_watchdog(unsigned long data) |
@@ -853,7 +861,7 @@ error: | |||
853 | if (!bus_info[dev->bus->number].tce_space && !translate_empty_slots) | 861 | if (!bus_info[dev->bus->number].tce_space && !translate_empty_slots) |
854 | continue; | 862 | continue; |
855 | calgary_disable_translation(dev); | 863 | calgary_disable_translation(dev); |
856 | calgary_free_tar(dev); | 864 | calgary_free_bus(dev); |
857 | pci_dev_put(dev); | 865 | pci_dev_put(dev); |
858 | } | 866 | } |
859 | 867 | ||