spapr: Cleanups relating to DRC awaiting_release field
'awaiting_release' indicates that the host has requested an unplug of the device attached to the DRC, but the guest has not (yet) put the device into a state where it is safe to complete removal. 1. Rename it to 'unplug_requested' which to me at least is clearer 2. Remove the ->release_pending() method used to check this from outside spapr_drc.c. The method only plausibly has one implementation, so use a plain function (spapr_drc_unplug_requested()) instead. 3. Remove it from the migration stream. Attempting to migrate mid-unplug is broken not just for spapr - in general management has no good way to determine if the device should be present on the destination or not. So, until that's fixed, there's no point adding extra things to the stream. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Reviewed-by: Greg Kurz <groug@kaod.org> Tested-by: Daniel Barboza <danielhb@linux.vnet.ibm.com>
This commit is contained in:
parent
a8dc47fd82
commit
f1c52354e5
|
@ -66,7 +66,7 @@ static uint32_t drc_isolate_physical(sPAPRDRConnector *drc)
|
||||||
* configured state, as suggested by the state diagram from PAPR+
|
* configured state, as suggested by the state diagram from PAPR+
|
||||||
* 2.7, 13.4
|
* 2.7, 13.4
|
||||||
*/
|
*/
|
||||||
if (drc->awaiting_release) {
|
if (drc->unplug_requested) {
|
||||||
uint32_t drc_index = spapr_drc_index(drc);
|
uint32_t drc_index = spapr_drc_index(drc);
|
||||||
if (drc->configured) {
|
if (drc->configured) {
|
||||||
trace_spapr_drc_set_isolation_state_finalizing(drc_index);
|
trace_spapr_drc_set_isolation_state_finalizing(drc_index);
|
||||||
|
@ -116,7 +116,7 @@ static uint32_t drc_isolate_logical(sPAPRDRConnector *drc)
|
||||||
* actually being unplugged, fail the isolation request here.
|
* actually being unplugged, fail the isolation request here.
|
||||||
*/
|
*/
|
||||||
if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_LMB
|
if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_LMB
|
||||||
&& !drc->awaiting_release) {
|
&& !drc->unplug_requested) {
|
||||||
return RTAS_OUT_HW_ERROR;
|
return RTAS_OUT_HW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ static uint32_t drc_isolate_logical(sPAPRDRConnector *drc)
|
||||||
* configured state, as suggested by the state diagram from PAPR+
|
* configured state, as suggested by the state diagram from PAPR+
|
||||||
* 2.7, 13.4
|
* 2.7, 13.4
|
||||||
*/
|
*/
|
||||||
if (drc->awaiting_release) {
|
if (drc->unplug_requested) {
|
||||||
uint32_t drc_index = spapr_drc_index(drc);
|
uint32_t drc_index = spapr_drc_index(drc);
|
||||||
if (drc->configured) {
|
if (drc->configured) {
|
||||||
trace_spapr_drc_set_isolation_state_finalizing(drc_index);
|
trace_spapr_drc_set_isolation_state_finalizing(drc_index);
|
||||||
|
@ -170,7 +170,7 @@ static uint32_t drc_set_usable(sPAPRDRConnector *drc)
|
||||||
if (!drc->dev) {
|
if (!drc->dev) {
|
||||||
return RTAS_OUT_NO_SUCH_INDICATOR;
|
return RTAS_OUT_NO_SUCH_INDICATOR;
|
||||||
}
|
}
|
||||||
if (drc->awaiting_release) {
|
if (drc->unplug_requested) {
|
||||||
/* Don't allow the guest to move a device away from UNUSABLE
|
/* Don't allow the guest to move a device away from UNUSABLE
|
||||||
* state when we want to unplug it */
|
* state when we want to unplug it */
|
||||||
return RTAS_OUT_NO_SUCH_INDICATOR;
|
return RTAS_OUT_NO_SUCH_INDICATOR;
|
||||||
|
@ -184,7 +184,7 @@ static uint32_t drc_set_usable(sPAPRDRConnector *drc)
|
||||||
static uint32_t drc_set_unusable(sPAPRDRConnector *drc)
|
static uint32_t drc_set_unusable(sPAPRDRConnector *drc)
|
||||||
{
|
{
|
||||||
drc->allocation_state = SPAPR_DR_ALLOCATION_STATE_UNUSABLE;
|
drc->allocation_state = SPAPR_DR_ALLOCATION_STATE_UNUSABLE;
|
||||||
if (drc->awaiting_release) {
|
if (drc->unplug_requested) {
|
||||||
uint32_t drc_index = spapr_drc_index(drc);
|
uint32_t drc_index = spapr_drc_index(drc);
|
||||||
trace_spapr_drc_set_allocation_state_finalizing(drc_index);
|
trace_spapr_drc_set_allocation_state_finalizing(drc_index);
|
||||||
spapr_drc_detach(drc);
|
spapr_drc_detach(drc);
|
||||||
|
@ -363,7 +363,7 @@ static void spapr_drc_release(sPAPRDRConnector *drc)
|
||||||
|
|
||||||
drck->release(drc->dev);
|
drck->release(drc->dev);
|
||||||
|
|
||||||
drc->awaiting_release = false;
|
drc->unplug_requested = false;
|
||||||
g_free(drc->fdt);
|
g_free(drc->fdt);
|
||||||
drc->fdt = NULL;
|
drc->fdt = NULL;
|
||||||
drc->fdt_start_offset = 0;
|
drc->fdt_start_offset = 0;
|
||||||
|
@ -375,7 +375,7 @@ void spapr_drc_detach(sPAPRDRConnector *drc)
|
||||||
{
|
{
|
||||||
trace_spapr_drc_detach(spapr_drc_index(drc));
|
trace_spapr_drc_detach(spapr_drc_index(drc));
|
||||||
|
|
||||||
drc->awaiting_release = true;
|
drc->unplug_requested = true;
|
||||||
|
|
||||||
if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_ISOLATED) {
|
if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_ISOLATED) {
|
||||||
trace_spapr_drc_awaiting_isolated(spapr_drc_index(drc));
|
trace_spapr_drc_awaiting_isolated(spapr_drc_index(drc));
|
||||||
|
@ -391,11 +391,6 @@ void spapr_drc_detach(sPAPRDRConnector *drc)
|
||||||
spapr_drc_release(drc);
|
spapr_drc_release(drc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool release_pending(sPAPRDRConnector *drc)
|
|
||||||
{
|
|
||||||
return drc->awaiting_release;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spapr_drc_reset(sPAPRDRConnector *drc)
|
void spapr_drc_reset(sPAPRDRConnector *drc)
|
||||||
{
|
{
|
||||||
trace_spapr_drc_reset(spapr_drc_index(drc));
|
trace_spapr_drc_reset(spapr_drc_index(drc));
|
||||||
|
@ -406,7 +401,7 @@ void spapr_drc_reset(sPAPRDRConnector *drc)
|
||||||
/* immediately upon reset we can safely assume DRCs whose devices
|
/* immediately upon reset we can safely assume DRCs whose devices
|
||||||
* are pending removal can be safely removed.
|
* are pending removal can be safely removed.
|
||||||
*/
|
*/
|
||||||
if (drc->awaiting_release) {
|
if (drc->unplug_requested) {
|
||||||
spapr_drc_release(drc);
|
spapr_drc_release(drc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,7 +449,7 @@ static bool spapr_drc_needed(void *opaque)
|
||||||
case SPAPR_DR_CONNECTOR_TYPE_LMB:
|
case SPAPR_DR_CONNECTOR_TYPE_LMB:
|
||||||
rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) &&
|
rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) &&
|
||||||
(drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) &&
|
(drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) &&
|
||||||
drc->configured && !drc->awaiting_release);
|
drc->configured);
|
||||||
break;
|
break;
|
||||||
case SPAPR_DR_CONNECTOR_TYPE_PHB:
|
case SPAPR_DR_CONNECTOR_TYPE_PHB:
|
||||||
case SPAPR_DR_CONNECTOR_TYPE_VIO:
|
case SPAPR_DR_CONNECTOR_TYPE_VIO:
|
||||||
|
@ -474,7 +469,6 @@ static const VMStateDescription vmstate_spapr_drc = {
|
||||||
VMSTATE_UINT32(allocation_state, sPAPRDRConnector),
|
VMSTATE_UINT32(allocation_state, sPAPRDRConnector),
|
||||||
VMSTATE_UINT32(dr_indicator, sPAPRDRConnector),
|
VMSTATE_UINT32(dr_indicator, sPAPRDRConnector),
|
||||||
VMSTATE_BOOL(configured, sPAPRDRConnector),
|
VMSTATE_BOOL(configured, sPAPRDRConnector),
|
||||||
VMSTATE_BOOL(awaiting_release, sPAPRDRConnector),
|
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -565,11 +559,9 @@ static void spapr_dr_connector_instance_init(Object *obj)
|
||||||
static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
|
static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dk = DEVICE_CLASS(k);
|
DeviceClass *dk = DEVICE_CLASS(k);
|
||||||
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
|
|
||||||
|
|
||||||
dk->realize = realize;
|
dk->realize = realize;
|
||||||
dk->unrealize = unrealize;
|
dk->unrealize = unrealize;
|
||||||
drck->release_pending = release_pending;
|
|
||||||
/*
|
/*
|
||||||
* Reason: it crashes FIXME find and document the real reason
|
* Reason: it crashes FIXME find and document the real reason
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1476,7 +1476,6 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler,
|
||||||
{
|
{
|
||||||
sPAPRPHBState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler));
|
sPAPRPHBState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler));
|
||||||
PCIDevice *pdev = PCI_DEVICE(plugged_dev);
|
PCIDevice *pdev = PCI_DEVICE(plugged_dev);
|
||||||
sPAPRDRConnectorClass *drck;
|
|
||||||
sPAPRDRConnector *drc = spapr_phb_get_pci_drc(phb, pdev);
|
sPAPRDRConnector *drc = spapr_phb_get_pci_drc(phb, pdev);
|
||||||
|
|
||||||
if (!phb->dr_enabled) {
|
if (!phb->dr_enabled) {
|
||||||
|
@ -1488,8 +1487,7 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler,
|
||||||
g_assert(drc);
|
g_assert(drc);
|
||||||
g_assert(drc->dev == plugged_dev);
|
g_assert(drc->dev == plugged_dev);
|
||||||
|
|
||||||
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
if (!spapr_drc_unplug_requested(drc)) {
|
||||||
if (!drck->release_pending(drc)) {
|
|
||||||
PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev)));
|
PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev)));
|
||||||
uint32_t slotnr = PCI_SLOT(pdev->devfn);
|
uint32_t slotnr = PCI_SLOT(pdev->devfn);
|
||||||
sPAPRDRConnector *func_drc;
|
sPAPRDRConnector *func_drc;
|
||||||
|
@ -1505,7 +1503,7 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler,
|
||||||
func_drck = SPAPR_DR_CONNECTOR_GET_CLASS(func_drc);
|
func_drck = SPAPR_DR_CONNECTOR_GET_CLASS(func_drc);
|
||||||
state = func_drck->dr_entity_sense(func_drc);
|
state = func_drck->dr_entity_sense(func_drc);
|
||||||
if (state == SPAPR_DR_ENTITY_SENSE_PRESENT
|
if (state == SPAPR_DR_ENTITY_SENSE_PRESENT
|
||||||
&& !func_drck->release_pending(func_drc)) {
|
&& !spapr_drc_unplug_requested(func_drc)) {
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"PCI: slot %d, function %d still present. "
|
"PCI: slot %d, function %d still present. "
|
||||||
"Must unplug all non-0 functions first.",
|
"Must unplug all non-0 functions first.",
|
||||||
|
|
|
@ -199,10 +199,9 @@ typedef struct sPAPRDRConnector {
|
||||||
bool configured;
|
bool configured;
|
||||||
sPAPRConfigureConnectorState *ccs;
|
sPAPRConfigureConnectorState *ccs;
|
||||||
|
|
||||||
bool awaiting_release;
|
|
||||||
|
|
||||||
/* device pointer, via link property */
|
/* device pointer, via link property */
|
||||||
DeviceState *dev;
|
DeviceState *dev;
|
||||||
|
bool unplug_requested;
|
||||||
} sPAPRDRConnector;
|
} sPAPRDRConnector;
|
||||||
|
|
||||||
typedef struct sPAPRDRConnectorClass {
|
typedef struct sPAPRDRConnectorClass {
|
||||||
|
@ -218,9 +217,6 @@ typedef struct sPAPRDRConnectorClass {
|
||||||
uint32_t (*isolate)(sPAPRDRConnector *drc);
|
uint32_t (*isolate)(sPAPRDRConnector *drc);
|
||||||
uint32_t (*unisolate)(sPAPRDRConnector *drc);
|
uint32_t (*unisolate)(sPAPRDRConnector *drc);
|
||||||
void (*release)(DeviceState *dev);
|
void (*release)(DeviceState *dev);
|
||||||
|
|
||||||
/* QEMU interfaces for managing hotplug operations */
|
|
||||||
bool (*release_pending)(sPAPRDRConnector *drc);
|
|
||||||
} sPAPRDRConnectorClass;
|
} sPAPRDRConnectorClass;
|
||||||
|
|
||||||
static inline bool spapr_drc_hotplugged(DeviceState *dev)
|
static inline bool spapr_drc_hotplugged(DeviceState *dev)
|
||||||
|
@ -244,4 +240,9 @@ void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
|
||||||
int fdt_start_offset, Error **errp);
|
int fdt_start_offset, Error **errp);
|
||||||
void spapr_drc_detach(sPAPRDRConnector *drc);
|
void spapr_drc_detach(sPAPRDRConnector *drc);
|
||||||
|
|
||||||
|
static inline bool spapr_drc_unplug_requested(sPAPRDRConnector *drc)
|
||||||
|
{
|
||||||
|
return drc->unplug_requested;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* HW_SPAPR_DRC_H */
|
#endif /* HW_SPAPR_DRC_H */
|
||||||
|
|
Loading…
Reference in a new issue