Skip to content

Commit 65f746e

Browse files
LuBaoluwilldeacon
authored andcommitted
iommu: Add quirk for Intel graphic devices in map_sg
Combining the sg segments exposes a bug in the Intel i915 driver which causes visual artifacts and the screen to freeze. This is most likely because of how the i915 handles the returned list. It probably doesn't respect the returned value specifying the number of elements in the list and instead depends on the previous behaviour of the Intel iommu driver which would return the same number of elements in the output list as in the input list. [ This has been fixed in the i915 tree, but we agreed to carry this fix temporarily in the iommu tree and revert it before 5.11 is released: https://lore.kernel.org/linux-iommu/[email protected]/ -- Will ] Signed-off-by: Tom Murphy <[email protected]> Signed-off-by: Lu Baolu <[email protected]> Tested-by: Logan Gunthorpe <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 82612d6 commit 65f746e

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

drivers/iommu/dma-iommu.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,33 @@ static int __finalise_sg(struct device *dev, struct scatterlist *sg, int nents,
878878
unsigned int cur_len = 0, max_len = dma_get_max_seg_size(dev);
879879
int i, count = 0;
880880

881+
/*
882+
* The Intel graphic driver is used to assume that the returned
883+
* sg list is not combound. This blocks the efforts of converting
884+
* Intel IOMMU driver to dma-iommu api's. Add this quirk to make the
885+
* device driver work and should be removed once it's fixed in i915
886+
* driver.
887+
*/
888+
if (IS_ENABLED(CONFIG_DRM_I915) && dev_is_pci(dev) &&
889+
to_pci_dev(dev)->vendor == PCI_VENDOR_ID_INTEL &&
890+
(to_pci_dev(dev)->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
891+
for_each_sg(sg, s, nents, i) {
892+
unsigned int s_iova_off = sg_dma_address(s);
893+
unsigned int s_length = sg_dma_len(s);
894+
unsigned int s_iova_len = s->length;
895+
896+
s->offset += s_iova_off;
897+
s->length = s_length;
898+
sg_dma_address(s) = dma_addr + s_iova_off;
899+
sg_dma_len(s) = s_length;
900+
dma_addr += s_iova_len;
901+
902+
pr_info_once("sg combining disabled due to i915 driver\n");
903+
}
904+
905+
return nents;
906+
}
907+
881908
for_each_sg(sg, s, nents, i) {
882909
/* Restore this segment's original unaligned fields first */
883910
unsigned int s_iova_off = sg_dma_address(s);

0 commit comments

Comments
 (0)