Thread (25 messages) 25 messages, 5 authors, 2014-07-22

Re: [PATCH v1 2/3] powerpc/powernv: Support PCI error injection

From: Michael Neuling <hidden>
Date: 2014-06-24 00:42:40

On Mon, 2014-06-23 at 12:14 +1000, Gavin Shan wrote:
The patch implements one OPAL firmware sysfs file to support PCI error
injection: "/sys/firmware/opal/errinjct", which will be used like the
way described as follows.
=20
According to PAPR spec, there are 3 RTAS calls related to error injection=
:
"ibm,open-errinjct": allocate token prior to doing error injection.
"ibm,close-errinjct": release the token allocated from "ibm,open-errinjct=
".
"ibm,errinjct": do error injection.
=20
Sysfs file /sys/firmware/opal/errinjct accepts strings that have fixed
format "ei_token ...". For now, we only support 32-bits and 64-bits
PCI error injection and they should have following strings written to
/sys/firmware/opal/errinjct as follows. We don't have corresponding
sysfs files for "ibm,open-errinjct" and "ibm,close-errinjct", which
means that we rely on userland to maintain the token by itself.
This sounds cool. =20

Can you document the sysfs interface in Documentation/powerpc?

Mikey
=20
32-bits PCI error: "7:addr:mask:iommu_group_id:function".
64-bits PCI error: "8:addr:mask:iommu_group_id:function".
=20
The above "7" and "8" represent 32-bits and 64-bits PCI error seperately
and "function" is one of the specific PCI errors (e.g. MMIO access addres=
s
parity error), which are defined by PAPR spec.
=20
Signed-off-by: Gavin Shan <redacted>
---
 arch/powerpc/include/asm/opal.h                |   1 +
 arch/powerpc/platforms/powernv/Makefile        |   2 +-
 arch/powerpc/platforms/powernv/opal-errinjct.c | 184 +++++++++++++++++++=
++++++
quoted hunk ↗ jump to hunk
 arch/powerpc/platforms/powernv/opal.c          |   2 +
 4 files changed, 188 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/platforms/powernv/opal-errinjct.c
=20
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/o=
pal.h
quoted hunk ↗ jump to hunk
index d982bb8..bf280d9 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -985,6 +985,7 @@ extern int opal_elog_init(void);
 extern void opal_platform_dump_init(void);
 extern void opal_sys_param_init(void);
 extern void opal_msglog_init(void);
+extern void opal_errinjct_init(void);
=20
 extern int opal_machine_check(struct pt_regs *regs);
 extern bool opal_mce_check_early_recovery(struct pt_regs *regs);
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platf=
orms/powernv/Makefile
quoted hunk ↗ jump to hunk
index 63cebb9..4711de8 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -1,7 +1,7 @@
 obj-y			+=3D setup.o opal-takeover.o opal-wrappers.o opal.o opal-async.o
 obj-y			+=3D opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
 obj-y			+=3D rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o
-obj-y			+=3D opal-msglog.o
+obj-y			+=3D opal-msglog.o opal-errinjct.o
=20
 obj-$(CONFIG_SMP)	+=3D smp.o
 obj-$(CONFIG_PCI)	+=3D pci.o pci-p5ioc2.o pci-ioda.o
diff --git a/arch/powerpc/platforms/powernv/opal-errinjct.c b/arch/powerp=
c/platforms/powernv/opal-errinjct.c
quoted hunk ↗ jump to hunk
new file mode 100644
index 0000000..29c9e83
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-errinjct.c
@@ -0,0 +1,184 @@
+/*
+ * The file supports error injection, which works based on OPAL API.
+ * For now, we only support PCI error injection. We need support
+ * injecting other types of errors in future.
+ *
+ * Copyright Gavin Shan, IBM Corporation 2014.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/msi.h>
+#include <linux/pci.h>
+#include <linux/iommu.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/kobject.h>
+
+#include <asm/msi_bitmap.h>
+#include <asm/iommu.h>
+#include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
+#include <asm/opal.h>
+
+#include "powernv.h"
+#include "pci.h"
+
+static DEFINE_MUTEX(errinjct_mutex);
+
+static int errinjct_iommu_group_to_phb_and_pe(uint32_t iommu_grp_id,
+					      uint64_t *phb_id,
+					      uint32_t *pe_num)
+{
+#ifdef CONFIG_IOMMU_API
+	struct iommu_group *iommu_grp;
+	struct iommu_table *tbl;
+	struct pnv_ioda_pe *pe;
+
+	iommu_grp =3D iommu_group_get_by_id(iommu_grp_id);
+	if (!iommu_grp)
+		return -ENODEV;
+
+	tbl =3D iommu_group_get_iommudata(iommu_grp);
+	if (!tbl)
+		return -ENODEV;
+
+	pe =3D container_of(tbl, struct pnv_ioda_pe, tce32_table);
+	if (!pe->phb)
+		return -ENODEV;
+
+	*phb_id =3D pe->phb->opal_id;
+	*pe_num =3D pe->pe_number;
+
+	return 0;
+#endif
+
+	return -ENXIO;
+}
+
+static int errinjct_ioa_bus_error(const char *buf, struct OpalErrinjct *=
ei)
+{
+	uint32_t iommu_grp_id;
+	int ret;
+
+	/* Extract parameters */
+	ret =3D sscanf(buf, "%x:%x:%x:%x:%x",
+		     &ei->type, &ei->ioa.addr,
+		     &ei->ioa.mask, &iommu_grp_id, ei->ioa.function);
+	if (ret !=3D 5)
+		return -EINVAL;
+
+	/* Invalid function ? */
+	if (ei->ioa.function < OpalEitIoaLoadMemAddr ||
+	    ei->ioa.function > OpalEitIoaDmaWriteMemTarget)
+		return -ERANGE;
+
+	/* Retrieve PHB ID and PE number */
+	ret =3D errinjct_iommu_group_to_phb_and_pe(iommu_grp_id,
+						 &ei->ioa.phb_id,
+						 &ei->ioa.pe);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int errinjct_ioa_bus_error64(const char *buf, struct OpalErrinjct=
 *ei)
quoted hunk ↗ jump to hunk
+{
+	uint32_t iommu_grp_id;
+	int ret;
+
+	/* Extract parameter */
+	ret =3D sscanf(buf, "%x:%llx:%llx:%x:%x",
+		     &ei->type, &ei->ioa64.addr,
+		     &ei->ioa64.mask, &iommu_grp_id, &ei->ioa64.function);
+	if (ret !=3D 5)
+		return -EINVAL;
+
+	/* Invalid function ? */
+	if (ei->ioa64.function < OpalEitIoaLoadMemAddr ||
+	    ei->ioa64.function > OpalEitIoaDmaWriteMemTarget)
+		return -ERANGE;
+
+	/* Retrieve PHB ID and PE number */
+	ret =3D errinjct_iommu_group_to_phb_and_pe(iommu_grp_id,
+						 &ei->ioa64.phb_id,
+						 &ei->ioa64.pe);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static ssize_t errinjct_store(struct kobject *kobj,
+			      struct kobj_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct OpalErrinjct ei;
+	int ret;
+	long rc;
+
+	/* Extract common parameters */
+	ret =3D sscanf(buf, "%x", &ei.type);
+	if (ret !=3D 1)
+		return -EINVAL;
+
+	/* Error injection might be in progress */
+	if (!mutex_trylock(&errinjct_mutex))
+		return -EAGAIN;
+
+	switch (ei.type) {
+	case OpalErrinjctTypeIoaBusError:
+		ret =3D errinjct_ioa_bus_error(buf, &ei);
+		break;
+	case OpalErrinjctTypeIoaBusError64:
+		ret =3D errinjct_ioa_bus_error64(buf, &ei);
+		break;
+	default:
+		ret =3D -ERANGE;
+	}
+
+	/* Invalid parameters ? */
+	if (ret)
+		goto mutex_unlock_exit;
+
+	/* OPAL call */
+	rc =3D opal_err_injct(&ei);
+	if (rc =3D=3D OPAL_SUCCESS)
+		ret =3D count;
+	else
+		ret =3D -EIO;
+
+mutex_unlock_exit:
+	mutex_unlock(&errinjct_mutex);
+	return ret;
+}
+
+static struct kobj_attribute errinjct_attr =3D
+	__ATTR(errinjct, 0600, NULL, errinjct_store);
+
+void __init opal_errinjct_init(void)
+{
+	int ret;
+
+	/* Make sure /sys/firmware/opal directory is created */
+	if (!opal_kobj) {
+		pr_warn("%s: opal kobject is not available\n",
+			__func__);
+		return;
+	}
+
+	/* Create the sysfs files */
+	ret =3D sysfs_create_file(opal_kobj, &errinjct_attr.attr);
+	if (ret)
+		pr_warn("%s: Cannot create sysfs file (%d)\n",
+			__func__, ret);
+}
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platfor=
ms/powernv/opal.c
quoted hunk ↗ jump to hunk
index 360ad80c..cb29bb5 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -604,6 +604,8 @@ static int __init opal_init(void)
 		opal_sys_param_init();
 		/* Setup message log interface. */
 		opal_msglog_init();
+		/* Setup error injection interface */
+		opal_errinjct_init();
 	}
=20
 	return 0;
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help