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
+

Reply via email to