The POWER9 core supports a new feature: ASB_Notify which requires the
support of the Special Purpose Register: TIDR.

The ASB_Notify command, generated by the AFU, will attempt to
wake-up the host thread identified by the particular LPID:PID:TID.

This patch assign a unique TIDR (thread id) for the current thread which
will be used in the process element entry.

A next patch will handle a new kind of "compatible" property in the
device-tree (PHB DT node) indicating which version of CAPI and which
features are supported, instead of handling PVR values.

Signed-off-by: Christophe Lombard <clomb...@linux.vnet.ibm.com>
Reviewed-by: Philippe Bergheaud <fe...@linux.vnet.ibm.com>

---
Changelog[v3]
 - Rebased to latest upstream.
 - Updated attr->tid field in cxllib_get_PE_attributes().

Changelog[v2]
 - Rebased to latest upstream.
 - Updated the ioctl interface.
 - Added a checking to allow updating the TIDR if a P9 chip is present.
---
 arch/powerpc/kernel/process.c |  2 ++
 drivers/misc/cxl/api.c        |  9 +++++++++
 drivers/misc/cxl/context.c    | 26 ++++++++++++++++++++++++++
 drivers/misc/cxl/cxl.h        |  4 ++++
 drivers/misc/cxl/cxllib.c     |  3 ++-
 drivers/misc/cxl/file.c       | 24 ++++++++++++++++++++++++
 drivers/misc/cxl/native.c     |  2 +-
 include/uapi/misc/cxl.h       | 17 ++++++++++++++++-
 8 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 5acb5a1..22a17c1 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1744,6 +1744,7 @@ int copy_thread(unsigned long clone_flags, unsigned long 
usp,
        kregs->nip = ppc_function_entry(f);
        return 0;
 }
+EXPORT_SYMBOL_GPL(clear_thread_tidr);
 
 /*
  * Set up a thread for executing a new program
@@ -1919,6 +1920,7 @@ int set_fpexc_mode(struct task_struct *tsk, unsigned int 
val)
                        | tsk->thread.fpexc_mode;
        return 0;
 }
+EXPORT_SYMBOL_GPL(set_thread_tidr);
 
 int get_fpexc_mode(struct task_struct *tsk, unsigned long adr)
 {
diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c
index 7c11bad..605272c 100644
--- a/drivers/misc/cxl/api.c
+++ b/drivers/misc/cxl/api.c
@@ -684,3 +684,12 @@ void _cxl_cx4_teardown_msi_irqs(struct pci_dev *pdev)
        }
 }
 /* Exported via cxl_base */
+
+int cxl_thread_tidr(struct cxl_context *ctx, u64 flags)
+{
+       if (!ctx)
+               return -EINVAL;
+
+       return cxl_context_thread_tidr(ctx, flags);
+}
+EXPORT_SYMBOL_GPL(cxl_thread_tidr);
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c
index 12a41b2..14e1a51 100644
--- a/drivers/misc/cxl/context.c
+++ b/drivers/misc/cxl/context.c
@@ -22,6 +22,7 @@
 #include <asm/cputable.h>
 #include <asm/current.h>
 #include <asm/copro.h>
+#include <asm/switch_to.h>
 
 #include "cxl.h"
 
@@ -42,6 +43,7 @@ int cxl_context_init(struct cxl_context *ctx, struct cxl_afu 
*afu, bool master)
 
        ctx->afu = afu;
        ctx->master = master;
+       ctx->tid = 0;
        ctx->pid = NULL; /* Set in start work ioctl */
        mutex_init(&ctx->mapping_lock);
        ctx->mapping = NULL;
@@ -362,3 +364,27 @@ void cxl_context_mm_count_put(struct cxl_context *ctx)
        if (ctx->mm)
                mmdrop(ctx->mm);
 }
+
+int cxl_context_thread_tidr(struct cxl_context *ctx, u64 flags)
+{
+       int rc = 0;
+
+       if (!cxl_is_power9())
+               return -ENODEV;
+
+       /* Clear any TIDR value assigned to the current thread */
+       if (flags == CXL_THREAD_TID_CLEAN) {
+               clear_thread_tidr(current);
+               ctx->tid = 0;
+       }
+
+       /* Assign a unique TIDR (thread id) for the current thread */
+       if (flags == CXL_THREAD_TID_ASSIGN) {
+               rc = set_thread_tidr(current);
+               if (!rc)
+                       ctx->tid = current->thread.tidr;
+       }
+       pr_devel("%s: current tidr: %d\n", __func__, ctx->tid);
+
+       return rc;
+}
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index e46a406..e372291 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -561,6 +561,7 @@ struct cxl_context {
        unsigned int sst_size, sst_lru;
 
        wait_queue_head_t wq;
+       u32 tid;
        /* use mm context associated with this pid for ds faults */
        struct pid *pid;
        spinlock_t lock; /* Protects pending_irq_mask, pending_fault and 
fault_addr */
@@ -1169,4 +1170,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);
 
+/* Handles an unique TIDR (thread id) for the current thread */
+int cxl_context_thread_tidr(struct cxl_context *ctx, u64 flags);
+
 #endif
diff --git a/drivers/misc/cxl/cxllib.c b/drivers/misc/cxl/cxllib.c
index dc9bc18..30ccba4 100644
--- a/drivers/misc/cxl/cxllib.c
+++ b/drivers/misc/cxl/cxllib.c
@@ -199,10 +199,11 @@ int cxllib_get_PE_attributes(struct task_struct *task,
                 */
                attr->pid = mm->context.id;
                mmput(mm);
+               attr->tid = task->thread.tidr;
        } else {
                attr->pid = 0;
+               attr->tid = 0;
        }
-       attr->tid = 0;
        return 0;
 }
 EXPORT_SYMBOL_GPL(cxllib_get_PE_attributes);
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c
index 76c0b0c..c9c79a9 100644
--- a/drivers/misc/cxl/file.c
+++ b/drivers/misc/cxl/file.c
@@ -300,6 +300,28 @@ static long afu_ioctl_get_afu_id(struct cxl_context *ctx,
        return 0;
 }
 
+static long afu_ioctl_thread_tidr(struct cxl_context *ctx,
+                                 struct cxl_ttid __user *uthreadtid)
+{
+       struct cxl_ttid threadtid = { 0 };
+       int rc;
+
+       if (copy_from_user(&threadtid, uthreadtid, sizeof(threadtid)))
+               return -EFAULT;
+
+       rc = cxl_context_thread_tidr(ctx, threadtid.flags);
+       if (rc)
+               goto out;
+
+       threadtid.tid = ctx->tid;
+       if (copy_to_user(uthreadtid, &threadtid, sizeof(threadtid)))
+               return -EFAULT;
+
+       rc = 0;
+out:
+       return rc;
+}
+
 long afu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        struct cxl_context *ctx = file->private_data;
@@ -319,6 +341,8 @@ long afu_ioctl(struct file *file, unsigned int cmd, 
unsigned long arg)
        case CXL_IOCTL_GET_AFU_ID:
                return afu_ioctl_get_afu_id(ctx, (struct cxl_afu_id __user *)
                                            arg);
+       case CXL_IOCTL_THREAD_TID:
+               return afu_ioctl_thread_tidr(ctx, (struct cxl_ttid __user 
*)arg);
        }
        return -EINVAL;
 }
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index 02b6b45..657c4a9 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -673,7 +673,7 @@ static int process_element_entry_psl9(struct cxl_context 
*ctx, u64 wed, u64 amr)
                pid = ctx->mm->context.id;
        }
 
-       ctx->elem->common.tid = 0;
+       ctx->elem->common.tid = cpu_to_be32(ctx->tid);
        ctx->elem->common.pid = cpu_to_be32(pid);
 
        ctx->elem->sr = cpu_to_be64(calculate_sr(ctx));
diff --git a/include/uapi/misc/cxl.h b/include/uapi/misc/cxl.h
index 49e8fd0..e703597 100644
--- a/include/uapi/misc/cxl.h
+++ b/include/uapi/misc/cxl.h
@@ -76,12 +76,27 @@ struct cxl_adapter_image {
        __u64 reserved4;
 };
 
+struct cxl_ttid {
+       __u64 flags;
+       __u64 tid;
+       __u64 reserved1;
+       __u64 reserved2;
+       __u64 reserved3;
+       __u64 reserved4;
+       __u64 reserved5;
+       __u64 reserved6;
+};
+
+#define CXL_THREAD_TID_CLEAN           0x0000000000000001ULL
+#define CXL_THREAD_TID_ASSIGN          0x0000000000000002ULL
+
 /* ioctl numbers */
 #define CXL_MAGIC 0xCA
 /* AFU devices */
 #define CXL_IOCTL_START_WORK           _IOW(CXL_MAGIC, 0x00, struct 
cxl_ioctl_start_work)
 #define CXL_IOCTL_GET_PROCESS_ELEMENT  _IOR(CXL_MAGIC, 0x01, __u32)
-#define CXL_IOCTL_GET_AFU_ID            _IOR(CXL_MAGIC, 0x02, struct 
cxl_afu_id)
+#define CXL_IOCTL_GET_AFU_ID           _IOR(CXL_MAGIC, 0x02, struct cxl_afu_id)
+#define CXL_IOCTL_THREAD_TID           _IOW(CXL_MAGIC, 0x03, struct cxl_ttid)
 /* adapter devices */
 #define CXL_IOCTL_DOWNLOAD_IMAGE        _IOW(CXL_MAGIC, 0x0A, struct 
cxl_adapter_image)
 #define CXL_IOCTL_VALIDATE_IMAGE        _IOW(CXL_MAGIC, 0x0B, struct 
cxl_adapter_image)
-- 
2.7.4

Reply via email to