Because spapr_phb_check_vfio_group() now safely returns an error on a non VFIO papr host bridge, it becomes safe to call spapr_phb_vfio_eeh_set_option() on any host bridge, not just the special VFIO host bridges.
So fold its code into rtas_ibm_set_eeh_option(), instead of only calling it via a class method. The presence of the eeh_set_option class method was also used to switch behaviour in rtas_ibm_get_config_addr_info2() and rtas_ibm_slot_error_detail(). We alter those to directly check if spapr_phb_check_vfio_group() returns an error. Signed-off-by: David Gibson <[email protected]> --- hw/ppc/spapr_pci.c | 68 ++++++++++++++++++++++++++++++++++++--------- hw/ppc/spapr_pci_vfio.c | 54 ----------------------------------- include/hw/pci-host/spapr.h | 1 - 3 files changed, 55 insertions(+), 68 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 4624b90..446770c 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -430,9 +430,10 @@ static void rtas_ibm_set_eeh_option(PowerPCCPU *cpu, target_ulong rets) { sPAPRPHBState *sphb; - sPAPRPHBClass *spc; + VFIOGroup *group; uint32_t addr, option; uint64_t buid; + uint32_t op; int ret; if ((nargs != 4) || (nret != 1)) { @@ -448,13 +449,52 @@ static void rtas_ibm_set_eeh_option(PowerPCCPU *cpu, goto param_error_exit; } - spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb); - if (!spc->eeh_set_option) { + ret = spapr_phb_check_vfio_group(sphb, &group); + if (ret != RTAS_OUT_SUCCESS) { + rtas_st(rets, 0, ret); + return; + } + + switch (option) { + case RTAS_EEH_DISABLE: + op = VFIO_EEH_PE_DISABLE; + break; + case RTAS_EEH_ENABLE: { + PCIHostState *phb; + PCIDevice *pdev; + + /* + * The EEH functionality is enabled on basis of PCI device, + * instead of PE. We need check the validity of the PCI + * device address. + */ + phb = PCI_HOST_BRIDGE(sphb); + pdev = pci_find_device(phb->bus, + (addr >> 16) & 0xFF, (addr >> 8) & 0xFF); + if (!pdev || !object_dynamic_cast(OBJECT(pdev), "vfio-pci")) { + goto param_error_exit; + } + + op = VFIO_EEH_PE_ENABLE; + break; + } + case RTAS_EEH_THAW_IO: + op = VFIO_EEH_PE_UNFREEZE_IO; + break; + case RTAS_EEH_THAW_DMA: + op = VFIO_EEH_PE_UNFREEZE_DMA; + break; + default: goto param_error_exit; } - ret = spc->eeh_set_option(sphb, addr, option); - rtas_st(rets, 0, ret); + ret = vfio_eeh_op(group, op); + if (ret < 0) { + rtas_st(rets, 0, RTAS_OUT_HW_ERROR); + return; + } + + rtas_st(rets, 0, RTAS_OUT_SUCCESS); return; param_error_exit: @@ -468,10 +508,10 @@ static void rtas_ibm_get_config_addr_info2(PowerPCCPU *cpu, target_ulong rets) { sPAPRPHBState *sphb; - sPAPRPHBClass *spc; PCIDevice *pdev; uint32_t addr, option; uint64_t buid; + int ret; if ((nargs != 4) || (nret != 2)) { goto param_error_exit; @@ -483,9 +523,10 @@ static void rtas_ibm_get_config_addr_info2(PowerPCCPU *cpu, goto param_error_exit; } - spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb); - if (!spc->eeh_set_option) { - goto param_error_exit; + ret = spapr_phb_check_vfio_group(sphb, NULL); + if (ret != RTAS_OUT_SUCCESS) { + rtas_st(rets, 0, ret); + return; } /* @@ -712,9 +753,9 @@ static void rtas_ibm_slot_error_detail(PowerPCCPU *cpu, target_ulong rets) { sPAPRPHBState *sphb; - sPAPRPHBClass *spc; int option; uint64_t buid; + int ret; if ((nargs != 8) || (nret != 1)) { goto param_error_exit; @@ -726,9 +767,10 @@ static void rtas_ibm_slot_error_detail(PowerPCCPU *cpu, goto param_error_exit; } - spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb); - if (!spc->eeh_set_option) { - goto param_error_exit; + ret = spapr_phb_check_vfio_group(sphb, NULL); + if (ret != RTAS_OUT_SUCCESS) { + rtas_st(rets, 0, ret); + return; } option = rtas_ld(args, 7); diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c index 03b7a10..0c34283 100644 --- a/hw/ppc/spapr_pci_vfio.c +++ b/hw/ppc/spapr_pci_vfio.c @@ -114,59 +114,6 @@ static void spapr_phb_vfio_reset(DeviceState *qdev) spapr_phb_vfio_eeh_reenable(SPAPR_PCI_VFIO_HOST_BRIDGE(qdev)); } -static int spapr_phb_vfio_eeh_set_option(sPAPRPHBState *sphb, - unsigned int addr, int option) -{ - VFIOGroup *group; - uint32_t op; - int ret; - - ret = spapr_phb_check_vfio_group(sphb, &group); - if (ret != RTAS_OUT_SUCCESS) { - return ret; - } - - switch (option) { - case RTAS_EEH_DISABLE: - op = VFIO_EEH_PE_DISABLE; - break; - case RTAS_EEH_ENABLE: { - PCIHostState *phb; - PCIDevice *pdev; - - /* - * The EEH functionality is enabled on basis of PCI device, - * instead of PE. We need check the validity of the PCI - * device address. - */ - phb = PCI_HOST_BRIDGE(sphb); - pdev = pci_find_device(phb->bus, - (addr >> 16) & 0xFF, (addr >> 8) & 0xFF); - if (!pdev || !object_dynamic_cast(OBJECT(pdev), "vfio-pci")) { - return RTAS_OUT_PARAM_ERROR; - } - - op = VFIO_EEH_PE_ENABLE; - break; - } - case RTAS_EEH_THAW_IO: - op = VFIO_EEH_PE_UNFREEZE_IO; - break; - case RTAS_EEH_THAW_DMA: - op = VFIO_EEH_PE_UNFREEZE_DMA; - break; - default: - return RTAS_OUT_PARAM_ERROR; - } - - ret = vfio_eeh_op(group, op); - if (ret < 0) { - return RTAS_OUT_HW_ERROR; - } - - return RTAS_OUT_SUCCESS; -} - static void spapr_phb_vfio_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -175,7 +122,6 @@ static void spapr_phb_vfio_class_init(ObjectClass *klass, void *data) dc->props = spapr_phb_vfio_properties; dc->reset = spapr_phb_vfio_reset; spc->finish_realize = spapr_phb_vfio_finish_realize; - spc->eeh_set_option = spapr_phb_vfio_eeh_set_option; } static const TypeInfo spapr_phb_vfio_info = { diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h index f0b749d..741fe65 100644 --- a/include/hw/pci-host/spapr.h +++ b/include/hw/pci-host/spapr.h @@ -50,7 +50,6 @@ struct sPAPRPHBClass { PCIHostBridgeClass parent_class; void (*finish_realize)(sPAPRPHBState *sphb, Error **errp); - int (*eeh_set_option)(sPAPRPHBState *sphb, unsigned int addr, int option); }; typedef struct spapr_pci_msi { -- 2.4.3
