aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorNishanth Aravamudan <nacc@us.ibm.com>2011-05-06 09:27:30 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-05-19 00:30:40 -0400
commit767303349e052ae0cb9e6495a70870da3459eeb6 (patch)
tree53c6839bef96ec7eb2c587c60665c06b672c5265 /arch/powerpc
parent31355403dba5aa7a700c69f91cd6266092932701 (diff)
powerpc: Fix kexec with dynamic dma windows
When we kexec we look for a particular property added by the first kernel, "linux,direct64-ddr-window-info", per-device where we already have set up dynamic dma windows. The current code, though, wasn't initializing the size of this property and thus when we kexec'd, we would find the property but read uninitialized memory resulting in garbage ddw values for the kexec'd kernel and panics. Fix this by setting the size at enable_ddw() time and ensuring that the size of the found property is valid at dupe_ddw_if_kexec() time. Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 6d5412a18b26..019009b10e62 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -730,16 +730,20 @@ static u64 dupe_ddw_if_kexec(struct pci_dev *dev, struct device_node *pdn)
730 pcidn = PCI_DN(dn); 730 pcidn = PCI_DN(dn);
731 direct64 = of_get_property(pdn, DIRECT64_PROPNAME, &len); 731 direct64 = of_get_property(pdn, DIRECT64_PROPNAME, &len);
732 if (direct64) { 732 if (direct64) {
733 window = kzalloc(sizeof(*window), GFP_KERNEL); 733 if (len < sizeof(struct dynamic_dma_window_prop)) {
734 if (!window) {
735 remove_ddw(pdn); 734 remove_ddw(pdn);
736 } else { 735 } else {
737 window->device = pdn; 736 window = kzalloc(sizeof(*window), GFP_KERNEL);
738 window->prop = direct64; 737 if (!window) {
739 spin_lock(&direct_window_list_lock); 738 remove_ddw(pdn);
740 list_add(&window->list, &direct_window_list); 739 } else {
741 spin_unlock(&direct_window_list_lock); 740 window->device = pdn;
742 dma_addr = direct64->dma_base; 741 window->prop = direct64;
742 spin_lock(&direct_window_list_lock);
743 list_add(&window->list, &direct_window_list);
744 spin_unlock(&direct_window_list_lock);
745 dma_addr = direct64->dma_base;
746 }
743 } 747 }
744 } 748 }
745 749
@@ -833,7 +837,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
833 struct device_node *dn; 837 struct device_node *dn;
834 const u32 *uninitialized_var(ddr_avail); 838 const u32 *uninitialized_var(ddr_avail);
835 struct direct_window *window; 839 struct direct_window *window;
836 struct property *uninitialized_var(win64); 840 struct property *win64;
837 struct dynamic_dma_window_prop *ddwprop; 841 struct dynamic_dma_window_prop *ddwprop;
838 842
839 mutex_lock(&direct_window_init_mutex); 843 mutex_lock(&direct_window_init_mutex);
@@ -907,6 +911,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
907 } 911 }
908 win64->name = kstrdup(DIRECT64_PROPNAME, GFP_KERNEL); 912 win64->name = kstrdup(DIRECT64_PROPNAME, GFP_KERNEL);
909 win64->value = ddwprop = kmalloc(sizeof(*ddwprop), GFP_KERNEL); 913 win64->value = ddwprop = kmalloc(sizeof(*ddwprop), GFP_KERNEL);
914 win64->length = sizeof(*ddwprop);
910 if (!win64->name || !win64->value) { 915 if (!win64->name || !win64->value) {
911 dev_info(&dev->dev, 916 dev_info(&dev->dev,
912 "couldn't allocate property name and value\n"); 917 "couldn't allocate property name and value\n");