aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'hw/ppc')
-rw-r--r--hw/ppc/spapr.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 079e493ef4..147fd2cfd3 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3061,14 +3061,13 @@ void spapr_lmb_release(DeviceState *dev)
return;
}
- spapr_pending_dimm_unplugs_remove(spapr, ds);
-
/*
* Now that all the LMBs have been removed by the guest, call the
* pc-dimm unplug handler to cleanup up the pc-dimm device.
*/
pc_dimm_memory_unplug(dev, &spapr->hotplug_memory, mr);
object_unparent(OBJECT(dev));
+ spapr_pending_dimm_unplugs_remove(spapr, ds);
}
static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
@@ -3097,6 +3096,19 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
goto out;
}
+ /*
+ * An existing pending dimm state for this DIMM means that there is an
+ * unplug operation in progress, waiting for the spapr_lmb_release
+ * callback to complete the job (BQL can't cover that far). In this case,
+ * bail out to avoid detaching DRCs that were already released.
+ */
+ if (spapr_pending_dimm_unplugs_find(spapr, dimm)) {
+ error_setg(&local_err,
+ "Memory unplug already in progress for device %s",
+ dev->id);
+ goto out;
+ }
+
spapr_pending_dimm_unplugs_add(spapr, nr_lmbs, dimm);
addr = addr_start;