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: Alastair D'Silva <alastair@d-silva.org> Acked-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
19df39581c
commit
e948e06fc6
@ -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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 @@
|
|||||||
#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,
|
|||||||
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,
|
|||||||
(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 @@ unlock:
|
|||||||
}
|
}
|
||||||
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 {
|
|||||||
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,
|
|||||||
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 {
|
|||||||
__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 {
|
|||||||
#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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user