forked from mirrors/linux
		
	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
					
				
					 6 changed files with 111 additions and 1 deletions
				
			
		|  | @ -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 @@ 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 { | ||||||
| 	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 a new issue
	
	 Alastair D'Silva
						Alastair D'Silva