@@ -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)
{
@@ -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);
}
@@ -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);
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(-)