]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 Jul 2019 17:05:39 +0000 (19:05 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 Jul 2019 17:05:39 +0000 (19:05 +0200)
added patches:
iommu-iova-fix-compilation-error-with-config_iommu_iova.patch
iommu-vt-d-don-t-queue_iova-if-there-is-no-flush-queue.patch

queue-4.19/iommu-iova-fix-compilation-error-with-config_iommu_iova.patch [new file with mode: 0644]
queue-4.19/iommu-vt-d-don-t-queue_iova-if-there-is-no-flush-queue.patch [new file with mode: 0644]
queue-4.19/series

diff --git a/queue-4.19/iommu-iova-fix-compilation-error-with-config_iommu_iova.patch b/queue-4.19/iommu-iova-fix-compilation-error-with-config_iommu_iova.patch
new file mode 100644 (file)
index 0000000..aa69397
--- /dev/null
@@ -0,0 +1,32 @@
+From 201c1db90cd643282185a00770f12f95da330eca Mon Sep 17 00:00:00 2001
+From: Joerg Roedel <jroedel@suse.de>
+Date: Tue, 23 Jul 2019 09:51:00 +0200
+Subject: iommu/iova: Fix compilation error with !CONFIG_IOMMU_IOVA
+
+From: Joerg Roedel <jroedel@suse.de>
+
+commit 201c1db90cd643282185a00770f12f95da330eca upstream.
+
+The stub function for !CONFIG_IOMMU_IOVA needs to be
+'static inline'.
+
+Fixes: effa467870c76 ('iommu/vt-d: Don't queue_iova() if there is no flush queue')
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Dmitry Safonov <dima@arista.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/iova.h |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/include/linux/iova.h
++++ b/include/linux/iova.h
+@@ -237,7 +237,7 @@ static inline void init_iova_domain(stru
+ {
+ }
+-bool has_iova_flush_queue(struct iova_domain *iovad)
++static inline bool has_iova_flush_queue(struct iova_domain *iovad)
+ {
+       return false;
+ }
diff --git a/queue-4.19/iommu-vt-d-don-t-queue_iova-if-there-is-no-flush-queue.patch b/queue-4.19/iommu-vt-d-don-t-queue_iova-if-there-is-no-flush-queue.patch
new file mode 100644 (file)
index 0000000..95187bc
--- /dev/null
@@ -0,0 +1,186 @@
+From effa467870c7612012885df4e246bdb8ffd8e44c Mon Sep 17 00:00:00 2001
+From: Dmitry Safonov <dima@arista.com>
+Date: Tue, 16 Jul 2019 22:38:05 +0100
+Subject: iommu/vt-d: Don't queue_iova() if there is no flush queue
+
+From: Dmitry Safonov <dima@arista.com>
+
+commit effa467870c7612012885df4e246bdb8ffd8e44c upstream.
+
+Intel VT-d driver was reworked to use common deferred flushing
+implementation. Previously there was one global per-cpu flush queue,
+afterwards - one per domain.
+
+Before deferring a flush, the queue should be allocated and initialized.
+
+Currently only domains with IOMMU_DOMAIN_DMA type initialize their flush
+queue. It's probably worth to init it for static or unmanaged domains
+too, but it may be arguable - I'm leaving it to iommu folks.
+
+Prevent queuing an iova flush if the domain doesn't have a queue.
+The defensive check seems to be worth to keep even if queue would be
+initialized for all kinds of domains. And is easy backportable.
+
+On 4.19.43 stable kernel it has a user-visible effect: previously for
+devices in si domain there were crashes, on sata devices:
+
+ BUG: spinlock bad magic on CPU#6, swapper/0/1
+  lock: 0xffff88844f582008, .magic: 00000000, .owner: <none>/-1, .owner_cpu: 0
+ CPU: 6 PID: 1 Comm: swapper/0 Not tainted 4.19.43 #1
+ Call Trace:
+  <IRQ>
+  dump_stack+0x61/0x7e
+  spin_bug+0x9d/0xa3
+  do_raw_spin_lock+0x22/0x8e
+  _raw_spin_lock_irqsave+0x32/0x3a
+  queue_iova+0x45/0x115
+  intel_unmap+0x107/0x113
+  intel_unmap_sg+0x6b/0x76
+  __ata_qc_complete+0x7f/0x103
+  ata_qc_complete+0x9b/0x26a
+  ata_qc_complete_multiple+0xd0/0xe3
+  ahci_handle_port_interrupt+0x3ee/0x48a
+  ahci_handle_port_intr+0x73/0xa9
+  ahci_single_level_irq_intr+0x40/0x60
+  __handle_irq_event_percpu+0x7f/0x19a
+  handle_irq_event_percpu+0x32/0x72
+  handle_irq_event+0x38/0x56
+  handle_edge_irq+0x102/0x121
+  handle_irq+0x147/0x15c
+  do_IRQ+0x66/0xf2
+  common_interrupt+0xf/0xf
+ RIP: 0010:__do_softirq+0x8c/0x2df
+
+The same for usb devices that use ehci-pci:
+ BUG: spinlock bad magic on CPU#0, swapper/0/1
+  lock: 0xffff88844f402008, .magic: 00000000, .owner: <none>/-1, .owner_cpu: 0
+ CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.19.43 #4
+ Call Trace:
+  <IRQ>
+  dump_stack+0x61/0x7e
+  spin_bug+0x9d/0xa3
+  do_raw_spin_lock+0x22/0x8e
+  _raw_spin_lock_irqsave+0x32/0x3a
+  queue_iova+0x77/0x145
+  intel_unmap+0x107/0x113
+  intel_unmap_page+0xe/0x10
+  usb_hcd_unmap_urb_setup_for_dma+0x53/0x9d
+  usb_hcd_unmap_urb_for_dma+0x17/0x100
+  unmap_urb_for_dma+0x22/0x24
+  __usb_hcd_giveback_urb+0x51/0xc3
+  usb_giveback_urb_bh+0x97/0xde
+  tasklet_action_common.isra.4+0x5f/0xa1
+  tasklet_action+0x2d/0x30
+  __do_softirq+0x138/0x2df
+  irq_exit+0x7d/0x8b
+  smp_apic_timer_interrupt+0x10f/0x151
+  apic_timer_interrupt+0xf/0x20
+  </IRQ>
+ RIP: 0010:_raw_spin_unlock_irqrestore+0x17/0x39
+
+Cc: David Woodhouse <dwmw2@infradead.org>
+Cc: Joerg Roedel <joro@8bytes.org>
+Cc: Lu Baolu <baolu.lu@linux.intel.com>
+Cc: iommu@lists.linux-foundation.org
+Cc: <stable@vger.kernel.org> # 4.14+
+Fixes: 13cf01744608 ("iommu/vt-d: Make use of iova deferred flushing")
+Signed-off-by: Dmitry Safonov <dima@arista.com>
+Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+[v4.14-port notes:
+o minor conflict with untrusted IOMMU devices check under if-condition]
+Signed-off-by: Dmitry Safonov <dima@arista.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/intel-iommu.c |    2 +-
+ drivers/iommu/iova.c        |   18 ++++++++++++++----
+ include/linux/iova.h        |    6 ++++++
+ 3 files changed, 21 insertions(+), 5 deletions(-)
+
+--- a/drivers/iommu/intel-iommu.c
++++ b/drivers/iommu/intel-iommu.c
+@@ -3721,7 +3721,7 @@ static void intel_unmap(struct device *d
+       freelist = domain_unmap(domain, start_pfn, last_pfn);
+-      if (intel_iommu_strict) {
++      if (intel_iommu_strict || !has_iova_flush_queue(&domain->iovad)) {
+               iommu_flush_iotlb_psi(iommu, domain, start_pfn,
+                                     nrpages, !freelist, 0);
+               /* free iova */
+--- a/drivers/iommu/iova.c
++++ b/drivers/iommu/iova.c
+@@ -65,9 +65,14 @@ init_iova_domain(struct iova_domain *iov
+ }
+ EXPORT_SYMBOL_GPL(init_iova_domain);
++bool has_iova_flush_queue(struct iova_domain *iovad)
++{
++      return !!iovad->fq;
++}
++
+ static void free_iova_flush_queue(struct iova_domain *iovad)
+ {
+-      if (!iovad->fq)
++      if (!has_iova_flush_queue(iovad))
+               return;
+       if (timer_pending(&iovad->fq_timer))
+@@ -85,13 +90,14 @@ static void free_iova_flush_queue(struct
+ int init_iova_flush_queue(struct iova_domain *iovad,
+                         iova_flush_cb flush_cb, iova_entry_dtor entry_dtor)
+ {
++      struct iova_fq __percpu *queue;
+       int cpu;
+       atomic64_set(&iovad->fq_flush_start_cnt,  0);
+       atomic64_set(&iovad->fq_flush_finish_cnt, 0);
+-      iovad->fq = alloc_percpu(struct iova_fq);
+-      if (!iovad->fq)
++      queue = alloc_percpu(struct iova_fq);
++      if (!queue)
+               return -ENOMEM;
+       iovad->flush_cb   = flush_cb;
+@@ -100,13 +106,17 @@ int init_iova_flush_queue(struct iova_do
+       for_each_possible_cpu(cpu) {
+               struct iova_fq *fq;
+-              fq = per_cpu_ptr(iovad->fq, cpu);
++              fq = per_cpu_ptr(queue, cpu);
+               fq->head = 0;
+               fq->tail = 0;
+               spin_lock_init(&fq->lock);
+       }
++      smp_wmb();
++
++      iovad->fq = queue;
++
+       timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
+       atomic_set(&iovad->fq_timer_on, 0);
+--- a/include/linux/iova.h
++++ b/include/linux/iova.h
+@@ -156,6 +156,7 @@ struct iova *reserve_iova(struct iova_do
+ void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
+ void init_iova_domain(struct iova_domain *iovad, unsigned long granule,
+       unsigned long start_pfn);
++bool has_iova_flush_queue(struct iova_domain *iovad);
+ int init_iova_flush_queue(struct iova_domain *iovad,
+                         iova_flush_cb flush_cb, iova_entry_dtor entry_dtor);
+ struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
+@@ -236,6 +237,11 @@ static inline void init_iova_domain(stru
+ {
+ }
++bool has_iova_flush_queue(struct iova_domain *iovad)
++{
++      return false;
++}
++
+ static inline int init_iova_flush_queue(struct iova_domain *iovad,
+                                       iova_flush_cb flush_cb,
+                                       iova_entry_dtor entry_dtor)
index 8ca4274534674e16ed45cb1992afae5a5af38541..e9b49af329b7c2d5e5590f7a36d13f0a69e30315 100644 (file)
@@ -14,3 +14,5 @@ media-cpia2_usb-first-wake-up-then-free-in-disconnect.patch
 media-pvrusb2-use-a-different-format-for-warnings.patch
 nfs-cleanup-if-nfs_match_client-is-interrupted.patch
 media-radio-raremono-change-devm_k-alloc-to-k-alloc.patch
+iommu-vt-d-don-t-queue_iova-if-there-is-no-flush-queue.patch
+iommu-iova-fix-compilation-error-with-config_iommu_iova.patch