Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os 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>

authored by

Alastair D'Silva and committed by
Michael Ellerman
e948e06f 19df3958

+111 -1
+4 -1
drivers/misc/ocxl/context.c
··· 34 34 mutex_init(&ctx->xsl_error_lock); 35 35 mutex_init(&ctx->irq_lock); 36 36 idr_init(&ctx->irq_idr); 37 + ctx->tidr = 0; 38 + 37 39 /* 38 40 * Keep a reference on the AFU to make sure it's valid for the 39 41 * duration of the life of the context ··· 67 65 { 68 66 int rc; 69 67 68 + // Locks both status & tidr 70 69 mutex_lock(&ctx->status_mutex); 71 70 if (ctx->status != OPENED) { 72 71 rc = -EIO; ··· 75 72 } 76 73 77 74 rc = ocxl_link_add_pe(ctx->afu->fn->link, ctx->pasid, 78 - current->mm->context.id, 0, amr, current->mm, 75 + current->mm->context.id, ctx->tidr, amr, current->mm, 79 76 xsl_fault_error, ctx); 80 77 if (rc) 81 78 goto out;
+53
drivers/misc/ocxl/file.c
··· 5 5 #include <linux/sched/signal.h> 6 6 #include <linux/uaccess.h> 7 7 #include <uapi/misc/ocxl.h> 8 + #include <asm/reg.h> 9 + #include <asm/switch_to.h> 8 10 #include "ocxl_internal.h" 9 11 10 12 ··· 125 123 return 0; 126 124 } 127 125 126 + #ifdef CONFIG_PPC64 127 + static long afu_ioctl_enable_p9_wait(struct ocxl_context *ctx, 128 + struct ocxl_ioctl_p9_wait __user *uarg) 129 + { 130 + struct ocxl_ioctl_p9_wait arg; 131 + 132 + memset(&arg, 0, sizeof(arg)); 133 + 134 + if (cpu_has_feature(CPU_FTR_P9_TIDR)) { 135 + enum ocxl_context_status status; 136 + 137 + // Locks both status & tidr 138 + mutex_lock(&ctx->status_mutex); 139 + if (!ctx->tidr) { 140 + if (set_thread_tidr(current)) 141 + return -ENOENT; 142 + 143 + ctx->tidr = current->thread.tidr; 144 + } 145 + 146 + status = ctx->status; 147 + mutex_unlock(&ctx->status_mutex); 148 + 149 + if (status == ATTACHED) { 150 + int rc; 151 + struct link *link = ctx->afu->fn->link; 152 + 153 + rc = ocxl_link_update_pe(link, ctx->pasid, ctx->tidr); 154 + if (rc) 155 + return rc; 156 + } 157 + 158 + arg.thread_id = ctx->tidr; 159 + } else 160 + return -ENOENT; 161 + 162 + if (copy_to_user(uarg, &arg, sizeof(arg))) 163 + return -EFAULT; 164 + 165 + return 0; 166 + } 167 + #endif 168 + 128 169 #define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" : \ 129 170 x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" : \ 130 171 x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" : \ 131 172 x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" : \ 132 173 x == OCXL_IOCTL_GET_METADATA ? "GET_METADATA" : \ 174 + x == OCXL_IOCTL_ENABLE_P9_WAIT ? "ENABLE_P9_WAIT" : \ 133 175 "UNKNOWN") 134 176 135 177 static long afu_ioctl(struct file *file, unsigned int cmd, ··· 231 185 rc = afu_ioctl_get_metadata(ctx, 232 186 (struct ocxl_ioctl_metadata __user *) args); 233 187 break; 188 + 189 + #ifdef CONFIG_PPC64 190 + case OCXL_IOCTL_ENABLE_P9_WAIT: 191 + rc = afu_ioctl_enable_p9_wait(ctx, 192 + (struct ocxl_ioctl_p9_wait __user *) args); 193 + break; 194 + #endif 234 195 235 196 default: 236 197 rc = -EINVAL;
+36
drivers/misc/ocxl/link.c
··· 544 544 } 545 545 EXPORT_SYMBOL_GPL(ocxl_link_add_pe); 546 546 547 + int ocxl_link_update_pe(void *link_handle, int pasid, __u16 tid) 548 + { 549 + struct link *link = (struct link *) link_handle; 550 + struct spa *spa = link->spa; 551 + struct ocxl_process_element *pe; 552 + int pe_handle, rc; 553 + 554 + if (pasid > SPA_PASID_MAX) 555 + return -EINVAL; 556 + 557 + pe_handle = pasid & SPA_PE_MASK; 558 + pe = spa->spa_mem + pe_handle; 559 + 560 + mutex_lock(&spa->spa_lock); 561 + 562 + pe->tid = tid; 563 + 564 + /* 565 + * The barrier makes sure the PE is updated 566 + * before we clear the NPU context cache below, so that the 567 + * old PE cannot be reloaded erroneously. 568 + */ 569 + mb(); 570 + 571 + /* 572 + * hook to platform code 573 + * On powerpc, the entry needs to be cleared from the context 574 + * cache of the NPU. 575 + */ 576 + rc = pnv_ocxl_spa_remove_pe_from_cache(link->platform_data, pe_handle); 577 + WARN_ON(rc); 578 + 579 + mutex_unlock(&spa->spa_lock); 580 + return rc; 581 + } 582 + 547 583 int ocxl_link_remove_pe(void *link_handle, int pasid) 548 584 { 549 585 struct link *link = (struct link *) link_handle;
+1
drivers/misc/ocxl/ocxl_internal.h
··· 77 77 struct ocxl_xsl_error xsl_error; 78 78 struct mutex irq_lock; 79 79 struct idr irq_idr; 80 + u16 tidr; // Thread ID used for P9 wait implementation 80 81 }; 81 82 82 83 struct ocxl_process_element {
+9
include/misc/ocxl.h
··· 188 188 void (*xsl_err_cb)(void *data, u64 addr, u64 dsisr), 189 189 void *xsl_err_data); 190 190 191 + /** 192 + * Update values within a Process Element 193 + * 194 + * link_handle: the link handle associated with the process element 195 + * pasid: the PASID for the AFU context 196 + * tid: the new thread id for the process element 197 + */ 198 + extern int ocxl_link_update_pe(void *link_handle, int pasid, __u16 tid); 199 + 191 200 /* 192 201 * Remove a Process Element from the Shared Process Area for a link 193 202 */
+8
include/uapi/misc/ocxl.h
··· 48 48 __u64 reserved[13]; // Total of 16*u64 49 49 }; 50 50 51 + struct ocxl_ioctl_p9_wait { 52 + __u16 thread_id; // The thread ID required to wake this thread 53 + __u16 reserved1; 54 + __u32 reserved2; 55 + __u64 reserved3[3]; 56 + }; 57 + 51 58 struct ocxl_ioctl_irq_fd { 52 59 __u64 irq_offset; 53 60 __s32 eventfd; ··· 69 62 #define OCXL_IOCTL_IRQ_FREE _IOW(OCXL_MAGIC, 0x12, __u64) 70 63 #define OCXL_IOCTL_IRQ_SET_FD _IOW(OCXL_MAGIC, 0x13, struct ocxl_ioctl_irq_fd) 71 64 #define OCXL_IOCTL_GET_METADATA _IOR(OCXL_MAGIC, 0x14, struct ocxl_ioctl_metadata) 65 + #define OCXL_IOCTL_ENABLE_P9_WAIT _IOR(OCXL_MAGIC, 0x15, struct ocxl_ioctl_p9_wait) 72 66 73 67 #endif /* _UAPI_MISC_OCXL_H */