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(-)
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);