dma: Avoid reentrancy in DMA transfer handlers

With the conversion of the block layer to coroutines, bdrv_read/write
have changed to run a nested event loop that calls qemu_bh_poll.
Consequently a scheduled BH can be called while a DMA transfer handler
runs and this means that DMA_run becomes reentrant.

Devices haven't been designed to cope with that, so instead of running a
nested transfer handler just wait for the next invocation of the BH from the
main loop.

This fixes some problems with the floppy device.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Kevin Wolf 2011-10-28 05:28:13 -04:00
parent 67403dbba7
commit acae6f1c4c

View File

@ -358,6 +358,14 @@ static void DMA_run (void)
struct dma_cont *d; struct dma_cont *d;
int icont, ichan; int icont, ichan;
int rearm = 0; int rearm = 0;
static int running = 0;
if (running) {
rearm = 1;
goto out;
} else {
running = 1;
}
d = dma_controllers; d = dma_controllers;
@ -374,6 +382,8 @@ static void DMA_run (void)
} }
} }
running = 0;
out:
if (rearm) if (rearm)
qemu_bh_schedule_idle(dma_bh); qemu_bh_schedule_idle(dma_bh);
} }