dma: keep a device alive while it has SGLists
Reviewed-by: Anthony Liguori <aliguori@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
cac3c384bb
commit
f487b677c2
@ -34,13 +34,16 @@ int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, AddressSpace *as)
|
void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint,
|
||||||
|
AddressSpace *as)
|
||||||
{
|
{
|
||||||
qsg->sg = g_malloc(alloc_hint * sizeof(ScatterGatherEntry));
|
qsg->sg = g_malloc(alloc_hint * sizeof(ScatterGatherEntry));
|
||||||
qsg->nsg = 0;
|
qsg->nsg = 0;
|
||||||
qsg->nalloc = alloc_hint;
|
qsg->nalloc = alloc_hint;
|
||||||
qsg->size = 0;
|
qsg->size = 0;
|
||||||
qsg->as = as;
|
qsg->as = as;
|
||||||
|
qsg->dev = dev;
|
||||||
|
object_ref(OBJECT(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len)
|
void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len)
|
||||||
@ -57,6 +60,7 @@ void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len)
|
|||||||
|
|
||||||
void qemu_sglist_destroy(QEMUSGList *qsg)
|
void qemu_sglist_destroy(QEMUSGList *qsg)
|
||||||
{
|
{
|
||||||
|
object_unref(OBJECT(qsg->dev));
|
||||||
g_free(qsg->sg);
|
g_free(qsg->sg);
|
||||||
memset(qsg, 0, sizeof(*qsg));
|
memset(qsg, 0, sizeof(*qsg));
|
||||||
}
|
}
|
||||||
|
@ -650,6 +650,8 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
|
|||||||
int off_idx = -1;
|
int off_idx = -1;
|
||||||
int off_pos = -1;
|
int off_pos = -1;
|
||||||
int tbl_entry_size;
|
int tbl_entry_size;
|
||||||
|
IDEBus *bus = &ad->port;
|
||||||
|
BusState *qbus = BUS(bus);
|
||||||
|
|
||||||
if (!sglist_alloc_hint) {
|
if (!sglist_alloc_hint) {
|
||||||
DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts);
|
DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts);
|
||||||
@ -691,7 +693,8 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_sglist_init(sglist, (sglist_alloc_hint - off_idx), ad->hba->as);
|
qemu_sglist_init(sglist, qbus->parent, (sglist_alloc_hint - off_idx),
|
||||||
|
ad->hba->as);
|
||||||
qemu_sglist_add(sglist, le64_to_cpu(tbl[off_idx].addr + off_pos),
|
qemu_sglist_add(sglist, le64_to_cpu(tbl[off_idx].addr + off_pos),
|
||||||
le32_to_cpu(tbl[off_idx].flags_size) + 1 - off_pos);
|
le32_to_cpu(tbl[off_idx].flags_size) + 1 - off_pos);
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
|
|||||||
|
|
||||||
s->io_buffer_size = io->len;
|
s->io_buffer_size = io->len;
|
||||||
|
|
||||||
qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1,
|
qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,
|
||||||
&address_space_memory);
|
&address_space_memory);
|
||||||
qemu_sglist_add(&s->sg, io->addr, io->len);
|
qemu_sglist_add(&s->sg, io->addr, io->len);
|
||||||
io->addr += io->len;
|
io->addr += io->len;
|
||||||
@ -127,7 +127,7 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
|
|||||||
s->io_buffer_index = 0;
|
s->io_buffer_index = 0;
|
||||||
s->io_buffer_size = io->len;
|
s->io_buffer_size = io->len;
|
||||||
|
|
||||||
qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1,
|
qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1,
|
||||||
&address_space_memory);
|
&address_space_memory);
|
||||||
qemu_sglist_add(&s->sg, io->addr, io->len);
|
qemu_sglist_add(&s->sg, io->addr, io->len);
|
||||||
io->addr += io->len;
|
io->addr += io->len;
|
||||||
|
@ -77,10 +77,12 @@ static void virtio_scsi_bad_req(void)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg,
|
static void qemu_sgl_init_external(VirtIOSCSIReq *req, struct iovec *sg,
|
||||||
hwaddr *addr, int num)
|
hwaddr *addr, int num)
|
||||||
{
|
{
|
||||||
qemu_sglist_init(qsgl, num, &address_space_memory);
|
QEMUSGList *qsgl = &req->qsgl;
|
||||||
|
|
||||||
|
qemu_sglist_init(qsgl, DEVICE(req->dev), num, &address_space_memory);
|
||||||
while (num--) {
|
while (num--) {
|
||||||
qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len);
|
qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len);
|
||||||
}
|
}
|
||||||
@ -99,11 +101,11 @@ static void virtio_scsi_parse_req(VirtIOSCSI *s, VirtQueue *vq,
|
|||||||
req->resp.buf = req->elem.in_sg[0].iov_base;
|
req->resp.buf = req->elem.in_sg[0].iov_base;
|
||||||
|
|
||||||
if (req->elem.out_num > 1) {
|
if (req->elem.out_num > 1) {
|
||||||
qemu_sgl_init_external(&req->qsgl, &req->elem.out_sg[1],
|
qemu_sgl_init_external(req, &req->elem.out_sg[1],
|
||||||
&req->elem.out_addr[1],
|
&req->elem.out_addr[1],
|
||||||
req->elem.out_num - 1);
|
req->elem.out_num - 1);
|
||||||
} else {
|
} else {
|
||||||
qemu_sgl_init_external(&req->qsgl, &req->elem.in_sg[1],
|
qemu_sgl_init_external(req, &req->elem.in_sg[1],
|
||||||
&req->elem.in_addr[1],
|
&req->elem.in_addr[1],
|
||||||
req->elem.in_num - 1);
|
req->elem.in_num - 1);
|
||||||
}
|
}
|
||||||
|
@ -1241,11 +1241,13 @@ static int ehci_init_transfer(EHCIPacket *p)
|
|||||||
{
|
{
|
||||||
uint32_t cpage, offset, bytes, plen;
|
uint32_t cpage, offset, bytes, plen;
|
||||||
dma_addr_t page;
|
dma_addr_t page;
|
||||||
|
USBBus *bus = &p->queue->ehci->bus;
|
||||||
|
BusState *qbus = BUS(bus);
|
||||||
|
|
||||||
cpage = get_field(p->qtd.token, QTD_TOKEN_CPAGE);
|
cpage = get_field(p->qtd.token, QTD_TOKEN_CPAGE);
|
||||||
bytes = get_field(p->qtd.token, QTD_TOKEN_TBYTES);
|
bytes = get_field(p->qtd.token, QTD_TOKEN_TBYTES);
|
||||||
offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK;
|
offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK;
|
||||||
qemu_sglist_init(&p->sgl, 5, p->queue->ehci->as);
|
qemu_sglist_init(&p->sgl, qbus->parent, 5, p->queue->ehci->as);
|
||||||
|
|
||||||
while (bytes > 0) {
|
while (bytes > 0) {
|
||||||
if (cpage > 4) {
|
if (cpage > 4) {
|
||||||
@ -1484,7 +1486,7 @@ static int ehci_process_itd(EHCIState *ehci,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_sglist_init(&ehci->isgl, 2, ehci->as);
|
qemu_sglist_init(&ehci->isgl, DEVICE(ehci), 2, ehci->as);
|
||||||
if (off + len > 4096) {
|
if (off + len > 4096) {
|
||||||
/* transfer crosses page border */
|
/* transfer crosses page border */
|
||||||
uint32_t len2 = off + len - 4096;
|
uint32_t len2 = off + len - 4096;
|
||||||
|
@ -702,7 +702,7 @@ static inline void pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len,
|
|||||||
static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev,
|
static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev,
|
||||||
int alloc_hint)
|
int alloc_hint)
|
||||||
{
|
{
|
||||||
qemu_sglist_init(qsg, alloc_hint, pci_get_address_space(dev));
|
qemu_sglist_init(qsg, DEVICE(dev), alloc_hint, pci_get_address_space(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const VMStateDescription vmstate_pci_device;
|
extern const VMStateDescription vmstate_pci_device;
|
||||||
|
@ -29,6 +29,7 @@ struct QEMUSGList {
|
|||||||
int nsg;
|
int nsg;
|
||||||
int nalloc;
|
int nalloc;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
DeviceState *dev;
|
||||||
AddressSpace *as;
|
AddressSpace *as;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -189,7 +190,8 @@ struct ScatterGatherEntry {
|
|||||||
dma_addr_t len;
|
dma_addr_t len;
|
||||||
};
|
};
|
||||||
|
|
||||||
void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, AddressSpace *as);
|
void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint,
|
||||||
|
AddressSpace *as);
|
||||||
void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
|
void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
|
||||||
void qemu_sglist_destroy(QEMUSGList *qsg);
|
void qemu_sglist_destroy(QEMUSGList *qsg);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user