Commit e948e06f authored by Alastair D'Silva's avatar Alastair D'Silva Committed by Michael Ellerman

ocxl: Expose the thread_id needed for wait on POWER9

In order to successfully issue as_notify, an AFU needs to know the TID
to notify, which in turn means that this information should be
available in userspace so it can be communicated to the AFU.
Signed-off-by: default avatarAlastair D'Silva <alastair@d-silva.org>
Acked-by: default avatarAndrew Donnellan <andrew.donnellan@au1.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 19df3958
...@@ -34,6 +34,8 @@ int ocxl_context_init(struct ocxl_context *ctx, struct ocxl_afu *afu, ...@@ -34,6 +34,8 @@ int ocxl_context_init(struct ocxl_context *ctx, struct ocxl_afu *afu,
mutex_init(&ctx->xsl_error_lock); mutex_init(&ctx->xsl_error_lock);
mutex_init(&ctx->irq_lock); mutex_init(&ctx->irq_lock);
idr_init(&ctx->irq_idr); idr_init(&ctx->irq_idr);
ctx->tidr = 0;
/* /*
* Keep a reference on the AFU to make sure it's valid for the * Keep a reference on the AFU to make sure it's valid for the
* duration of the life of the context * duration of the life of the context
...@@ -65,6 +67,7 @@ int ocxl_context_attach(struct ocxl_context *ctx, u64 amr) ...@@ -65,6 +67,7 @@ int ocxl_context_attach(struct ocxl_context *ctx, u64 amr)
{ {
int rc; int rc;
// Locks both status & tidr
mutex_lock(&ctx->status_mutex); mutex_lock(&ctx->status_mutex);
if (ctx->status != OPENED) { if (ctx->status != OPENED) {
rc = -EIO; rc = -EIO;
...@@ -72,7 +75,7 @@ int ocxl_context_attach(struct ocxl_context *ctx, u64 amr) ...@@ -72,7 +75,7 @@ int ocxl_context_attach(struct ocxl_context *ctx, u64 amr)
} }
rc = ocxl_link_add_pe(ctx->afu->fn->link, ctx->pasid, rc = ocxl_link_add_pe(ctx->afu->fn->link, ctx->pasid,
current->mm->context.id, 0, amr, current->mm, current->mm->context.id, ctx->tidr, amr, current->mm,
xsl_fault_error, ctx); xsl_fault_error, ctx);
if (rc) if (rc)
goto out; goto out;
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include <linux/sched/signal.h> #include <linux/sched/signal.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <uapi/misc/ocxl.h> #include <uapi/misc/ocxl.h>
#include <asm/reg.h>
#include <asm/switch_to.h>
#include "ocxl_internal.h" #include "ocxl_internal.h"
...@@ -123,11 +125,55 @@ static long afu_ioctl_get_metadata(struct ocxl_context *ctx, ...@@ -123,11 +125,55 @@ static long afu_ioctl_get_metadata(struct ocxl_context *ctx,
return 0; return 0;
} }
#ifdef CONFIG_PPC64
static long afu_ioctl_enable_p9_wait(struct ocxl_context *ctx,
struct ocxl_ioctl_p9_wait __user *uarg)
{
struct ocxl_ioctl_p9_wait arg;
memset(&arg, 0, sizeof(arg));
if (cpu_has_feature(CPU_FTR_P9_TIDR)) {
enum ocxl_context_status status;
// Locks both status & tidr
mutex_lock(&ctx->status_mutex);
if (!ctx->tidr) {
if (set_thread_tidr(current))
return -ENOENT;
ctx->tidr = current->thread.tidr;
}
status = ctx->status;
mutex_unlock(&ctx->status_mutex);
if (status == ATTACHED) {
int rc;
struct link *link = ctx->afu->fn->link;
rc = ocxl_link_update_pe(link, ctx->pasid, ctx->tidr);
if (rc)
return rc;
}
arg.thread_id = ctx->tidr;
} else
return -ENOENT;
if (copy_to_user(uarg, &arg, sizeof(arg)))
return -EFAULT;
return 0;
}
#endif
#define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" : \ #define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" : \
x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" : \ x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" : \
x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" : \ x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" : \
x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" : \ x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" : \
x == OCXL_IOCTL_GET_METADATA ? "GET_METADATA" : \ x == OCXL_IOCTL_GET_METADATA ? "GET_METADATA" : \
x == OCXL_IOCTL_ENABLE_P9_WAIT ? "ENABLE_P9_WAIT" : \
"UNKNOWN") "UNKNOWN")
static long afu_ioctl(struct file *file, unsigned int cmd, static long afu_ioctl(struct file *file, unsigned int cmd,
...@@ -186,6 +232,13 @@ static long afu_ioctl(struct file *file, unsigned int cmd, ...@@ -186,6 +232,13 @@ static long afu_ioctl(struct file *file, unsigned int cmd,
(struct ocxl_ioctl_metadata __user *) args); (struct ocxl_ioctl_metadata __user *) args);
break; break;
#ifdef CONFIG_PPC64
case OCXL_IOCTL_ENABLE_P9_WAIT:
rc = afu_ioctl_enable_p9_wait(ctx,
(struct ocxl_ioctl_p9_wait __user *) args);
break;
#endif
default: default:
rc = -EINVAL; rc = -EINVAL;
} }
......
...@@ -544,6 +544,42 @@ int ocxl_link_add_pe(void *link_handle, int pasid, u32 pidr, u32 tidr, ...@@ -544,6 +544,42 @@ int ocxl_link_add_pe(void *link_handle, int pasid, u32 pidr, u32 tidr,
} }
EXPORT_SYMBOL_GPL(ocxl_link_add_pe); EXPORT_SYMBOL_GPL(ocxl_link_add_pe);
int ocxl_link_update_pe(void *link_handle, int pasid, __u16 tid)
{
struct link *link = (struct link *) link_handle;
struct spa *spa = link->spa;
struct ocxl_process_element *pe;
int pe_handle, rc;
if (pasid > SPA_PASID_MAX)
return -EINVAL;
pe_handle = pasid & SPA_PE_MASK;
pe = spa->spa_mem + pe_handle;
mutex_lock(&spa->spa_lock);
pe->tid = tid;
/*
* The barrier makes sure the PE is updated
* before we clear the NPU context cache below, so that the
* old PE cannot be reloaded erroneously.
*/
mb();
/*
* hook to platform code
* On powerpc, the entry needs to be cleared from the context
* cache of the NPU.
*/
rc = pnv_ocxl_spa_remove_pe_from_cache(link->platform_data, pe_handle);
WARN_ON(rc);
mutex_unlock(&spa->spa_lock);
return rc;
}
int ocxl_link_remove_pe(void *link_handle, int pasid) int ocxl_link_remove_pe(void *link_handle, int pasid)
{ {
struct link *link = (struct link *) link_handle; struct link *link = (struct link *) link_handle;
......
...@@ -77,6 +77,7 @@ struct ocxl_context { ...@@ -77,6 +77,7 @@ struct ocxl_context {
struct ocxl_xsl_error xsl_error; struct ocxl_xsl_error xsl_error;
struct mutex irq_lock; struct mutex irq_lock;
struct idr irq_idr; struct idr irq_idr;
u16 tidr; // Thread ID used for P9 wait implementation
}; };
struct ocxl_process_element { struct ocxl_process_element {
......
...@@ -188,6 +188,15 @@ extern int ocxl_link_add_pe(void *link_handle, int pasid, u32 pidr, u32 tidr, ...@@ -188,6 +188,15 @@ extern int ocxl_link_add_pe(void *link_handle, int pasid, u32 pidr, u32 tidr,
void (*xsl_err_cb)(void *data, u64 addr, u64 dsisr), void (*xsl_err_cb)(void *data, u64 addr, u64 dsisr),
void *xsl_err_data); void *xsl_err_data);
/**
* Update values within a Process Element
*
* link_handle: the link handle associated with the process element
* pasid: the PASID for the AFU context
* tid: the new thread id for the process element
*/
extern int ocxl_link_update_pe(void *link_handle, int pasid, __u16 tid);
/* /*
* Remove a Process Element from the Shared Process Area for a link * Remove a Process Element from the Shared Process Area for a link
*/ */
......
...@@ -48,6 +48,13 @@ struct ocxl_ioctl_metadata { ...@@ -48,6 +48,13 @@ struct ocxl_ioctl_metadata {
__u64 reserved[13]; // Total of 16*u64 __u64 reserved[13]; // Total of 16*u64
}; };
struct ocxl_ioctl_p9_wait {
__u16 thread_id; // The thread ID required to wake this thread
__u16 reserved1;
__u32 reserved2;
__u64 reserved3[3];
};
struct ocxl_ioctl_irq_fd { struct ocxl_ioctl_irq_fd {
__u64 irq_offset; __u64 irq_offset;
__s32 eventfd; __s32 eventfd;
...@@ -62,5 +69,6 @@ struct ocxl_ioctl_irq_fd { ...@@ -62,5 +69,6 @@ struct ocxl_ioctl_irq_fd {
#define OCXL_IOCTL_IRQ_FREE _IOW(OCXL_MAGIC, 0x12, __u64) #define OCXL_IOCTL_IRQ_FREE _IOW(OCXL_MAGIC, 0x12, __u64)
#define OCXL_IOCTL_IRQ_SET_FD _IOW(OCXL_MAGIC, 0x13, struct ocxl_ioctl_irq_fd) #define OCXL_IOCTL_IRQ_SET_FD _IOW(OCXL_MAGIC, 0x13, struct ocxl_ioctl_irq_fd)
#define OCXL_IOCTL_GET_METADATA _IOR(OCXL_MAGIC, 0x14, struct ocxl_ioctl_metadata) #define OCXL_IOCTL_GET_METADATA _IOR(OCXL_MAGIC, 0x14, struct ocxl_ioctl_metadata)
#define OCXL_IOCTL_ENABLE_P9_WAIT _IOR(OCXL_MAGIC, 0x15, struct ocxl_ioctl_p9_wait)
#endif /* _UAPI_MISC_OCXL_H */ #endif /* _UAPI_MISC_OCXL_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment