diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2015-02-16 14:08:22 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-09-09 15:34:53 +0200 |
commit | 19d2b5e6ff7202c2bf45c547efa85ae6c2d76bbd (patch) | |
tree | 84d9d315b0307a886ee6df399c2450caf790bd23 /hw/dma | |
parent | 5f5b5942d56a138baad0ae01458d5d0e62d5be68 (diff) |
i8257: rewrite DMA_schedule to avoid hooking into the CPU loop
The i8257 DMA controller uses an idle bottom half, which by default
does not cause the main loop to exit. Therefore, the DMA_schedule
function is there to ensure that the CPU relinquishes the iothread
mutex to the iothread.
However, this is not enough since the iothread will call
aio_compute_timeout() and go to sleep again. In the iothread
world, forcing execution of the idle bottom half is much simpler,
and only requires a call to qemu_notify_event(). Do it, removing
the need for the "cpu_request_exit" pseudo-irq. The next patch
will remove it.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/dma')
-rw-r--r-- | hw/dma/i8257.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/hw/dma/i8257.c b/hw/dma/i8257.c index a414029bea..409ba7d01f 100644 --- a/hw/dma/i8257.c +++ b/hw/dma/i8257.c @@ -358,6 +358,7 @@ static void channel_run (int ncont, int ichan) } static QEMUBH *dma_bh; +static bool dma_bh_scheduled; static void DMA_run (void) { @@ -390,12 +391,15 @@ static void DMA_run (void) running = 0; out: - if (rearm) + if (rearm) { qemu_bh_schedule_idle(dma_bh); + dma_bh_scheduled = true; + } } static void DMA_run_bh(void *unused) { + dma_bh_scheduled = false; DMA_run(); } @@ -458,12 +462,14 @@ int DMA_write_memory (int nchan, void *buf, int pos, int len) return len; } -/* request the emulator to transfer a new DMA memory block ASAP */ -void DMA_schedule(int nchan) +/* request the emulator to transfer a new DMA memory block ASAP (even + * if the idle bottom half would not have exited the iothread yet). + */ +void DMA_schedule(void) { - struct dma_cont *d = &dma_controllers[nchan > 3]; - - qemu_irq_pulse(*d->cpu_request_exit); + if (dma_bh_scheduled) { + qemu_notify_event(); + } } static void dma_reset(void *opaque) |