aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilton Miller <miltonm@bga.com>2011-05-11 08:24:59 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-05-19 03:25:28 -0400
commitc85667802bb5093c4054f8a887a90dd0acf82d3e (patch)
tree739b32c42b8a83e142cd64b48d6723ac666ddc22
parent2573f6842201a00f139237e4b42ab16711b582af (diff)
powerpc/pseries/iommu: Find windows after kexec during boot
Move the discovery of windows previously setup from when the pci driver calls set_dma_mask to an arch_initcall. When kexecing into a kernel with dynamic dma windows allocated, we need to find the windows early so that memory hot remove will be able to delete the tces mapping the to be removed memory and memory hotplug add will map the new memory into the window. We should not wait for the driver to be loaded and the device to be probed. The iommu init hooks are before kmalloc is setup, so defer to arch_initcall. Signed-off-by: Milton Miller <miltonm@bga.com> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c52
1 files changed, 24 insertions, 28 deletions
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index a0421ac46d4e..a48f12644239 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -695,9 +695,9 @@ static void remove_ddw(struct device_node *np)
695 np->full_name, ret, ddr_avail[2], liobn); 695 np->full_name, ret, ddr_avail[2], liobn);
696 696
697delprop: 697delprop:
698 ret = of_remove_property(np, win64); 698 ret = prom_remove_property(np, win64);
699 if (ret) 699 if (ret)
700 pr_warning("%s: failed to remove direct window property: %d\n" 700 pr_warning("%s: failed to remove direct window property: %d\n",
701 np->full_name, ret); 701 np->full_name, ret);
702} 702}
703 703
@@ -725,38 +725,38 @@ static u64 dupe_ddw_if_already_created(struct pci_dev *dev, struct device_node *
725 return dma_addr; 725 return dma_addr;
726} 726}
727 727
728static u64 dupe_ddw_if_kexec(struct pci_dev *dev, struct device_node *pdn) 728static int find_existing_ddw_windows(void)
729{ 729{
730 struct device_node *dn;
731 struct pci_dn *pcidn;
732 int len; 730 int len;
731 struct device_node *pdn;
733 struct direct_window *window; 732 struct direct_window *window;
734 const struct dynamic_dma_window_prop *direct64; 733 const struct dynamic_dma_window_prop *direct64;
735 u64 dma_addr = 0;
736 734
737 dn = pci_device_to_OF_node(dev); 735 if (!firmware_has_feature(FW_FEATURE_LPAR))
738 pcidn = PCI_DN(dn); 736 return 0;
739 direct64 = of_get_property(pdn, DIRECT64_PROPNAME, &len); 737
740 if (direct64) { 738 for_each_node_with_property(pdn, DIRECT64_PROPNAME) {
741 if (len < sizeof(struct dynamic_dma_window_prop)) { 739 direct64 = of_get_property(pdn, DIRECT64_PROPNAME, &len);
740 if (!direct64)
741 continue;
742
743 window = kzalloc(sizeof(*window), GFP_KERNEL);
744 if (!window || len < sizeof(struct dynamic_dma_window_prop)) {
745 kfree(window);
742 remove_ddw(pdn); 746 remove_ddw(pdn);
743 } else { 747 continue;
744 window = kzalloc(sizeof(*window), GFP_KERNEL);
745 if (!window) {
746 remove_ddw(pdn);
747 } else {
748 window->device = pdn;
749 window->prop = direct64;
750 spin_lock(&direct_window_list_lock);
751 list_add(&window->list, &direct_window_list);
752 spin_unlock(&direct_window_list_lock);
753 dma_addr = direct64->dma_base;
754 }
755 } 748 }
749
750 window->device = pdn;
751 window->prop = direct64;
752 spin_lock(&direct_window_list_lock);
753 list_add(&window->list, &direct_window_list);
754 spin_unlock(&direct_window_list_lock);
756 } 755 }
757 756
758 return dma_addr; 757 return 0;
759} 758}
759machine_arch_initcall(pseries, find_existing_ddw_windows);
760 760
761static int query_ddw(struct pci_dev *dev, const u32 *ddr_avail, 761static int query_ddw(struct pci_dev *dev, const u32 *ddr_avail,
762 struct ddw_query_response *query) 762 struct ddw_query_response *query)
@@ -854,10 +854,6 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
854 if (dma_addr != 0) 854 if (dma_addr != 0)
855 goto out_unlock; 855 goto out_unlock;
856 856
857 dma_addr = dupe_ddw_if_kexec(dev, pdn);
858 if (dma_addr != 0)
859 goto out_unlock;
860
861 /* 857 /*
862 * the ibm,ddw-applicable property holds the tokens for: 858 * the ibm,ddw-applicable property holds the tokens for:
863 * ibm,query-pe-dma-window 859 * ibm,query-pe-dma-window