diff mbox

[13/22] powerpc/eeh: Emulate RTAS call ibm,read-slot-reset-state2

Message ID 1399253291-3975-14-git-send-email-gwshan@linux.vnet.ibm.com
State New, archived
Headers show

Commit Message

Gavin Shan May 5, 2014, 1:28 a.m. UTC
The RTAS call "ibm,read-slot-reset-state2" is being used to retrieve
the various states of the specified PE, e.g. reset state, frozen DMA,
frozen MMIO etc. The patch implements the backend to emulate the
RTAS call.

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

Patch

diff --git a/arch/powerpc/platforms/powernv/eeh-rtas.c b/arch/powerpc/platforms/powernv/eeh-rtas.c
index 3e38d13..031ee8c 100644
--- a/arch/powerpc/platforms/powernv/eeh-rtas.c
+++ b/arch/powerpc/platforms/powernv/eeh-rtas.c
@@ -260,6 +260,80 @@  out:
 	return ret;
 }
 
+static int kvmppc_eeh_get_state2(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 result, ret = 0;
+
+	/* Sanity check on parameter */
+	if (args->nargs != 3 || (args->nret != 4 && args->nret != 5)) {
+		pr_warn("%s: Non-matched argument (%d, %d) - (3, 4/5)\n",
+			__func__, args->nargs, args->nret);
+		ret = -3;
+		goto out;
+	}
+
+	/* Figure out the address */
+	if (kvmppc_eeh_format_addr(vcpu, args, &addr, false, &edev, &pe)) {
+		ret = -3;
+		goto out;
+	}
+
+	/* Make sure 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 disabled on PHB#%d\n",
+			__func__, hose->global_number);
+		ret = -3;
+		args->rets[2] = 0;
+		goto out;
+	}
+
+	/*
+	 * Mark EEH supported on the PCI device. Otherwise,
+	 * the PE state is meaningless to the guest
+	 */
+	args->rets[2] = 1;
+
+	/* Call to the IOC dependent function */
+	if (phb->eeh_ops && phb->eeh_ops->get_state) {
+		result = phb->eeh_ops->get_state(pe);
+
+		if (!(result & EEH_STATE_RESET_ACTIVE) &&
+		    (result & EEH_STATE_DMA_ENABLED) &&
+		    (result & EEH_STATE_MMIO_ENABLED))
+			args->rets[1] = 0;
+		else if (result & EEH_STATE_RESET_ACTIVE)
+			args->rets[1] = 1;
+		else if (!(result & EEH_STATE_RESET_ACTIVE) &&
+			 !(result & EEH_STATE_DMA_ENABLED) &&
+			 !(result & EEH_STATE_MMIO_ENABLED))
+			args->rets[1] = 2;
+		else if (!(result & EEH_STATE_RESET_ACTIVE) &&
+			(result & EEH_STATE_DMA_ENABLED) &&
+			!(result & EEH_STATE_MMIO_ENABLED))
+			args->rets[1] = 4;
+		else {
+			args->rets[1] = 5;
+			args->rets[3] = 1000;
+		}
+
+		ret = 0;
+	} else {
+		pr_warn("%s: Unsupported request\n",
+			__func__);
+		ret = -3;
+	}
+out:
+	return ret;
+}
+
 /**
  * kvmppc_eeh_rtas - Backend for EEH RTAS emulation
  * @vcpu: KVM virtual CPU
@@ -282,6 +356,9 @@  void kvmppc_eeh_rtas(struct kvm_vcpu *vcpu, struct rtas_args *args, int op)
 	case eeh_rtas_set_slot_reset:
 		ret = kvmppc_eeh_set_reset(vcpu, args);
 		break;
+	case eeh_rtas_read_slot_reset_state2:
+		ret = kvmppc_eeh_get_state2(vcpu, args);
+		break;
 	default:
 		pr_warn("%s: Unsupported EEH RTAS service#%d\n",
 			__func__, op);