All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/3] ide: add TRIM support
@ 2011-05-19  8:57 Christoph Hellwig
  2011-05-19  8:57 ` [Qemu-devel] [PATCH 1/3] make dma_bdrv_io available to drivers Christoph Hellwig
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Christoph Hellwig @ 2011-05-19  8:57 UTC (permalink / raw)
  To: qemu-devel

This patchset resurrects my older patches to add TRIM support.  The
old approach to pass an action handler through the IDE subsystem doesn't
work any more after the refactoring for the AHCI driver, so not we simple
switch on the type of command passed in.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH 1/3] make dma_bdrv_io available to drivers
  2011-05-19  8:57 [Qemu-devel] [PATCH 0/3] ide: add TRIM support Christoph Hellwig
@ 2011-05-19  8:57 ` Christoph Hellwig
  2011-05-19  8:58 ` [Qemu-devel] [PATCH 2/3] ide: allow other dma comands than read and write Christoph Hellwig
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Christoph Hellwig @ 2011-05-19  8:57 UTC (permalink / raw)
  To: qemu-devel

Make dma_bdrv_io available for drivers, and pass an explicit I/O function
instead of hardcoding bdrv_aio_readv/bdrv_aio_writev.  This is required
to implement non-READ/WRITE dma commands in the ide driver, e.g. the
upcoming TRIM support.

Signed-off-by: Christoph Hellwig <hch@lst.de>

Index: qemu/dma-helpers.c
===================================================================
--- qemu.orig/dma-helpers.c	2010-12-16 17:40:25.422004054 +0100
+++ qemu/dma-helpers.c	2011-05-03 11:12:36.340387288 +0200
@@ -47,6 +47,7 @@ typedef struct {
     target_phys_addr_t sg_cur_byte;
     QEMUIOVector iov;
     QEMUBH *bh;
+    DMAIOFunc *io_func;
 } DMAAIOCB;
 
 static void dma_bdrv_cb(void *opaque, int ret);
@@ -116,13 +117,8 @@ static void dma_bdrv_cb(void *opaque, in
         return;
     }
 
-    if (dbs->is_write) {
-        dbs->acb = bdrv_aio_writev(dbs->bs, dbs->sector_num, &dbs->iov,
-                                   dbs->iov.size / 512, dma_bdrv_cb, dbs);
-    } else {
-        dbs->acb = bdrv_aio_readv(dbs->bs, dbs->sector_num, &dbs->iov,
-                                  dbs->iov.size / 512, dma_bdrv_cb, dbs);
-    }
+    dbs->acb = dbs->io_func(dbs->bs, dbs->sector_num, &dbs->iov,
+                            dbs->iov.size / 512, dma_bdrv_cb, dbs);
     if (!dbs->acb) {
         dma_bdrv_unmap(dbs);
         qemu_iovec_destroy(&dbs->iov);
@@ -144,12 +140,12 @@ static AIOPool dma_aio_pool = {
     .cancel             = dma_aio_cancel,
 };
 
-static BlockDriverAIOCB *dma_bdrv_io(
+BlockDriverAIOCB *dma_bdrv_io(
     BlockDriverState *bs, QEMUSGList *sg, uint64_t sector_num,
-    BlockDriverCompletionFunc *cb, void *opaque,
-    int is_write)
+    DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
+    void *opaque, int is_write)
 {
-    DMAAIOCB *dbs =  qemu_aio_get(&dma_aio_pool, bs, cb, opaque);
+    DMAAIOCB *dbs = qemu_aio_get(&dma_aio_pool, bs, cb, opaque);
 
     dbs->acb = NULL;
     dbs->bs = bs;
@@ -158,6 +154,7 @@ static BlockDriverAIOCB *dma_bdrv_io(
     dbs->sg_cur_index = 0;
     dbs->sg_cur_byte = 0;
     dbs->is_write = is_write;
+    dbs->io_func = io_func;
     dbs->bh = NULL;
     qemu_iovec_init(&dbs->iov, sg->nsg);
     dma_bdrv_cb(dbs, 0);
@@ -173,12 +170,12 @@ BlockDriverAIOCB *dma_bdrv_read(BlockDri
                                 QEMUSGList *sg, uint64_t sector,
                                 void (*cb)(void *opaque, int ret), void *opaque)
 {
-    return dma_bdrv_io(bs, sg, sector, cb, opaque, 0);
+    return dma_bdrv_io(bs, sg, sector, bdrv_aio_readv, cb, opaque, 0);
 }
 
 BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
                                  QEMUSGList *sg, uint64_t sector,
                                  void (*cb)(void *opaque, int ret), void *opaque)
 {
-    return dma_bdrv_io(bs, sg, sector, cb, opaque, 1);
+    return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque, 1);
 }
Index: qemu/dma.h
===================================================================
--- qemu.orig/dma.h	2010-12-16 17:40:25.431007267 +0100
+++ qemu/dma.h	2011-05-03 11:12:36.343720604 +0200
@@ -32,6 +32,14 @@ void qemu_sglist_add(QEMUSGList *qsg, ta
                      target_phys_addr_t len);
 void qemu_sglist_destroy(QEMUSGList *qsg);
 
+typedef BlockDriverAIOCB *DMAIOFunc(BlockDriverState *bs, int64_t sector_num,
+                                 QEMUIOVector *iov, int nb_sectors,
+                                 BlockDriverCompletionFunc *cb, void *opaque);
+
+BlockDriverAIOCB *dma_bdrv_io(BlockDriverState *bs,
+                              QEMUSGList *sg, uint64_t sector_num,
+                              DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
+                              void *opaque, int is_write);
 BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
                                 QEMUSGList *sg, uint64_t sector,
                                 BlockDriverCompletionFunc *cb, void *opaque);

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH 2/3] ide: allow other dma comands than read and write
  2011-05-19  8:57 [Qemu-devel] [PATCH 0/3] ide: add TRIM support Christoph Hellwig
  2011-05-19  8:57 ` [Qemu-devel] [PATCH 1/3] make dma_bdrv_io available to drivers Christoph Hellwig
@ 2011-05-19  8:58 ` Christoph Hellwig
  2011-05-19  8:58 ` [Qemu-devel] [PATCH 3/3] ide: add TRIM support Christoph Hellwig
  2011-06-07 11:13 ` [Qemu-devel] [PATCH 0/3] " Christoph Hellwig
  3 siblings, 0 replies; 10+ messages in thread
From: Christoph Hellwig @ 2011-05-19  8:58 UTC (permalink / raw)
  To: qemu-devel

Replace the is_read flag with a dma_cmd flag to allow the dma and
restart logic to handler other commands like TRIM.

Signed-off-by: Christoph Hellwig <hch@lst.de>

Index: qemu/hw/ide/core.c
===================================================================
--- qemu.orig/hw/ide/core.c	2011-05-18 20:24:04.318125593 +0200
+++ qemu/hw/ide/core.c	2011-05-18 20:30:20.855172933 +0200
@@ -473,7 +473,7 @@ handle_rw_error:
     if (ret < 0) {
         int op = BM_STATUS_DMA_RETRY;
 
-        if (s->is_read)
+        if (s->dma_cmd == IDE_DMA_READ)
             op |= BM_STATUS_RETRY_READ;
         if (ide_handle_rw_error(s, -ret, op)) {
             return;
@@ -483,7 +483,7 @@ handle_rw_error:
     n = s->io_buffer_size >> 9;
     sector_num = ide_get_sector(s);
     if (n > 0) {
-        dma_buf_commit(s, s->is_read);
+        dma_buf_commit(s, ide_cmd_is_read(s));
         sector_num += n;
         ide_set_sector(s, sector_num);
         s->nsector -= n;
@@ -500,20 +500,23 @@ handle_rw_error:
     n = s->nsector;
     s->io_buffer_index = 0;
     s->io_buffer_size = n * 512;
-    if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->is_read) == 0)
+    if (s->bus->dma->ops->prepare_buf(s->bus->dma, ide_cmd_is_read(s)) == 0)
         goto eot;
 
 #ifdef DEBUG_AIO
-    printf("ide_dma_cb: sector_num=%" PRId64 " n=%d, is_read=%d\n",
-           sector_num, n, s->is_read);
+    printf("ide_dma_cb: sector_num=%" PRId64 " n=%d, cmd_cmd=%d\n",
+           sector_num, n, s->dma_cmd);
 #endif
 
-    if (s->is_read) {
+    switch (s->dma_cmd) {
+    case IDE_DMA_READ:
         s->bus->dma->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
                                            ide_dma_cb, s);
-    } else {
+        break;
+    case IDE_DMA_WRITE:
         s->bus->dma->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
                                             ide_dma_cb, s);
+        break;
     }
 
     if (!s->bus->dma->aiocb) {
@@ -527,12 +530,12 @@ eot:
    ide_set_inactive(s);
 }
 
-static void ide_sector_start_dma(IDEState *s, int is_read)
+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->is_read = is_read;
+    s->dma_cmd = dma_cmd;
     s->bus->dma->ops->start_dma(s->bus->dma, s, ide_dma_cb);
 }
 
@@ -915,7 +918,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t
         if (!s->bs)
             goto abort_cmd;
 	ide_cmd_lba48_transform(s, lba48);
-        ide_sector_start_dma(s, 1);
+        ide_sector_start_dma(s, IDE_DMA_READ);
         break;
 	case WIN_WRITEDMA_EXT:
 	lba48 = 1;
@@ -924,7 +927,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t
         if (!s->bs)
             goto abort_cmd;
 	ide_cmd_lba48_transform(s, lba48);
-        ide_sector_start_dma(s, 0);
+        ide_sector_start_dma(s, IDE_DMA_WRITE);
         s->media_changed = 1;
         break;
     case WIN_READ_NATIVE_MAX_EXT:
Index: qemu/hw/ide/internal.h
===================================================================
--- qemu.orig/hw/ide/internal.h	2011-05-18 20:24:04.334126497 +0200
+++ qemu/hw/ide/internal.h	2011-05-18 20:28:17.133626100 +0200
@@ -379,6 +379,14 @@ struct unreported_events {
     bool new_media;
 };
 
+enum ide_dma_cmd {
+    IDE_DMA_READ,
+    IDE_DMA_WRITE,
+};
+
+#define ide_cmd_is_read(s) \
+	((s)->dma_cmd == IDE_DMA_READ)
+
 /* NOTE: IDEState represents in fact one drive */
 struct IDEState {
     IDEBus *bus;
@@ -446,7 +454,7 @@ struct IDEState {
     uint32_t mdata_size;
     uint8_t *mdata_storage;
     int media_changed;
-    int is_read;
+    enum ide_dma_cmd dma_cmd;
     /* SMART */
     uint8_t smart_enabled;
     uint8_t smart_autosave;
Index: qemu/hw/ide/macio.c
===================================================================
--- qemu.orig/hw/ide/macio.c	2011-05-18 20:24:04.346126902 +0200
+++ qemu/hw/ide/macio.c	2011-05-18 20:28:17.145627191 +0200
@@ -145,12 +145,17 @@ static void pmac_ide_transfer_cb(void *o
     io->addr += io->len;
     io->len = 0;
 
-    if (s->is_read)
+    switch (s->dma_cmd) {
+    case IDE_DMA_READ:
         m->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
 		                 pmac_ide_transfer_cb, io);
-    else
+        break;
+    case IDE_DMA_WRITE:
         m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
 		                  pmac_ide_transfer_cb, io);
+        break;
+    }
+
     if (!m->aiocb)
         pmac_ide_transfer_cb(io, -1);
 }
Index: qemu/hw/ide/pci.c
===================================================================
--- qemu.orig/hw/ide/pci.c	2011-05-18 20:24:04.362126865 +0200
+++ qemu/hw/ide/pci.c	2011-05-18 20:28:17.153625872 +0200
@@ -169,7 +169,7 @@ static int bmdma_set_inactive(IDEDMA *dm
     return 0;
 }
 
-static void bmdma_restart_dma(BMDMAState *bm, int is_read)
+static void bmdma_restart_dma(BMDMAState *bm, enum ide_dma_cmd dma_cmd)
 {
     IDEState *s = bmdma_active_if(bm);
 
@@ -177,7 +177,7 @@ static void bmdma_restart_dma(BMDMAState
     s->io_buffer_index = 0;
     s->io_buffer_size = 0;
     s->nsector = bm->nsector;
-    s->is_read = is_read;
+    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);
@@ -195,7 +195,7 @@ static void bmdma_restart_bh(void *opaqu
 
     if (bm->status & BM_STATUS_DMA_RETRY) {
         bm->status &= ~(BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ);
-        bmdma_restart_dma(bm, is_read);
+        bmdma_restart_dma(bm, is_read ? IDE_DMA_READ : IDE_DMA_WRITE);
     } else if (bm->status & BM_STATUS_PIO_RETRY) {
         bm->status &= ~(BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ);
         if (is_read) {

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH 3/3] ide: add TRIM support
  2011-05-19  8:57 [Qemu-devel] [PATCH 0/3] ide: add TRIM support Christoph Hellwig
  2011-05-19  8:57 ` [Qemu-devel] [PATCH 1/3] make dma_bdrv_io available to drivers Christoph Hellwig
  2011-05-19  8:58 ` [Qemu-devel] [PATCH 2/3] ide: allow other dma comands than read and write Christoph Hellwig
@ 2011-05-19  8:58 ` Christoph Hellwig
  2011-06-10 11:47   ` Kevin Wolf
                     ` (2 more replies)
  2011-06-07 11:13 ` [Qemu-devel] [PATCH 0/3] " Christoph Hellwig
  3 siblings, 3 replies; 10+ messages in thread
From: Christoph Hellwig @ 2011-05-19  8:58 UTC (permalink / raw)
  To: qemu-devel

Add support for TRIM sub function of the data set management command,
and wire it up to the qemu discard infrastructure.

Signed-off-by: Christoph Hellwig <hch@lst.de>

Index: qemu/hw/ide/core.c
===================================================================
--- qemu.orig/hw/ide/core.c	2011-05-18 20:30:20.855172933 +0200
+++ qemu/hw/ide/core.c	2011-05-18 20:32:26.237625024 +0200
@@ -124,6 +124,9 @@ static void ide_identify(IDEState *s)
     put_le16(p + 66, 120);
     put_le16(p + 67, 120);
     put_le16(p + 68, 120);
+    if (dev && dev->conf.discard_granularity) {
+        put_le16(p + 69, (1 << 14)); /* determinate TRIM behavior */
+    }
 
     if (s->ncq_queues) {
         put_le16(p + 75, s->ncq_queues - 1);
@@ -157,6 +160,9 @@ static void ide_identify(IDEState *s)
     dev = s->unit ? s->bus->slave : s->bus->master;
     if (dev && dev->conf.physical_block_size)
         put_le16(p + 106, 0x6000 | get_physical_block_exp(&dev->conf));
+    if (dev && dev->conf.discard_granularity) {
+        put_le16(p + 169, 1); /* TRIM support */
+    }
 
     memcpy(s->identify_data, p, sizeof(s->identify_data));
     s->identify_set = 1;
@@ -299,6 +305,72 @@ static void ide_set_signature(IDEState *
     }
 }
 
+typedef struct TrimAIOCB {
+    BlockDriverAIOCB common;
+    QEMUBH *bh;
+    int ret;
+} TrimAIOCB;
+
+static void trim_aio_cancel(BlockDriverAIOCB *acb)
+{
+    TrimAIOCB *iocb = container_of(acb, TrimAIOCB, common);
+
+    qemu_bh_delete(iocb->bh);
+    iocb->bh = NULL;
+    qemu_aio_release(iocb);
+}
+
+static AIOPool trim_aio_pool = {
+    .aiocb_size         = sizeof(TrimAIOCB),
+    .cancel             = trim_aio_cancel,
+};
+
+static void ide_trim_bh_cb(void *opaque)
+{
+    TrimAIOCB *iocb = opaque;
+
+    iocb->common.cb(iocb->common.opaque, iocb->ret);
+
+    qemu_bh_delete(iocb->bh);
+    iocb->bh = NULL;
+
+    qemu_aio_release(iocb);
+}
+
+BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs,
+        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    TrimAIOCB *iocb;
+    int i, j, ret;
+
+    iocb = qemu_aio_get(&trim_aio_pool, bs, cb, opaque);
+    iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
+    iocb->ret = 0;
+
+    for (j = 0; j < qiov->niov; j++) {
+        uint64_t *buffer = qiov->iov[j].iov_base;
+
+        for (i = 0; i < qiov->iov[j].iov_len / 8; i++) {
+            /* 6-byte LBA + 2-byte range per entry */
+            uint64_t entry = le64_to_cpu(buffer[i]);
+            uint64_t sector = entry & 0x0000ffffffffffffULL;
+            uint16_t count = entry >> 48;
+
+            if (count == 0)
+                break;
+
+            ret = bdrv_discard(bs, sector * 512, count * 512);
+            if (!iocb->ret)
+                iocb->ret = ret;
+        }
+    }
+
+    qemu_bh_schedule(iocb->bh);
+
+    return &iocb->common;
+}
+
 static inline void ide_abort_command(IDEState *s)
 {
     s->status = READY_STAT | ERR_STAT;
@@ -475,6 +547,9 @@ handle_rw_error:
 
         if (s->dma_cmd == IDE_DMA_READ)
             op |= BM_STATUS_RETRY_READ;
+        else if (s->dma_cmd == IDE_DMA_TRIM)
+            op |= BM_STATUS_RETRY_TRIM;
+
         if (ide_handle_rw_error(s, -ret, op)) {
             return;
         }
@@ -517,6 +592,10 @@ handle_rw_error:
         s->bus->dma->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
                                             ide_dma_cb, s);
         break;
+    case IDE_DMA_TRIM:
+        s->bus->dma->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num,
+                                         ide_issue_trim, ide_dma_cb, s, 1);
+        break;
     }
 
     if (!s->bus->dma->aiocb) {
@@ -817,6 +896,17 @@ void ide_exec_cmd(IDEBus *bus, uint32_t
         return;
 
     switch(val) {
+    case WIN_DSM:
+        switch (s->feature) {
+        case DSM_TRIM:
+            if (!s->bs)
+                goto abort_cmd;
+            ide_sector_start_dma(s, IDE_DMA_TRIM);
+            break;
+        default:
+            goto abort_cmd;
+        }
+        break;
     case WIN_IDENTIFY:
         if (s->bs && s->drive_kind != IDE_CD) {
             if (s->drive_kind != IDE_CFATA)
Index: qemu/hw/ide/internal.h
===================================================================
--- qemu.orig/hw/ide/internal.h	2011-05-18 20:28:17.133626100 +0200
+++ qemu/hw/ide/internal.h	2011-05-18 20:30:58.937624890 +0200
@@ -62,7 +62,11 @@ typedef struct IDEDMAOps IDEDMAOps;
  */
 #define CFA_REQ_EXT_ERROR_CODE		0x03 /* CFA Request Extended Error Code */
 /*
- *	0x04->0x07 Reserved
+ *      0x04->0x05 Reserved
+ */
+#define WIN_DSM                         0x06
+/*
+ *      0x07 Reserved
  */
 #define WIN_SRST			0x08 /* ATAPI soft reset command */
 #define WIN_DEVICE_RESET		0x08
@@ -190,6 +194,9 @@ typedef struct IDEDMAOps IDEDMAOps;
 
 #define IDE_DMA_BUF_SECTORS 256
 
+/* feature values for Data Set Management */
+#define DSM_TRIM                        0x01
+
 #if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS)
 #error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS"
 #endif
@@ -382,6 +389,7 @@ struct unreported_events {
 enum ide_dma_cmd {
     IDE_DMA_READ,
     IDE_DMA_WRITE,
+    IDE_DMA_TRIM,
 };
 
 #define ide_cmd_is_read(s) \
@@ -517,6 +525,7 @@ struct IDEDeviceInfo {
 #define BM_STATUS_PIO_RETRY  0x10
 #define BM_STATUS_RETRY_READ  0x20
 #define BM_STATUS_RETRY_FLUSH 0x40
+#define BM_STATUS_RETRY_TRIM 0x80
 
 #define BM_CMD_START     0x01
 #define BM_CMD_READ      0x08
@@ -583,6 +592,9 @@ void ide_transfer_start(IDEState *s, uin
                         EndTransferFunc *end_transfer_func);
 void ide_transfer_stop(IDEState *s);
 void ide_set_inactive(IDEState *s);
+BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs,
+        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
 
 /* hw/ide/atapi.c */
 void ide_atapi_cmd(IDEState *s);
Index: qemu/hw/ide/qdev.c
===================================================================
--- qemu.orig/hw/ide/qdev.c	2011-05-18 20:28:17.137626185 +0200
+++ qemu/hw/ide/qdev.c	2011-05-18 20:30:39.387125836 +0200
@@ -125,6 +125,11 @@ static int ide_drive_initfn(IDEDevice *d
     const char *serial;
     DriveInfo *dinfo;
 
+    if (dev->conf.discard_granularity && dev->conf.discard_granularity != 512) {
+        error_report("discard_granularity must be 512 for ide");
+        return -1;
+    }
+
     serial = dev->serial;
     if (!serial) {
         /* try to fall back to value set with legacy -drive serial=... */
Index: qemu/hw/ide/macio.c
===================================================================
--- qemu.orig/hw/ide/macio.c	2011-05-18 20:28:17.145627191 +0200
+++ qemu/hw/ide/macio.c	2011-05-18 20:30:39.387125836 +0200
@@ -154,6 +154,10 @@ static void pmac_ide_transfer_cb(void *o
         m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
 		                  pmac_ide_transfer_cb, io);
         break;
+    case IDE_DMA_TRIM:
+        m->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num,
+                               ide_issue_trim, pmac_ide_transfer_cb, s, 1);
+        break;
     }
 
     if (!m->aiocb)
Index: qemu/hw/ide/pci.c
===================================================================
--- qemu.orig/hw/ide/pci.c	2011-05-18 20:28:17.153625872 +0200
+++ qemu/hw/ide/pci.c	2011-05-18 20:33:06.102141553 +0200
@@ -205,6 +205,9 @@ static void bmdma_restart_bh(void *opaqu
         }
     } else if (bm->status & BM_STATUS_RETRY_FLUSH) {
         ide_flush_cache(bmdma_active_if(bm));
+    } else if (bm->status & BM_STATUS_RETRY_TRIM) {
+        bm->status &= ~BM_STATUS_RETRY_TRIM;
+        bmdma_restart_dma(bm, IDE_DMA_TRIM);
     }
 }
 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH 0/3] ide: add TRIM support
  2011-05-19  8:57 [Qemu-devel] [PATCH 0/3] ide: add TRIM support Christoph Hellwig
                   ` (2 preceding siblings ...)
  2011-05-19  8:58 ` [Qemu-devel] [PATCH 3/3] ide: add TRIM support Christoph Hellwig
@ 2011-06-07 11:13 ` Christoph Hellwig
  2011-06-07 14:11   ` Kevin Wolf
  3 siblings, 1 reply; 10+ messages in thread
From: Christoph Hellwig @ 2011-06-07 11:13 UTC (permalink / raw)
  To: qemu-devel

ping?

On Thu, May 19, 2011 at 10:57:48AM +0200, Christoph Hellwig wrote:
> This patchset resurrects my older patches to add TRIM support.  The
> old approach to pass an action handler through the IDE subsystem doesn't
> work any more after the refactoring for the AHCI driver, so not we simple
> switch on the type of command passed in.
---end quoted text---

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH 0/3] ide: add TRIM support
  2011-06-07 11:13 ` [Qemu-devel] [PATCH 0/3] " Christoph Hellwig
@ 2011-06-07 14:11   ` Kevin Wolf
  0 siblings, 0 replies; 10+ messages in thread
From: Kevin Wolf @ 2011-06-07 14:11 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: qemu-devel

Am 07.06.2011 13:13, schrieb Christoph Hellwig:
> ping?

Sorry, forgot to answer... The problem that I had with this was that you
add to the BM status register abuse with BM_STATUS_RETRY_TRIM. I
intended to look into this and then review the rest of it.

We'll need to have a fix for all the other abused bits anyway, so I
guess we can as well temporarily abuse one more bit (it happens to be
reserved/hardwired to 0 in my specs) and fix it only on top.

Kevin

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH 3/3] ide: add TRIM support
  2011-05-19  8:58 ` [Qemu-devel] [PATCH 3/3] ide: add TRIM support Christoph Hellwig
@ 2011-06-10 11:47   ` Kevin Wolf
  2011-06-10 14:04   ` Kevin Wolf
  2011-06-14 15:54   ` [Qemu-devel] [PATCH v2 " Kevin Wolf
  2 siblings, 0 replies; 10+ messages in thread
From: Kevin Wolf @ 2011-06-10 11:47 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: qemu-devel

Am 19.05.2011 10:58, schrieb Christoph Hellwig:
> Add support for TRIM sub function of the data set management command,
> and wire it up to the qemu discard infrastructure.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> 
> Index: qemu/hw/ide/core.c
> ===================================================================
> --- qemu.orig/hw/ide/core.c	2011-05-18 20:30:20.855172933 +0200
> +++ qemu/hw/ide/core.c	2011-05-18 20:32:26.237625024 +0200
> @@ -124,6 +124,9 @@ static void ide_identify(IDEState *s)
>      put_le16(p + 66, 120);
>      put_le16(p + 67, 120);
>      put_le16(p + 68, 120);
> +    if (dev && dev->conf.discard_granularity) {
> +        put_le16(p + 69, (1 << 14)); /* determinate TRIM behavior */
> +    }
>  
>      if (s->ncq_queues) {
>          put_le16(p + 75, s->ncq_queues - 1);
> @@ -157,6 +160,9 @@ static void ide_identify(IDEState *s)
>      dev = s->unit ? s->bus->slave : s->bus->master;
>      if (dev && dev->conf.physical_block_size)
>          put_le16(p + 106, 0x6000 | get_physical_block_exp(&dev->conf));
> +    if (dev && dev->conf.discard_granularity) {
> +        put_le16(p + 169, 1); /* TRIM support */
> +    }
>  
>      memcpy(s->identify_data, p, sizeof(s->identify_data));
>      s->identify_set = 1;
> @@ -299,6 +305,72 @@ static void ide_set_signature(IDEState *
>      }
>  }
>  
> +typedef struct TrimAIOCB {
> +    BlockDriverAIOCB common;
> +    QEMUBH *bh;
> +    int ret;
> +} TrimAIOCB;
> +
> +static void trim_aio_cancel(BlockDriverAIOCB *acb)
> +{
> +    TrimAIOCB *iocb = container_of(acb, TrimAIOCB, common);
> +
> +    qemu_bh_delete(iocb->bh);
> +    iocb->bh = NULL;
> +    qemu_aio_release(iocb);
> +}
> +
> +static AIOPool trim_aio_pool = {
> +    .aiocb_size         = sizeof(TrimAIOCB),
> +    .cancel             = trim_aio_cancel,
> +};
> +
> +static void ide_trim_bh_cb(void *opaque)
> +{
> +    TrimAIOCB *iocb = opaque;
> +
> +    iocb->common.cb(iocb->common.opaque, iocb->ret);
> +
> +    qemu_bh_delete(iocb->bh);
> +    iocb->bh = NULL;
> +
> +    qemu_aio_release(iocb);
> +}
> +
> +BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs,
> +        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> +        BlockDriverCompletionFunc *cb, void *opaque)
> +{
> +    TrimAIOCB *iocb;
> +    int i, j, ret;
> +
> +    iocb = qemu_aio_get(&trim_aio_pool, bs, cb, opaque);
> +    iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
> +    iocb->ret = 0;
> +
> +    for (j = 0; j < qiov->niov; j++) {
> +        uint64_t *buffer = qiov->iov[j].iov_base;
> +
> +        for (i = 0; i < qiov->iov[j].iov_len / 8; i++) {
> +            /* 6-byte LBA + 2-byte range per entry */
> +            uint64_t entry = le64_to_cpu(buffer[i]);
> +            uint64_t sector = entry & 0x0000ffffffffffffULL;
> +            uint16_t count = entry >> 48;
> +
> +            if (count == 0)
> +                break;
> +
> +            ret = bdrv_discard(bs, sector * 512, count * 512);

Hm... bdrv_discard wants sector numbers instead of bytes, doesn't it?

If you agree, I'll send out and apply a fixed and rebased version.

Kevin

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH 3/3] ide: add TRIM support
  2011-05-19  8:58 ` [Qemu-devel] [PATCH 3/3] ide: add TRIM support Christoph Hellwig
  2011-06-10 11:47   ` Kevin Wolf
@ 2011-06-10 14:04   ` Kevin Wolf
  2011-06-14 15:54   ` [Qemu-devel] [PATCH v2 " Kevin Wolf
  2 siblings, 0 replies; 10+ messages in thread
From: Kevin Wolf @ 2011-06-10 14:04 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: qemu-devel

Am 19.05.2011 10:58, schrieb Christoph Hellwig:
> Add support for TRIM sub function of the data set management command,
> and wire it up to the qemu discard infrastructure.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

> Index: qemu/hw/ide/pci.c
> ===================================================================
> --- qemu.orig/hw/ide/pci.c	2011-05-18 20:28:17.153625872 +0200
> +++ qemu/hw/ide/pci.c	2011-05-18 20:33:06.102141553 +0200
> @@ -205,6 +205,9 @@ static void bmdma_restart_bh(void *opaqu
>          }
>      } else if (bm->status & BM_STATUS_RETRY_FLUSH) {
>          ide_flush_cache(bmdma_active_if(bm));
> +    } else if (bm->status & BM_STATUS_RETRY_TRIM) {
> +        bm->status &= ~BM_STATUS_RETRY_TRIM;
> +        bmdma_restart_dma(bm, IDE_DMA_TRIM);
>      }
>  }

Just noticed that this is wrong. BM_STATUS_DMA_RETRY is always set at
the same time, so this is dead code.

Kevin

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v2 3/3] ide: add TRIM support
  2011-05-19  8:58 ` [Qemu-devel] [PATCH 3/3] ide: add TRIM support Christoph Hellwig
  2011-06-10 11:47   ` Kevin Wolf
  2011-06-10 14:04   ` Kevin Wolf
@ 2011-06-14 15:54   ` Kevin Wolf
  2 siblings, 0 replies; 10+ messages in thread
From: Kevin Wolf @ 2011-06-14 15:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, hch

From: Christoph Hellwig <hch@lst.de>

Add support for TRIM sub function of the data set management command,
and wire it up to the qemu discard infrastructure.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
v2:
- Fixed bdrv_discard call (takes sectors, not bytes)
- Fixed TRIM restart after failure
- Fixed use of uninitialised variable
- Fixed coding style
---
 hw/ide/core.c     |   97 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 hw/ide/internal.h |   14 +++++++-
 hw/ide/macio.c    |    4 ++
 hw/ide/pci.c      |    9 ++++-
 hw/ide/qdev.c     |    5 +++
 5 files changed, 124 insertions(+), 5 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 14bda82..ca17a43 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -78,7 +78,7 @@ static void ide_identify(IDEState *s)
 {
     uint16_t *p;
     unsigned int oldsize;
-    IDEDevice *dev;
+    IDEDevice *dev = s->unit ? s->bus->slave : s->bus->master;
 
     if (s->identify_set) {
 	memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
@@ -124,6 +124,9 @@ static void ide_identify(IDEState *s)
     put_le16(p + 66, 120);
     put_le16(p + 67, 120);
     put_le16(p + 68, 120);
+    if (dev && dev->conf.discard_granularity) {
+        put_le16(p + 69, (1 << 14)); /* determinate TRIM behavior */
+    }
 
     if (s->ncq_queues) {
         put_le16(p + 75, s->ncq_queues - 1);
@@ -154,9 +157,12 @@ static void ide_identify(IDEState *s)
     put_le16(p + 101, s->nb_sectors >> 16);
     put_le16(p + 102, s->nb_sectors >> 32);
     put_le16(p + 103, s->nb_sectors >> 48);
-    dev = s->unit ? s->bus->slave : s->bus->master;
+
     if (dev && dev->conf.physical_block_size)
         put_le16(p + 106, 0x6000 | get_physical_block_exp(&dev->conf));
+    if (dev && dev->conf.discard_granularity) {
+        put_le16(p + 169, 1); /* TRIM support */
+    }
 
     memcpy(s->identify_data, p, sizeof(s->identify_data));
     s->identify_set = 1;
@@ -299,6 +305,74 @@ static void ide_set_signature(IDEState *s)
     }
 }
 
+typedef struct TrimAIOCB {
+    BlockDriverAIOCB common;
+    QEMUBH *bh;
+    int ret;
+} TrimAIOCB;
+
+static void trim_aio_cancel(BlockDriverAIOCB *acb)
+{
+    TrimAIOCB *iocb = container_of(acb, TrimAIOCB, common);
+
+    qemu_bh_delete(iocb->bh);
+    iocb->bh = NULL;
+    qemu_aio_release(iocb);
+}
+
+static AIOPool trim_aio_pool = {
+    .aiocb_size         = sizeof(TrimAIOCB),
+    .cancel             = trim_aio_cancel,
+};
+
+static void ide_trim_bh_cb(void *opaque)
+{
+    TrimAIOCB *iocb = opaque;
+
+    iocb->common.cb(iocb->common.opaque, iocb->ret);
+
+    qemu_bh_delete(iocb->bh);
+    iocb->bh = NULL;
+
+    qemu_aio_release(iocb);
+}
+
+BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs,
+        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    TrimAIOCB *iocb;
+    int i, j, ret;
+
+    iocb = qemu_aio_get(&trim_aio_pool, bs, cb, opaque);
+    iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
+    iocb->ret = 0;
+
+    for (j = 0; j < qiov->niov; j++) {
+        uint64_t *buffer = qiov->iov[j].iov_base;
+
+        for (i = 0; i < qiov->iov[j].iov_len / 8; i++) {
+            /* 6-byte LBA + 2-byte range per entry */
+            uint64_t entry = le64_to_cpu(buffer[i]);
+            uint64_t sector = entry & 0x0000ffffffffffffULL;
+            uint16_t count = entry >> 48;
+
+            if (count == 0) {
+                break;
+            }
+
+            ret = bdrv_discard(bs, sector, count);
+            if (!iocb->ret) {
+                iocb->ret = ret;
+            }
+        }
+    }
+
+    qemu_bh_schedule(iocb->bh);
+
+    return &iocb->common;
+}
+
 static inline void ide_abort_command(IDEState *s)
 {
     s->status = READY_STAT | ERR_STAT;
@@ -474,6 +548,9 @@ handle_rw_error:
 
         if (s->dma_cmd == IDE_DMA_READ)
             op |= BM_STATUS_RETRY_READ;
+        else if (s->dma_cmd == IDE_DMA_TRIM)
+            op |= BM_STATUS_RETRY_TRIM;
+
         if (ide_handle_rw_error(s, -ret, op)) {
             return;
         }
@@ -519,6 +596,10 @@ handle_rw_error:
         s->bus->dma->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
                                             ide_dma_cb, s);
         break;
+    case IDE_DMA_TRIM:
+        s->bus->dma->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num,
+                                         ide_issue_trim, ide_dma_cb, s, 1);
+        break;
     }
 
     if (!s->bus->dma->aiocb) {
@@ -818,6 +899,18 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
         return;
 
     switch(val) {
+    case WIN_DSM:
+        switch (s->feature) {
+        case DSM_TRIM:
+            if (!s->bs) {
+                goto abort_cmd;
+            }
+            ide_sector_start_dma(s, IDE_DMA_TRIM);
+            break;
+        default:
+            goto abort_cmd;
+        }
+        break;
     case WIN_IDENTIFY:
         if (s->bs && s->drive_kind != IDE_CD) {
             if (s->drive_kind != IDE_CFATA)
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index ea3edf5..02e805f 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -62,7 +62,11 @@ typedef struct IDEDMAOps IDEDMAOps;
  */
 #define CFA_REQ_EXT_ERROR_CODE		0x03 /* CFA Request Extended Error Code */
 /*
- *	0x04->0x07 Reserved
+ *      0x04->0x05 Reserved
+ */
+#define WIN_DSM                         0x06
+/*
+ *      0x07 Reserved
  */
 #define WIN_SRST			0x08 /* ATAPI soft reset command */
 #define WIN_DEVICE_RESET		0x08
@@ -190,6 +194,9 @@ typedef struct IDEDMAOps IDEDMAOps;
 
 #define IDE_DMA_BUF_SECTORS 256
 
+/* feature values for Data Set Management */
+#define DSM_TRIM                        0x01
+
 #if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS)
 #error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS"
 #endif
@@ -382,6 +389,7 @@ struct unreported_events {
 enum ide_dma_cmd {
     IDE_DMA_READ,
     IDE_DMA_WRITE,
+    IDE_DMA_TRIM,
 };
 
 #define ide_cmd_is_read(s) \
@@ -521,6 +529,7 @@ struct IDEDeviceInfo {
 #define BM_STATUS_PIO_RETRY  0x10
 #define BM_STATUS_RETRY_READ  0x20
 #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 | \
@@ -591,6 +600,9 @@ 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);
+BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs,
+        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque);
 
 /* hw/ide/atapi.c */
 void ide_atapi_cmd(IDEState *s);
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 099b8cb..7daeb31 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -154,6 +154,10 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
         m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
 		                  pmac_ide_transfer_cb, io);
         break;
+    case IDE_DMA_TRIM:
+        m->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num,
+                               ide_issue_trim, pmac_ide_transfer_cb, s, 1);
+        break;
     }
 
     if (!m->aiocb)
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 80c5794..c940375 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -200,8 +200,13 @@ static void bmdma_restart_bh(void *opaque)
     is_read = !!(bus->error_status & BM_STATUS_RETRY_READ);
 
     if (bus->error_status & BM_STATUS_DMA_RETRY) {
-        bus->error_status &= ~(BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ);
-        bmdma_restart_dma(bm, is_read ? IDE_DMA_READ : IDE_DMA_WRITE);
+        if (bus->error_status & BM_STATUS_RETRY_TRIM) {
+            bus->error_status &= ~BM_STATUS_RETRY_TRIM;
+            bmdma_restart_dma(bm, IDE_DMA_TRIM);
+        } else {
+            bus->error_status &= ~(BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ);
+            bmdma_restart_dma(bm, is_read ? IDE_DMA_READ : IDE_DMA_WRITE);
+        }
     } else if (bus->error_status & BM_STATUS_PIO_RETRY) {
         bus->error_status &= ~(BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ);
         if (is_read) {
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 3f9dc89..d9b8f24 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -125,6 +125,11 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
     const char *serial;
     DriveInfo *dinfo;
 
+    if (dev->conf.discard_granularity && dev->conf.discard_granularity != 512) {
+        error_report("discard_granularity must be 512 for ide");
+        return -1;
+    }
+
     serial = dev->serial;
     if (!serial) {
         /* try to fall back to value set with legacy -drive serial=... */
-- 
1.7.5.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH 2/3] ide: allow other dma comands than read and write
  2011-05-03 12:06 Christoph Hellwig
@ 2011-05-03 12:06 ` Christoph Hellwig
  0 siblings, 0 replies; 10+ messages in thread
From: Christoph Hellwig @ 2011-05-03 12:06 UTC (permalink / raw)
  To: qemu-devel

Replace the is_read flag with a dma_cmd flag to allow the dma and
restart logic to handler other commands like TRIM.

Signed-off-by: Christoph Hellwig <hch@lst.de>

Index: qemu/hw/ide/core.c
===================================================================
--- qemu.orig/hw/ide/core.c	2011-05-03 11:32:14.727336751 +0200
+++ qemu/hw/ide/core.c	2011-05-03 11:35:56.259469943 +0200
@@ -473,7 +473,7 @@ handle_rw_error:
     if (ret < 0) {
         int op = BM_STATUS_DMA_RETRY;
 
-        if (s->is_read)
+        if (s->dma_cmd == IDE_DMA_READ)
             op |= BM_STATUS_RETRY_READ;
         if (ide_handle_rw_error(s, -ret, op)) {
             return;
@@ -483,7 +483,7 @@ handle_rw_error:
     n = s->io_buffer_size >> 9;
     sector_num = ide_get_sector(s);
     if (n > 0) {
-        dma_buf_commit(s, s->is_read);
+        dma_buf_commit(s, ide_cmd_is_read(s));
         sector_num += n;
         ide_set_sector(s, sector_num);
         s->nsector -= n;
@@ -500,20 +500,23 @@ handle_rw_error:
     n = s->nsector;
     s->io_buffer_index = 0;
     s->io_buffer_size = n * 512;
-    if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->is_read) == 0)
+    if (s->bus->dma->ops->prepare_buf(s->bus->dma, ide_cmd_is_read(s)) == 0)
         goto eot;
 
 #ifdef DEBUG_AIO
-    printf("ide_dma_cb: sector_num=%" PRId64 " n=%d, is_read=%d\n",
-           sector_num, n, s->is_read);
+    printf("ide_dma_cb: sector_num=%" PRId64 " n=%d, cmd_cmd=%d\n",
+           sector_num, n, s->dma_cmd);
 #endif
 
-    if (s->is_read) {
+    switch (s->dma_cmd) {
+    case IDE_DMA_READ:
         s->bus->dma->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
                                            ide_dma_cb, s);
-    } else {
+        break;
+    case IDE_DMA_WRITE:
         s->bus->dma->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
                                             ide_dma_cb, s);
+        break;
     }
 
     if (!s->bus->dma->aiocb) {
@@ -527,12 +530,12 @@ eot:
    ide_set_inactive(s);
 }
 
-static void ide_sector_start_dma(IDEState *s, int is_read)
+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->is_read = is_read;
+    s->dma_cmd = dma_cmd;
     s->bus->dma->ops->start_dma(s->bus->dma, s, ide_dma_cb);
 }
 
@@ -915,7 +918,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t
         if (!s->bs)
             goto abort_cmd;
 	ide_cmd_lba48_transform(s, lba48);
-        ide_sector_start_dma(s, 1);
+        ide_sector_start_dma(s, IDE_DMA_READ);
         break;
 	case WIN_WRITEDMA_EXT:
 	lba48 = 1;
@@ -924,7 +927,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t
         if (!s->bs)
             goto abort_cmd;
 	ide_cmd_lba48_transform(s, lba48);
-        ide_sector_start_dma(s, 0);
+        ide_sector_start_dma(s, IDE_DMA_WRITE);
         s->media_changed = 1;
         break;
     case WIN_READ_NATIVE_MAX_EXT:
Index: qemu/hw/ide/internal.h
===================================================================
--- qemu.orig/hw/ide/internal.h	2011-05-03 11:32:13.884007986 +0200
+++ qemu/hw/ide/internal.h	2011-05-03 11:36:05.526086407 +0200
@@ -379,6 +379,14 @@ struct unreported_events {
     bool new_media;
 };
 
+enum ide_dma_cmd {
+    IDE_DMA_READ,
+    IDE_DMA_WRITE,
+};
+
+#define ide_cmd_is_read(s) \
+	((s)->dma_cmd == IDE_DMA_READ)
+
 /* NOTE: IDEState represents in fact one drive */
 struct IDEState {
     IDEBus *bus;
@@ -446,7 +454,7 @@ struct IDEState {
     uint32_t mdata_size;
     uint8_t *mdata_storage;
     int media_changed;
-    int is_read;
+    enum ide_dma_cmd dma_cmd;
     /* SMART */
     uint8_t smart_enabled;
     uint8_t smart_autosave;
Index: qemu/hw/ide/macio.c
===================================================================
--- qemu.orig/hw/ide/macio.c	2011-05-03 11:32:14.740670013 +0200
+++ qemu/hw/ide/macio.c	2011-05-03 11:35:56.302803041 +0200
@@ -145,12 +145,17 @@ static void pmac_ide_transfer_cb(void *o
     io->addr += io->len;
     io->len = 0;
 
-    if (s->is_read)
+    switch (s->dma_cmd) {
+    case IDE_DMA_READ:
         m->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
 		                 pmac_ide_transfer_cb, io);
-    else
+        break;
+    case IDE_DMA_WRITE:
         m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
 		                  pmac_ide_transfer_cb, io);
+        break;
+    }
+
     if (!m->aiocb)
         pmac_ide_transfer_cb(io, -1);
 }
Index: qemu/hw/ide/pci.c
===================================================================
--- qemu.orig/hw/ide/pci.c	2011-05-03 11:32:13.854008149 +0200
+++ qemu/hw/ide/pci.c	2011-05-03 11:32:27.877265512 +0200
@@ -169,7 +169,7 @@ static int bmdma_set_inactive(IDEDMA *dm
     return 0;
 }
 
-static void bmdma_restart_dma(BMDMAState *bm, int is_read)
+static void bmdma_restart_dma(BMDMAState *bm, enum ide_dma_cmd dma_cmd)
 {
     IDEState *s = bmdma_active_if(bm);
 
@@ -177,7 +177,7 @@ static void bmdma_restart_dma(BMDMAState
     s->io_buffer_index = 0;
     s->io_buffer_size = 0;
     s->nsector = bm->nsector;
-    s->is_read = is_read;
+    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);
@@ -195,7 +195,7 @@ static void bmdma_restart_bh(void *opaqu
 
     if (bm->status & BM_STATUS_DMA_RETRY) {
         bm->status &= ~(BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ);
-        bmdma_restart_dma(bm, is_read);
+        bmdma_restart_dma(bm, is_read ? IDE_DMA_READ : IDE_DMA_WRITE);
     } else if (bm->status & BM_STATUS_PIO_RETRY) {
         bm->status &= ~(BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ);
         if (is_read) {

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2011-06-14 15:52 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-19  8:57 [Qemu-devel] [PATCH 0/3] ide: add TRIM support Christoph Hellwig
2011-05-19  8:57 ` [Qemu-devel] [PATCH 1/3] make dma_bdrv_io available to drivers Christoph Hellwig
2011-05-19  8:58 ` [Qemu-devel] [PATCH 2/3] ide: allow other dma comands than read and write Christoph Hellwig
2011-05-19  8:58 ` [Qemu-devel] [PATCH 3/3] ide: add TRIM support Christoph Hellwig
2011-06-10 11:47   ` Kevin Wolf
2011-06-10 14:04   ` Kevin Wolf
2011-06-14 15:54   ` [Qemu-devel] [PATCH v2 " Kevin Wolf
2011-06-07 11:13 ` [Qemu-devel] [PATCH 0/3] " Christoph Hellwig
2011-06-07 14:11   ` Kevin Wolf
  -- strict thread matches above, loose matches on Subject: below --
2011-05-03 12:06 Christoph Hellwig
2011-05-03 12:06 ` [Qemu-devel] [PATCH 2/3] ide: allow other dma comands than read and write Christoph Hellwig

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.