diff options
Diffstat (limited to 'drivers/misc/cxl/file.c')
-rw-r--r-- | drivers/misc/cxl/file.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c index 4bfad9f6dc9f..76c0b0ca9388 100644 --- a/drivers/misc/cxl/file.c +++ b/drivers/misc/cxl/file.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/sched/mm.h> | 21 | #include <linux/sched/mm.h> |
22 | #include <linux/mmu_context.h> | ||
22 | #include <asm/cputable.h> | 23 | #include <asm/cputable.h> |
23 | #include <asm/current.h> | 24 | #include <asm/current.h> |
24 | #include <asm/copro.h> | 25 | #include <asm/copro.h> |
@@ -220,9 +221,12 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, | |||
220 | /* ensure this mm_struct can't be freed */ | 221 | /* ensure this mm_struct can't be freed */ |
221 | cxl_context_mm_count_get(ctx); | 222 | cxl_context_mm_count_get(ctx); |
222 | 223 | ||
223 | /* decrement the use count */ | 224 | if (ctx->mm) { |
224 | if (ctx->mm) | 225 | /* decrement the use count from above */ |
225 | mmput(ctx->mm); | 226 | mmput(ctx->mm); |
227 | /* make TLBIs for this context global */ | ||
228 | mm_context_add_copro(ctx->mm); | ||
229 | } | ||
226 | 230 | ||
227 | /* | 231 | /* |
228 | * Increment driver use count. Enables global TLBIs for hash | 232 | * Increment driver use count. Enables global TLBIs for hash |
@@ -230,6 +234,20 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, | |||
230 | */ | 234 | */ |
231 | cxl_ctx_get(); | 235 | cxl_ctx_get(); |
232 | 236 | ||
237 | /* | ||
238 | * A barrier is needed to make sure all TLBIs are global | ||
239 | * before we attach and the context starts being used by the | ||
240 | * adapter. | ||
241 | * | ||
242 | * Needed after mm_context_add_copro() for radix and | ||
243 | * cxl_ctx_get() for hash/p8. | ||
244 | * | ||
245 | * The barrier should really be mb(), since it involves a | ||
246 | * device. However, it's only useful when we have local | ||
247 | * vs. global TLBIs, i.e SMP=y. So keep smp_mb(). | ||
248 | */ | ||
249 | smp_mb(); | ||
250 | |||
233 | trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); | 251 | trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); |
234 | 252 | ||
235 | if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor, | 253 | if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor, |
@@ -240,6 +258,8 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, | |||
240 | ctx->pid = NULL; | 258 | ctx->pid = NULL; |
241 | cxl_ctx_put(); | 259 | cxl_ctx_put(); |
242 | cxl_context_mm_count_put(ctx); | 260 | cxl_context_mm_count_put(ctx); |
261 | if (ctx->mm) | ||
262 | mm_context_remove_copro(ctx->mm); | ||
243 | goto out; | 263 | goto out; |
244 | } | 264 | } |
245 | 265 | ||