ide: Clear error_status after restarting flush
authorKevin Wolf <kwolf@redhat.com>
Fri, 10 Jun 2011 14:32:13 +0000 (16:32 +0200)
committerKevin Wolf <kwolf@redhat.com>
Wed, 15 Jun 2011 13:39:13 +0000 (15:39 +0200)
Clearing the error status flag was missing for restarting flushes. Now that the
error status is separate from the BM status register, we can simply set it to 0
after restarting the request. This ensures that we never forget to clear a bit.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
hw/ide/pci.c

index c940375..9f3050a 100644 (file)
@@ -189,6 +189,7 @@ static void bmdma_restart_bh(void *opaque)
     BMDMAState *bm = opaque;
     IDEBus *bus = bm->bus;
     int is_read;
+    int error_status;
 
     qemu_bh_delete(bm->bh);
     bm->bh = NULL;
@@ -199,22 +200,25 @@ static void bmdma_restart_bh(void *opaque)
 
     is_read = !!(bus->error_status & BM_STATUS_RETRY_READ);
 
-    if (bus->error_status & BM_STATUS_DMA_RETRY) {
-        if (bus->error_status & BM_STATUS_RETRY_TRIM) {
-            bus->error_status &= ~BM_STATUS_RETRY_TRIM;
+    /* The error status must be cleared before resubmitting the request: The
+     * request may fail again, and this case can only be distinguished if the
+     * called function can set a new error status. */
+    error_status = bus->error_status;
+    bus->error_status = 0;
+
+    if (error_status & BM_STATUS_DMA_RETRY) {
+        if (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);
+    } else if (error_status & BM_STATUS_PIO_RETRY) {
         if (is_read) {
             ide_sector_read(bmdma_active_if(bm));
         } else {
             ide_sector_write(bmdma_active_if(bm));
         }
-    } else if (bus->error_status & BM_STATUS_RETRY_FLUSH) {
+    } else if (error_status & BM_STATUS_RETRY_FLUSH) {
         ide_flush_cache(bmdma_active_if(bm));
     }
 }