4 * Copyright (c) 2009 Red Hat
6 * This work is licensed under the terms of the GNU General Public License
7 * (GNU GPL), version 2 or later.
11 #include "block_int.h"
13 void qemu_sglist_init(QEMUSGList
*qsg
, int alloc_hint
)
15 qsg
->sg
= g_malloc(alloc_hint
* sizeof(ScatterGatherEntry
));
17 qsg
->nalloc
= alloc_hint
;
21 void qemu_sglist_add(QEMUSGList
*qsg
, dma_addr_t base
, dma_addr_t len
)
23 if (qsg
->nsg
== qsg
->nalloc
) {
24 qsg
->nalloc
= 2 * qsg
->nalloc
+ 1;
25 qsg
->sg
= g_realloc(qsg
->sg
, qsg
->nalloc
* sizeof(ScatterGatherEntry
));
27 qsg
->sg
[qsg
->nsg
].base
= base
;
28 qsg
->sg
[qsg
->nsg
].len
= len
;
33 void qemu_sglist_destroy(QEMUSGList
*qsg
)
39 BlockDriverAIOCB common
;
41 BlockDriverAIOCB
*acb
;
47 dma_addr_t sg_cur_byte
;
53 static void dma_bdrv_cb(void *opaque
, int ret
);
55 static void reschedule_dma(void *opaque
)
57 DMAAIOCB
*dbs
= (DMAAIOCB
*)opaque
;
59 qemu_bh_delete(dbs
->bh
);
64 static void continue_after_map_failure(void *opaque
)
66 DMAAIOCB
*dbs
= (DMAAIOCB
*)opaque
;
68 dbs
->bh
= qemu_bh_new(reschedule_dma
, dbs
);
69 qemu_bh_schedule(dbs
->bh
);
72 static void dma_bdrv_unmap(DMAAIOCB
*dbs
)
76 for (i
= 0; i
< dbs
->iov
.niov
; ++i
) {
77 cpu_physical_memory_unmap(dbs
->iov
.iov
[i
].iov_base
,
78 dbs
->iov
.iov
[i
].iov_len
, !dbs
->to_dev
,
79 dbs
->iov
.iov
[i
].iov_len
);
81 qemu_iovec_reset(&dbs
->iov
);
84 static void dma_complete(DMAAIOCB
*dbs
, int ret
)
88 dbs
->common
.cb(dbs
->common
.opaque
, ret
);
90 qemu_iovec_destroy(&dbs
->iov
);
92 qemu_bh_delete(dbs
->bh
);
95 if (!dbs
->in_cancel
) {
96 /* Requests may complete while dma_aio_cancel is in progress. In
97 * this case, the AIOCB should not be released because it is still
98 * referenced by dma_aio_cancel. */
99 qemu_aio_release(dbs
);
103 static void dma_bdrv_cb(void *opaque
, int ret
)
105 DMAAIOCB
*dbs
= (DMAAIOCB
*)opaque
;
106 target_phys_addr_t cur_addr
, cur_len
;
110 dbs
->sector_num
+= dbs
->iov
.size
/ 512;
113 if (dbs
->sg_cur_index
== dbs
->sg
->nsg
|| ret
< 0) {
114 dma_complete(dbs
, ret
);
118 while (dbs
->sg_cur_index
< dbs
->sg
->nsg
) {
119 cur_addr
= dbs
->sg
->sg
[dbs
->sg_cur_index
].base
+ dbs
->sg_cur_byte
;
120 cur_len
= dbs
->sg
->sg
[dbs
->sg_cur_index
].len
- dbs
->sg_cur_byte
;
121 mem
= cpu_physical_memory_map(cur_addr
, &cur_len
, !dbs
->to_dev
);
124 qemu_iovec_add(&dbs
->iov
, mem
, cur_len
);
125 dbs
->sg_cur_byte
+= cur_len
;
126 if (dbs
->sg_cur_byte
== dbs
->sg
->sg
[dbs
->sg_cur_index
].len
) {
127 dbs
->sg_cur_byte
= 0;
132 if (dbs
->iov
.size
== 0) {
133 cpu_register_map_client(dbs
, continue_after_map_failure
);
137 dbs
->acb
= dbs
->io_func(dbs
->bs
, dbs
->sector_num
, &dbs
->iov
,
138 dbs
->iov
.size
/ 512, dma_bdrv_cb
, dbs
);
140 dma_complete(dbs
, -EIO
);
144 static void dma_aio_cancel(BlockDriverAIOCB
*acb
)
146 DMAAIOCB
*dbs
= container_of(acb
, DMAAIOCB
, common
);
149 BlockDriverAIOCB
*acb
= dbs
->acb
;
151 dbs
->in_cancel
= true;
152 bdrv_aio_cancel(acb
);
153 dbs
->in_cancel
= false;
155 dbs
->common
.cb
= NULL
;
156 dma_complete(dbs
, 0);
159 static AIOPool dma_aio_pool
= {
160 .aiocb_size
= sizeof(DMAAIOCB
),
161 .cancel
= dma_aio_cancel
,
164 BlockDriverAIOCB
*dma_bdrv_io(
165 BlockDriverState
*bs
, QEMUSGList
*sg
, uint64_t sector_num
,
166 DMAIOFunc
*io_func
, BlockDriverCompletionFunc
*cb
,
167 void *opaque
, bool to_dev
)
169 DMAAIOCB
*dbs
= qemu_aio_get(&dma_aio_pool
, bs
, cb
, opaque
);
174 dbs
->sector_num
= sector_num
;
175 dbs
->sg_cur_index
= 0;
176 dbs
->sg_cur_byte
= 0;
177 dbs
->to_dev
= to_dev
;
178 dbs
->io_func
= io_func
;
180 qemu_iovec_init(&dbs
->iov
, sg
->nsg
);
186 BlockDriverAIOCB
*dma_bdrv_read(BlockDriverState
*bs
,
187 QEMUSGList
*sg
, uint64_t sector
,
188 void (*cb
)(void *opaque
, int ret
), void *opaque
)
190 return dma_bdrv_io(bs
, sg
, sector
, bdrv_aio_readv
, cb
, opaque
, false);
193 BlockDriverAIOCB
*dma_bdrv_write(BlockDriverState
*bs
,
194 QEMUSGList
*sg
, uint64_t sector
,
195 void (*cb
)(void *opaque
, int ret
), void *opaque
)
197 return dma_bdrv_io(bs
, sg
, sector
, bdrv_aio_writev
, cb
, opaque
, true);