@@ -3724,6 +3724,10 @@ void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev,
if (!spapr_drc_unplug_requested(drc)) {
spapr_drc_unplug_request(drc);
spapr_hotplug_req_remove_by_index(drc);
+ } else {
+ error_setg(errp, "core-id %d unplug is still pending, %d seconds "
+ "timeout remaining",
+ cc->core_id, spapr_drc_unplug_timeout_remaining_sec(drc));
}
}
@@ -409,6 +409,8 @@ void spapr_drc_unplug_request(SpaprDrc *drc)
drc->unplug_requested = true;
+ spapr_drc_start_unplug_timeout_timer(drc);
+
if (drc->state != drck->empty_state) {
trace_spapr_drc_awaiting_quiesce(spapr_drc_index(drc));
return;
@@ -417,6 +419,16 @@ void spapr_drc_unplug_request(SpaprDrc *drc)
spapr_drc_release(drc);
}
+int spapr_drc_unplug_timeout_remaining_sec(SpaprDrc *drc)
+{
+ if (drc->unplug_requested && timer_pending(drc->unplug_timeout_timer)) {
+ return (qemu_timeout_ns_to_ms(drc->unplug_timeout_timer->expire_time) -
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)) / 1000;
+ }
+
+ return 0;
+}
+
bool spapr_drc_reset(SpaprDrc *drc)
{
SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
@@ -710,6 +722,7 @@ static void spapr_drc_cpu_class_init(ObjectClass *k, void *data)
drck->drc_name_prefix = "CPU ";
drck->release = spapr_core_release;
drck->dt_populate = spapr_core_dt_populate;
+ drck->unplug_timeout_seconds = 15;
}
static void spapr_drc_pci_class_init(ObjectClass *k, void *data)
@@ -248,6 +248,7 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask);
*/
void spapr_drc_attach(SpaprDrc *drc, DeviceState *d);
void spapr_drc_unplug_request(SpaprDrc *drc);
+int spapr_drc_unplug_timeout_remaining_sec(SpaprDrc *drc);
/*
* Reset all DRCs, causing pending hot-plug/unplug requests to complete.