[PATCH 12/22] powerpc/eeh: Emulate RTAS call ibm,set-slot-reset
Gavin Shan
gwshan at linux.vnet.ibm.com
Mon May 5 11:28:01 EST 2014
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 <gwshan at 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
More information about the Linuxppc-dev
mailing list