From a209f4615c6853a226e847810b6c607c71b6a046 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Tue, 17 Feb 2015 17:55:53 +0800 Subject: virtio-blk: Check return value of blk_aio_ioctl Since commit 1dc936aa84 (virtio-blk: Use blk_aio_ioctl) we silently lose the request if blk_aio_ioctl returns NULL (not implemented). Fix it by directly returning VIRTIO_BLK_S_UNSUPP as we used to do. Signed-off-by: Fam Zheng Reviewed-by: Stefan Hajnoczi [ kwolf: Fixed build error on win32 ] Signed-off-by: Kevin Wolf --- hw/block/virtio-blk.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index cb71772..3ad5fe4 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -201,6 +201,7 @@ static int virtio_blk_handle_scsi_req(VirtIOBlockReq *req) #ifdef __linux__ int i; VirtIOBlockIoctlReq *ioctl_req; + BlockAIOCB *acb; #endif /* @@ -278,8 +279,13 @@ static int virtio_blk_handle_scsi_req(VirtIOBlockReq *req) ioctl_req->hdr.sbp = elem->in_sg[elem->in_num - 3].iov_base; ioctl_req->hdr.mx_sb_len = elem->in_sg[elem->in_num - 3].iov_len; - blk_aio_ioctl(blk->blk, SG_IO, &ioctl_req->hdr, - virtio_blk_ioctl_complete, ioctl_req); + acb = blk_aio_ioctl(blk->blk, SG_IO, &ioctl_req->hdr, + virtio_blk_ioctl_complete, ioctl_req); + if (!acb) { + g_free(ioctl_req); + status = VIRTIO_BLK_S_UNSUPP; + goto fail; + } return -EINPROGRESS; #else abort(); -- cgit v1.1 From 0eb28a42284ec32e6f283985d2d638474a05eba4 Mon Sep 17 00:00:00 2001 From: Ekaterina Tumanova Date: Mon, 16 Feb 2015 12:47:58 +0100 Subject: BlockConf: Call backend functions to detect geometry and blocksizes geometry: hd_geometry_guess function autodetects the drive geometry. This patch adds a block backend call, that probes the backing device geometry. If the inner driver method is implemented and succeeds (currently only for DASDs), the blkconf_geometry will pass-through the backing device geometry. Otherwise will fallback to old logic. blocksize: This patch initializes blocksize properties to 0. In order to set the property a blkconf_blocksizes was introduced. If user didn't set physical or logical blocksize, it will retrieve its value from a driver (only succeeds for DASD), otherwise it will set default 512 value. The blkconf_blocksizes call was added to all users of BlkConf. Signed-off-by: Ekaterina Tumanova Reviewed-by: Markus Armbruster Reviewed-by: Stefan Hajnoczi Message-id: 1424087278-49393-6-git-send-email-tumanova@linux.vnet.ibm.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/block/block.c | 24 ++++++++++++++++++++++++ hw/block/hd-geometry.c | 10 +++++++++- hw/block/nvme.c | 1 + hw/block/virtio-blk.c | 1 + hw/core/qdev-properties.c | 3 ++- hw/ide/qdev.c | 1 + hw/scsi/scsi-disk.c | 2 ++ hw/usb/dev-storage.c | 1 + 8 files changed, 41 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/block/block.c b/hw/block/block.c index a625773..f7243e5 100644 --- a/hw/block/block.c +++ b/hw/block/block.c @@ -25,6 +25,30 @@ void blkconf_serial(BlockConf *conf, char **serial) } } +void blkconf_blocksizes(BlockConf *conf) +{ + BlockBackend *blk = conf->blk; + BlockSizes blocksizes; + int backend_ret; + + backend_ret = blk_probe_blocksizes(blk, &blocksizes); + /* fill in detected values if they are not defined via qemu command line */ + if (!conf->physical_block_size) { + if (!backend_ret) { + conf->physical_block_size = blocksizes.phys; + } else { + conf->physical_block_size = BDRV_SECTOR_SIZE; + } + } + if (!conf->logical_block_size) { + if (!backend_ret) { + conf->logical_block_size = blocksizes.log; + } else { + conf->logical_block_size = BDRV_SECTOR_SIZE; + } + } +} + void blkconf_geometry(BlockConf *conf, int *ptrans, unsigned cyls_max, unsigned heads_max, unsigned secs_max, Error **errp) diff --git a/hw/block/hd-geometry.c b/hw/block/hd-geometry.c index 6fcf74d..b187878 100644 --- a/hw/block/hd-geometry.c +++ b/hw/block/hd-geometry.c @@ -121,8 +121,16 @@ void hd_geometry_guess(BlockBackend *blk, int *ptrans) { int cylinders, heads, secs, translation; + HDGeometry geo; - if (guess_disk_lchs(blk, &cylinders, &heads, &secs) < 0) { + /* Try to probe the backing device geometry, otherwise fallback + to the old logic. (as of 12/2014 probing only succeeds on DASDs) */ + if (blk_probe_geometry(blk, &geo) == 0) { + *pcyls = geo.cylinders; + *psecs = geo.sectors; + *pheads = geo.heads; + translation = BIOS_ATA_TRANSLATION_NONE; + } else if (guess_disk_lchs(blk, &cylinders, &heads, &secs) < 0) { /* no LCHS guess: use a standard physical disk geometry */ guess_chs_for_size(blk, pcyls, pheads, psecs); translation = hd_bios_chs_auto_trans(*pcyls, *pheads, *psecs); diff --git a/hw/block/nvme.c b/hw/block/nvme.c index ce079ae..0f3dfb9 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -765,6 +765,7 @@ static int nvme_init(PCIDevice *pci_dev) if (!n->serial) { return -1; } + blkconf_blocksizes(&n->conf); pci_conf = pci_dev->config; pci_conf[PCI_INTERRUPT_PIN] = 1; diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 3ad5fe4..2acfef8 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -893,6 +893,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) error_propagate(errp, err); return; } + blkconf_blocksizes(&conf->conf); virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK, sizeof(struct virtio_blk_config)); diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 2e47f70..ba81709 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -580,7 +580,8 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque, error_propagate(errp, local_err); return; } - if (value < min || value > max) { + /* value of 0 means "unset" */ + if (value && (value < min || value > max)) { error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, dev->id?:"", name, (int64_t)value, min, max); return; diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index b4103fa..788b361 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -163,6 +163,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) return -1; } + blkconf_blocksizes(&dev->conf); if (dev->conf.logical_block_size != 512) { error_report("logical_block_size must be 512 for IDE"); return -1; diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index f65618d..2921728 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2251,6 +2251,7 @@ static void scsi_realize(SCSIDevice *dev, Error **errp) } blkconf_serial(&s->qdev.conf, &s->serial); + blkconf_blocksizes(&s->qdev.conf); if (dev->type == TYPE_DISK) { blkconf_geometry(&dev->conf, NULL, 65535, 255, 255, &err); if (err) { @@ -2290,6 +2291,7 @@ static void scsi_realize(SCSIDevice *dev, Error **errp) static void scsi_hd_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); + blkconf_blocksizes(&s->qdev.conf); s->qdev.blocksize = s->qdev.conf.logical_block_size; s->qdev.type = TYPE_DISK; if (!s->product) { diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 65d9aa6..8edc314 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -611,6 +611,7 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp) } blkconf_serial(&s->conf, &dev->serial); + blkconf_blocksizes(&s->conf); /* * Hack alert: this pretends to be a block device, but it's really -- cgit v1.1 From 06b95b1ee75706592929e7e91cf18373fd0e6697 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:17:50 -0500 Subject: ide: start extracting ide_restart_dma out of bmdma_restart_dma This patch begins refactoring the restart dma functions out of bmdma to be shared with AHCI and other future IDE HBA implementations. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-2-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/pci.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'hw') diff --git a/hw/ide/pci.c b/hw/ide/pci.c index e3f2054..da3e392 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -184,18 +184,24 @@ static void bmdma_set_inactive(IDEDMA *dma, bool more) } } -static void bmdma_restart_dma(BMDMAState *bm, enum ide_dma_cmd dma_cmd) +static void bmdma_restart_dma(BMDMAState *bm) { IDEState *s = bmdma_active_if(bm); ide_set_sector(s, bm->sector_num); + s->nsector = bm->nsector; + bm->cur_addr = bm->addr; +} + +static void ide_restart_dma(IDEState *s, enum ide_dma_cmd dma_cmd) +{ + BMDMAState *bm = DO_UPCAST(BMDMAState, dma, s->bus->dma); + + bmdma_restart_dma(bm); s->io_buffer_index = 0; s->io_buffer_size = 0; - s->nsector = bm->nsector; s->dma_cmd = dma_cmd; - bm->cur_addr = bm->addr; - bm->dma_cb = ide_dma_cb; - bmdma_start_dma(&bm->dma, s, bm->dma_cb); + bmdma_start_dma(&bm->dma, s, ide_dma_cb); } /* TODO This should be common IDE code */ @@ -203,6 +209,7 @@ static void bmdma_restart_bh(void *opaque) { BMDMAState *bm = opaque; IDEBus *bus = bm->bus; + IDEState *s; bool is_read; int error_status; @@ -213,6 +220,7 @@ static void bmdma_restart_bh(void *opaque) return; } + s = bmdma_active_if(bm); is_read = (bus->error_status & IDE_RETRY_READ) != 0; /* The error status must be cleared before resubmitting the request: The @@ -223,18 +231,18 @@ static void bmdma_restart_bh(void *opaque) if (error_status & IDE_RETRY_DMA) { if (error_status & IDE_RETRY_TRIM) { - bmdma_restart_dma(bm, IDE_DMA_TRIM); + ide_restart_dma(s, IDE_DMA_TRIM); } else { - bmdma_restart_dma(bm, is_read ? IDE_DMA_READ : IDE_DMA_WRITE); + ide_restart_dma(s, is_read ? IDE_DMA_READ : IDE_DMA_WRITE); } } else if (error_status & IDE_RETRY_PIO) { if (is_read) { - ide_sector_read(bmdma_active_if(bm)); + ide_sector_read(s); } else { - ide_sector_write(bmdma_active_if(bm)); + ide_sector_write(s); } } else if (error_status & IDE_RETRY_FLUSH) { - ide_flush_cache(bmdma_active_if(bm)); + ide_flush_cache(s); } else { IDEState *s = bmdma_active_if(bm); -- cgit v1.1 From bd8892c4e6d681517c687ec5ac86eed46b3bb23b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:17:51 -0500 Subject: ide: prepare to move restart to common code This patch adds the restart_dma callback and adjusts the ide_restart_dma function to utilize this callback to call the BMDMA-specific restart code instead of statically executing BMDMA-specific code. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-3-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/internal.h | 1 + hw/ide/pci.c | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'hw') diff --git a/hw/ide/internal.h b/hw/ide/internal.h index ee9a57f..2566503 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -437,6 +437,7 @@ struct IDEDMAOps { DMAu32Func *commit_buf; DMAIntFunc *rw_buf; DMAIntFunc *set_unit; + DMAVoidFunc *restart_dma; DMAStopFunc *set_inactive; DMAVoidFunc *cmd_done; DMARestartFunc *restart_cb; diff --git a/hw/ide/pci.c b/hw/ide/pci.c index da3e392..34fc4fb 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -184,8 +184,9 @@ static void bmdma_set_inactive(IDEDMA *dma, bool more) } } -static void bmdma_restart_dma(BMDMAState *bm) +static void bmdma_restart_dma(IDEDMA *dma) { + BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); IDEState *s = bmdma_active_if(bm); ide_set_sector(s, bm->sector_num); @@ -195,13 +196,13 @@ static void bmdma_restart_dma(BMDMAState *bm) static void ide_restart_dma(IDEState *s, enum ide_dma_cmd dma_cmd) { - BMDMAState *bm = DO_UPCAST(BMDMAState, dma, s->bus->dma); - - bmdma_restart_dma(bm); + if (s->bus->dma->ops->restart_dma) { + s->bus->dma->ops->restart_dma(s->bus->dma); + } s->io_buffer_index = 0; s->io_buffer_size = 0; s->dma_cmd = dma_cmd; - bmdma_start_dma(&bm->dma, s, ide_dma_cb); + ide_start_dma(s, ide_dma_cb); } /* TODO This should be common IDE code */ @@ -532,6 +533,7 @@ static const struct IDEDMAOps bmdma_ops = { .prepare_buf = bmdma_prepare_buf, .rw_buf = bmdma_rw_buf, .set_unit = bmdma_set_unit, + .restart_dma = bmdma_restart_dma, .set_inactive = bmdma_set_inactive, .restart_cb = bmdma_restart_cb, .reset = bmdma_reset, -- cgit v1.1 From f878c916077d510be3276dad7c36f606cdcea80a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:17:52 -0500 Subject: ide: introduce ide_register_restart_cb A helper is added that registers the IDEDMAOp .restart_cb() via qemu_add_vm_change_state_handler instead of requiring each HBA to register the callback themselves. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-4-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/cmd646.c | 3 +-- hw/ide/core.c | 5 +++++ hw/ide/internal.h | 1 + hw/ide/piix.c | 3 +-- hw/ide/via.c | 3 +-- 5 files changed, 9 insertions(+), 6 deletions(-) (limited to 'hw') diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index c8b0322..0374653 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -368,8 +368,7 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev) bmdma_init(&d->bus[i], &d->bmdma[i], d); d->bmdma[i].bus = &d->bus[i]; - qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb, - &d->bmdma[i].dma); + ide_register_restart_cb(&d->bus[i]); } vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d); diff --git a/hw/ide/core.c b/hw/ide/core.c index ac3f015..5a42771 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2330,6 +2330,11 @@ static const IDEDMAOps ide_dma_nop_ops = { .restart_cb = ide_nop_restart, }; +void ide_register_restart_cb(IDEBus *bus) +{ + qemu_add_vm_change_state_handler(bus->dma->ops->restart_cb, bus->dma); +} + static IDEDMA ide_dma_nop = { .ops = &ide_dma_nop_ops, .aiocb = NULL, diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 2566503..57ef5ca 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -551,6 +551,7 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind, int chs_trans); void ide_init2(IDEBus *bus, qemu_irq irq); void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2); +void ide_register_restart_cb(IDEBus *bus); void ide_exec_cmd(IDEBus *bus, uint32_t val); void ide_dma_cb(void *opaque, int ret); diff --git a/hw/ide/piix.c b/hw/ide/piix.c index b0172fb..247dd4f 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -143,8 +143,7 @@ static void pci_piix_init_ports(PCIIDEState *d) { bmdma_init(&d->bus[i], &d->bmdma[i], d); d->bmdma[i].bus = &d->bus[i]; - qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb, - &d->bmdma[i].dma); + ide_register_restart_cb(&d->bus[i]); } } diff --git a/hw/ide/via.c b/hw/ide/via.c index 4d8089d..fb3d8a0 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -166,8 +166,7 @@ static void vt82c686b_init_ports(PCIIDEState *d) { bmdma_init(&d->bus[i], &d->bmdma[i], d); d->bmdma[i].bus = &d->bus[i]; - qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb, - &d->bmdma[i].dma); + ide_register_restart_cb(&d->bus[i]); } } -- cgit v1.1 From 2745df813d82724f2633a9b2ba7f7c5717d7509b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:17:53 -0500 Subject: ide: do not use BMDMA in restart callback Whenever an error stops the VM, ide_handle_rw_error does "s->bus->dma->unit = s->unit". So we can just use idebus_active_if. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-5-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/pci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 34fc4fb..62c88d7 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -217,17 +217,17 @@ static void bmdma_restart_bh(void *opaque) qemu_bh_delete(bm->bh); bm->bh = NULL; - if (bm->unit == (uint8_t) -1) { + error_status = bus->error_status; + if (bus->error_status == 0) { return; } - s = bmdma_active_if(bm); + s = idebus_active_if(bus); is_read = (bus->error_status & IDE_RETRY_READ) != 0; /* The error status must be cleared before resubmitting the request: The * request may fail again, and this case can only be distinguished if the * called function can set a new error status. */ - error_status = bus->error_status; bus->error_status = 0; if (error_status & IDE_RETRY_DMA) { -- cgit v1.1 From d34fceda8feb6c36722f41f3e1db40cf2af82ea8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:17:54 -0500 Subject: ide: pass IDEBus to the restart_cb Pass the containing IDEBus to the restart_cb instead of the more specific BMDMAState child. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-6-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/core.c | 2 +- hw/ide/pci.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'hw') diff --git a/hw/ide/core.c b/hw/ide/core.c index 5a42771..9d510b1 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2332,7 +2332,7 @@ static const IDEDMAOps ide_dma_nop_ops = { void ide_register_restart_cb(IDEBus *bus) { - qemu_add_vm_change_state_handler(bus->dma->ops->restart_cb, bus->dma); + qemu_add_vm_change_state_handler(bus->dma->ops->restart_cb, bus); } static IDEDMA ide_dma_nop = { diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 62c88d7..45254d4 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -208,8 +208,8 @@ static void ide_restart_dma(IDEState *s, enum ide_dma_cmd dma_cmd) /* TODO This should be common IDE code */ static void bmdma_restart_bh(void *opaque) { - BMDMAState *bm = opaque; - IDEBus *bus = bm->bus; + IDEBus *bus = opaque; + BMDMAState *bm = DO_UPCAST(BMDMAState, dma, bus->dma); IDEState *s; bool is_read; int error_status; @@ -260,14 +260,14 @@ static void bmdma_restart_bh(void *opaque) static void bmdma_restart_cb(void *opaque, int running, RunState state) { - IDEDMA *dma = opaque; - BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); + IDEBus *bus = opaque; + BMDMAState *bm = DO_UPCAST(BMDMAState, dma, bus->dma); if (!running) return; if (!bm->bh) { - bm->bh = qemu_bh_new(bmdma_restart_bh, &bm->dma); + bm->bh = qemu_bh_new(bmdma_restart_bh, bus); qemu_bh_schedule(bm->bh); } } -- cgit v1.1 From 9898586d8929a7f1293fc64164b67a79289b074f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:17:55 -0500 Subject: ide: move restart callback to common code With BMDMA specific excised from the restart functions, create a HBA-agnostic restart callback to be shared between the different HBAs. Change the callback registered with the vmstate_change handler to always point to ide_restart_cb instead of relying on the IDEDMAOps.restart_cb() member. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-7-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/core.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- hw/ide/internal.h | 2 ++ hw/ide/pci.c | 79 ------------------------------------------------------ hw/ide/pci.h | 1 - 4 files changed, 81 insertions(+), 81 deletions(-) (limited to 'hw') diff --git a/hw/ide/core.c b/hw/ide/core.c index 9d510b1..a4250f6 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2314,6 +2314,10 @@ static int ide_nop_int(IDEDMA *dma, int x) return 0; } +static void ide_nop(IDEDMA *dma) +{ +} + static int32_t ide_nop_int32(IDEDMA *dma, int x) { return 0; @@ -2325,14 +2329,88 @@ static void ide_nop_restart(void *opaque, int x, RunState y) static const IDEDMAOps ide_dma_nop_ops = { .prepare_buf = ide_nop_int32, + .restart_dma = ide_nop, .rw_buf = ide_nop_int, .set_unit = ide_nop_int, .restart_cb = ide_nop_restart, }; +static void ide_restart_dma(IDEState *s, enum ide_dma_cmd dma_cmd) +{ + s->bus->dma->ops->restart_dma(s->bus->dma); + s->io_buffer_index = 0; + s->io_buffer_size = 0; + s->dma_cmd = dma_cmd; + ide_start_dma(s, ide_dma_cb); +} + +static void ide_restart_bh(void *opaque) +{ + IDEBus *bus = opaque; + IDEState *s; + bool is_read; + int error_status; + + qemu_bh_delete(bus->bh); + bus->bh = NULL; + + error_status = bus->error_status; + if (bus->error_status == 0) { + return; + } + + s = idebus_active_if(bus); + is_read = (bus->error_status & IDE_RETRY_READ) != 0; + + /* The error status must be cleared before resubmitting the request: The + * request may fail again, and this case can only be distinguished if the + * called function can set a new error status. */ + bus->error_status = 0; + + if (error_status & IDE_RETRY_DMA) { + if (error_status & IDE_RETRY_TRIM) { + ide_restart_dma(s, IDE_DMA_TRIM); + } else { + ide_restart_dma(s, is_read ? IDE_DMA_READ : IDE_DMA_WRITE); + } + } else if (error_status & IDE_RETRY_PIO) { + if (is_read) { + ide_sector_read(s); + } else { + ide_sector_write(s); + } + } else if (error_status & IDE_RETRY_FLUSH) { + ide_flush_cache(s); + } else { + /* + * We've not got any bits to tell us about ATAPI - but + * we do have the end_transfer_func that tells us what + * we're trying to do. + */ + if (s->end_transfer_func == ide_atapi_cmd) { + ide_atapi_dma_restart(s); + } + } +} + +static void ide_restart_cb(void *opaque, int running, RunState state) +{ + IDEBus *bus = opaque; + + if (!running) + return; + + if (!bus->bh) { + bus->bh = qemu_bh_new(ide_restart_bh, bus); + qemu_bh_schedule(bus->bh); + } +} + void ide_register_restart_cb(IDEBus *bus) { - qemu_add_vm_change_state_handler(bus->dma->ops->restart_cb, bus); + if (bus->dma->ops->restart_dma) { + qemu_add_vm_change_state_handler(ide_restart_cb, bus); + } } static IDEDMA ide_dma_nop = { diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 57ef5ca..9a11c3c 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -456,6 +456,8 @@ struct IDEBus { IDEDevice *master; IDEDevice *slave; IDEState ifs[2]; + QEMUBH *bh; + int bus_id; int max_units; IDEDMA *dma; diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 45254d4..cd1bbb0 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -194,84 +194,6 @@ static void bmdma_restart_dma(IDEDMA *dma) bm->cur_addr = bm->addr; } -static void ide_restart_dma(IDEState *s, enum ide_dma_cmd dma_cmd) -{ - if (s->bus->dma->ops->restart_dma) { - s->bus->dma->ops->restart_dma(s->bus->dma); - } - s->io_buffer_index = 0; - s->io_buffer_size = 0; - s->dma_cmd = dma_cmd; - ide_start_dma(s, ide_dma_cb); -} - -/* TODO This should be common IDE code */ -static void bmdma_restart_bh(void *opaque) -{ - IDEBus *bus = opaque; - BMDMAState *bm = DO_UPCAST(BMDMAState, dma, bus->dma); - IDEState *s; - bool is_read; - int error_status; - - qemu_bh_delete(bm->bh); - bm->bh = NULL; - - error_status = bus->error_status; - if (bus->error_status == 0) { - return; - } - - s = idebus_active_if(bus); - is_read = (bus->error_status & IDE_RETRY_READ) != 0; - - /* The error status must be cleared before resubmitting the request: The - * request may fail again, and this case can only be distinguished if the - * called function can set a new error status. */ - bus->error_status = 0; - - if (error_status & IDE_RETRY_DMA) { - if (error_status & IDE_RETRY_TRIM) { - ide_restart_dma(s, IDE_DMA_TRIM); - } else { - ide_restart_dma(s, is_read ? IDE_DMA_READ : IDE_DMA_WRITE); - } - } else if (error_status & IDE_RETRY_PIO) { - if (is_read) { - ide_sector_read(s); - } else { - ide_sector_write(s); - } - } else if (error_status & IDE_RETRY_FLUSH) { - ide_flush_cache(s); - } else { - IDEState *s = bmdma_active_if(bm); - - /* - * We've not got any bits to tell us about ATAPI - but - * we do have the end_transfer_func that tells us what - * we're trying to do. - */ - if (s->end_transfer_func == ide_atapi_cmd) { - ide_atapi_dma_restart(s); - } - } -} - -static void bmdma_restart_cb(void *opaque, int running, RunState state) -{ - IDEBus *bus = opaque; - BMDMAState *bm = DO_UPCAST(BMDMAState, dma, bus->dma); - - if (!running) - return; - - if (!bm->bh) { - bm->bh = qemu_bh_new(bmdma_restart_bh, bus); - qemu_bh_schedule(bm->bh); - } -} - static void bmdma_cancel(BMDMAState *bm) { if (bm->status & BM_STATUS_DMAING) { @@ -535,7 +457,6 @@ static const struct IDEDMAOps bmdma_ops = { .set_unit = bmdma_set_unit, .restart_dma = bmdma_restart_dma, .set_inactive = bmdma_set_inactive, - .restart_cb = bmdma_restart_cb, .reset = bmdma_reset, }; diff --git a/hw/ide/pci.h b/hw/ide/pci.h index 2e9314a..ea4e051 100644 --- a/hw/ide/pci.h +++ b/hw/ide/pci.h @@ -28,7 +28,6 @@ typedef struct BMDMAState { uint32_t nsector; MemoryRegion addr_ioport; MemoryRegion extra_io; - QEMUBH *bh; qemu_irq irq; /* Bit 0-2 and 7: BM status register -- cgit v1.1 From fe09c7c9f0e8ed8793e986cf616c8de0a9518fd7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:17:56 -0500 Subject: ide: remove restart_cb callback With restarts now handled by ide_restart_cb and the IDEDMAOps.restart_dma() member, remove the old restart_cb callback. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-8-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/ahci.c | 5 ----- hw/ide/core.c | 5 ----- hw/ide/internal.h | 1 - hw/ide/macio.c | 5 ----- 4 files changed, 16 deletions(-) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 5651372..3892025 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1252,10 +1252,6 @@ static void ahci_irq_set(void *opaque, int n, int level) { } -static void ahci_dma_restart_cb(void *opaque, int running, RunState state) -{ -} - static const IDEDMAOps ahci_dma_ops = { .start_dma = ahci_start_dma, .start_transfer = ahci_start_transfer, @@ -1264,7 +1260,6 @@ static const IDEDMAOps ahci_dma_ops = { .rw_buf = ahci_dma_rw_buf, .set_unit = ahci_dma_set_unit, .cmd_done = ahci_cmd_done, - .restart_cb = ahci_dma_restart_cb, }; void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) diff --git a/hw/ide/core.c b/hw/ide/core.c index a4250f6..0a3d244 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2323,16 +2323,11 @@ static int32_t ide_nop_int32(IDEDMA *dma, int x) return 0; } -static void ide_nop_restart(void *opaque, int x, RunState y) -{ -} - static const IDEDMAOps ide_dma_nop_ops = { .prepare_buf = ide_nop_int32, .restart_dma = ide_nop, .rw_buf = ide_nop_int, .set_unit = ide_nop_int, - .restart_cb = ide_nop_restart, }; static void ide_restart_dma(IDEState *s, enum ide_dma_cmd dma_cmd) diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 9a11c3c..44cce5b 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -440,7 +440,6 @@ struct IDEDMAOps { DMAVoidFunc *restart_dma; DMAStopFunc *set_inactive; DMAVoidFunc *cmd_done; - DMARestartFunc *restart_cb; DMAVoidFunc *reset; }; diff --git a/hw/ide/macio.c b/hw/ide/macio.c index f6074f2..e7a5c99 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -558,10 +558,6 @@ static int32_t ide_nop_int32(IDEDMA *dma, int x) return 0; } -static void ide_nop_restart(void *opaque, int x, RunState y) -{ -} - static void ide_dbdma_start(IDEDMA *dma, IDEState *s, BlockCompletionFunc *cb) { @@ -577,7 +573,6 @@ static const IDEDMAOps dbdma_ops = { .prepare_buf = ide_nop_int32, .rw_buf = ide_nop_int, .set_unit = ide_nop_int, - .restart_cb = ide_nop_restart, }; static void macio_ide_realizefn(DeviceState *dev, Error **errp) -- cgit v1.1 From a96cb236290ef8e54b061b30c41835e435905d7a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:17:57 -0500 Subject: ide: replace set_unit callback with more IDEBus state Start moving the initial state of the current request to IDEBus, so that AHCI can use it. The set_unit callback is not used anymore once this is done. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-9-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/ahci.c | 7 ------- hw/ide/core.c | 6 ++++-- hw/ide/internal.h | 2 +- hw/ide/macio.c | 1 - hw/ide/pci.c | 19 ++++++------------- hw/ide/pci.h | 6 ++++-- 6 files changed, 15 insertions(+), 26 deletions(-) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 3892025..bc6d5ce 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1226,12 +1226,6 @@ static int ahci_dma_rw_buf(IDEDMA *dma, int is_write) return 1; } -static int ahci_dma_set_unit(IDEDMA *dma, int unit) -{ - /* only a single unit per link */ - return 0; -} - static void ahci_cmd_done(IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); @@ -1258,7 +1252,6 @@ static const IDEDMAOps ahci_dma_ops = { .prepare_buf = ahci_dma_prepare_buf, .commit_buf = ahci_commit_buf, .rw_buf = ahci_dma_rw_buf, - .set_unit = ahci_dma_set_unit, .cmd_done = ahci_cmd_done, }; diff --git a/hw/ide/core.c b/hw/ide/core.c index 0a3d244..7607d03 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -646,6 +646,7 @@ static void dma_buf_commit(IDEState *s, uint32_t tx_bytes) void ide_set_inactive(IDEState *s, bool more) { s->bus->dma->aiocb = NULL; + s->bus->retry_unit = -1; if (s->bus->dma->ops->set_inactive) { s->bus->dma->ops->set_inactive(s->bus->dma, more); } @@ -666,7 +667,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op) BlockErrorAction action = blk_get_error_action(s->blk, is_read, error); if (action == BLOCK_ERROR_ACTION_STOP) { - s->bus->dma->ops->set_unit(s->bus->dma, s->unit); + assert(s->bus->retry_unit == s->unit); s->bus->error_status = op; } else if (action == BLOCK_ERROR_ACTION_REPORT) { if (op & IDE_RETRY_DMA) { @@ -799,6 +800,7 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd) void ide_start_dma(IDEState *s, BlockCompletionFunc *cb) { + s->bus->retry_unit = s->unit; if (s->bus->dma->ops->start_dma) { s->bus->dma->ops->start_dma(s->bus->dma, s, cb); } @@ -2327,11 +2329,11 @@ static const IDEDMAOps ide_dma_nop_ops = { .prepare_buf = ide_nop_int32, .restart_dma = ide_nop, .rw_buf = ide_nop_int, - .set_unit = ide_nop_int, }; static void ide_restart_dma(IDEState *s, enum ide_dma_cmd dma_cmd) { + s->unit = s->bus->retry_unit; s->bus->dma->ops->restart_dma(s->bus->dma); s->io_buffer_index = 0; s->io_buffer_size = 0; diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 44cce5b..9630f61 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -436,7 +436,6 @@ struct IDEDMAOps { DMAInt32Func *prepare_buf; DMAu32Func *commit_buf; DMAIntFunc *rw_buf; - DMAIntFunc *set_unit; DMAVoidFunc *restart_dma; DMAStopFunc *set_inactive; DMAVoidFunc *cmd_done; @@ -465,6 +464,7 @@ struct IDEBus { qemu_irq irq; int error_status; + uint8_t retry_unit; }; #define TYPE_IDE_DEVICE "ide-device" diff --git a/hw/ide/macio.c b/hw/ide/macio.c index e7a5c99..a009674 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -572,7 +572,6 @@ static const IDEDMAOps dbdma_ops = { .start_dma = ide_dbdma_start, .prepare_buf = ide_nop_int32, .rw_buf = ide_nop_int, - .set_unit = ide_nop_int, }; static void macio_ide_realizefn(DeviceState *dev, Error **errp) diff --git a/hw/ide/pci.c b/hw/ide/pci.c index cd1bbb0..2b0e886 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -42,7 +42,6 @@ static void bmdma_start_dma(IDEDMA *dma, IDEState *s, { BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); - bm->unit = s->unit; bm->dma_cb = dma_cb; bm->cur_prd_last = 0; bm->cur_prd_addr = 0; @@ -163,20 +162,11 @@ static int bmdma_rw_buf(IDEDMA *dma, int is_write) return 1; } -static int bmdma_set_unit(IDEDMA *dma, int unit) -{ - BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); - bm->unit = unit; - - return 0; -} - static void bmdma_set_inactive(IDEDMA *dma, bool more) { BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); bm->dma_cb = NULL; - bm->unit = -1; if (more) { bm->status |= BM_STATUS_DMAING; } else { @@ -335,6 +325,7 @@ static void ide_bmdma_pre_save(void *opaque) BMDMAState *bm = opaque; uint8_t abused_bits = BM_MIGRATION_COMPAT_STATUS_BITS; + bm->migration_retry_unit = bm->bus->retry_unit; bm->migration_compat_status = (bm->status & ~abused_bits) | (bm->bus->error_status & abused_bits); } @@ -351,6 +342,9 @@ static int ide_bmdma_post_load(void *opaque, int version_id) bm->status = bm->migration_compat_status & ~abused_bits; bm->bus->error_status |= bm->migration_compat_status & abused_bits; } + if (bm->bus->error_status) { + bm->bus->retry_unit = bm->migration_retry_unit; + } return 0; } @@ -389,7 +383,7 @@ static const VMStateDescription vmstate_bmdma = { VMSTATE_UINT32(addr, BMDMAState), VMSTATE_INT64(sector_num, BMDMAState), VMSTATE_UINT32(nsector, BMDMAState), - VMSTATE_UINT8(unit, BMDMAState), + VMSTATE_UINT8(migration_retry_unit, BMDMAState), VMSTATE_END_OF_LIST() }, .subsections = (VMStateSubsection []) { @@ -413,7 +407,7 @@ static int ide_pci_post_load(void *opaque, int version_id) for(i = 0; i < 2; i++) { /* current versions always store 0/1, but older version stored bigger values. We only need last bit */ - d->bmdma[i].unit &= 1; + d->bmdma[i].migration_retry_unit &= 1; ide_bmdma_post_load(&d->bmdma[i], -1); } @@ -454,7 +448,6 @@ static const struct IDEDMAOps bmdma_ops = { .start_dma = bmdma_start_dma, .prepare_buf = bmdma_prepare_buf, .rw_buf = bmdma_rw_buf, - .set_unit = bmdma_set_unit, .restart_dma = bmdma_restart_dma, .set_inactive = bmdma_set_inactive, .reset = bmdma_reset, diff --git a/hw/ide/pci.h b/hw/ide/pci.h index ea4e051..222a163 100644 --- a/hw/ide/pci.h +++ b/hw/ide/pci.h @@ -33,6 +33,8 @@ typedef struct BMDMAState { /* Bit 0-2 and 7: BM status register * Bit 3-6: bus->error_status */ uint8_t migration_compat_status; + uint8_t migration_retry_unit; + struct PCIIDEState *pci_dev; } BMDMAState; @@ -61,8 +63,8 @@ typedef struct PCIIDEState { static inline IDEState *bmdma_active_if(BMDMAState *bmdma) { - assert(bmdma->unit != (uint8_t)-1); - return bmdma->bus->ifs + bmdma->unit; + assert(bmdma->bus->retry_unit != (uint8_t)-1); + return bmdma->bus->ifs + bmdma->bus->retry_unit; } -- cgit v1.1 From dc5d0af49a90571813b9cbcea90c0bbbea0d4a22 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:17:58 -0500 Subject: ide: place initial state of the current request to IDEBus This moves more common restarting logic to the core IDE code. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-10-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/core.c | 6 ++++++ hw/ide/internal.h | 2 ++ hw/ide/pci.c | 15 ++++++--------- hw/ide/pci.h | 5 ++--- 4 files changed, 16 insertions(+), 12 deletions(-) (limited to 'hw') diff --git a/hw/ide/core.c b/hw/ide/core.c index 7607d03..71ec1e7 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -647,6 +647,8 @@ void ide_set_inactive(IDEState *s, bool more) { s->bus->dma->aiocb = NULL; s->bus->retry_unit = -1; + s->bus->retry_sector_num = 0; + s->bus->retry_nsector = 0; if (s->bus->dma->ops->set_inactive) { s->bus->dma->ops->set_inactive(s->bus->dma, more); } @@ -801,6 +803,8 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd) void ide_start_dma(IDEState *s, BlockCompletionFunc *cb) { s->bus->retry_unit = s->unit; + s->bus->retry_sector_num = ide_get_sector(s); + s->bus->retry_nsector = s->nsector; if (s->bus->dma->ops->start_dma) { s->bus->dma->ops->start_dma(s->bus->dma, s, cb); } @@ -2334,6 +2338,8 @@ static const IDEDMAOps ide_dma_nop_ops = { static void ide_restart_dma(IDEState *s, enum ide_dma_cmd dma_cmd) { s->unit = s->bus->retry_unit; + ide_set_sector(s, s->bus->retry_sector_num); + s->nsector = s->bus->retry_nsector; s->bus->dma->ops->restart_dma(s->bus->dma); s->io_buffer_index = 0; s->io_buffer_size = 0; diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 9630f61..02206a9 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -465,6 +465,8 @@ struct IDEBus { int error_status; uint8_t retry_unit; + int64_t retry_sector_num; + uint32_t retry_nsector; }; #define TYPE_IDE_DEVICE "ide-device" diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 2b0e886..fab2abc 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -46,8 +46,6 @@ static void bmdma_start_dma(IDEDMA *dma, IDEState *s, bm->cur_prd_last = 0; bm->cur_prd_addr = 0; bm->cur_prd_len = 0; - bm->sector_num = ide_get_sector(s); - bm->nsector = s->nsector; if (bm->status & BM_STATUS_DMAING) { bm->dma_cb(bmdma_active_if(bm), 0); @@ -177,10 +175,7 @@ static void bmdma_set_inactive(IDEDMA *dma, bool more) static void bmdma_restart_dma(IDEDMA *dma) { BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); - IDEState *s = bmdma_active_if(bm); - ide_set_sector(s, bm->sector_num); - s->nsector = bm->nsector; bm->cur_addr = bm->addr; } @@ -207,8 +202,6 @@ static void bmdma_reset(IDEDMA *dma) bm->cur_prd_last = 0; bm->cur_prd_addr = 0; bm->cur_prd_len = 0; - bm->sector_num = 0; - bm->nsector = 0; } static void bmdma_irq(void *opaque, int n, int level) @@ -326,6 +319,8 @@ static void ide_bmdma_pre_save(void *opaque) uint8_t abused_bits = BM_MIGRATION_COMPAT_STATUS_BITS; bm->migration_retry_unit = bm->bus->retry_unit; + bm->migration_retry_sector_num = bm->bus->retry_sector_num; + bm->migration_retry_nsector = bm->bus->retry_nsector; bm->migration_compat_status = (bm->status & ~abused_bits) | (bm->bus->error_status & abused_bits); } @@ -343,6 +338,8 @@ static int ide_bmdma_post_load(void *opaque, int version_id) bm->bus->error_status |= bm->migration_compat_status & abused_bits; } if (bm->bus->error_status) { + bm->bus->retry_sector_num = bm->migration_retry_sector_num; + bm->bus->retry_nsector = bm->migration_retry_nsector; bm->bus->retry_unit = bm->migration_retry_unit; } @@ -381,8 +378,8 @@ static const VMStateDescription vmstate_bmdma = { VMSTATE_UINT8(cmd, BMDMAState), VMSTATE_UINT8(migration_compat_status, BMDMAState), VMSTATE_UINT32(addr, BMDMAState), - VMSTATE_INT64(sector_num, BMDMAState), - VMSTATE_UINT32(nsector, BMDMAState), + VMSTATE_INT64(migration_retry_sector_num, BMDMAState), + VMSTATE_UINT32(migration_retry_nsector, BMDMAState), VMSTATE_UINT8(migration_retry_unit, BMDMAState), VMSTATE_END_OF_LIST() }, diff --git a/hw/ide/pci.h b/hw/ide/pci.h index 222a163..0f2d4b9 100644 --- a/hw/ide/pci.h +++ b/hw/ide/pci.h @@ -22,10 +22,7 @@ typedef struct BMDMAState { uint32_t cur_prd_last; uint32_t cur_prd_addr; uint32_t cur_prd_len; - uint8_t unit; BlockCompletionFunc *dma_cb; - int64_t sector_num; - uint32_t nsector; MemoryRegion addr_ioport; MemoryRegion extra_io; qemu_irq irq; @@ -34,6 +31,8 @@ typedef struct BMDMAState { * Bit 3-6: bus->error_status */ uint8_t migration_compat_status; uint8_t migration_retry_unit; + int64_t migration_retry_sector_num; + uint32_t migration_retry_nsector; struct PCIIDEState *pci_dev; } BMDMAState; -- cgit v1.1 From d12b9ff2a4e21587e5b180008c88a0e6e1ec8ac5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:17:59 -0500 Subject: ide: migrate initial request state via IDEBus This only breaks backwards migration compatibility if the bus is in an error state. It is in principle possible to avoid this by making two subsections (one for version 1, and one for version 2, but with the same name) with different "_needed" callbacks. The v1 callback would return true if error_status != 0 and the bus is PATA; the v2 callback would return true if error_status != 0 and the bus is AHCI. Forward migration keeps working. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-11-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/ide/core.c b/hw/ide/core.c index 71ec1e7..b62a94a 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2643,10 +2643,13 @@ const VMStateDescription vmstate_ide_drive = { static const VMStateDescription vmstate_ide_error_status = { .name ="ide_bus/error", - .version_id = 1, + .version_id = 2, .minimum_version_id = 1, .fields = (VMStateField[]) { VMSTATE_INT32(error_status, IDEBus), + VMSTATE_INT64_V(retry_sector_num, IDEBus, 2), + VMSTATE_UINT32_V(retry_nsector, IDEBus, 2), + VMSTATE_UINT8_V(retry_unit, IDEBus, 2), VMSTATE_END_OF_LIST() } }; -- cgit v1.1 From c71c06d437d4cccf753cb41731e5a71f54317a01 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:18:00 -0500 Subject: ide: commonize io_buffer_index initialization Resetting the io_buffer_index to 0 is commonized, with the exception of the case within ide_atapi_cmd_reply, where we need to reset this index to 0 prior to the ide_atapi_cmd_reply_end call. Note that not all calls to ide_atapi_cmd_reply_end expect the index to be 0, so setting it there is not appropriate. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-12-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/atapi.c | 3 +-- hw/ide/core.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index 1bf8b34..950e311 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -252,7 +252,6 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) s->packet_transfer_size = size; s->io_buffer_size = size; /* dma: send the reply data as one chunk */ s->elementary_transfer_size = 0; - s->io_buffer_index = 0; if (s->atapi_dma) { block_acct_start(blk_get_stats(s->blk), &s->acct, size, @@ -261,6 +260,7 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) ide_start_dma(s, ide_atapi_cmd_read_dma_cb); } else { s->status = READY_STAT | SEEK_STAT; + s->io_buffer_index = 0; ide_atapi_cmd_reply_end(s); } } @@ -368,7 +368,6 @@ static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors, { s->lba = lba; s->packet_transfer_size = nb_sectors * sector_size; - s->io_buffer_index = 0; s->io_buffer_size = 0; s->cd_sector_size = sector_size; diff --git a/hw/ide/core.c b/hw/ide/core.c index b62a94a..ff28db0 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -780,7 +780,6 @@ eot: static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd) { s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; - s->io_buffer_index = 0; s->io_buffer_size = 0; s->dma_cmd = dma_cmd; @@ -802,6 +801,7 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd) void ide_start_dma(IDEState *s, BlockCompletionFunc *cb) { + s->io_buffer_index = 0; s->bus->retry_unit = s->unit; s->bus->retry_sector_num = ide_get_sector(s); s->bus->retry_nsector = s->nsector; @@ -2341,7 +2341,6 @@ static void ide_restart_dma(IDEState *s, enum ide_dma_cmd dma_cmd) ide_set_sector(s, s->bus->retry_sector_num); s->nsector = s->bus->retry_nsector; s->bus->dma->ops->restart_dma(s->bus->dma); - s->io_buffer_index = 0; s->io_buffer_size = 0; s->dma_cmd = dma_cmd; ide_start_dma(s, ide_dma_cb); -- cgit v1.1 From 4e2b8b4a4e8fcc598f7b9df15aa8949a1ab096e8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:18:01 -0500 Subject: ide: make more functions static Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-13-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/core.c | 12 ++++++++---- hw/ide/internal.h | 4 ---- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'hw') diff --git a/hw/ide/core.c b/hw/ide/core.c index ff28db0..ef52f35 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -561,6 +561,8 @@ static bool ide_sect_range_ok(IDEState *s, return true; } +static void ide_sector_read(IDEState *s); + static void ide_sector_read_cb(void *opaque, int ret) { IDEState *s = opaque; @@ -595,7 +597,7 @@ static void ide_sector_read_cb(void *opaque, int ret) s->io_buffer_offset += 512 * n; } -void ide_sector_read(IDEState *s) +static void ide_sector_read(IDEState *s) { int64_t sector_num; int n; @@ -682,7 +684,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op) return action != BLOCK_ERROR_ACTION_IGNORE; } -void ide_dma_cb(void *opaque, int ret) +static void ide_dma_cb(void *opaque, int ret) { IDEState *s = opaque; int n; @@ -810,6 +812,8 @@ void ide_start_dma(IDEState *s, BlockCompletionFunc *cb) } } +static void ide_sector_write(IDEState *s); + static void ide_sector_write_timer_cb(void *opaque) { IDEState *s = opaque; @@ -869,7 +873,7 @@ static void ide_sector_write_cb(void *opaque, int ret) } } -void ide_sector_write(IDEState *s) +static void ide_sector_write(IDEState *s) { int64_t sector_num; int n; @@ -923,7 +927,7 @@ static void ide_flush_cb(void *opaque, int ret) ide_set_irq(s->bus); } -void ide_flush_cache(IDEState *s) +static void ide_flush_cache(IDEState *s) { if (s->blk == NULL) { ide_flush_cb(s, 0); diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 02206a9..0d5f881 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -557,10 +557,6 @@ void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2); void ide_register_restart_cb(IDEBus *bus); void ide_exec_cmd(IDEBus *bus, uint32_t val); -void ide_dma_cb(void *opaque, int ret); -void ide_sector_write(IDEState *s); -void ide_sector_read(IDEState *s); -void ide_flush_cache(IDEState *s); void ide_transfer_start(IDEState *s, uint8_t *buf, int size, EndTransferFunc *end_transfer_func); -- cgit v1.1 From d32c76b3add2cb5216ae6931ef06632b802a6f68 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:18:02 -0500 Subject: ide: support PIO restart for the ISA controller Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-14-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/isa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/ide/isa.c b/hw/ide/isa.c index c0c4e1b..9f80503 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -74,7 +74,8 @@ static void isa_ide_realizefn(DeviceState *dev, Error **errp) isa_init_irq(isadev, &s->irq, s->isairq); ide_init2(&s->bus, s->irq); vmstate_register(dev, 0, &vmstate_ide_isa, s); -}; + ide_register_restart_cb(&s->bus); +} ISADevice *isa_ide_init(ISABus *bus, int iobase, int iobase2, int isairq, DriveInfo *hd0, DriveInfo *hd1) -- cgit v1.1 From bd6649101d044df446c66949cb6c1462c8989726 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 23 Feb 2015 11:18:03 -0500 Subject: ahci: Migrate IDEStatus Amazingly, we weren't doing this before. Make sure we migrate the IDEState structure that belongs to the AHCIDevice.IDEBus structure during migrations. No version numbering changes because AHCI is not officially migratable (and we can all see with good reason why) so we do not impact any official builds by altering the stream and leaving it at version 1. This fixes the rerror=stop/werror=stop test case where we wish to migrate a halted job. Previously, the error code would not migrate, so even if the job completed successfully, AHCI would report an error because it would still have the placeholder error code from initialization time. Reviewed-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-15-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/ahci.c | 1 + hw/ide/internal.h | 3 +++ 2 files changed, 4 insertions(+) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index bc6d5ce..3f4fc77 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1321,6 +1321,7 @@ static const VMStateDescription vmstate_ahci_device = { .version_id = 1, .fields = (VMStateField[]) { VMSTATE_IDE_BUS(port, AHCIDevice), + VMSTATE_IDE_DRIVE(port.ifs[0], AHCIDevice), VMSTATE_UINT32(port_state, AHCIDevice), VMSTATE_UINT32(finished, AHCIDevice), VMSTATE_UINT32(port_regs.lst_addr, AHCIDevice), diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 0d5f881..965cc55 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -526,6 +526,9 @@ extern const VMStateDescription vmstate_ide_drive; #define VMSTATE_IDE_DRIVES(_field, _state) \ VMSTATE_STRUCT_ARRAY(_field, _state, 2, 3, vmstate_ide_drive, IDEState) +#define VMSTATE_IDE_DRIVE(_field, _state) \ + VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_drive, IDEState) + void ide_bus_reset(IDEBus *bus); int64_t ide_get_sector(IDEState *s); void ide_set_sector(IDEState *s, int64_t sector_num); -- cgit v1.1 From e8ef87433ee005d304ba19c56488474432eb0c53 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Feb 2015 11:18:04 -0500 Subject: ahci: add support for restarting non-queued commands This is easy, since start_dma already restarts processing from the beginning of the PRDT. Migration is also easy to cover; the comment about busy_slot is wrong, busy_slot will only be set if there is an error. In this case we have nothing to do really. The core IDE code will restart the operation and command list processing will proceed after the erroring command has been completed. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Message-id: 1424708286-16483-16-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/ahci.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 3f4fc77..56a4867 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1160,6 +1160,11 @@ static void ahci_start_dma(IDEDMA *dma, IDEState *s, dma_cb(s, 0); } +static void ahci_restart_dma(IDEDMA *dma) +{ + /* Nothing to do, ahci_start_dma already resets s->io_buffer_offset. */ +} + /** * Called in DMA R/W chains to read the PRDT, utilizing ahci_populate_sglist. * Not currently invoked by PIO R/W chains, @@ -1248,6 +1253,7 @@ static void ahci_irq_set(void *opaque, int n, int level) static const IDEDMAOps ahci_dma_ops = { .start_dma = ahci_start_dma, + .restart_dma = ahci_restart_dma, .start_transfer = ahci_start_transfer, .prepare_buf = ahci_dma_prepare_buf, .commit_buf = ahci_commit_buf, @@ -1282,6 +1288,7 @@ void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) ad->port_no = i; ad->port.dma = &ad->dma; ad->port.dma->ops = &ahci_dma_ops; + ide_register_restart_cb(&ad->port); } } @@ -1360,16 +1367,16 @@ static int ahci_state_post_load(void *opaque, int version_id) map_page(s->as, &ad->res_fis, ((uint64_t)pr->fis_addr_hi << 32) | pr->fis_addr, 256); /* - * All pending i/o should be flushed out on a migrate. However, - * we might not have cleared the busy_slot since this is done - * in a bh. Also, issue i/o against any slots that are pending. + * If an error is present, ad->busy_slot will be valid and not -1. + * In this case, an operation is waiting to resume and will re-check + * for additional AHCI commands to execute upon completion. + * + * In the case where no error was present, busy_slot will be -1, + * and we should check to see if there are additional commands waiting. */ - if ((ad->busy_slot != -1) && - !(ad->port.ifs[0].status & (BUSY_STAT|DRQ_STAT))) { - pr->cmd_issue &= ~(1 << ad->busy_slot); - ad->busy_slot = -1; + if (ad->busy_slot == -1) { + check_cmd(s, i); } - check_cmd(s, i); } return 0; -- cgit v1.1 From c27c73aaf924655b2cc2e74384a639805acededb Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 23 Feb 2015 11:18:05 -0500 Subject: ahci: Recompute cur_cmd on migrate post load When the AHCI HBA device is migrated, all of the information that led to the request being created is stored in the AHCIDevice structures, except for pointers into guest data where return information needs to be stored. The "cur_cmd" field is usually responsible for this. To rebuild the cur_cmd pointer post-migration, we can utilize the busy_slot index to figure out where the command header we are still processing is. This allows a machine in a halted state from rerror=stop or werror=stop to be migrated and resume operations without issue. Signed-off-by: John Snow Message-id: 1424708286-16483-17-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/ide/ahci.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 56a4867..e1ae36f 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1376,6 +1376,13 @@ static int ahci_state_post_load(void *opaque, int version_id) */ if (ad->busy_slot == -1) { check_cmd(s, i); + } else { + /* We are in the middle of a command, and may need to access + * the command header in guest memory again. */ + if (ad->busy_slot < 0 || ad->busy_slot >= AHCI_MAX_CMDS) { + return -1; + } + ad->cur_cmd = &((AHCICmdHdr *)ad->lst)[ad->busy_slot]; } } -- cgit v1.1 From 4c0542ea60d21b56a9157d3f6331d2df8990d3bb Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 16 Feb 2015 12:09:40 +0800 Subject: virtio-blk: Remove the stale FIXME comment By default, we have ioeventfd enabled, so the IO request processing is in IO thread; in the vcpu thread, guest mode is returned to as quickly as possible, and completion is delivered via irqfd. Therefore this comment from the initial implementation is barely relevant. Signed-off-by: Fam Zheng Reviewed-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/block/virtio-blk.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'hw') diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 2acfef8..0468297 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -597,12 +597,6 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) if (mrb.num_reqs) { virtio_blk_submit_multireq(s->blk, &mrb); } - - /* - * FIXME: Want to check for completions before returning to guest mode, - * so cached reads and writes are reported as quickly as possible. But - * that should be done in the generic block layer. - */ } static void virtio_blk_dma_restart_bh(void *opaque) -- cgit v1.1 From df1d4c341a735334de23513f17bf110c8c49b3e7 Mon Sep 17 00:00:00 2001 From: Ekaterina Tumanova Date: Wed, 4 Mar 2015 11:02:16 +0100 Subject: scsi-hd: fix property unset case Commit c53659f0 ("BlockConf: Call backend functions to detect geometry and blocksizes") causes a segmentation fault on the invalid configuration of a scsi device without a drive. Let's check for conf.blk before calling blkconf_blocksizes. The error will be handled later on in scsi_realize anyway. Reported-by: Max Reitz Reviewed-by: Stefan Hajnoczi Reviewed-by: Max Reitz Signed-off-by: Ekaterina Tumanova Signed-off-by: Kevin Wolf --- hw/scsi/scsi-disk.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 2921728..54d71f4 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2291,7 +2291,12 @@ static void scsi_realize(SCSIDevice *dev, Error **errp) static void scsi_hd_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); - blkconf_blocksizes(&s->qdev.conf); + /* can happen for devices without drive. The error message for missing + * backend will be issued in scsi_realize + */ + if (s->qdev.conf.blk) { + blkconf_blocksizes(&s->qdev.conf); + } s->qdev.blocksize = s->qdev.conf.logical_block_size; s->qdev.type = TYPE_DISK; if (!s->product) { -- cgit v1.1