aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2010-08-09 08:25:12 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2010-08-09 08:25:12 -0500
commitf040236cd549ff0546b846d162c50557a76a7ec3 (patch)
tree6bde7b9dbb3dadf73b3faf27a612fa16f784d4bb /hw
parenta523eb06ec3fb2f4f4f4d362bb23704811d11379 (diff)
parent953844d102f5b682f0835f021f2ed2ad9fb7734c (diff)
downloadqemu-f040236cd549ff0546b846d162c50557a76a7ec3.zip
qemu-f040236cd549ff0546b846d162c50557a76a7ec3.tar.gz
qemu-f040236cd549ff0546b846d162c50557a76a7ec3.tar.bz2
Merge remote branch 'kwolf/for-anthony' into staging
Diffstat (limited to 'hw')
-rw-r--r--hw/ide/pci.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 4331d77..ec90f26 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -40,8 +40,27 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
printf("%s: 0x%08x\n", __func__, val);
#endif
if (!(val & BM_CMD_START)) {
- /* XXX: do it better */
- ide_dma_cancel(bm);
+ /*
+ * We can't cancel Scatter Gather DMA in the middle of the
+ * operation or a partial (not full) DMA transfer would reach
+ * the storage so we wait for completion instead (we beahve
+ * like if the DMA was completed by the time the guest trying
+ * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
+ * set).
+ *
+ * In the future we'll be able to safely cancel the I/O if the
+ * whole DMA operation will be submitted to disk with a single
+ * aio operation with preadv/pwritev.
+ */
+ if (bm->aiocb) {
+ qemu_aio_flush();
+#ifdef DEBUG_IDE
+ if (bm->aiocb)
+ printf("ide_dma_cancel: aiocb still pending");
+ if (bm->status & BM_STATUS_DMAING)
+ printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
+#endif
+ }
bm->cmd = val & 0x09;
} else {
if (!(bm->status & BM_STATUS_DMAING)) {