@@ -1738,6 +1738,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
@@ -1913,6 +1914,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)
{
@@ -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);
@@ -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;
+}
@@ -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
@@ -202,7 +202,7 @@ int cxllib_get_PE_attributes(struct task_struct *task,
} else {
attr->pid = 0;
}
- attr->tid = 0;
+ attr->tid = current->thread.tidr;
return 0;
}
EXPORT_SYMBOL_GPL(cxllib_get_PE_attributes);
@@ -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;
}
@@ -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));
@@ -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)
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. Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com> --- 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 | 2 +- drivers/misc/cxl/file.c | 24 ++++++++++++++++++++++++ drivers/misc/cxl/native.c | 2 +- include/uapi/misc/cxl.h | 17 ++++++++++++++++- 8 files changed, 83 insertions(+), 3 deletions(-)