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:
parent
67403dbba7
commit
acae6f1c4c
10
hw/dma.c
10
hw/dma.c
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user