[RFC] cxl: Enable use of custom PE-id for contexts

Vaibhav Jain vaibhav at linux.vnet.ibm.com
Mon Aug 28 14:15:55 AEST 2017


Some AFUs differentiate between multiple PE's based on their
PE-ids. Unfortunately presently cxl provides no way for external
users (libcxl/kernel-api) to control the id assigned to a specific
PE. The ids are currently assigned serially to PE's and are dolled out
using an idr table.

With this patch external users of the cxl api can request a specific
__u16 peid to be used when issuing CXL_IOCTL_START_WORK or calling
cxl_start_context(). Struct cxl_ioctl_start_work has a new member named
use_pe that can be used to provide the PE-id to be used. Also a new
CXL_START_WORK flag named CXL_START_WORK_CUSTOM_PE has been introduced
to indicated to cxl to try to switch the PE-id of the context to the
value provided in use_pe before attaching the context to the AFU.

The switching of context PE-id is done by inserting the
same context with the requested PE-id from struct cxl_ioctl_start_work
and removing the previously allocated PE-id from the afu->contexts_idr
table. In case an existing context with the requested PE-id already
exists the first step above will fail causing the context attach to
abort and an error is returned back to caller.

Signed-off-by: Vaibhav Jain <vaibhav at linux.vnet.ibm.com>
---
 drivers/misc/cxl/api.c     |  7 ++++++
 drivers/misc/cxl/context.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/misc/cxl/cxl.h     |  3 +++
 drivers/misc/cxl/file.c    | 12 ++++++++--
 include/uapi/misc/cxl.h    |  9 ++++----
 5 files changed, 80 insertions(+), 6 deletions(-)

diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c
index 1a138c83f877..3c34f486a0ce 100644
--- a/drivers/misc/cxl/api.c
+++ b/drivers/misc/cxl/api.c
@@ -505,6 +505,13 @@ int cxl_start_work(struct cxl_context *ctx,
 {
 	int rc;
 
+	/* If requesting a custom PE id ? */
+	if (work->flags & CXL_START_WORK_CUSTOM_PE) {
+		rc = cxl_context_switch_pe(ctx, work->use_pe);
+		if (rc)
+			return rc;
+	}
+
 	/* code taken from afu_ioctl_start_work */
 	if (!(work->flags & CXL_START_WORK_NUM_IRQS))
 		work->num_interrupts = ctx->afu->pp_irqs;
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c
index 8c32040b9c09..3699891a84be 100644
--- a/drivers/misc/cxl/context.c
+++ b/drivers/misc/cxl/context.c
@@ -117,6 +117,61 @@ int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master)
 	return 0;
 }
 
+/*
+ * Switch the PE# if context ctx to newpe
+ */
+int cxl_context_switch_pe(struct cxl_context *ctx, __u16 newpe)
+{
+	int rc, oldpe = 0;
+
+	pr_debug("Switching PE#%u to PE#%u\n", ctx->pe, newpe);
+	/* Assigning custom PE only supported on bare-metal right now */
+	if (!cpu_has_feature(CPU_FTR_HVMODE)) {
+		pr_err("Assigning custom PE# only supported on bare metal\n");
+		return -EINVAL;
+	}
+
+	/* Silently ignore if newpe == ctx->pe */
+	if (newpe ==  ctx->pe)
+		return 0;
+
+	/* Bunch of sanity validations */
+	if (newpe < ctx->afu->adapter->min_pe ||
+	    newpe >= (ctx->afu->adapter->min_pe + ctx->afu->num_procs)) {
+		pr_debug("Cant assign out of range PE#%u\n", newpe);
+		return -EINVAL;
+	}
+
+	if (ctx->pe_inserted) {
+		pr_debug("Cant switch PE for attached PE#%u\n", ctx->pe);
+		return -EINVAL;
+	}
+
+	/* serialize access to the idr table */
+	mutex_lock(&ctx->afu->contexts_lock);
+	idr_preload(GFP_KERNEL);
+	rc = idr_alloc(&ctx->afu->contexts_idr, ctx, newpe, newpe + 1,
+		       GFP_NOWAIT);
+	/* if successful allocation then remove the existing idr entry */
+	if (rc >= 0) {
+		idr_remove(&ctx->afu->contexts_idr, ctx->pe);
+		oldpe = ctx->pe;
+		ctx->pe = newpe;
+		ctx->external_pe = ctx->pe;
+		ctx->elem = &ctx->afu->native->spa[newpe];
+	}
+	idr_preload_end();
+	mutex_unlock(&ctx->afu->contexts_lock);
+
+	if (rc >= 0)
+		pr_debug("Switched PE#%u -> PE%u\n", oldpe, ctx->pe);
+	else
+		pr_debug("Unable to switch PE#%u->PE%u. Error=%d\n",
+			 oldpe, ctx->pe, rc);
+
+	return rc >= 0 ? 0 : rc;
+}
+
 void cxl_context_set_mapping(struct cxl_context *ctx,
 			struct address_space *mapping)
 {
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index b1afeccbb97f..6d7c0accb30e 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -1171,4 +1171,7 @@ void cxl_context_mm_count_get(struct cxl_context *ctx);
 /* Decrements the reference count to "struct mm_struct" */
 void cxl_context_mm_count_put(struct cxl_context *ctx);
 
+/* Switch the PE# of given context ctx to newpe */
+int cxl_context_switch_pe(struct cxl_context *ctx, __u16 newpe);
+
 #endif
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c
index 0761271d68c5..7ae7020aa062 100644
--- a/drivers/misc/cxl/file.c
+++ b/drivers/misc/cxl/file.c
@@ -173,12 +173,20 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
 	 * flags are set it's invalid
 	 */
 	if (work.reserved1 || work.reserved2 || work.reserved3 ||
-	    work.reserved4 || work.reserved5 || work.reserved6 ||
-	    (work.flags & ~CXL_START_WORK_ALL)) {
+	    work.reserved4 || work.reserved5 ||
+	    ((work.flags & ~CXL_START_WORK_ALL) &&
+	     !(work.flags & CXL_START_WORK_CUSTOM_PE))) {
 		rc = -EINVAL;
 		goto out;
 	}
 
+	/* If requesting a custom PE id ? */
+	if (work.flags & CXL_START_WORK_CUSTOM_PE) {
+		rc = cxl_context_switch_pe(ctx, work.use_pe);
+		if (rc)
+			goto out;
+	}
+
 	if (!(work.flags & CXL_START_WORK_NUM_IRQS))
 		work.num_interrupts = ctx->afu->pp_irqs;
 	else if ((work.num_interrupts < ctx->afu->pp_irqs) ||
diff --git a/include/uapi/misc/cxl.h b/include/uapi/misc/cxl.h
index 180d526a55c3..0d585dc46369 100644
--- a/include/uapi/misc/cxl.h
+++ b/include/uapi/misc/cxl.h
@@ -19,18 +19,19 @@ struct cxl_ioctl_start_work {
 	__u64 work_element_descriptor;
 	__u64 amr;
 	__s16 num_interrupts;
-	__s16 reserved1;
-	__s32 reserved2;
+	__u16 use_pe;
+	__s32 reserved1;
+	__u64 reserved2;
 	__u64 reserved3;
 	__u64 reserved4;
 	__u64 reserved5;
-	__u64 reserved6;
 };
 
 #define CXL_START_WORK_AMR		0x0000000000000001ULL
 #define CXL_START_WORK_NUM_IRQS		0x0000000000000002ULL
 #define CXL_START_WORK_ERR_FF		0x0000000000000004ULL
-#define CXL_START_WORK_ALL		(CXL_START_WORK_AMR |\
+#define CXL_START_WORK_CUSTOM_PE	0x0000000000000008ULL
+#define CXL_START_WORK_ALL		(CXL_START_WORK_AMR |		\
 					 CXL_START_WORK_NUM_IRQS |\
 					 CXL_START_WORK_ERR_FF)
 
-- 
2.13.5



More information about the Linuxppc-dev mailing list