The RTAS call "ibm,set-slot-reset" is being used to reset one
particular PE, either foundamental or hot reset. The patche intends
to implement the backend to emulate the RTAS call.

Signed-off-by: Gavin Shan <gws...@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/powernv/eeh-rtas.c | 92 +++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)

diff --git a/arch/powerpc/platforms/powernv/eeh-rtas.c 
b/arch/powerpc/platforms/powernv/eeh-rtas.c
index 1a037fd..3e38d13 100644
--- a/arch/powerpc/platforms/powernv/eeh-rtas.c
+++ b/arch/powerpc/platforms/powernv/eeh-rtas.c
@@ -171,6 +171,95 @@ out:
        return ret;
 }
 
+static int kvmppc_eeh_set_reset(struct kvm_vcpu *vcpu,
+                               struct rtas_args *args)
+{
+       struct pci_controller *hose;
+       struct pnv_phb *phb;
+       struct eeh_dev *edev;
+       struct eeh_pe *pe;
+       struct eeh_vfio_pci_addr addr;
+       int opcode;
+       int ret = 0;
+
+       /* Sanity check on parameter */
+       if (args->nargs != 4 || args->nret != 1) {
+               pr_warn("%s: Non-matched arguments (%d, %d) - (4, 1)\n",
+                       __func__, args->nargs, args->nret);
+               ret = -3;
+               goto out;
+       }
+
+       /* Sanity check on opcode */
+       opcode = args->args[3];
+       if (opcode != EEH_RESET_DEACTIVATE &&
+           opcode != EEH_RESET_HOT &&
+           opcode != EEH_RESET_FUNDAMENTAL) {
+               pr_warn("%s: Unsupported opcode %d\n",
+                       __func__, opcode);
+               ret = -3;
+               goto out;
+       }
+
+       /* Figure out the address. We always have PE address */
+       if (kvmppc_eeh_format_addr(vcpu, args, &addr, false, &edev, &pe)) {
+               ret = -3;
+               goto out;
+       }
+
+       /* Insure that the EEH stuff has been initialized */
+       hose = pe->phb;
+       phb = hose->private_data;
+       if (!(phb->flags & PNV_PHB_FLAG_EEH)) {
+               pr_warn("%s: EEH disable on PHB#%d\n",
+                       __func__, hose->global_number);
+               ret = -7;
+               goto out;
+       }
+
+       /* Call into the IODA dependent backend to do the reset */
+       if (!phb->eeh_ops ||
+           !phb->eeh_ops->set_option ||
+           !phb->eeh_ops->reset) {
+               pr_warn("%s: Unsupported request\n", __func__);
+               ret = -7;
+       } else {
+               /*
+                * The frozen PE might be caused by the mechanism called
+                * PAPR error injection, which is supposed to be one-shot
+                * without "sticky" bit as being stated by the spec. But
+                * the reality isn't that, at least on P7IOC. So we have
+                * to clear that to avoid recrusive error, which fail the
+                * recovery.
+                */
+               if (opcode == EEH_RESET_DEACTIVATE)
+                       opal_pci_reset(phb->opal_id,
+                                      OPAL_PHB_ERROR,
+                                      OPAL_ASSERT_RESET);
+
+               if (phb->eeh_ops->reset(pe, opcode)) {
+                       pr_warn("%s: Failure from backend\n",
+                               __func__);
+                       ret = -1;
+                       goto out;
+               }
+
+               /*
+                * The PE is still in frozen state and we need clear that.
+                * It's good to clear frozen state after deassert to avoid
+                * messy IO access during reset, which might cause recrusive
+                * frozen PE.
+                */
+               if (opcode == EEH_RESET_DEACTIVATE) {
+                       phb->eeh_ops->set_option(pe, EEH_OPT_THAW_MMIO);
+                       phb->eeh_ops->set_option(pe, EEH_OPT_THAW_DMA);
+               }
+       }
+
+out:
+       return ret;
+}
+
 /**
  * kvmppc_eeh_rtas - Backend for EEH RTAS emulation
  * @vcpu: KVM virtual CPU
@@ -190,6 +279,9 @@ void kvmppc_eeh_rtas(struct kvm_vcpu *vcpu, struct 
rtas_args *args, int op)
        case eeh_rtas_set_option:
                ret = kvmppc_eeh_set_option(vcpu, args);
                break;
+       case eeh_rtas_set_slot_reset:
+               ret = kvmppc_eeh_set_reset(vcpu, args);
+               break;
        default:
                pr_warn("%s: Unsupported EEH RTAS service#%d\n",
                        __func__, op);
-- 
1.8.3.2

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to