g_free(dimm_state);
}
-static void spapr_lmb_release(DeviceState *dev, void *opaque)
+/* Callback to be called during DRC release. */
+void spapr_lmb_release(DeviceState *dev)
{
HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl);
g_assert(drc);
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
- drck->detach(drc, dev, spapr_lmb_release, NULL, errp);
+ drck->detach(drc, dev, errp);
addr += SPAPR_MEMORY_BLOCK_SIZE;
}
object_unparent(OBJECT(dev));
}
-static void spapr_core_release(DeviceState *dev, void *opaque)
+/* Callback to be called during DRC release. */
+void spapr_core_release(DeviceState *dev)
{
HotplugHandler *hotplug_ctrl;
g_assert(drc);
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
- drck->detach(drc, dev, spapr_core_release, NULL, &local_err);
+ drck->detach(drc, dev, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
#include "qapi/visitor.h"
#include "qemu/error-report.h"
#include "hw/ppc/spapr.h" /* for RTAS return codes */
+#include "hw/pci-host/spapr.h" /* spapr_phb_remove_pci_device_cb callback */
#include "trace.h"
#define DRC_CONTAINER_PATH "/dr-connector"
if (drc->awaiting_release) {
if (drc->configured) {
trace_spapr_drc_set_isolation_state_finalizing(get_index(drc));
- drck->detach(drc, DEVICE(drc->dev), drc->detach_cb,
- drc->detach_cb_opaque, NULL);
+ drck->detach(drc, DEVICE(drc->dev), NULL);
} else {
trace_spapr_drc_set_isolation_state_deferring(get_index(drc));
}
if (drc->awaiting_release &&
drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
trace_spapr_drc_set_allocation_state_finalizing(get_index(drc));
- drck->detach(drc, DEVICE(drc->dev), drc->detach_cb,
- drc->detach_cb_opaque, NULL);
+ drck->detach(drc, DEVICE(drc->dev), NULL);
} else if (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) {
drc->awaiting_allocation = false;
}
NULL, 0, NULL);
}
-static void detach(sPAPRDRConnector *drc, DeviceState *d,
- spapr_drc_detach_cb *detach_cb,
- void *detach_cb_opaque, Error **errp)
+static void detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp)
{
trace_spapr_drc_detach(get_index(drc));
- drc->detach_cb = detach_cb;
- drc->detach_cb_opaque = detach_cb_opaque;
-
/* if we've signalled device presence to the guest, or if the guest
* has gone ahead and configured the device (via manually-executed
* device add via drmgr in guest, namely), we need to wait
drc->indicator_state = SPAPR_DR_INDICATOR_STATE_INACTIVE;
- if (drc->detach_cb) {
- drc->detach_cb(drc->dev, drc->detach_cb_opaque);
+ /* Calling release callbacks based on drc->type. */
+ switch (drc->type) {
+ case SPAPR_DR_CONNECTOR_TYPE_CPU:
+ spapr_core_release(drc->dev);
+ break;
+ case SPAPR_DR_CONNECTOR_TYPE_PCI:
+ spapr_phb_remove_pci_device_cb(drc->dev);
+ break;
+ case SPAPR_DR_CONNECTOR_TYPE_LMB:
+ spapr_lmb_release(drc->dev);
+ break;
+ case SPAPR_DR_CONNECTOR_TYPE_PHB:
+ case SPAPR_DR_CONNECTOR_TYPE_VIO:
+ default:
+ g_assert(false);
}
drc->awaiting_release = false;
drc->fdt_start_offset = 0;
object_property_del(OBJECT(drc), "device", NULL);
drc->dev = NULL;
- drc->detach_cb = NULL;
- drc->detach_cb_opaque = NULL;
}
static bool release_pending(sPAPRDRConnector *drc)
* force removal if we are
*/
if (drc->awaiting_release) {
- drck->detach(drc, DEVICE(drc->dev), drc->detach_cb,
- drc->detach_cb_opaque, NULL);
+ drck->detach(drc, DEVICE(drc->dev), NULL);
}
/* non-PCI devices may be awaiting a transition to UNUSABLE */
}
}
-static void spapr_phb_remove_pci_device_cb(DeviceState *dev, void *opaque)
+/* Callback to be called during DRC release. */
+void spapr_phb_remove_pci_device_cb(DeviceState *dev)
{
/* some version guests do not wait for completion of a device
* cleanup (generally done asynchronously by the kernel) before
{
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
- drck->detach(drc, DEVICE(pdev), spapr_phb_remove_pci_device_cb, phb, errp);
+ drck->detach(drc, DEVICE(pdev), errp);
}
static sPAPRDRConnector *spapr_phb_get_pci_func_drc(sPAPRPHBState *phb,
PCIDevice *spapr_pci_find_dev(sPAPRMachineState *spapr, uint64_t buid,
uint32_t config_addr);
+/* PCI release callback. */
+void spapr_phb_remove_pci_device_cb(DeviceState *dev);
+
/* VFIO EEH hooks */
#ifdef CONFIG_LINUX
bool spapr_phb_eeh_available(sPAPRPHBState *sphb);
void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset,
sPAPRMachineState *spapr);
+/* CPU and LMB DRC release callbacks. */
+void spapr_core_release(DeviceState *dev);
+void spapr_lmb_release(DeviceState *dev);
+
/* rtas-configure-connector state */
struct sPAPRConfigureConnectorState {
uint32_t drc_index;
SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE = -9003,
} sPAPRDRCCResponse;
-typedef void (spapr_drc_detach_cb)(DeviceState *d, void *opaque);
-
typedef struct sPAPRDRConnector {
/*< private >*/
DeviceState parent;
/* device pointer, via link property */
DeviceState *dev;
- spapr_drc_detach_cb *detach_cb;
- void *detach_cb_opaque;
} sPAPRDRConnector;
typedef struct sPAPRDRConnectorClass {
/* QEMU interfaces for managing hotplug operations */
void (*attach)(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
int fdt_start_offset, bool coldplug, Error **errp);
- void (*detach)(sPAPRDRConnector *drc, DeviceState *d,
- spapr_drc_detach_cb *detach_cb,
- void *detach_cb_opaque, Error **errp);
+ void (*detach)(sPAPRDRConnector *drc, DeviceState *d, Error **errp);
bool (*release_pending)(sPAPRDRConnector *drc);
void (*set_signalled)(sPAPRDRConnector *drc);
} sPAPRDRConnectorClass;