diff options
Diffstat (limited to 'hw/ppc')
-rw-r--r-- | hw/ppc/spapr.c | 16 |
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; |