From 2af643776b942d1ce16966c74ec1bef014aac32a Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 20 Sep 2011 16:10:05 +0200
Subject: [PATCH 13/13] ide: link BMDMA and IDEState at device creation.

RH-Author: Paolo Bonzini <pbonzini@redhat.com>
Message-id: <1316535005-26089-1-git-send-email-pbonzini@redhat.com>
Patchwork-id: 33005
O-Subject: [RHEL 6.2 KVM PATCH] ide: link BMDMA and IDEState at device creation.
Bugzilla: 739480
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Alex Williamson <alex.williamson@redhat.com>
RH-Acked-by: Christoph Hellwig <chellwig@redhat.com>

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=739480

Upstream status: 61d9d6b0

Brew build: https://brewweb.devel.redhat.com/taskinfo?taskID=3646955

We attach the BMDMA to the IDE bus in a PCI BAR map() function.  This
does not work correctly when the error status subsection has to be
sent.

Instead, do once-only work in the device's init function.

These are the PIIX parts of upstream commit 61d9d6b0.  The others did
not compile in the version that was pushed upstream, so I just stripped
them.

This is a regression caused by the fix for bug 698537 (upstream def93791).
QE only reproduced the bug in 1/60 chances, but the segfault accessing
bm->bus relates very well to this patch, and this one was already upstream
when Kevin fixed the bug there.

Hence sanity tested only (boot+migrate), but please review and ack.
---
 hw/ide/piix.c |   33 +++++++++++++++++++++++----------
 1 files changed, 23 insertions(+), 10 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 hw/ide/piix.c |   33 +++++++++++++++++++++++----------
 1 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index fd48d5d..5224ae0 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -76,10 +76,6 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
 
     for(i = 0;i < 2; i++) {
         BMDMAState *bm = &d->bmdma[i];
-        d->bus[i].bmdma = bm;
-        bm->bus = d->bus+i;
-        qemu_add_vm_change_state_handler(ide_dma_restart_cb, bm);
-
         register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm);
 
         register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm);
@@ -95,6 +91,28 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
     }
 }
 
+static void pci_piix_init_ports(PCIIDEState *d) {
+    int i;
+    struct {
+        int iobase;
+        int iobase2;
+        int isairq;
+    } port_info[] = {
+        {0x1f0, 0x3f6, 14},
+        {0x170, 0x376, 15},
+    };
+
+    for (i = 0; i < 2; i++) {
+        ide_bus_new(&d->bus[i], &d->dev.qdev, i);
+        ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2);
+        ide_init2(&d->bus[i], isa_reserve_irq(port_info[i].isairq));
+
+        d->bus[i].bmdma = &d->bmdma[i];
+        d->bmdma[i].bus = &d->bus[i];
+        qemu_add_vm_change_state_handler(ide_dma_restart_cb, &d->bmdma[i]);
+    }
+}
+
 static void piix3_reset(void *opaque)
 {
     PCIIDEState *d = opaque;
@@ -126,13 +144,8 @@ static int pci_piix_ide_initfn(PCIIDEState *d)
 
     vmstate_register(&d->dev.qdev, 0, &vmstate_ide_pci, d);
 
-    ide_bus_new(&d->bus[0], &d->dev.qdev, 0);
-    ide_bus_new(&d->bus[1], &d->dev.qdev, 1);
-    ide_init_ioport(&d->bus[0], 0x1f0, 0x3f6);
-    ide_init_ioport(&d->bus[1], 0x170, 0x376);
+    pci_piix_init_ports(d);
 
-    ide_init2(&d->bus[0], isa_reserve_irq(14));
-    ide_init2(&d->bus[1], isa_reserve_irq(15));
     return 0;
 }
 
-- 
1.7.4.4

