From 69f72a22213a6909bf4aef06133c976b508e370a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:05 -0400 Subject: ide: stash aiocb for flushes This ensures that operations are completed after a reset Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/ide/core.c b/hw/ide/core.c index db191a6c3e..79985f9f49 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -831,6 +831,8 @@ static void ide_flush_cb(void *opaque, int ret) { IDEState *s = opaque; + s->pio_aiocb = NULL; + if (ret < 0) { /* XXX: What sector number to set here? */ if (ide_handle_rw_error(s, -ret, BM_STATUS_RETRY_FLUSH)) { @@ -853,7 +855,7 @@ void ide_flush_cache(IDEState *s) s->status |= BUSY_STAT; bdrv_acct_start(s->bs, &s->acct, 0, BDRV_ACCT_FLUSH); - bdrv_aio_flush(s->bs, ide_flush_cb, s); + s->pio_aiocb = bdrv_aio_flush(s->bs, ide_flush_cb, s); } static void ide_cfata_metadata_inquiry(IDEState *s) -- cgit v1.2.3-55-g7522 From 1374bec0634aac9a460fe3b57bbe8b1aa7a99cb7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:06 -0400 Subject: ide: simplify reset callbacks Drop the unused return value and make the callback optional. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 6 ------ hw/ide/core.c | 5 +++-- hw/ide/internal.h | 3 ++- hw/ide/macio.c | 1 - hw/ide/pci.c | 4 +--- 5 files changed, 6 insertions(+), 13 deletions(-) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 604152a823..273712faaa 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1147,11 +1147,6 @@ static void ahci_dma_restart_cb(void *opaque, int running, RunState state) { } -static int ahci_dma_reset(IDEDMA *dma) -{ - return 0; -} - static const IDEDMAOps ahci_dma_ops = { .start_dma = ahci_start_dma, .start_transfer = ahci_start_transfer, @@ -1162,7 +1157,6 @@ static const IDEDMAOps ahci_dma_ops = { .set_inactive = ahci_dma_set_inactive, .async_cmd_done = ahci_async_cmd_done, .restart_cb = ahci_dma_restart_cb, - .reset = ahci_dma_reset, }; void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) diff --git a/hw/ide/core.c b/hw/ide/core.c index 79985f9f49..4183a3abe2 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2088,7 +2088,9 @@ void ide_bus_reset(IDEBus *bus) } /* reset dma provider too */ - bus->dma->ops->reset(bus->dma); + if (bus->dma->ops->reset) { + bus->dma->ops->reset(bus->dma); + } } static bool ide_cd_is_tray_open(void *opaque) @@ -2226,7 +2228,6 @@ static const IDEDMAOps ide_dma_nop_ops = { .add_status = ide_nop_int, .set_inactive = ide_nop, .restart_cb = ide_nop_restart, - .reset = ide_nop, }; static IDEDMA ide_dma_nop = { diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 0567a522f5..6cca46f506 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -320,6 +320,7 @@ typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind; typedef void EndTransferFunc(IDEState *); typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockDriverCompletionFunc *); +typedef void DMAVoidFunc(IDEDMA *); typedef int DMAFunc(IDEDMA *); typedef int DMAIntFunc(IDEDMA *, int); typedef void DMARestartFunc(void *, int, RunState); @@ -435,7 +436,7 @@ struct IDEDMAOps { DMAFunc *set_inactive; DMAFunc *async_cmd_done; DMARestartFunc *restart_cb; - DMAFunc *reset; + DMAVoidFunc *reset; }; struct IDEDMA { diff --git a/hw/ide/macio.c b/hw/ide/macio.c index c14a1ddddb..ca39e3f9b6 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -578,7 +578,6 @@ static const IDEDMAOps dbdma_ops = { .add_status = ide_nop_int, .set_inactive = ide_nop, .restart_cb = ide_nop_restart, - .reset = ide_nop, }; static void macio_ide_realizefn(DeviceState *dev, Error **errp) diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 6257a21ed2..c24496a992 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -247,7 +247,7 @@ static void bmdma_cancel(BMDMAState *bm) } } -static int bmdma_reset(IDEDMA *dma) +static void bmdma_reset(IDEDMA *dma) { BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); @@ -264,8 +264,6 @@ static int bmdma_reset(IDEDMA *dma) bm->cur_prd_len = 0; bm->sector_num = 0; bm->nsector = 0; - - return 0; } static int bmdma_start_transfer(IDEDMA *dma) -- cgit v1.2.3-55-g7522 From 829b933b704a329d60d2ea1fe4c8e8e0a5505d8a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:07 -0400 Subject: ide: simplify set_inactive callbacks Drop the unused return value and make the callback optional. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 6 ------ hw/ide/core.c | 5 +++-- hw/ide/internal.h | 2 +- hw/ide/macio.c | 1 - hw/ide/pci.c | 4 +--- 5 files changed, 5 insertions(+), 13 deletions(-) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 273712faaa..679357fc12 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1116,11 +1116,6 @@ static int ahci_dma_add_status(IDEDMA *dma, int status) return 0; } -static int ahci_dma_set_inactive(IDEDMA *dma) -{ - return 0; -} - static int ahci_async_cmd_done(IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); @@ -1154,7 +1149,6 @@ static const IDEDMAOps ahci_dma_ops = { .rw_buf = ahci_dma_rw_buf, .set_unit = ahci_dma_set_unit, .add_status = ahci_dma_add_status, - .set_inactive = ahci_dma_set_inactive, .async_cmd_done = ahci_async_cmd_done, .restart_cb = ahci_dma_restart_cb, }; diff --git a/hw/ide/core.c b/hw/ide/core.c index 4183a3abe2..d52a6f6104 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -595,7 +595,9 @@ static void ide_async_cmd_done(IDEState *s) void ide_set_inactive(IDEState *s) { s->bus->dma->aiocb = NULL; - s->bus->dma->ops->set_inactive(s->bus->dma); + if (s->bus->dma->ops->set_inactive) { + s->bus->dma->ops->set_inactive(s->bus->dma); + } ide_async_cmd_done(s); } @@ -2226,7 +2228,6 @@ static const IDEDMAOps ide_dma_nop_ops = { .rw_buf = ide_nop_int, .set_unit = ide_nop_int, .add_status = ide_nop_int, - .set_inactive = ide_nop, .restart_cb = ide_nop_restart, }; diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 6cca46f506..34064cf1a8 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -433,7 +433,7 @@ struct IDEDMAOps { DMAIntFunc *rw_buf; DMAIntFunc *set_unit; DMAIntFunc *add_status; - DMAFunc *set_inactive; + DMAVoidFunc *set_inactive; DMAFunc *async_cmd_done; DMARestartFunc *restart_cb; DMAVoidFunc *reset; diff --git a/hw/ide/macio.c b/hw/ide/macio.c index ca39e3f9b6..0e26bac67f 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -576,7 +576,6 @@ static const IDEDMAOps dbdma_ops = { .rw_buf = ide_nop_int, .set_unit = ide_nop_int, .add_status = ide_nop_int, - .set_inactive = ide_nop, .restart_cb = ide_nop_restart, }; diff --git a/hw/ide/pci.c b/hw/ide/pci.c index c24496a992..9dc3cc5611 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -160,15 +160,13 @@ static int bmdma_add_status(IDEDMA *dma, int status) return 0; } -static int bmdma_set_inactive(IDEDMA *dma) +static void bmdma_set_inactive(IDEDMA *dma) { BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); bm->status &= ~BM_STATUS_DMAING; bm->dma_cb = NULL; bm->unit = -1; - - return 0; } static void bmdma_restart_dma(BMDMAState *bm, enum ide_dma_cmd dma_cmd) -- cgit v1.2.3-55-g7522 From c039cb1e5a7bf1f71fddbbe199eff7fbbfddb416 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:08 -0400 Subject: ide: simplify async_cmd_done callbacks Drop the unused return value. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 4 +--- hw/ide/internal.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 679357fc12..e494503330 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1116,7 +1116,7 @@ static int ahci_dma_add_status(IDEDMA *dma, int status) return 0; } -static int ahci_async_cmd_done(IDEDMA *dma) +static void ahci_async_cmd_done(IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); @@ -1130,8 +1130,6 @@ static int ahci_async_cmd_done(IDEDMA *dma) ad->check_bh = qemu_bh_new(ahci_check_cmd_bh, ad); qemu_bh_schedule(ad->check_bh); } - - return 0; } static void ahci_irq_set(void *opaque, int n, int level) diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 34064cf1a8..940dd4510c 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -434,7 +434,7 @@ struct IDEDMAOps { DMAIntFunc *set_unit; DMAIntFunc *add_status; DMAVoidFunc *set_inactive; - DMAFunc *async_cmd_done; + DMAVoidFunc *async_cmd_done; DMARestartFunc *restart_cb; DMAVoidFunc *reset; }; -- cgit v1.2.3-55-g7522 From 446351236b6e9c53b25e30d107c6235347df1dde Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:09 -0400 Subject: ide: simplify start_transfer callbacks Drop the unused return value and make the callback optional. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 4 +--- hw/ide/core.c | 10 +++------- hw/ide/internal.h | 3 +-- hw/ide/macio.c | 6 ------ hw/ide/pci.c | 6 ------ 5 files changed, 5 insertions(+), 24 deletions(-) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index e494503330..adbac3d52f 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -991,7 +991,7 @@ out: } /* DMA dev <-> ram */ -static int ahci_start_transfer(IDEDMA *dma) +static void ahci_start_transfer(IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); IDEState *s = &ad->port.ifs[0]; @@ -1041,8 +1041,6 @@ out: /* done with DMA */ ahci_trigger_irq(ad->hba, ad, PORT_IRQ_STAT_DSS); } - - return 0; } static void ahci_start_dma(IDEDMA *dma, IDEState *s, diff --git a/hw/ide/core.c b/hw/ide/core.c index d52a6f6104..e5ddecb811 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -434,7 +434,9 @@ void ide_transfer_start(IDEState *s, uint8_t *buf, int size, if (!(s->status & ERR_STAT)) { s->status |= DRQ_STAT; } - s->bus->dma->ops->start_transfer(s->bus->dma); + if (s->bus->dma->ops->start_transfer) { + s->bus->dma->ops->start_transfer(s->bus->dma); + } } void ide_transfer_stop(IDEState *s) @@ -2207,11 +2209,6 @@ static void ide_nop_start(IDEDMA *dma, IDEState *s, { } -static int ide_nop(IDEDMA *dma) -{ - return 0; -} - static int ide_nop_int(IDEDMA *dma, int x) { return 0; @@ -2223,7 +2220,6 @@ static void ide_nop_restart(void *opaque, int x, RunState y) static const IDEDMAOps ide_dma_nop_ops = { .start_dma = ide_nop_start, - .start_transfer = ide_nop, .prepare_buf = ide_nop_int, .rw_buf = ide_nop_int, .set_unit = ide_nop_int, diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 940dd4510c..64fbf2fb62 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -321,7 +321,6 @@ typedef void EndTransferFunc(IDEState *); typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockDriverCompletionFunc *); typedef void DMAVoidFunc(IDEDMA *); -typedef int DMAFunc(IDEDMA *); typedef int DMAIntFunc(IDEDMA *, int); typedef void DMARestartFunc(void *, int, RunState); @@ -428,7 +427,7 @@ struct IDEState { struct IDEDMAOps { DMAStartFunc *start_dma; - DMAFunc *start_transfer; + DMAVoidFunc *start_transfer; DMAIntFunc *prepare_buf; DMAIntFunc *rw_buf; DMAIntFunc *set_unit; diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 0e26bac67f..b7cedb65a5 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -545,11 +545,6 @@ static void macio_ide_reset(DeviceState *dev) ide_bus_reset(&d->bus); } -static int ide_nop(IDEDMA *dma) -{ - return 0; -} - static int ide_nop_int(IDEDMA *dma, int x) { return 0; @@ -571,7 +566,6 @@ static void ide_dbdma_start(IDEDMA *dma, IDEState *s, static const IDEDMAOps dbdma_ops = { .start_dma = ide_dbdma_start, - .start_transfer = ide_nop, .prepare_buf = ide_nop_int, .rw_buf = ide_nop_int, .set_unit = ide_nop_int, diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 9dc3cc5611..1ee8c0a4d5 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -264,11 +264,6 @@ static void bmdma_reset(IDEDMA *dma) bm->nsector = 0; } -static int bmdma_start_transfer(IDEDMA *dma) -{ - return 0; -} - static void bmdma_irq(void *opaque, int n, int level) { BMDMAState *bm = opaque; @@ -500,7 +495,6 @@ void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table) static const struct IDEDMAOps bmdma_ops = { .start_dma = bmdma_start_dma, - .start_transfer = bmdma_start_transfer, .prepare_buf = bmdma_prepare_buf, .rw_buf = bmdma_rw_buf, .set_unit = bmdma_set_unit, -- cgit v1.2.3-55-g7522 From 4855b57639d181362678ab09614a7f753df8e466 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:10 -0400 Subject: ide: wrap start_dma callback Make it optional and prepare for the next patches. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/atapi.c | 6 ++---- hw/ide/core.c | 15 ++++++++------- hw/ide/internal.h | 1 + 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'hw') diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index f7d2009c00..d13395ed2c 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -255,8 +255,7 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) if (s->atapi_dma) { bdrv_acct_start(s->bs, &s->acct, size, BDRV_ACCT_READ); s->status = READY_STAT | SEEK_STAT | DRQ_STAT; - s->bus->dma->ops->start_dma(s->bus->dma, s, - ide_atapi_cmd_read_dma_cb); + ide_start_dma(s, ide_atapi_cmd_read_dma_cb); } else { s->status = READY_STAT | SEEK_STAT; ide_atapi_cmd_reply_end(s); @@ -375,8 +374,7 @@ static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors, /* XXX: check if BUSY_STAT should be set */ s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; - s->bus->dma->ops->start_dma(s->bus->dma, s, - ide_atapi_cmd_read_dma_cb); + ide_start_dma(s, ide_atapi_cmd_read_dma_cb); } static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors, diff --git a/hw/ide/core.c b/hw/ide/core.c index e5ddecb811..aa561ae4f8 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -745,7 +745,14 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd) break; } - s->bus->dma->ops->start_dma(s->bus->dma, s, ide_dma_cb); + ide_start_dma(s, ide_dma_cb); +} + +void ide_start_dma(IDEState *s, BlockDriverCompletionFunc *cb) +{ + if (s->bus->dma->ops->start_dma) { + s->bus->dma->ops->start_dma(s->bus->dma, s, cb); + } } static void ide_sector_write_timer_cb(void *opaque) @@ -2204,11 +2211,6 @@ static void ide_init1(IDEBus *bus, int unit) ide_sector_write_timer_cb, s); } -static void ide_nop_start(IDEDMA *dma, IDEState *s, - BlockDriverCompletionFunc *cb) -{ -} - static int ide_nop_int(IDEDMA *dma, int x) { return 0; @@ -2219,7 +2221,6 @@ static void ide_nop_restart(void *opaque, int x, RunState y) } static const IDEDMAOps ide_dma_nop_ops = { - .start_dma = ide_nop_start, .prepare_buf = ide_nop_int, .rw_buf = ide_nop_int, .set_unit = ide_nop_int, diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 64fbf2fb62..2fe1f0a316 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -532,6 +532,7 @@ void ide_bus_reset(IDEBus *bus); int64_t ide_get_sector(IDEState *s); void ide_set_sector(IDEState *s, int64_t sector_num); +void ide_start_dma(IDEState *s, BlockDriverCompletionFunc *cb); void ide_dma_error(IDEState *s); void ide_atapi_cmd_ok(IDEState *s); -- cgit v1.2.3-55-g7522 From 0def37baf9add908c5462b0b8e2d3f80b563a9f9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:11 -0400 Subject: ide: remove wrong setting of BM_STATUS_INT Similar to the case removed in commit 69c38b8 (ide/core: Remove explicit setting of BM_STATUS_INT, 2011-05-19), the only remaining use of add_status(..., BM_STATUS_INT) is for short PRDs. The flag should not be raised in this case. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 4 ---- hw/ide/atapi.c | 1 - 2 files changed, 5 deletions(-) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index adbac3d52f..14677ece97 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1107,10 +1107,6 @@ static int ahci_dma_add_status(IDEDMA *dma, int status) AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); DPRINTF(ad->port_no, "set status: %x\n", status); - if (status & BM_STATUS_INT) { - ahci_trigger_irq(ad->hba, ad, PORT_IRQ_STAT_DSS); - } - return 0; } diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index d13395ed2c..46ed3f54c0 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -355,7 +355,6 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) eot: bdrv_acct_done(s->bs, &s->acct); - s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT); ide_set_inactive(s); } -- cgit v1.2.3-55-g7522 From 0e7ce54cf5fb9b7e8d19a5a4eb1facf123edbcef Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:12 -0400 Subject: ide: fold add_status callback into set_inactive It is now called only after the set_inactive callback. Put the two together. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 9 --------- hw/ide/atapi.c | 2 +- hw/ide/core.c | 12 ++++-------- hw/ide/internal.h | 6 +++--- hw/ide/macio.c | 1 - hw/ide/pci.c | 19 +++++++------------ 6 files changed, 15 insertions(+), 34 deletions(-) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 14677ece97..0ec5627a6c 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1102,14 +1102,6 @@ static int ahci_dma_set_unit(IDEDMA *dma, int unit) return 0; } -static int ahci_dma_add_status(IDEDMA *dma, int status) -{ - AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); - DPRINTF(ad->port_no, "set status: %x\n", status); - - return 0; -} - static void ahci_async_cmd_done(IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); @@ -1140,7 +1132,6 @@ static const IDEDMAOps ahci_dma_ops = { .prepare_buf = ahci_dma_prepare_buf, .rw_buf = ahci_dma_rw_buf, .set_unit = ahci_dma_set_unit, - .add_status = ahci_dma_add_status, .async_cmd_done = ahci_async_cmd_done, .restart_cb = ahci_dma_restart_cb, }; diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index 46ed3f54c0..3b419b3d05 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -355,7 +355,7 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) eot: bdrv_acct_done(s->bs, &s->acct); - ide_set_inactive(s); + ide_set_inactive(s, false); } /* start a CD-CDROM read command with DMA */ diff --git a/hw/ide/core.c b/hw/ide/core.c index aa561ae4f8..24f24ce7e4 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -594,11 +594,11 @@ static void ide_async_cmd_done(IDEState *s) } } -void ide_set_inactive(IDEState *s) +void ide_set_inactive(IDEState *s, bool more) { s->bus->dma->aiocb = NULL; if (s->bus->dma->ops->set_inactive) { - s->bus->dma->ops->set_inactive(s->bus->dma); + s->bus->dma->ops->set_inactive(s->bus->dma, more); } ide_async_cmd_done(s); } @@ -608,7 +608,7 @@ void ide_dma_error(IDEState *s) ide_transfer_stop(s); s->error = ABRT_ERR; s->status = READY_STAT | ERR_STAT; - ide_set_inactive(s); + ide_set_inactive(s, false); ide_set_irq(s->bus); } @@ -719,10 +719,7 @@ eot: if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { bdrv_acct_done(s->bs, &s->acct); } - ide_set_inactive(s); - if (stay_active) { - s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_DMAING); - } + ide_set_inactive(s, stay_active); } static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd) @@ -2224,7 +2221,6 @@ static const IDEDMAOps ide_dma_nop_ops = { .prepare_buf = ide_nop_int, .rw_buf = ide_nop_int, .set_unit = ide_nop_int, - .add_status = ide_nop_int, .restart_cb = ide_nop_restart, }; diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 2fe1f0a316..b35e52ce98 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -322,6 +322,7 @@ typedef void EndTransferFunc(IDEState *); typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockDriverCompletionFunc *); typedef void DMAVoidFunc(IDEDMA *); typedef int DMAIntFunc(IDEDMA *, int); +typedef void DMAStopFunc(IDEDMA *, bool); typedef void DMARestartFunc(void *, int, RunState); struct unreported_events { @@ -431,8 +432,7 @@ struct IDEDMAOps { DMAIntFunc *prepare_buf; DMAIntFunc *rw_buf; DMAIntFunc *set_unit; - DMAIntFunc *add_status; - DMAVoidFunc *set_inactive; + DMAStopFunc *set_inactive; DMAVoidFunc *async_cmd_done; DMARestartFunc *restart_cb; DMAVoidFunc *reset; @@ -565,7 +565,7 @@ void ide_flush_cache(IDEState *s); void ide_transfer_start(IDEState *s, uint8_t *buf, int size, EndTransferFunc *end_transfer_func); void ide_transfer_stop(IDEState *s); -void ide_set_inactive(IDEState *s); +void ide_set_inactive(IDEState *s, bool more); BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); diff --git a/hw/ide/macio.c b/hw/ide/macio.c index b7cedb65a5..b0c0d400d9 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -569,7 +569,6 @@ static const IDEDMAOps dbdma_ops = { .prepare_buf = ide_nop_int, .rw_buf = ide_nop_int, .set_unit = ide_nop_int, - .add_status = ide_nop_int, .restart_cb = ide_nop_restart, }; diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 1ee8c0a4d5..73267a444f 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -152,21 +152,17 @@ static int bmdma_set_unit(IDEDMA *dma, int unit) return 0; } -static int bmdma_add_status(IDEDMA *dma, int status) +static void bmdma_set_inactive(IDEDMA *dma, bool more) { BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); - bm->status |= status; - return 0; -} - -static void bmdma_set_inactive(IDEDMA *dma) -{ - BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); - - bm->status &= ~BM_STATUS_DMAING; bm->dma_cb = NULL; bm->unit = -1; + if (more) { + bm->status |= BM_STATUS_DMAING; + } else { + bm->status &= ~BM_STATUS_DMAING; + } } static void bmdma_restart_dma(BMDMAState *bm, enum ide_dma_cmd dma_cmd) @@ -241,7 +237,7 @@ static void bmdma_cancel(BMDMAState *bm) { if (bm->status & BM_STATUS_DMAING) { /* cancel DMA request */ - bmdma_set_inactive(&bm->dma); + bmdma_set_inactive(&bm->dma, false); } } @@ -498,7 +494,6 @@ static const struct IDEDMAOps bmdma_ops = { .prepare_buf = bmdma_prepare_buf, .rw_buf = bmdma_rw_buf, .set_unit = bmdma_set_unit, - .add_status = bmdma_add_status, .set_inactive = bmdma_set_inactive, .restart_cb = bmdma_restart_cb, .reset = bmdma_reset, -- cgit v1.2.3-55-g7522 From 7e2648df86a36c063a34196b3bede0a13ebc6809 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:13 -0400 Subject: ide: move BM_STATUS bits to pci.[ch] They are not used by AHCI, and should not be even available there. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/internal.h | 11 ----------- hw/ide/pci.c | 4 ++++ hw/ide/pci.h | 7 +++++++ 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'hw') diff --git a/hw/ide/internal.h b/hw/ide/internal.h index b35e52ce98..f369b0bc26 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -484,10 +484,6 @@ struct IDEDevice { uint64_t wwn; }; -#define BM_STATUS_DMAING 0x01 -#define BM_STATUS_ERROR 0x02 -#define BM_STATUS_INT 0x04 - /* FIXME These are not status register bits */ #define BM_STATUS_DMA_RETRY 0x08 #define BM_STATUS_PIO_RETRY 0x10 @@ -495,13 +491,6 @@ struct IDEDevice { #define BM_STATUS_RETRY_FLUSH 0x40 #define BM_STATUS_RETRY_TRIM 0x80 -#define BM_MIGRATION_COMPAT_STATUS_BITS \ - (BM_STATUS_DMA_RETRY | BM_STATUS_PIO_RETRY | \ - BM_STATUS_RETRY_READ | BM_STATUS_RETRY_FLUSH) - -#define BM_CMD_START 0x01 -#define BM_CMD_READ 0x08 - static inline IDEState *idebus_active_if(IDEBus *bus) { return bus->ifs + bus->unit; diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 73267a444f..0e82cabffe 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -33,6 +33,10 @@ #define BMDMA_PAGE_SIZE 4096 +#define BM_MIGRATION_COMPAT_STATUS_BITS \ + (BM_STATUS_DMA_RETRY | BM_STATUS_PIO_RETRY | \ + BM_STATUS_RETRY_READ | BM_STATUS_RETRY_FLUSH) + static void bmdma_start_dma(IDEDMA *dma, IDEState *s, BlockDriverCompletionFunc *dma_cb) { diff --git a/hw/ide/pci.h b/hw/ide/pci.h index 2428275c8d..517711f913 100644 --- a/hw/ide/pci.h +++ b/hw/ide/pci.h @@ -3,6 +3,13 @@ #include +#define BM_STATUS_DMAING 0x01 +#define BM_STATUS_ERROR 0x02 +#define BM_STATUS_INT 0x04 + +#define BM_CMD_START 0x01 +#define BM_CMD_READ 0x08 + typedef struct BMDMAState { IDEDMA dma; uint8_t cmd; -- cgit v1.2.3-55-g7522 From fd648f10af1ef41ac37d99ccc341261d6db69ff4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:14 -0400 Subject: ide: move retry constants out of BM_STATUS_* namespace Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/core.c | 20 ++++++++++---------- hw/ide/internal.h | 12 ++++++------ hw/ide/pci.c | 14 +++++++------- 3 files changed, 23 insertions(+), 23 deletions(-) (limited to 'hw') diff --git a/hw/ide/core.c b/hw/ide/core.c index 24f24ce7e4..00fe043d11 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -523,8 +523,8 @@ static void ide_sector_read_cb(void *opaque, int ret) bdrv_acct_done(s->bs, &s->acct); if (ret != 0) { - if (ide_handle_rw_error(s, -ret, BM_STATUS_PIO_RETRY | - BM_STATUS_RETRY_READ)) { + if (ide_handle_rw_error(s, -ret, IDE_RETRY_PIO | + IDE_RETRY_READ)) { return; } } @@ -614,14 +614,14 @@ void ide_dma_error(IDEState *s) static int ide_handle_rw_error(IDEState *s, int error, int op) { - bool is_read = (op & BM_STATUS_RETRY_READ) != 0; + bool is_read = (op & IDE_RETRY_READ) != 0; BlockErrorAction action = bdrv_get_error_action(s->bs, is_read, error); if (action == BLOCK_ERROR_ACTION_STOP) { s->bus->dma->ops->set_unit(s->bus->dma, s->unit); s->bus->error_status = op; } else if (action == BLOCK_ERROR_ACTION_REPORT) { - if (op & BM_STATUS_DMA_RETRY) { + if (op & IDE_RETRY_DMA) { dma_buf_commit(s); ide_dma_error(s); } else { @@ -640,12 +640,12 @@ void ide_dma_cb(void *opaque, int ret) bool stay_active = false; if (ret < 0) { - int op = BM_STATUS_DMA_RETRY; + int op = IDE_RETRY_DMA; if (s->dma_cmd == IDE_DMA_READ) - op |= BM_STATUS_RETRY_READ; + op |= IDE_RETRY_READ; else if (s->dma_cmd == IDE_DMA_TRIM) - op |= BM_STATUS_RETRY_TRIM; + op |= IDE_RETRY_TRIM; if (ide_handle_rw_error(s, -ret, op)) { return; @@ -769,7 +769,7 @@ static void ide_sector_write_cb(void *opaque, int ret) s->status &= ~BUSY_STAT; if (ret != 0) { - if (ide_handle_rw_error(s, -ret, BM_STATUS_PIO_RETRY)) { + if (ide_handle_rw_error(s, -ret, IDE_RETRY_PIO)) { return; } } @@ -843,7 +843,7 @@ static void ide_flush_cb(void *opaque, int ret) if (ret < 0) { /* XXX: What sector number to set here? */ - if (ide_handle_rw_error(s, -ret, BM_STATUS_RETRY_FLUSH)) { + if (ide_handle_rw_error(s, -ret, IDE_RETRY_FLUSH)) { return; } } @@ -2338,7 +2338,7 @@ static bool ide_drive_pio_state_needed(void *opaque) IDEState *s = opaque; return ((s->status & DRQ_STAT) != 0) - || (s->bus->error_status & BM_STATUS_PIO_RETRY); + || (s->bus->error_status & IDE_RETRY_PIO); } static bool ide_tray_state_needed(void *opaque) diff --git a/hw/ide/internal.h b/hw/ide/internal.h index f369b0bc26..b919e96ff8 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -484,12 +484,12 @@ struct IDEDevice { uint64_t wwn; }; -/* FIXME These are not status register bits */ -#define BM_STATUS_DMA_RETRY 0x08 -#define BM_STATUS_PIO_RETRY 0x10 -#define BM_STATUS_RETRY_READ 0x20 -#define BM_STATUS_RETRY_FLUSH 0x40 -#define BM_STATUS_RETRY_TRIM 0x80 +/* These are used for the error_status field of IDEBus */ +#define IDE_RETRY_DMA 0x08 +#define IDE_RETRY_PIO 0x10 +#define IDE_RETRY_READ 0x20 +#define IDE_RETRY_FLUSH 0x40 +#define IDE_RETRY_TRIM 0x80 static inline IDEState *idebus_active_if(IDEBus *bus) { diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 0e82cabffe..2397f355cc 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -34,8 +34,8 @@ #define BMDMA_PAGE_SIZE 4096 #define BM_MIGRATION_COMPAT_STATUS_BITS \ - (BM_STATUS_DMA_RETRY | BM_STATUS_PIO_RETRY | \ - BM_STATUS_RETRY_READ | BM_STATUS_RETRY_FLUSH) + (IDE_RETRY_DMA | IDE_RETRY_PIO | \ + IDE_RETRY_READ | IDE_RETRY_FLUSH) static void bmdma_start_dma(IDEDMA *dma, IDEState *s, BlockDriverCompletionFunc *dma_cb) @@ -198,7 +198,7 @@ static void bmdma_restart_bh(void *opaque) return; } - is_read = (bus->error_status & BM_STATUS_RETRY_READ) != 0; + 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 @@ -206,19 +206,19 @@ static void bmdma_restart_bh(void *opaque) error_status = bus->error_status; bus->error_status = 0; - if (error_status & BM_STATUS_DMA_RETRY) { - if (error_status & BM_STATUS_RETRY_TRIM) { + if (error_status & IDE_RETRY_DMA) { + if (error_status & IDE_RETRY_TRIM) { bmdma_restart_dma(bm, IDE_DMA_TRIM); } else { bmdma_restart_dma(bm, is_read ? IDE_DMA_READ : IDE_DMA_WRITE); } - } else if (error_status & BM_STATUS_PIO_RETRY) { + } else if (error_status & IDE_RETRY_PIO) { if (is_read) { ide_sector_read(bmdma_active_if(bm)); } else { ide_sector_write(bmdma_active_if(bm)); } - } else if (error_status & BM_STATUS_RETRY_FLUSH) { + } else if (error_status & IDE_RETRY_FLUSH) { ide_flush_cache(bmdma_active_if(bm)); } } -- cgit v1.2.3-55-g7522 From 1f88f77348e14bd9f781db7ff66d2f680daa1d62 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:15 -0400 Subject: ahci: remove duplicate PORT_IRQ_* constants These are defined twice, just use one set consistently. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 6 +++--- hw/ide/ahci.h | 21 --------------------- 2 files changed, 3 insertions(+), 24 deletions(-) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 0ec5627a6c..e1f27bda51 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -584,7 +584,7 @@ static void ahci_write_fis_sdb(AHCIState *s, int port, uint32_t finished) s->dev[port].finished |= finished; *(uint32_t*)(sdb_fis + 4) = cpu_to_le32(s->dev[port].finished); - ahci_trigger_irq(s, &s->dev[port], PORT_IRQ_STAT_SDBS); + ahci_trigger_irq(s, &s->dev[port], PORT_IRQ_SDB_FIS); } static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) @@ -629,7 +629,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) } if (d2h_fis[2] & ERR_STAT) { - ahci_trigger_irq(ad->hba, ad, PORT_IRQ_STAT_TFES); + ahci_trigger_irq(ad->hba, ad, PORT_IRQ_TF_ERR); } ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS); @@ -1039,7 +1039,7 @@ out: if (!(s->status & DRQ_STAT)) { /* done with DMA */ - ahci_trigger_irq(ad->hba, ad, PORT_IRQ_STAT_DSS); + ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS); } } diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h index f418b30ce7..1543df7b7d 100644 --- a/hw/ide/ahci.h +++ b/hw/ide/ahci.h @@ -132,27 +132,6 @@ #define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */ #define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */ -#define PORT_IRQ_STAT_DHRS (1 << 0) /* Device to Host Register FIS */ -#define PORT_IRQ_STAT_PSS (1 << 1) /* PIO Setup FIS */ -#define PORT_IRQ_STAT_DSS (1 << 2) /* DMA Setup FIS */ -#define PORT_IRQ_STAT_SDBS (1 << 3) /* Set Device Bits */ -#define PORT_IRQ_STAT_UFS (1 << 4) /* Unknown FIS */ -#define PORT_IRQ_STAT_DPS (1 << 5) /* Descriptor Processed */ -#define PORT_IRQ_STAT_PCS (1 << 6) /* Port Connect Change Status */ -#define PORT_IRQ_STAT_DMPS (1 << 7) /* Device Mechanical Presence - Status */ -#define PORT_IRQ_STAT_PRCS (1 << 22) /* File Ready Status */ -#define PORT_IRQ_STAT_IPMS (1 << 23) /* Incorrect Port Multiplier - Status */ -#define PORT_IRQ_STAT_OFS (1 << 24) /* Overflow Status */ -#define PORT_IRQ_STAT_INFS (1 << 26) /* Interface Non-Fatal Error - Status */ -#define PORT_IRQ_STAT_IFS (1 << 27) /* Interface Fatal Error */ -#define PORT_IRQ_STAT_HBDS (1 << 28) /* Host Bus Data Error Status */ -#define PORT_IRQ_STAT_HBFS (1 << 29) /* Host Bus Fatal Error Status */ -#define PORT_IRQ_STAT_TFES (1 << 30) /* Task File Error Status */ -#define PORT_IRQ_STAT_CPDS (1U << 31) /* Code Port Detect Status */ - /* ap->flags bits */ #define AHCI_FLAG_NO_NCQ (1 << 24) #define AHCI_FLAG_IGN_IRQ_IF_ERR (1 << 25) /* ignore IRQ_IF_ERR */ -- cgit v1.2.3-55-g7522 From 08ee9e3368be0e9394037d339fc4ebf1392a9896 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:16 -0400 Subject: ide: stop PIO transfer on errors This will provide a hook for sending the result of the command via the FIS receive area. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/ide/core.c b/hw/ide/core.c index 00fe043d11..91a17e6f1d 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -420,6 +420,7 @@ BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs, static inline void ide_abort_command(IDEState *s) { + ide_transfer_stop(s); s->status = READY_STAT | ERR_STAT; s->error = ABRT_ERR; } @@ -605,9 +606,7 @@ void ide_set_inactive(IDEState *s, bool more) void ide_dma_error(IDEState *s) { - ide_transfer_stop(s); - s->error = ABRT_ERR; - s->status = READY_STAT | ERR_STAT; + ide_abort_command(s); ide_set_inactive(s, false); ide_set_irq(s->bus); } -- cgit v1.2.3-55-g7522 From c7e73adb48abb9fc5cbfc4f1ce6090fbdb0bdbea Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:17 -0400 Subject: ide: make all commands go through cmd_done AHCI has code to fill in the D2H FIS trigger the IRQ all over the place. Centralize this in a single cmd_done callback by generalizing the existing async_cmd_done callback. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 16 +++------------- hw/ide/atapi.c | 2 +- hw/ide/core.c | 20 +++++++++++--------- hw/ide/internal.h | 2 +- 4 files changed, 16 insertions(+), 24 deletions(-) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index e1f27bda51..b40ec06c3a 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -969,11 +969,6 @@ static int handle_cmd(AHCIState *s, int port, int slot) /* We're ready to process the command in FIS byte 2. */ ide_exec_cmd(&s->dev[port].port, cmd_fis[2]); - - if ((s->dev[port].port.ifs[0].status & (READY_STAT|DRQ_STAT|BUSY_STAT)) == - READY_STAT) { - ahci_write_fis_d2h(&s->dev[port], cmd_fis); - } } out: @@ -1036,11 +1031,6 @@ out: } s->end_transfer_func(s); - - if (!(s->status & DRQ_STAT)) { - /* done with DMA */ - ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS); - } } static void ahci_start_dma(IDEDMA *dma, IDEState *s, @@ -1102,11 +1092,11 @@ static int ahci_dma_set_unit(IDEDMA *dma, int unit) return 0; } -static void ahci_async_cmd_done(IDEDMA *dma) +static void ahci_cmd_done(IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); - DPRINTF(ad->port_no, "async cmd done\n"); + DPRINTF(ad->port_no, "cmd done\n"); /* update d2h status */ ahci_write_fis_d2h(ad, NULL); @@ -1132,7 +1122,7 @@ static const IDEDMAOps ahci_dma_ops = { .prepare_buf = ahci_dma_prepare_buf, .rw_buf = ahci_dma_rw_buf, .set_unit = ahci_dma_set_unit, - .async_cmd_done = ahci_async_cmd_done, + .cmd_done = ahci_cmd_done, .restart_cb = ahci_dma_restart_cb, }; diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index 3b419b3d05..3d92b52dbc 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -174,9 +174,9 @@ void ide_atapi_cmd_reply_end(IDEState *s) #endif if (s->packet_transfer_size <= 0) { /* end of transfer */ - ide_transfer_stop(s); s->status = READY_STAT | SEEK_STAT; s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + ide_transfer_stop(s); ide_set_irq(s->bus); #ifdef DEBUG_IDE_ATAPI printf("status=0x%x\n", s->status); diff --git a/hw/ide/core.c b/hw/ide/core.c index 91a17e6f1d..bdb0a804cf 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -440,12 +440,20 @@ void ide_transfer_start(IDEState *s, uint8_t *buf, int size, } } +static void ide_cmd_done(IDEState *s) +{ + if (s->bus->dma->ops->cmd_done) { + s->bus->dma->ops->cmd_done(s->bus->dma); + } +} + void ide_transfer_stop(IDEState *s) { s->end_transfer_func = ide_transfer_stop; s->data_ptr = s->io_buffer; s->data_end = s->io_buffer; s->status &= ~DRQ_STAT; + ide_cmd_done(s); } int64_t ide_get_sector(IDEState *s) @@ -588,20 +596,13 @@ static void dma_buf_commit(IDEState *s) qemu_sglist_destroy(&s->sg); } -static void ide_async_cmd_done(IDEState *s) -{ - if (s->bus->dma->ops->async_cmd_done) { - s->bus->dma->ops->async_cmd_done(s->bus->dma); - } -} - void ide_set_inactive(IDEState *s, bool more) { s->bus->dma->aiocb = NULL; if (s->bus->dma->ops->set_inactive) { s->bus->dma->ops->set_inactive(s->bus->dma, more); } - ide_async_cmd_done(s); + ide_cmd_done(s); } void ide_dma_error(IDEState *s) @@ -849,7 +850,7 @@ static void ide_flush_cb(void *opaque, int ret) bdrv_acct_done(s->bs, &s->acct); s->status = READY_STAT | SEEK_STAT; - ide_async_cmd_done(s); + ide_cmd_done(s); ide_set_irq(s->bus); } @@ -1773,6 +1774,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) s->status |= SEEK_STAT; } + ide_cmd_done(s); ide_set_irq(s->bus); } } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index b919e96ff8..5c19f79437 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -433,7 +433,7 @@ struct IDEDMAOps { DMAIntFunc *rw_buf; DMAIntFunc *set_unit; DMAStopFunc *set_inactive; - DMAVoidFunc *async_cmd_done; + DMAVoidFunc *cmd_done; DMARestartFunc *restart_cb; DMAVoidFunc *reset; }; -- cgit v1.2.3-55-g7522 From 088415202b9dadb387cb6d9fd25324ae7fd4da4b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:18 -0400 Subject: ahci: construct PIO Setup FIS for PIO commands PIO commands should put a PIO Setup FIS in the receive area when data transfer ends. Currently QEMU does not do this and only places the D2H FIS at the end of the operation. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'hw') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index b40ec06c3a..4cda0d0075 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -587,6 +587,71 @@ static void ahci_write_fis_sdb(AHCIState *s, int port, uint32_t finished) ahci_trigger_irq(s, &s->dev[port], PORT_IRQ_SDB_FIS); } +static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len) +{ + AHCIPortRegs *pr = &ad->port_regs; + uint8_t *pio_fis, *cmd_fis; + uint64_t tbl_addr; + dma_addr_t cmd_len = 0x80; + + if (!ad->res_fis || !(pr->cmd & PORT_CMD_FIS_RX)) { + return; + } + + /* map cmd_fis */ + tbl_addr = le64_to_cpu(ad->cur_cmd->tbl_addr); + cmd_fis = dma_memory_map(ad->hba->as, tbl_addr, &cmd_len, + DMA_DIRECTION_TO_DEVICE); + + if (cmd_fis == NULL) { + DPRINTF(ad->port_no, "dma_memory_map failed in ahci_write_fis_pio"); + ahci_trigger_irq(ad->hba, ad, PORT_IRQ_HBUS_ERR); + return; + } + + if (cmd_len != 0x80) { + DPRINTF(ad->port_no, + "dma_memory_map mapped too few bytes in ahci_write_fis_pio"); + dma_memory_unmap(ad->hba->as, cmd_fis, cmd_len, + DMA_DIRECTION_TO_DEVICE, cmd_len); + ahci_trigger_irq(ad->hba, ad, PORT_IRQ_HBUS_ERR); + return; + } + + pio_fis = &ad->res_fis[RES_FIS_PSFIS]; + + pio_fis[0] = 0x5f; + pio_fis[1] = (ad->hba->control_regs.irqstatus ? (1 << 6) : 0); + pio_fis[2] = ad->port.ifs[0].status; + pio_fis[3] = ad->port.ifs[0].error; + + pio_fis[4] = cmd_fis[4]; + pio_fis[5] = cmd_fis[5]; + pio_fis[6] = cmd_fis[6]; + pio_fis[7] = cmd_fis[7]; + pio_fis[8] = cmd_fis[8]; + pio_fis[9] = cmd_fis[9]; + pio_fis[10] = cmd_fis[10]; + pio_fis[11] = cmd_fis[11]; + pio_fis[12] = cmd_fis[12]; + pio_fis[13] = cmd_fis[13]; + pio_fis[14] = 0; + pio_fis[15] = ad->port.ifs[0].status; + pio_fis[16] = len & 255; + pio_fis[17] = len >> 8; + pio_fis[18] = 0; + pio_fis[19] = 0; + + if (pio_fis[2] & ERR_STAT) { + ahci_trigger_irq(ad->hba, ad, PORT_IRQ_TF_ERR); + } + + ahci_trigger_irq(ad->hba, ad, PORT_IRQ_PIOS_FIS); + + dma_memory_unmap(ad->hba->as, cmd_fis, cmd_len, + DMA_DIRECTION_TO_DEVICE, cmd_len); +} + static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) { AHCIPortRegs *pr = &ad->port_regs; @@ -1031,6 +1096,11 @@ out: } s->end_transfer_func(s); + + if (!(s->status & DRQ_STAT)) { + /* done with PIO send/receive */ + ahci_write_fis_pio(ad, le32_to_cpu(ad->cur_cmd->status)); + } } static void ahci_start_dma(IDEDMA *dma, IDEState *s, -- cgit v1.2.3-55-g7522 From 552b48f44df99e095f04245a48d3b839bbe9912c Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 4 Aug 2014 17:11:19 -0400 Subject: q35: Enable the ioapic device to be seen by qtest. Currently, the ioapic device can not be found in a qtest environment when requesting "irq_interrupt_in ioapic" via the qtest socket. By mirroring how the ioapic is added in i44ofx (hw/i440/pc_piix.c), as a child of "q35," the device is able to be seen by qtest. Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/i386/pc_q35.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index c39ee98933..0dd7e02160 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -236,7 +236,7 @@ static void pc_q35_init(MachineState *machine) gsi_state->i8259_irq[i] = i8259[i]; } if (pci_enabled) { - ioapic_init_gsi(gsi_state, NULL); + ioapic_init_gsi(gsi_state, "q35"); } qdev_init_nofail(icc_bridge); -- cgit v1.2.3-55-g7522 From 58f16a7b47e0e8418b1222b6adc08d2b7079a4c0 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Fri, 8 Aug 2014 17:23:32 +0100 Subject: cmd646: add constants for CNTRL register access Signed-off-by: Mark Cave-Ayland Signed-off-by: Stefan Hajnoczi --- hw/ide/cmd646.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index a8e35fe38f..d8395ef248 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -33,6 +33,9 @@ #include /* CMD646 specific */ +#define CNTRL 0x51 +#define CNTRL_EN_CH0 0x04 +#define CNTRL_EN_CH1 0x08 #define MRDMODE 0x71 #define MRDMODE_INTR_CH0 0x04 #define MRDMODE_INTR_CH1 0x08 @@ -269,10 +272,10 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev) pci_conf[PCI_CLASS_PROG] = 0x8f; - pci_conf[0x51] = 0x04; // enable IDE0 + pci_conf[CNTRL] = CNTRL_EN_CH0; // enable IDE0 if (d->secondary) { /* XXX: if not enabled, really disable the seconday IDE controller */ - pci_conf[0x51] |= 0x08; /* enable IDE1 */ + pci_conf[CNTRL] |= CNTRL_EN_CH1; /* enable IDE1 */ } setup_cmd646_bar(d, 0); -- cgit v1.2.3-55-g7522 From 5bbc0a703d8241a866f51856336aeb2a2d54b79f Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Fri, 8 Aug 2014 17:23:33 +0100 Subject: cmd646: synchronise DMA interrupt status with UDMA interrupt status Make sure that the standard DMA interrupt status bits reflect any changes made to the UDMA interrupt status bits. The CMD646U2 datasheet claims that these bits are equivalent, and they must be synchronised for guests that manipulate both registers. Signed-off-by: Mark Cave-Ayland Signed-off-by: Stefan Hajnoczi --- hw/ide/cmd646.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'hw') diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index d8395ef248..c3c6c53d91 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -33,9 +33,13 @@ #include /* CMD646 specific */ +#define CFR 0x50 +#define CFR_INTR_CH0 0x04 #define CNTRL 0x51 #define CNTRL_EN_CH0 0x04 #define CNTRL_EN_CH1 0x08 +#define ARTTIM23 0x57 +#define ARTTIM23_INTR_CH1 0x10 #define MRDMODE 0x71 #define MRDMODE_INTR_CH0 0x04 #define MRDMODE_INTR_CH1 0x08 @@ -126,6 +130,22 @@ static void setup_cmd646_bar(PCIIDEState *d, int bus_num) "cmd646-data", 8); } +static void cmd646_update_dma_interrupts(PCIDevice *pd) +{ + /* Sync DMA interrupt status from UDMA interrupt status */ + if (pd->config[MRDMODE] & MRDMODE_INTR_CH0) { + pd->config[CFR] |= CFR_INTR_CH0; + } else { + pd->config[CFR] &= ~CFR_INTR_CH0; + } + + if (pd->config[MRDMODE] & MRDMODE_INTR_CH1) { + pd->config[ARTTIM23] |= ARTTIM23_INTR_CH1; + } else { + pd->config[ARTTIM23] &= ~ARTTIM23_INTR_CH1; + } +} + static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size) { @@ -184,6 +204,7 @@ static void bmdma_write(void *opaque, hwaddr addr, case 1: pci_dev->config[MRDMODE] = (pci_dev->config[MRDMODE] & ~0x30) | (val & 0x30); + cmd646_update_dma_interrupts(pci_dev); cmd646_update_irq(bm->pci_dev); break; case 2: @@ -249,6 +270,7 @@ static void cmd646_set_irq(void *opaque, int channel, int level) } else { pd->config[MRDMODE] &= ~irq_mask; } + cmd646_update_dma_interrupts(pd); cmd646_update_irq(d); } -- cgit v1.2.3-55-g7522 From dab91a1e138e9d0cb7dc0744c1e41e9f18af0fc4 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Fri, 8 Aug 2014 17:23:34 +0100 Subject: cmd646: switch cmd646_update_irq() to accept PCIDevice instead of PCIIDEState This is in preparation for adding configuration space accessors which accept PCIDevice as a parameter. Signed-off-by: Mark Cave-Ayland Signed-off-by: Stefan Hajnoczi --- hw/ide/cmd646.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'hw') diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index c3c6c53d91..11a3e52d71 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -48,7 +48,7 @@ #define UDIDETCR0 0x73 #define UDIDETCR1 0x7B -static void cmd646_update_irq(PCIIDEState *d); +static void cmd646_update_irq(PCIDevice *pd); static uint64_t cmd646_cmd_read(void *opaque, hwaddr addr, unsigned size) @@ -205,7 +205,7 @@ static void bmdma_write(void *opaque, hwaddr addr, pci_dev->config[MRDMODE] = (pci_dev->config[MRDMODE] & ~0x30) | (val & 0x30); cmd646_update_dma_interrupts(pci_dev); - cmd646_update_irq(bm->pci_dev); + cmd646_update_irq(pci_dev); break; case 2: bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06); @@ -245,9 +245,8 @@ static void bmdma_setup_bar(PCIIDEState *d) /* XXX: call it also when the MRDMODE is changed from the PCI config registers */ -static void cmd646_update_irq(PCIIDEState *d) +static void cmd646_update_irq(PCIDevice *pd) { - PCIDevice *pd = PCI_DEVICE(d); int pci_level; pci_level = ((pd->config[MRDMODE] & MRDMODE_INTR_CH0) && @@ -271,7 +270,7 @@ static void cmd646_set_irq(void *opaque, int channel, int level) pd->config[MRDMODE] &= ~irq_mask; } cmd646_update_dma_interrupts(pd); - cmd646_update_irq(d); + cmd646_update_irq(pd); } static void cmd646_reset(void *opaque) -- cgit v1.2.3-55-g7522 From 1d113ef874c04486cf4ee2894b2ef84bf8d17543 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Fri, 8 Aug 2014 17:23:35 +0100 Subject: cmd646: allow MRDMODE interrupt status bits clearing from PCI config space Make sure that we also update the normal DMA interrupt status bits at the same time, and alter the IRQ if being cleared accordingly. Signed-off-by: Mark Cave-Ayland Signed-off-by: Stefan Hajnoczi --- hw/ide/cmd646.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 11a3e52d71..b8dc4ab9ea 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -243,8 +243,6 @@ static void bmdma_setup_bar(PCIIDEState *d) } } -/* XXX: call it also when the MRDMODE is changed from the PCI config - registers */ static void cmd646_update_irq(PCIDevice *pd) { int pci_level; @@ -283,6 +281,30 @@ static void cmd646_reset(void *opaque) } } +static uint32_t cmd646_pci_config_read(PCIDevice *d, + uint32_t address, int len) +{ + return pci_default_read_config(d, address, len); +} + +static void cmd646_pci_config_write(PCIDevice *d, uint32_t addr, uint32_t val, + int l) +{ + uint32_t i; + + pci_default_write_config(d, addr, val, l); + + for (i = addr; i < addr + l; i++) { + switch (i) { + case MRDMODE: + cmd646_update_dma_interrupts(d); + break; + } + } + + cmd646_update_irq(d); +} + /* CMD646 PCI IDE controller */ static int pci_cmd646_ide_initfn(PCIDevice *dev) { @@ -299,6 +321,10 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev) pci_conf[CNTRL] |= CNTRL_EN_CH1; /* enable IDE1 */ } + /* Set write-to-clear interrupt bits */ + dev->wmask[MRDMODE] = 0x0; + dev->w1cmask[MRDMODE] = MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1; + setup_cmd646_bar(d, 0); setup_cmd646_bar(d, 1); pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd646_bar[0].data); @@ -371,6 +397,8 @@ static void cmd646_ide_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_CMD_646; k->revision = 0x07; k->class_id = PCI_CLASS_STORAGE_IDE; + k->config_read = cmd646_pci_config_read; + k->config_write = cmd646_pci_config_write; dc->props = cmd646_ide_properties; } -- cgit v1.2.3-55-g7522 From 271dddd133125ee00e347b154bb9d44e228929bb Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Fri, 8 Aug 2014 17:23:36 +0100 Subject: cmd646: synchronise UDMA interrupt status with DMA interrupt status Make sure that both registers are synchronised when being accessed through PCI configuration space. Signed-off-by: Mark Cave-Ayland Signed-off-by: Stefan Hajnoczi --- hw/ide/cmd646.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'hw') diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index b8dc4ab9ea..74d0deb6dd 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -146,6 +146,22 @@ static void cmd646_update_dma_interrupts(PCIDevice *pd) } } +static void cmd646_update_udma_interrupts(PCIDevice *pd) +{ + /* Sync UDMA interrupt status from DMA interrupt status */ + if (pd->config[CFR] & CFR_INTR_CH0) { + pd->config[MRDMODE] |= MRDMODE_INTR_CH0; + } else { + pd->config[MRDMODE] &= ~MRDMODE_INTR_CH0; + } + + if (pd->config[ARTTIM23] & ARTTIM23_INTR_CH1) { + pd->config[MRDMODE] |= MRDMODE_INTR_CH1; + } else { + pd->config[MRDMODE] &= ~MRDMODE_INTR_CH1; + } +} + static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size) { @@ -296,6 +312,10 @@ static void cmd646_pci_config_write(PCIDevice *d, uint32_t addr, uint32_t val, for (i = addr; i < addr + l; i++) { switch (i) { + case CFR: + case ARTTIM23: + cmd646_update_udma_interrupts(d); + break; case MRDMODE: cmd646_update_dma_interrupts(d); break; @@ -322,6 +342,10 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev) } /* Set write-to-clear interrupt bits */ + dev->wmask[CFR] = 0x0; + dev->w1cmask[CFR] = CFR_INTR_CH0; + dev->wmask[ARTTIM23] = 0x0; + dev->w1cmask[ARTTIM23] = ARTTIM23_INTR_CH1; dev->wmask[MRDMODE] = 0x0; dev->w1cmask[MRDMODE] = MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1; -- cgit v1.2.3-55-g7522 From 267e1a204c073eac28b1510bcc2404668d306e17 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 25 Jul 2014 14:10:46 +0200 Subject: dataplane: print why starting failed Setting up guest or host notifiers may fail, but the user will have no idea why: Let's print the error returned by the callback. Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck Signed-off-by: Stefan Hajnoczi --- hw/block/dataplane/virtio-blk.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'hw') diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index d6ba65ca23..527a53ce37 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -218,6 +218,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); VirtIOBlock *vblk = VIRTIO_BLK(s->vdev); VirtQueue *vq; + int r; if (s->started) { return; @@ -236,16 +237,18 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) } /* Set up guest notifier (irq) */ - if (k->set_guest_notifiers(qbus->parent, 1, true) != 0) { - fprintf(stderr, "virtio-blk failed to set guest notifier, " - "ensure -enable-kvm is set\n"); + r = k->set_guest_notifiers(qbus->parent, 1, true); + if (r != 0) { + fprintf(stderr, "virtio-blk failed to set guest notifier (%d), " + "ensure -enable-kvm is set\n", r); exit(1); } s->guest_notifier = virtio_queue_get_guest_notifier(vq); /* Set up virtqueue notify */ - if (k->set_host_notifier(qbus->parent, 0, true) != 0) { - fprintf(stderr, "virtio-blk failed to set host notifier\n"); + r = k->set_host_notifier(qbus->parent, 0, true); + if (r != 0) { + fprintf(stderr, "virtio-blk failed to set host notifier (%d)\n", r); exit(1); } s->host_notifier = *virtio_queue_get_host_notifier(vq); -- cgit v1.2.3-55-g7522 From f9907ebc4cc37d0317ee67cfa8d6618eaf8f658b Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 25 Jul 2014 14:10:47 +0200 Subject: dataplane: fail notifier setting gracefully The dataplane code is currently doing a hard exit if it fails to set up either guest or host notifiers. In practice, this may mean that a guest suddenly dies after a dataplane device failed to come up (e.g., when a file descriptor limit is hit for tne nth device). Let's just try to unwind the setup instead and return. Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck Signed-off-by: Stefan Hajnoczi --- hw/block/dataplane/virtio-blk.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 527a53ce37..94e1a29ef5 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -232,8 +232,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) vq = virtio_get_queue(s->vdev, 0); if (!vring_setup(&s->vring, s->vdev, 0)) { - s->starting = false; - return; + goto fail_vring; } /* Set up guest notifier (irq) */ @@ -241,7 +240,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) if (r != 0) { fprintf(stderr, "virtio-blk failed to set guest notifier (%d), " "ensure -enable-kvm is set\n", r); - exit(1); + goto fail_guest_notifiers; } s->guest_notifier = virtio_queue_get_guest_notifier(vq); @@ -249,7 +248,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) r = k->set_host_notifier(qbus->parent, 0, true); if (r != 0) { fprintf(stderr, "virtio-blk failed to set host notifier (%d)\n", r); - exit(1); + goto fail_host_notifier; } s->host_notifier = *virtio_queue_get_host_notifier(vq); @@ -269,6 +268,14 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) aio_context_acquire(s->ctx); aio_set_event_notifier(s->ctx, &s->host_notifier, handle_notify); aio_context_release(s->ctx); + return; + + fail_host_notifier: + k->set_guest_notifiers(qbus->parent, 1, false); + fail_guest_notifiers: + vring_teardown(&s->vring, s->vdev, 0); + fail_vring: + s->starting = false; } /* Context: QEMU global mutex held */ -- cgit v1.2.3-55-g7522 From 2f5f70fa5f41e3893a781c065be76e56db4f2e32 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 25 Jul 2014 14:10:48 +0200 Subject: dataplane: stop trying on notifier error If we fail to set up guest or host notifiers, there's no use trying again every time the guest kicks, so disable dataplane in that case. Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck Signed-off-by: Stefan Hajnoczi --- hw/block/dataplane/virtio-blk.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 94e1a29ef5..24a6b71395 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -28,6 +28,7 @@ struct VirtIOBlockDataPlane { bool started; bool starting; bool stopping; + bool disabled; VirtIOBlkConf *blk; @@ -220,7 +221,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) VirtQueue *vq; int r; - if (s->started) { + if (s->started || s->disabled) { return; } @@ -274,6 +275,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s) k->set_guest_notifiers(qbus->parent, 1, false); fail_guest_notifiers: vring_teardown(&s->vring, s->vdev, 0); + s->disabled = true; fail_vring: s->starting = false; } @@ -284,6 +286,13 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s) BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); VirtIOBlock *vblk = VIRTIO_BLK(s->vdev); + + + /* Better luck next time. */ + if (s->disabled) { + s->disabled = false; + return; + } if (!s->started || s->stopping) { return; } -- cgit v1.2.3-55-g7522 From f7f3ff1da0c451befc8d32f977f9c352d1303f40 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 12 Aug 2014 18:29:41 +0200 Subject: ide: Fix segfault when flushing a device that doesn't exist Signed-off-by: Kevin Wolf Signed-off-by: Stefan Hajnoczi --- hw/ide/core.c | 4 +++- tests/ide-test.c | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/ide/core.c b/hw/ide/core.c index bdb0a804cf..82dd4afd84 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -848,7 +848,9 @@ static void ide_flush_cb(void *opaque, int ret) } } - bdrv_acct_done(s->bs, &s->acct); + if (s->bs) { + bdrv_acct_done(s->bs, &s->acct); + } s->status = READY_STAT | SEEK_STAT; ide_cmd_done(s); ide_set_irq(s->bus); diff --git a/tests/ide-test.c b/tests/ide-test.c index a77a037d1e..ffce6ed669 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -564,6 +564,19 @@ static void test_retry_flush(void) ide_test_quit(); } +static void test_flush_nodev(void) +{ + ide_test_start(""); + + /* FLUSH CACHE command on device 0*/ + outb(IDE_BASE + reg_device, 0); + outb(IDE_BASE + reg_command, CMD_FLUSH_CACHE); + + /* Just testing that qemu doesn't crash... */ + + ide_test_quit(); +} + int main(int argc, char **argv) { const char *arch = qtest_get_arch(); @@ -601,6 +614,7 @@ int main(int argc, char **argv) qtest_add_func("/ide/bmdma/teardown", test_bmdma_teardown); qtest_add_func("/ide/flush", test_flush); + qtest_add_func("/ide/flush_nodev", test_flush_nodev); qtest_add_func("/ide/retry/flush", test_retry_flush); -- cgit v1.2.3-55-g7522 From a83ceea8ffa5ed8f0b09d6ed1f33da6aae8b14e4 Mon Sep 17 00:00:00 2001 From: Marc MarĂ­ Date: Tue, 12 Aug 2014 13:41:51 +0200 Subject: virtio-blk: Correct bug in support for flexible descriptor layout Without this correction, only a three descriptor layout is accepted, and requests with just two descriptors are not completed and no error message is displayed. Signed-off-by: Stefan Hajnoczi Signed-off-by: Marc MarĂ­ Signed-off-by: Stefan Hajnoczi --- hw/block/virtio-blk.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'hw') diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index c241c5002b..302c39e2be 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -404,19 +404,19 @@ void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb) * NB: per existing s/n string convention the string is * terminated by '\0' only when shorter than buffer. */ - strncpy(req->elem.in_sg[0].iov_base, - s->blk.serial ? s->blk.serial : "", - MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES)); + const char *serial = s->blk.serial ? s->blk.serial : ""; + size_t size = MIN(strlen(serial) + 1, + MIN(iov_size(in_iov, in_num), + VIRTIO_BLK_ID_BYTES)); + iov_from_buf(in_iov, in_num, 0, serial, size); virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); virtio_blk_free_request(req); } else if (type & VIRTIO_BLK_T_OUT) { - qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1], - req->elem.out_num - 1); + qemu_iovec_init_external(&req->qiov, iov, out_num); virtio_blk_handle_write(req, mrb); } else if (type == VIRTIO_BLK_T_IN || type == VIRTIO_BLK_T_BARRIER) { /* VIRTIO_BLK_T_IN is 0, so we can't just & it. */ - qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0], - req->elem.in_num - 1); + qemu_iovec_init_external(&req->qiov, in_iov, in_num); virtio_blk_handle_read(req); } else { virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP); -- cgit v1.2.3-55-g7522 From d66168ed687325aa6d338ce3a3cff18ce3098ed6 Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Wed, 13 Aug 2014 11:23:31 +0400 Subject: ide: only constrain read/write requests to drive size, not other types Commit 58ac321135a introduced a check to ide dma processing which constrains all requests to drive size. However, apparently, some valid requests (like TRIM) does not fit in this constraint, and fails in 2.1. So check the range only for reads and writes. Cc: qemu-stable@nongnu.org Signed-off-by: Michael Tokarev Signed-off-by: Markus Armbruster Signed-off-by: Stefan Hajnoczi --- hw/ide/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/ide/core.c b/hw/ide/core.c index 82dd4afd84..b48127f921 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -692,7 +692,8 @@ void ide_dma_cb(void *opaque, int ret) sector_num, n, s->dma_cmd); #endif - if (!ide_sect_range_ok(s, sector_num, n)) { + if ((s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) && + !ide_sect_range_ok(s, sector_num, n)) { dma_buf_commit(s); ide_dma_error(s); return; -- cgit v1.2.3-55-g7522