* (GNU GPL), version 2 or later.
*/
+#include "qemu/osdep.h"
+#include "sysemu/block-backend.h"
#include "sysemu/dma.h"
#include "trace.h"
-#include "qemu/range.h"
#include "qemu/thread.h"
#include "qemu/main-loop.h"
memset(fillbuf, c, FILLBUF_SIZE);
while (len > 0) {
l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE;
- error |= address_space_rw(as, addr, fillbuf, l, true);
+ error |= address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED,
+ fillbuf, l, true);
len -= l;
addr += l;
}
}
typedef struct {
- BlockDriverAIOCB common;
- BlockDriverState *bs;
- BlockDriverAIOCB *acb;
+ BlockAIOCB common;
+ BlockBackend *blk;
+ BlockAIOCB *acb;
QEMUSGList *sg;
uint64_t sector_num;
DMADirection dir;
- bool in_cancel;
int sg_cur_index;
dma_addr_t sg_cur_byte;
QEMUIOVector iov;
DMAIOFunc *io_func;
} DMAAIOCB;
-static void dma_bdrv_cb(void *opaque, int ret);
+static void dma_blk_cb(void *opaque, int ret);
static void reschedule_dma(void *opaque)
{
qemu_bh_delete(dbs->bh);
dbs->bh = NULL;
- dma_bdrv_cb(dbs, 0);
+ dma_blk_cb(dbs, 0);
}
-static void continue_after_map_failure(void *opaque)
-{
- DMAAIOCB *dbs = (DMAAIOCB *)opaque;
-
- dbs->bh = qemu_bh_new(reschedule_dma, dbs);
- qemu_bh_schedule(dbs->bh);
-}
-
-static void dma_bdrv_unmap(DMAAIOCB *dbs)
+static void dma_blk_unmap(DMAAIOCB *dbs)
{
int i;
{
trace_dma_complete(dbs, ret, dbs->common.cb);
- dma_bdrv_unmap(dbs);
+ dma_blk_unmap(dbs);
if (dbs->common.cb) {
dbs->common.cb(dbs->common.opaque, ret);
}
qemu_bh_delete(dbs->bh);
dbs->bh = NULL;
}
- if (!dbs->in_cancel) {
- /* Requests may complete while dma_aio_cancel is in progress. In
- * this case, the AIOCB should not be released because it is still
- * referenced by dma_aio_cancel. */
- qemu_aio_release(dbs);
- }
+ qemu_aio_unref(dbs);
}
-static void dma_bdrv_cb(void *opaque, int ret)
+static void dma_blk_cb(void *opaque, int ret)
{
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
dma_addr_t cur_addr, cur_len;
void *mem;
- trace_dma_bdrv_cb(dbs, ret);
+ trace_dma_blk_cb(dbs, ret);
dbs->acb = NULL;
dbs->sector_num += dbs->iov.size / 512;
- dma_bdrv_unmap(dbs);
if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
dma_complete(dbs, ret);
return;
}
+ dma_blk_unmap(dbs);
while (dbs->sg_cur_index < dbs->sg->nsg) {
cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte;
if (dbs->iov.size == 0) {
trace_dma_map_wait(dbs);
- cpu_register_map_client(dbs, continue_after_map_failure);
+ dbs->bh = aio_bh_new(blk_get_aio_context(dbs->blk),
+ reschedule_dma, dbs);
+ cpu_register_map_client(dbs->bh);
return;
}
- dbs->acb = dbs->io_func(dbs->bs, dbs->sector_num, &dbs->iov,
- dbs->iov.size / 512, dma_bdrv_cb, dbs);
+ if (dbs->iov.size & ~BDRV_SECTOR_MASK) {
+ qemu_iovec_discard_back(&dbs->iov, dbs->iov.size & ~BDRV_SECTOR_MASK);
+ }
+
+ dbs->acb = dbs->io_func(dbs->blk, dbs->sector_num, &dbs->iov,
+ dbs->iov.size / 512, dma_blk_cb, dbs);
assert(dbs->acb);
}
-static void dma_aio_cancel(BlockDriverAIOCB *acb)
+static void dma_aio_cancel(BlockAIOCB *acb)
{
DMAAIOCB *dbs = container_of(acb, DMAAIOCB, common);
trace_dma_aio_cancel(dbs);
if (dbs->acb) {
- BlockDriverAIOCB *acb = dbs->acb;
- dbs->acb = NULL;
- dbs->in_cancel = true;
- bdrv_aio_cancel(acb);
- dbs->in_cancel = false;
+ blk_aio_cancel_async(dbs->acb);
+ }
+ if (dbs->bh) {
+ cpu_unregister_map_client(dbs->bh);
+ qemu_bh_delete(dbs->bh);
+ dbs->bh = NULL;
}
- dbs->common.cb = NULL;
- dma_complete(dbs, 0);
}
+
static const AIOCBInfo dma_aiocb_info = {
.aiocb_size = sizeof(DMAAIOCB),
- .cancel = dma_aio_cancel,
+ .cancel_async = dma_aio_cancel,
};
-BlockDriverAIOCB *dma_bdrv_io(
- BlockDriverState *bs, QEMUSGList *sg, uint64_t sector_num,
- DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
+BlockAIOCB *dma_blk_io(
+ BlockBackend *blk, QEMUSGList *sg, uint64_t sector_num,
+ DMAIOFunc *io_func, BlockCompletionFunc *cb,
void *opaque, DMADirection dir)
{
- DMAAIOCB *dbs = qemu_aio_get(&dma_aiocb_info, bs, cb, opaque);
+ DMAAIOCB *dbs = blk_aio_get(&dma_aiocb_info, blk, cb, opaque);
- trace_dma_bdrv_io(dbs, bs, sector_num, (dir == DMA_DIRECTION_TO_DEVICE));
+ trace_dma_blk_io(dbs, blk, sector_num, (dir == DMA_DIRECTION_TO_DEVICE));
dbs->acb = NULL;
- dbs->bs = bs;
+ dbs->blk = blk;
dbs->sg = sg;
dbs->sector_num = sector_num;
dbs->sg_cur_index = 0;
dbs->io_func = io_func;
dbs->bh = NULL;
qemu_iovec_init(&dbs->iov, sg->nsg);
- dma_bdrv_cb(dbs, 0);
+ dma_blk_cb(dbs, 0);
return &dbs->common;
}
-BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
- QEMUSGList *sg, uint64_t sector,
- void (*cb)(void *opaque, int ret), void *opaque)
+BlockAIOCB *dma_blk_read(BlockBackend *blk,
+ QEMUSGList *sg, uint64_t sector,
+ void (*cb)(void *opaque, int ret), void *opaque)
{
- return dma_bdrv_io(bs, sg, sector, bdrv_aio_readv, cb, opaque,
- DMA_DIRECTION_FROM_DEVICE);
+ return dma_blk_io(blk, sg, sector, blk_aio_readv, cb, opaque,
+ DMA_DIRECTION_FROM_DEVICE);
}
-BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
- QEMUSGList *sg, uint64_t sector,
- void (*cb)(void *opaque, int ret), void *opaque)
+BlockAIOCB *dma_blk_write(BlockBackend *blk,
+ QEMUSGList *sg, uint64_t sector,
+ void (*cb)(void *opaque, int ret), void *opaque)
{
- return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque,
- DMA_DIRECTION_TO_DEVICE);
+ return dma_blk_io(blk, sg, sector, blk_aio_writev, cb, opaque,
+ DMA_DIRECTION_TO_DEVICE);
}
return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_TO_DEVICE);
}
-void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie,
+void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
QEMUSGList *sg, enum BlockAcctType type)
{
- bdrv_acct_start(bs, cookie, sg->size, type);
+ block_acct_start(blk_get_stats(blk), cookie, sg->size, type);
}