Messages in this thread Patch in this message | | | Subject | Re: [PATCH v3 4/6] powerpc/pseries/iommu: Remove default DMA window before creating DDW | From | Leonardo Bras <> | Date | Tue, 14 Jul 2020 03:46:29 -0300 |
| |
In fact, the changes over the last patch are more complex than the current patch. Just for reference, that's how enable_ddw() currently patches:
@@ -1087,7 +1119,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) struct device_node *dn; u32 ddw_avail[DDW_APPLICABLE_SIZE]; struct direct_window *window; - struct property *win64; + struct property *win64, *default_win = NULL; struct dynamic_dma_window_prop *ddwprop; struct failed_ddw_pdn *fpdn;
@@ -1133,14 +1165,38 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) if (ret != 0) goto out_failed; + /* + * If there is no window available, remove the default DMA window, + * if it's present. This will make all the resources available to the + * new DDW window. + * If anything fails after this, we need to restore it, so also check + * for extensions presence. + */ if (query.windows_available == 0) { - /* - * no additional windows are available for this device. - * We might be able to reallocate the existing window, - * trading in for a larger page size. - */ - dev_dbg(&dev->dev, "no free dynamic windows"); - goto out_failed; + int reset_win_ext; + + default_win = of_find_property(pdn, "ibm,dma-window", NULL); + if (!default_win) + goto out_failed; + + reset_win_ext = ddw_read_ext(pdn, DDW_EXT_RESET_DMA_WIN, NULL); + if (reset_win_ext) { + default_win = NULL; + goto out_failed; + } + + remove_dma_window(pdn, ddw_avail, default_win); + + /* Query again, to check if the window is available */ + ret = query_ddw(dev, ddw_avail, &query, pdn); + if (ret != 0) + goto out_failed; + + if (query.windows_available == 0) { + /* no windows are available for this device. */ + dev_dbg(&dev->dev, "no free dynamic windows"); + goto out_failed; + } } if (query.page_size & 4) { page_shift = 24; /* 16MB */ @@ -1231,6 +1287,8 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) kfree(win64); out_failed: + if (default_win) + reset_dma_window(dev, pdn); fpdn = kzalloc(sizeof(*fpdn), GFP_KERNEL); if (!fpdn)
| |