intel-iommu: Check for identity mapping candidate using system dma mask
authorChris Wright <chrisw@sous-sol.org>
Sat, 28 May 2011 18:15:02 +0000 (13:15 -0500)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Wed, 1 Jun 2011 11:47:34 +0000 (12:47 +0100)
The identity mapping code appears to make the assumption that if the
devices dma_mask is greater than 32bits the device can use identity
mapping.  But that is not true: take the case where we have a 40bit
device in a 44bit architecture. The device can potentially receive a
physical address that it will truncate and cause incorrect addresses
to be used.

Instead check to see if the device's dma_mask is large enough
to address the system's dma_mask.

Signed-off-by: Mike Travis <travis@sgi.com>
Reviewed-by: Mike Habeck <habeck@sgi.com>
Cc: stable@kernel.org
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
drivers/pci/intel-iommu.c

index 4eaec2fa136948c8799fc9630fe7fad927c1257c..dcf051d53b7417e80e01b905b36be811e2768685 100644 (file)
@@ -2316,8 +2316,19 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
         * Assume that they will -- if they turn out not to be, then we can 
         * take them out of the 1:1 domain later.
         */
-       if (!startup)
-               return pdev->dma_mask > DMA_BIT_MASK(32);
+       if (!startup) {
+               /*
+                * If the device's dma_mask is less than the system's memory
+                * size then this is not a candidate for identity mapping.
+                */
+               u64 dma_mask = pdev->dma_mask;
+
+               if (pdev->dev.coherent_dma_mask &&
+                   pdev->dev.coherent_dma_mask < dma_mask)
+                       dma_mask = pdev->dev.coherent_dma_mask;
+
+               return dma_mask >= dma_get_required_mask(&pdev->dev);
+       }
 
        return 1;
 }