All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Dāvis Mosāns" <davispuh@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: "Vinod Koul" <vkoul@kernel.org>,
	dmaengine@vger.kernel.org, "Dāvis Mosāns" <davispuh@gmail.com>
Subject: [PATCH v2] dmaengine: fix async channel removal for dma_issue_pending_all
Date: Tue, 22 Feb 2022 03:53:26 +0200	[thread overview]
Message-ID: <20220222015325.14245-1-davispuh@gmail.com> (raw)
In-Reply-To: <20220217205147.35586-1-davispuh@gmail.com>

dma channels can be removed asynchronously while we iterate over them.
Without this various crashes can happen in dma_issue_pending_all.

One such example:

kernel: BUG: kernel NULL pointer dereference, address: 0000000000000018
kernel: #PF: supervisor read access in kernel mode
kernel: #PF: error_code(0x0000) - not-present page
kernel: PGD 0 P4D 0
kernel: Oops: 0000 [#1] PREEMPT SMP NOPTI
kernel: RIP: 0010:dma_issue_pending_all (drivers/dma/dmaengine.c:562)
All code
========
   0:   48 8b 45 20             mov    0x20(%rbp),%rax
   4:   48 8d 68 e0             lea    -0x20(%rax),%rbp
   8:   48 3d 60 36 35 bc       cmp    $0xffffffffbc353660,%rax
   e:   74 4d                   je     0x5d
  10:   48 8b 45 48             mov    0x48(%rbp),%rax
  14:   f6 c4 02                test   $0x2,%ah
  17:   75 e7                   jne    0x0
  19:   48 8b 45 10             mov    0x10(%rbp),%rax
  1d:   4c 8d 65 10             lea    0x10(%rbp),%r12
  21:   48 8d 58 c8             lea    -0x38(%rax),%rbx
  25:   49 39 c4                cmp    %rax,%r12
  28:   74 d6                   je     0x0
  2a:*  8b 43 50                mov    0x50(%rbx),%eax          <-- trapping instruction
  2d:   85 c0                   test   %eax,%eax
  2f:   74 0f                   je     0x40
  31:   48 8b 85 88 01 00 00    mov    0x188(%rbp),%rax
  38:   48 89 df                mov    %rbx,%rdi
  3b:   0f ae e8                lfence
  3e:   ff d0                   call   *%rax

kernel: RSP: 0018:ffffbc5004897de8 EFLAGS: 00010282
kernel: RAX: 0000000000000000 RBX: ffffffffffffffc8 RCX: 0000000000000000
kernel: RDX: ffff9c2300e36a28 RSI: 0000000000000202 RDI: ffff9c2300e36a10
kernel: RBP: ffff9c24473a3970 R08: 0000000000000001 R09: 0000000000000000
kernel: R10: ffff9c23ab165ea9 R11: 0000000000000000 R12: ffff9c24473a3980
kernel: R13: ffff9c2367bca000 R14: ffff9c23112ae000 R15: 0000000000000000
kernel: FS:  0000000000000000(0000) GS:ffff9c2a5d500000(0000) knlGS:0000000000000000
kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
kernel: CR2: 0000000000000018 CR3: 0000000700d0a000 CR4: 00000000003506e0
kernel: Call Trace:
kernel:  <TASK>
kernel: raid5d (drivers/md/raid5.c:6563) raid456
kernel: ? schedule (arch/x86/include/asm/preempt.h:85 (discriminator 1) kernel/sched/core.c:6370 (discriminator 1))
kernel: md_thread (drivers/md/md.c:7923) md_mod
kernel: ? do_wait_intr (kernel/sched/wait.c:415)
kernel: ? md_submit_bio (drivers/md/md.c:7887) md_mod
kernel: kthread (kernel/kthread.c:377)
kernel: ? kthread_complete_and_exit (kernel/kthread.c:332)
kernel: ret_from_fork (arch/x86/entry/entry_64.S:301)
kernel:  </TASK>

Signed-off-by: Dāvis Mosāns <davispuh@gmail.com>
---
 drivers/dma/dmaengine.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 2cfa8458b51be..fe53a507a8f95 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -360,7 +360,7 @@ static struct dma_chan *min_chan(enum dma_transaction_type cap, int cpu)
  */
 static void dma_channel_rebalance(void)
 {
-	struct dma_chan *chan;
+	struct dma_chan *chan, *n;
 	struct dma_device *device;
 	int cpu;
 	int cap;
@@ -373,7 +373,7 @@ static void dma_channel_rebalance(void)
 	list_for_each_entry(device, &dma_device_list, global_node) {
 		if (dma_has_cap(DMA_PRIVATE, device->cap_mask))
 			continue;
-		list_for_each_entry(chan, &device->channels, device_node)
+		list_for_each_entry_safe(chan, n, &device->channels, device_node)
 			chan->table_count = 0;
 	}
 
@@ -552,18 +552,18 @@ EXPORT_SYMBOL(dma_find_channel);
  */
 void dma_issue_pending_all(void)
 {
-	struct dma_device *device;
-	struct dma_chan *chan;
+	struct dma_device *device, *_d;
+	struct dma_chan *chan, *n;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(device, &dma_device_list, global_node) {
+	mutex_lock(&dma_list_mutex);
+	list_for_each_entry_safe(device, _d, &dma_device_list, global_node) {
 		if (dma_has_cap(DMA_PRIVATE, device->cap_mask))
 			continue;
-		list_for_each_entry(chan, &device->channels, device_node)
+		list_for_each_entry_safe(chan, n, &device->channels, device_node)
 			if (chan->client_count)
 				device->device_issue_pending(chan);
 	}
-	rcu_read_unlock();
+	mutex_unlock(&dma_list_mutex);
 }
 EXPORT_SYMBOL(dma_issue_pending_all);
 
-- 
2.35.1


      reply	other threads:[~2022-02-22  1:55 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-17 20:51 [PATCH] dmaengine: fix dma_issue_pending_all to work with async channel removal Dāvis Mosāns
2022-02-22  1:53 ` Dāvis Mosāns [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220222015325.14245-1-davispuh@gmail.com \
    --to=davispuh@gmail.com \
    --cc=dmaengine@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=vkoul@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.