Patchwork [RFC,v2,18/21] acpi_piix4: Update dimm bitmap state on hot-remove fail

login
register
mail settings
Submitter Vasilis Liaskovitis
Date July 11, 2012, 10:32 a.m.
Message ID <1342002726-18258-19-git-send-email-vasilis.liaskovitis@profitbricks.com>
Download mbox | patch
Permalink /patch/170432/
State New
Headers show

Comments

Vasilis Liaskovitis - July 11, 2012, 10:32 a.m.
This allows failed hot operations to be retried at anytime. This only
works for guests that use _OST notification. Other guests cannot retry failed
hot operations on same devices until after reboot.

Signed-off-by: Vasilis Liaskovitis <vasilis.liaskovitis@profitbricks.com>
---
 hw/acpi_piix4.c |   20 +++++++++++++++++++-
 hw/dimm.c       |   16 +++++++++++++++-
 hw/dimm.h       |    2 +-
 3 files changed, 35 insertions(+), 3 deletions(-)

Patch

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index ebc5de7..db631cc 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -599,6 +599,7 @@  static uint32_t pcirmv_read(void *opaque, uint32_t addr)
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
                                 PCIHotplugState state);
 static int piix4_dimm_hotplug(DeviceState *qdev, SysBusDevice *dev, int add);
+static int piix4_dimm_revert(DeviceState *qdev, SysBusDevice *dev, int add);
 
 static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 {
@@ -627,7 +628,7 @@  static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
     }
 
     pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
-    dimm_register_hotplug(piix4_dimm_hotplug, &s->dev.qdev);
+    dimm_register_hotplug(piix4_dimm_hotplug, piix4_dimm_revert, &s->dev.qdev);
 }
 
 static void enable_device(PIIX4PMState *s, int slot)
@@ -696,6 +697,23 @@  void piix4_dimm_state_sync(PIIX4PMState *s)
     }
 }
 
+static int piix4_dimm_revert(DeviceState *qdev, SysBusDevice *dev, int add)
+{
+    PCIDevice *pci_dev = DO_UPCAST(PCIDevice, qdev, qdev);
+    PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, pci_dev);
+    struct gpe_regs *g = &s->gperegs;
+    DimmState *slot = DIMM(dev);
+    int idx = slot->idx;
+
+    if (add) {
+        g->mems_sts[idx/8] &= ~(1 << (idx%8));
+    }
+    else {
+        g->mems_sts[idx/8] |= (1 << (idx%8));
+    }
+    return 0;
+}
+
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
 				PCIHotplugState state)
 {
diff --git a/hw/dimm.c b/hw/dimm.c
index ba104cc..2115567 100644
--- a/hw/dimm.c
+++ b/hw/dimm.c
@@ -25,6 +25,7 @@ 
 
 static DeviceState *dimm_hotplug_qdev;
 static dimm_hotplug_fn dimm_hotplug;
+static dimm_hotplug_fn dimm_revert;
 static QTAILQ_HEAD(Dimmlist, DimmState)  dimmlist;
 static QTAILQ_HEAD(dimm_hp_result_head, dimm_hp_result)  dimm_hp_result_queue;
 
@@ -77,10 +78,12 @@  DimmState *dimm_create(char *id, uint64_t size, uint64_t node, uint32_t
     return mdev;
 }
 
-void dimm_register_hotplug(dimm_hotplug_fn hotplug, DeviceState *qdev)
+void dimm_register_hotplug(dimm_hotplug_fn hotplug, dimm_hotplug_fn revert,
+        DeviceState *qdev)
 {
     dimm_hotplug_qdev = qdev;
     dimm_hotplug = hotplug;
+    dimm_revert = revert;
     dimm_scan_populated();
 }
 
@@ -211,10 +214,20 @@  void dimm_notify(uint32_t idx, uint32_t event)
             s->pending = false;
             break;
         case DIMM_REMOVE_FAIL:
+            QTAILQ_INSERT_TAIL(&dimm_hp_result_queue, result, next);
+            s->pending = false;
+            if (dimm_revert)
+                dimm_revert(dimm_hotplug_qdev, (SysBusDevice*)s, 0);
+            break;
         case DIMM_ADD_SUCCESS:
+            QTAILQ_INSERT_TAIL(&dimm_hp_result_queue, result, next);
+            s->pending = false;
+            break;
         case DIMM_ADD_FAIL:
             QTAILQ_INSERT_TAIL(&dimm_hp_result_queue, result, next);
             s->pending = false;
+            if (dimm_revert)
+                dimm_revert(dimm_hotplug_qdev, (SysBusDevice*)s, 1);
             break;
         default:
             g_free(result);
@@ -288,6 +301,7 @@  static void dimm_class_init(ObjectClass *klass, void *data)
     dc->props = dimm_properties;
     sc->init = dimm_init;
     dimm_hotplug = NULL;
+    dimm_revert = NULL;
     QTAILQ_INIT(&dimmlist);
     QTAILQ_INIT(&dimm_hp_result_queue);
 }
diff --git a/hw/dimm.h b/hw/dimm.h
index 0fa6137..b563e3f 100644
--- a/hw/dimm.h
+++ b/hw/dimm.h
@@ -54,7 +54,7 @@  void dimm_depopulate(DimmState *s);
 int dimm_do(Monitor *mon, const QDict *qdict, bool add);
 DimmState *dimm_find_from_idx(uint32_t idx);
 DimmState *dimm_find_from_name(char *id);
-void dimm_register_hotplug(dimm_hotplug_fn hotplug, DeviceState *qdev);
+void dimm_register_hotplug(dimm_hotplug_fn hotplug, dimm_hotplug_fn revert, DeviceState *qdev);
 void dimm_calc_offsets(dimm_calcoffset_fn calcfn);
 void dimm_activate(DimmState *slot);
 void dimm_deactivate(DimmState *slot);