linux4.11: fix iommu error on (new?) AMD processors

see:
 https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-amdgpu/+bug/1683184
patch:
 https://patchwork.freedesktop.org/series/21684/
This commit is contained in:
Piraty 2017-05-26 10:25:43 +02:00
parent e8889b3398
commit 38db97d1b9
2 changed files with 61 additions and 1 deletions

View File

@ -0,0 +1,60 @@
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 63cacf5..1edeebec 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2227,15 +2227,26 @@ static struct iommu_group *amd_iommu_device_group(struct device *dev)
static void __queue_flush(struct flush_queue *queue)
{
- struct protection_domain *domain;
- unsigned long flags;
int idx;
- /* First flush TLB of all known domains */
- spin_lock_irqsave(&amd_iommu_pd_lock, flags);
- list_for_each_entry(domain, &amd_iommu_pd_list, list)
- domain_flush_tlb(domain);
- spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
+ /* First flush TLB of all domains which were added to flush queue */
+ for (idx = 0; idx < queue->next; ++idx) {
+ struct flush_queue_entry *entry;
+
+ entry = queue->entries + idx;
+
+ /*
+ * There might be cases where multiple IOVA entries for the
+ * same domain are queued in the flush queue. To avoid
+ * flushing the same domain again, we check whether the
+ * flag is set or not. This improves the efficiency of
+ * flush operation.
+ */
+ if (!entry->dma_dom->domain.already_flushed) {
+ entry->dma_dom->domain.already_flushed = true;
+ domain_flush_tlb(&entry->dma_dom->domain);
+ }
+ }
/* Wait until flushes have completed */
domain_flush_complete(NULL);
@@ -2289,6 +2300,8 @@ static void queue_add(struct dma_ops_domain *dma_dom,
pages = __roundup_pow_of_two(pages);
address >>= PAGE_SHIFT;
+ dma_dom->domain.already_flushed = false;
+
queue = get_cpu_ptr(&flush_queue);
spin_lock_irqsave(&queue->lock, flags);
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 4de8f41..4f5519d 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -454,6 +454,8 @@ struct protection_domain {
bool updated; /* complete domain flush required */
unsigned dev_cnt; /* devices assigned to this domain */
unsigned dev_iommu[MAX_IOMMUS]; /* per-IOMMU reference count */
+ bool already_flushed; /* flag to avoid flushing the same domain again
+ in a single invocation of __queue_flush() */
};
/*

View File

@ -1,7 +1,7 @@
# Template file for 'linux4.11'
pkgname=linux4.11
version=4.11.3
revision=1
revision=2
patch_args="-Np1"
wrksrc="linux-${version}"
maintainer="Juan RP <xtraeme@voidlinux.eu>"