Commit 3bf983e4 authored by Gaurav Batra's avatar Gaurav Batra Committed by Michael Ellerman

powerpc/pseries/iommu: enable_ddw incorrectly returns direct mapping for SR-IOV device

When a device is initialized, the driver invokes dma_supported() twice -
first for streaming mappings followed by coherent mappings. For an
SR-IOV device, default window is deleted and DDW created. With vPMEM
enabled, TCE mappings are dynamically created for both vPMEM and SR-IOV
device.  There are no direct mappings.

First time when dma_supported() is called with 64 bit mask, DDW is created
and marked as dynamic window. The second time dma_supported() is called,
enable_ddw() finds existing window for the device and incorrectly returns
it as "direct mapping".

This only happens when size of DDW is big enough to map max LPAR memory.

This results in streaming TCEs to not get dynamically mapped, since code
incorrently assumes these are already pre-mapped. The adapter initially
comes up but goes down due to EEH.

Fixes: 381ceda8 ("powerpc/pseries/iommu: Make use of DDW for indirect mapping")
Cc: stable@vger.kernel.org # v5.15+
Signed-off-by: default avatarGaurav Batra <gbatra@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20231003030802.47914-1-gbatra@linux.vnet.ibm.com
parent efce8422
...@@ -914,7 +914,8 @@ static int remove_ddw(struct device_node *np, bool remove_prop, const char *win_ ...@@ -914,7 +914,8 @@ static int remove_ddw(struct device_node *np, bool remove_prop, const char *win_
return 0; return 0;
} }
static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *window_shift) static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *window_shift,
bool *direct_mapping)
{ {
struct dma_win *window; struct dma_win *window;
const struct dynamic_dma_window_prop *dma64; const struct dynamic_dma_window_prop *dma64;
...@@ -927,6 +928,7 @@ static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *windo ...@@ -927,6 +928,7 @@ static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *windo
dma64 = window->prop; dma64 = window->prop;
*dma_addr = be64_to_cpu(dma64->dma_base); *dma_addr = be64_to_cpu(dma64->dma_base);
*window_shift = be32_to_cpu(dma64->window_shift); *window_shift = be32_to_cpu(dma64->window_shift);
*direct_mapping = window->direct;
found = true; found = true;
break; break;
} }
...@@ -1270,10 +1272,8 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) ...@@ -1270,10 +1272,8 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
mutex_lock(&dma_win_init_mutex); mutex_lock(&dma_win_init_mutex);
if (find_existing_ddw(pdn, &dev->dev.archdata.dma_offset, &len)) { if (find_existing_ddw(pdn, &dev->dev.archdata.dma_offset, &len, &direct_mapping))
direct_mapping = (len >= max_ram_len);
goto out_unlock; goto out_unlock;
}
/* /*
* If we already went through this for a previous function of * If we already went through this for a previous function of
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment