Skip to content

Commit 14b6f00

Browse files
Nishanth Aravamudanozbenh
authored andcommitted
pseries/iommu: Remove DDW on kexec
pseries/iommu: remove DDW on kexec We currently insert a property in the device-tree when we successfully configure DDW for a given slot. This was meant to be an optimization to speed up kexec/kdump, so that we don't need to make the RTAS calls again to re-configured DDW in the new kernel. However, we end up tripping a plpar_tce_stuff failure on kexec/kdump because we unconditionally parse the ibm,dma-window property for the node at bus/dev setup time. This property contains the 32-bit DMA window LIOBN, which is distinct from the DDW window's. We pass that LIOBN (via iommu_table_init -> iommu_table_clear -> tce_free -> tce_freemulti_pSeriesLP) to plpar_tce_stuff, which fails because that 32-bit window is no longer present after 25ebc45 ("powerpc/pseries/iommu: remove default window before attempting DDW manipulation"). I believe the simplest, easiest-to-maintain fix is to just change our initcall to, rather than detecting and updating the new kernel's DDW knowledge, just remove all DDW configurations. When the drivers re-initialize, we will set everything back up as it was before. Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
1 parent a1dabad commit 14b6f00

File tree

1 file changed

+50
-38
lines changed
  • arch/powerpc/platforms/pseries

1 file changed

+50
-38
lines changed

arch/powerpc/platforms/pseries/iommu.c

Lines changed: 50 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -787,33 +787,68 @@ static u64 find_existing_ddw(struct device_node *pdn)
787787
return dma_addr;
788788
}
789789

790+
static void __restore_default_window(struct eeh_dev *edev,
791+
u32 ddw_restore_token)
792+
{
793+
u32 cfg_addr;
794+
u64 buid;
795+
int ret;
796+
797+
/*
798+
* Get the config address and phb buid of the PE window.
799+
* Rely on eeh to retrieve this for us.
800+
* Retrieve them from the pci device, not the node with the
801+
* dma-window property
802+
*/
803+
cfg_addr = edev->config_addr;
804+
if (edev->pe_config_addr)
805+
cfg_addr = edev->pe_config_addr;
806+
buid = edev->phb->buid;
807+
808+
do {
809+
ret = rtas_call(ddw_restore_token, 3, 1, NULL, cfg_addr,
810+
BUID_HI(buid), BUID_LO(buid));
811+
} while (rtas_busy_delay(ret));
812+
pr_info("ibm,reset-pe-dma-windows(%x) %x %x %x returned %d\n",
813+
ddw_restore_token, cfg_addr, BUID_HI(buid), BUID_LO(buid), ret);
814+
}
815+
790816
static int find_existing_ddw_windows(void)
791817
{
792-
int len;
793818
struct device_node *pdn;
794-
struct direct_window *window;
795819
const struct dynamic_dma_window_prop *direct64;
820+
const u32 *ddw_extensions;
796821

797822
if (!firmware_has_feature(FW_FEATURE_LPAR))
798823
return 0;
799824

800825
for_each_node_with_property(pdn, DIRECT64_PROPNAME) {
801-
direct64 = of_get_property(pdn, DIRECT64_PROPNAME, &len);
826+
direct64 = of_get_property(pdn, DIRECT64_PROPNAME, NULL);
802827
if (!direct64)
803828
continue;
804829

805-
window = kzalloc(sizeof(*window), GFP_KERNEL);
806-
if (!window || len < sizeof(struct dynamic_dma_window_prop)) {
807-
kfree(window);
808-
remove_ddw(pdn);
809-
continue;
810-
}
830+
/*
831+
* We need to ensure the IOMMU table is active when we
832+
* return from the IOMMU setup so that the common code
833+
* can clear the table or find the holes. To that end,
834+
* first, remove any existing DDW configuration.
835+
*/
836+
remove_ddw(pdn);
811837

812-
window->device = pdn;
813-
window->prop = direct64;
814-
spin_lock(&direct_window_list_lock);
815-
list_add(&window->list, &direct_window_list);
816-
spin_unlock(&direct_window_list_lock);
838+
/*
839+
* Second, if we are running on a new enough level of
840+
* firmware where the restore API is present, use it to
841+
* restore the 32-bit window, which was removed in
842+
* create_ddw.
843+
* If the API is not present, then create_ddw couldn't
844+
* have removed the 32-bit window in the first place, so
845+
* removing the DDW configuration should be sufficient.
846+
*/
847+
ddw_extensions = of_get_property(pdn, "ibm,ddw-extensions",
848+
NULL);
849+
if (ddw_extensions && ddw_extensions[0] > 0)
850+
__restore_default_window(of_node_to_eeh_dev(pdn),
851+
ddw_extensions[1]);
817852
}
818853

819854
return 0;
@@ -886,30 +921,7 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
886921
static void restore_default_window(struct pci_dev *dev,
887922
u32 ddw_restore_token)
888923
{
889-
struct eeh_dev *edev;
890-
u32 cfg_addr;
891-
u64 buid;
892-
int ret;
893-
894-
/*
895-
* Get the config address and phb buid of the PE window.
896-
* Rely on eeh to retrieve this for us.
897-
* Retrieve them from the pci device, not the node with the
898-
* dma-window property
899-
*/
900-
edev = pci_dev_to_eeh_dev(dev);
901-
cfg_addr = edev->config_addr;
902-
if (edev->pe_config_addr)
903-
cfg_addr = edev->pe_config_addr;
904-
buid = edev->phb->buid;
905-
906-
do {
907-
ret = rtas_call(ddw_restore_token, 3, 1, NULL, cfg_addr,
908-
BUID_HI(buid), BUID_LO(buid));
909-
} while (rtas_busy_delay(ret));
910-
dev_info(&dev->dev,
911-
"ibm,reset-pe-dma-windows(%x) %x %x %x returned %d\n",
912-
ddw_restore_token, cfg_addr, BUID_HI(buid), BUID_LO(buid), ret);
924+
__restore_default_window(pci_dev_to_eeh_dev(dev), ddw_restore_token);
913925
}
914926

915927
/*

0 commit comments

Comments
 (0)