pseries/iommu: Restore iommu table pointer when restoring iommu ops
authorNishanth Aravamudan <nacc@us.ibm.com>
Mon, 9 May 2011 12:58:03 +0000 (12:58 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Thu, 19 May 2011 04:30:43 +0000 (14:30 +1000)
When we swtich to direct dma ops, we set the dma data union to have the
dma offset.  When we switch back to iommu table ops because of a later
dma_set_mask, we need to restore the iommu table pointer. Without this
change, crashes have been observed on kexec where (for reasons still
being investigated) we fall back to a 32-bit dma mask on a particular
device and then panic because the table pointer is not valid.

The easiset way to find this value is to call
pci_dma_dev_setup_pSeriesLP which will search up the pci tree until it
finds the node with the table.

Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Cc: Milton Miller <miltonm@bga.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/platforms/pseries/iommu.c

index 019009b10e6283d388f40217a9b1d6192d09fad9..48eec3b870264ef28e7c0951d215e10fb40642dc 100644 (file)
@@ -1029,10 +1029,10 @@ static int dma_set_mask_pSeriesLP(struct device *dev, u64 dma_mask)
        if (!dev->dma_mask || !dma_supported(dev, dma_mask))
                return -EIO;
 
+       pdev = to_pci_dev(dev);
+
        /* only attempt to use a new window if 64-bit DMA is requested */
        if (!disable_ddw && dma_mask == DMA_BIT_MASK(64)) {
-               pdev = to_pci_dev(dev);
-
                dn = pci_device_to_OF_node(pdev);
                dev_dbg(dev, "node is %s\n", dn->full_name);
 
@@ -1063,6 +1063,7 @@ static int dma_set_mask_pSeriesLP(struct device *dev, u64 dma_mask)
        if (!ddw_enabled) {
                dev_info(dev, "Using 32-bit DMA via iommu\n");
                set_dma_ops(dev, &dma_iommu_ops);
+               pci_dma_dev_setup_pSeriesLP(pdev);
        }
 
        *dev->dma_mask = dma_mask;