summaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/pseries
diff options
context:
space:
mode:
authorNishanth Aravamudan <nacc@us.ibm.com>2011-05-06 13:27:30 (GMT)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-05-19 04:30:40 (GMT)
commit767303349e052ae0cb9e6495a70870da3459eeb6 (patch)
tree53c6839bef96ec7eb2c587c60665c06b672c5265 /arch/powerpc/platforms/pseries
parent31355403dba5aa7a700c69f91cd6266092932701 (diff)
downloadlinux-767303349e052ae0cb9e6495a70870da3459eeb6.tar.xz
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/platforms/pseries')
-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 6d5412a..019009b 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)
pcidn = PCI_DN(dn);
direct64 = of_get_property(pdn, DIRECT64_PROPNAME, &len);
if (direct64) {
- window = kzalloc(sizeof(*window), GFP_KERNEL);
- if (!window) {
+ if (len < sizeof(struct dynamic_dma_window_prop)) {
remove_ddw(pdn);
} else {
- window->device = pdn;
- window->prop = direct64;
- spin_lock(&direct_window_list_lock);
- list_add(&window->list, &direct_window_list);
- spin_unlock(&direct_window_list_lock);
- dma_addr = direct64->dma_base;
+ window = kzalloc(sizeof(*window), GFP_KERNEL);
+ if (!window) {
+ remove_ddw(pdn);
+ } else {
+ window->device = pdn;
+ window->prop = direct64;
+ spin_lock(&direct_window_list_lock);
+ list_add(&window->list, &direct_window_list);
+ spin_unlock(&direct_window_list_lock);
+ dma_addr = direct64->dma_base;
+ }
}
}
@@ -833,7 +837,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
struct device_node *dn;
const u32 *uninitialized_var(ddr_avail);
struct direct_window *window;
- struct property *uninitialized_var(win64);
+ struct property *win64;
struct dynamic_dma_window_prop *ddwprop;
mutex_lock(&direct_window_init_mutex);
@@ -907,6 +911,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
}
win64->name = kstrdup(DIRECT64_PROPNAME, GFP_KERNEL);
win64->value = ddwprop = kmalloc(sizeof(*ddwprop), GFP_KERNEL);
+ win64->length = sizeof(*ddwprop);
if (!win64->name || !win64->value) {
dev_info(&dev->dev,
"couldn't allocate property name and value\n");