aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/ide.c22
-rw-r--r--hw/scsi-disk.c21
-rw-r--r--hw/virtio-blk.c20
3 files changed, 54 insertions, 9 deletions
diff --git a/hw/ide.c b/hw/ide.c
index 1e56786f18..2eea43835c 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -501,6 +501,7 @@ typedef struct BMDMAState {
QEMUIOVector qiov;
int64_t sector_num;
uint32_t nsector;
+ QEMUBH *bh;
} BMDMAState;
typedef struct PCIIDEState {
@@ -1109,11 +1110,13 @@ static void ide_sector_write(IDEState *s)
}
}
-static void ide_dma_restart_cb(void *opaque, int running, int reason)
+static void ide_dma_restart_bh(void *opaque)
{
BMDMAState *bm = opaque;
- if (!running)
- return;
+
+ qemu_bh_delete(bm->bh);
+ bm->bh = NULL;
+
if (bm->status & BM_STATUS_DMA_RETRY) {
bm->status &= ~BM_STATUS_DMA_RETRY;
ide_dma_restart(bm->ide_if);
@@ -1123,6 +1126,19 @@ static void ide_dma_restart_cb(void *opaque, int running, int reason)
}
}
+static void ide_dma_restart_cb(void *opaque, int running, int reason)
+{
+ BMDMAState *bm = opaque;
+
+ if (!running)
+ return;
+
+ if (!bm->bh) {
+ bm->bh = qemu_bh_new(ide_dma_restart_bh, bm);
+ qemu_bh_schedule(bm->bh);
+ }
+}
+
static void ide_write_dma_cb(void *opaque, int ret)
{
BMDMAState *bm = opaque;
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 8b6426fd8c..5b825c9f79 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -74,6 +74,7 @@ struct SCSIDeviceState
scsi_completionfn completion;
void *opaque;
char drive_serial_str[21];
+ QEMUBH *bh;
};
/* Global pool of SCSIRequest structures. */
@@ -308,12 +309,13 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
return 0;
}
-static void scsi_dma_restart_cb(void *opaque, int running, int reason)
+static void scsi_dma_restart_bh(void *opaque)
{
SCSIDeviceState *s = opaque;
SCSIRequest *r = s->requests;
- if (!running)
- return;
+
+ qemu_bh_delete(s->bh);
+ s->bh = NULL;
while (r) {
if (r->status & SCSI_REQ_STATUS_RETRY) {
@@ -324,6 +326,19 @@ static void scsi_dma_restart_cb(void *opaque, int running, int reason)
}
}
+static void scsi_dma_restart_cb(void *opaque, int running, int reason)
+{
+ SCSIDeviceState *s = opaque;
+
+ if (!running)
+ return;
+
+ if (!s->bh) {
+ s->bh = qemu_bh_new(scsi_dma_restart_bh, s);
+ qemu_bh_schedule(s->bh);
+ }
+}
+
/* Return a pointer to the data buffer. */
static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
{
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 2beff5224a..5036b5b024 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -26,6 +26,7 @@ typedef struct VirtIOBlock
VirtQueue *vq;
void *rq;
char serial_str[BLOCK_SERIAL_STRLEN + 1];
+ QEMUBH *bh;
} VirtIOBlock;
static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
@@ -302,13 +303,13 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
*/
}
-static void virtio_blk_dma_restart_cb(void *opaque, int running, int reason)
+static void virtio_blk_dma_restart_bh(void *opaque)
{
VirtIOBlock *s = opaque;
VirtIOBlockReq *req = s->rq;
- if (!running)
- return;
+ qemu_bh_delete(s->bh);
+ s->bh = NULL;
s->rq = NULL;
@@ -318,6 +319,19 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running, int reason)
}
}
+static void virtio_blk_dma_restart_cb(void *opaque, int running, int reason)
+{
+ VirtIOBlock *s = opaque;
+
+ if (!running)
+ return;
+
+ if (!s->bh) {
+ s->bh = qemu_bh_new(virtio_blk_dma_restart_bh, s);
+ qemu_bh_schedule(s->bh);
+ }
+}
+
static void virtio_blk_reset(VirtIODevice *vdev)
{
/*