6f9d9cf
From 86f1e4e2f57af82aae0944ed704ab91dc36fc9b7 Mon Sep 17 00:00:00 2001
6f9d9cf
From: Kevin Wolf <kwolf@redhat.com>
6f9d9cf
Date: Fri, 28 Oct 2011 05:28:13 -0400
6f9d9cf
Subject: [PATCH 2/2] dma: Avoid reentrancy in DMA transfer handlers
6f9d9cf
6f9d9cf
With the conversion of the block layer to coroutines, bdrv_read/write
6f9d9cf
have changed to run a nested event loop that calls qemu_bh_poll.
6f9d9cf
Consequently a scheduled BH can be called while a DMA transfer handler
6f9d9cf
runs and this means that DMA_run becomes reentrant.
6f9d9cf
6f9d9cf
Devices haven't been designed to cope with that, so instead of running a
6f9d9cf
nested transfer handler just wait for the next invocation of the BH from the
6f9d9cf
main loop.
6f9d9cf
6f9d9cf
This fixes some problems with the floppy device.
6f9d9cf
6f9d9cf
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6f9d9cf
---
6f9d9cf
 hw/dma.c |   10 ++++++++++
6f9d9cf
 1 files changed, 10 insertions(+), 0 deletions(-)
6f9d9cf
6f9d9cf
diff --git a/hw/dma.c b/hw/dma.c
6f9d9cf
index 8a7302a..0a9322d 100644
6f9d9cf
--- a/hw/dma.c
6f9d9cf
+++ b/hw/dma.c
6f9d9cf
@@ -358,6 +358,14 @@ static void DMA_run (void)
6f9d9cf
     struct dma_cont *d;
6f9d9cf
     int icont, ichan;
6f9d9cf
     int rearm = 0;
6f9d9cf
+    static int running = 0;
6f9d9cf
+
6f9d9cf
+    if (running) {
6f9d9cf
+        rearm = 1;
6f9d9cf
+        goto out;
6f9d9cf
+    } else {
6f9d9cf
+        running = 1;
6f9d9cf
+    }
6f9d9cf
 
6f9d9cf
     d = dma_controllers;
6f9d9cf
 
6f9d9cf
@@ -374,6 +382,8 @@ static void DMA_run (void)
6f9d9cf
         }
6f9d9cf
     }
6f9d9cf
 
6f9d9cf
+    running = 0;
6f9d9cf
+out:
6f9d9cf
     if (rearm)
6f9d9cf
         qemu_bh_schedule_idle(dma_bh);
6f9d9cf
 }
6f9d9cf
-- 
6f9d9cf
1.7.7.5
6f9d9cf