commit: 41b21d285ad76e01ad0c800e9c8589b2741c4213 Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Tue Jun 19 23:30:01 2018 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Tue Jun 19 23:30:01 2018 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=41b21d28
Revert iommu patch. See bug #658538. 0000_README | 4 + 1800_iommu-amd-dma-direct-revert.patch | 164 +++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) diff --git a/0000_README b/0000_README index df97765..a4cf389 100644 --- a/0000_README +++ b/0000_README @@ -51,6 +51,10 @@ Patch: 1001_linux-4.17.2.patch From: http://www.kernel.org Desc: Linux 4.17.2 +Patch: 1800_iommu-amd-dma-direct-revert.patch +From: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/patch/?id=e16c4790de39dc861b749674c2a9319507f6f64f +Desc: Revert iommu/amd_iommu: Use CONFIG_DMA_DIRECT_OPS=y and dma_direct_{alloc,free}(). See bug #658538. + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1800_iommu-amd-dma-direct-revert.patch b/1800_iommu-amd-dma-direct-revert.patch new file mode 100644 index 0000000..a78fa02 --- /dev/null +++ b/1800_iommu-amd-dma-direct-revert.patch @@ -0,0 +1,164 @@ +From e16c4790de39dc861b749674c2a9319507f6f64f Mon Sep 17 00:00:00 2001 +From: Linus Torvalds <[email protected]> +Date: Mon, 11 Jun 2018 12:22:12 -0700 +Subject: Revert "iommu/amd_iommu: Use CONFIG_DMA_DIRECT_OPS=y and + dma_direct_{alloc,free}()" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This reverts commit b468620f2a1dfdcfddfd6fa54367b8bcc1b51248. + +It turns out that this broke drm on AMD platforms. Quoting Gabriel C: + "I can confirm reverting b468620f2a1dfdcfddfd6fa54367b8bcc1b51248 fixes + that issue for me. + + The GPU is working fine with SME enabled. + + Now with working GPU :) I can also confirm performance is back to + normal without doing any other workarounds" + +Christan König analyzed it partially: + "As far as I analyzed it we now get an -ENOMEM from dma_alloc_attrs() + in drivers/gpu/drm/ttm/ttm_page_alloc_dma.c when IOMMU is enabled" + +and Christoph Hellwig responded: + "I think the prime issue is that dma_direct_alloc respects the dma + mask. Which we don't need if actually using the iommu. This would be + mostly harmless exept for the the SEV bit high in the address that + makes the checks fail. + + For now I'd say revert this commit for 4.17/4.18-rc and I'll look into + addressing these issues properly" + +Reported-and-bisected-by: Gabriel C <[email protected]> +Acked-by: Christoph Hellwig <[email protected]> +Cc: Christian König <[email protected]> +Cc: Michel Dänzer <[email protected]> +Cc: Joerg Roedel <[email protected]> +Cc: Tom Lendacky <[email protected]> +Cc: Andrew Morton <[email protected]> +Cc: [email protected] # v4.17 +Signed-off-by: Linus Torvalds <[email protected]> +--- + drivers/iommu/Kconfig | 1 - + drivers/iommu/amd_iommu.c | 68 ++++++++++++++++++++++++++++++++--------------- + 2 files changed, 47 insertions(+), 22 deletions(-) + +diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig +index 8ea77ef..e055d22 100644 +--- a/drivers/iommu/Kconfig ++++ b/drivers/iommu/Kconfig +@@ -107,7 +107,6 @@ config IOMMU_PGTABLES_L2 + # AMD IOMMU support + config AMD_IOMMU + bool "AMD IOMMU support" +- select DMA_DIRECT_OPS + select SWIOTLB + select PCI_MSI + select PCI_ATS +diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c +index 0cea80be..596b95c 100644 +--- a/drivers/iommu/amd_iommu.c ++++ b/drivers/iommu/amd_iommu.c +@@ -2596,32 +2596,51 @@ static void *alloc_coherent(struct device *dev, size_t size, + unsigned long attrs) + { + u64 dma_mask = dev->coherent_dma_mask; +- struct protection_domain *domain = get_domain(dev); +- bool is_direct = false; +- void *virt_addr; ++ struct protection_domain *domain; ++ struct dma_ops_domain *dma_dom; ++ struct page *page; ++ ++ domain = get_domain(dev); ++ if (PTR_ERR(domain) == -EINVAL) { ++ page = alloc_pages(flag, get_order(size)); ++ *dma_addr = page_to_phys(page); ++ return page_address(page); ++ } else if (IS_ERR(domain)) ++ return NULL; + +- if (IS_ERR(domain)) { +- if (PTR_ERR(domain) != -EINVAL) ++ dma_dom = to_dma_ops_domain(domain); ++ size = PAGE_ALIGN(size); ++ dma_mask = dev->coherent_dma_mask; ++ flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); ++ flag |= __GFP_ZERO; ++ ++ page = alloc_pages(flag | __GFP_NOWARN, get_order(size)); ++ if (!page) { ++ if (!gfpflags_allow_blocking(flag)) + return NULL; +- is_direct = true; +- } + +- virt_addr = dma_direct_alloc(dev, size, dma_addr, flag, attrs); +- if (!virt_addr || is_direct) +- return virt_addr; ++ page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT, ++ get_order(size), flag); ++ if (!page) ++ return NULL; ++ } + + if (!dma_mask) + dma_mask = *dev->dma_mask; + +- *dma_addr = __map_single(dev, to_dma_ops_domain(domain), +- virt_to_phys(virt_addr), PAGE_ALIGN(size), +- DMA_BIDIRECTIONAL, dma_mask); ++ *dma_addr = __map_single(dev, dma_dom, page_to_phys(page), ++ size, DMA_BIDIRECTIONAL, dma_mask); ++ + if (*dma_addr == AMD_IOMMU_MAPPING_ERROR) + goto out_free; +- return virt_addr; ++ ++ return page_address(page); + + out_free: +- dma_direct_free(dev, size, virt_addr, *dma_addr, attrs); ++ ++ if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT)) ++ __free_pages(page, get_order(size)); ++ + return NULL; + } + +@@ -2632,17 +2651,24 @@ static void free_coherent(struct device *dev, size_t size, + void *virt_addr, dma_addr_t dma_addr, + unsigned long attrs) + { +- struct protection_domain *domain = get_domain(dev); ++ struct protection_domain *domain; ++ struct dma_ops_domain *dma_dom; ++ struct page *page; + ++ page = virt_to_page(virt_addr); + size = PAGE_ALIGN(size); + +- if (!IS_ERR(domain)) { +- struct dma_ops_domain *dma_dom = to_dma_ops_domain(domain); ++ domain = get_domain(dev); ++ if (IS_ERR(domain)) ++ goto free_mem; + +- __unmap_single(dma_dom, dma_addr, size, DMA_BIDIRECTIONAL); +- } ++ dma_dom = to_dma_ops_domain(domain); ++ ++ __unmap_single(dma_dom, dma_addr, size, DMA_BIDIRECTIONAL); + +- dma_direct_free(dev, size, virt_addr, dma_addr, attrs); ++free_mem: ++ if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT)) ++ __free_pages(page, get_order(size)); + } + + /* +-- +cgit v1.1 +
