aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlastair D'Silva <alastair@d-silva.org>2019-06-20 00:12:01 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-07-03 15:29:47 -0400
commit60e8523e2ea18dc0c0cea69d6c1d69a065019062 (patch)
treeff0c7696430960d500575631703f84e57f10ef37
parent7ce98fb6c53d2311b3e9faae90b1a9c1a96534db (diff)
ocxl: Allow contexts to be attached with a NULL mm
If an OpenCAPI context is to be used directly by a kernel driver, there may not be a suitable mm to use. The patch makes the mm parameter to ocxl_context_attach optional. Signed-off-by: Alastair D'Silva <alastair@d-silva.org> Acked-by: Andrew Donnellan <ajd@linux.ibm.com> Acked-by: Frederic Barrat <fbarrat@linux.ibm.com> Acked-by: Nicholas Piggin <npiggin@gmail.com> Link: https://lore.kernel.org/r/20190620041203.12274-1-alastair@au1.ibm.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--arch/powerpc/mm/book3s64/radix_tlb.c5
-rw-r--r--drivers/misc/ocxl/context.c9
-rw-r--r--drivers/misc/ocxl/link.c28
3 files changed, 35 insertions, 7 deletions
diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c
index bb9835681315..ce8a77fae6a7 100644
--- a/arch/powerpc/mm/book3s64/radix_tlb.c
+++ b/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -666,6 +666,11 @@ EXPORT_SYMBOL(radix__flush_tlb_page);
666#define radix__flush_all_mm radix__local_flush_all_mm 666#define radix__flush_all_mm radix__local_flush_all_mm
667#endif /* CONFIG_SMP */ 667#endif /* CONFIG_SMP */
668 668
669/*
670 * If kernel TLBIs ever become local rather than global, then
671 * drivers/misc/ocxl/link.c:ocxl_link_add_pe will need some work, as it
672 * assumes kernel TLBIs are global.
673 */
669void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end) 674void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end)
670{ 675{
671 _tlbie_pid(0, RIC_FLUSH_ALL); 676 _tlbie_pid(0, RIC_FLUSH_ALL);
diff --git a/drivers/misc/ocxl/context.c b/drivers/misc/ocxl/context.c
index bab9c9364184..994563a078eb 100644
--- a/drivers/misc/ocxl/context.c
+++ b/drivers/misc/ocxl/context.c
@@ -69,6 +69,7 @@ static void xsl_fault_error(void *data, u64 addr, u64 dsisr)
69int ocxl_context_attach(struct ocxl_context *ctx, u64 amr, struct mm_struct *mm) 69int ocxl_context_attach(struct ocxl_context *ctx, u64 amr, struct mm_struct *mm)
70{ 70{
71 int rc; 71 int rc;
72 unsigned long pidr = 0;
72 73
73 // Locks both status & tidr 74 // Locks both status & tidr
74 mutex_lock(&ctx->status_mutex); 75 mutex_lock(&ctx->status_mutex);
@@ -77,9 +78,11 @@ int ocxl_context_attach(struct ocxl_context *ctx, u64 amr, struct mm_struct *mm)
77 goto out; 78 goto out;
78 } 79 }
79 80
80 rc = ocxl_link_add_pe(ctx->afu->fn->link, ctx->pasid, 81 if (mm)
81 mm->context.id, ctx->tidr, amr, mm, 82 pidr = mm->context.id;
82 xsl_fault_error, ctx); 83
84 rc = ocxl_link_add_pe(ctx->afu->fn->link, ctx->pasid, pidr, ctx->tidr,
85 amr, mm, xsl_fault_error, ctx);
83 if (rc) 86 if (rc)
84 goto out; 87 goto out;
85 88
diff --git a/drivers/misc/ocxl/link.c b/drivers/misc/ocxl/link.c
index cce5b0d64505..58d111afd9f6 100644
--- a/drivers/misc/ocxl/link.c
+++ b/drivers/misc/ocxl/link.c
@@ -224,6 +224,17 @@ static irqreturn_t xsl_fault_handler(int irq, void *data)
224 ack_irq(spa, ADDRESS_ERROR); 224 ack_irq(spa, ADDRESS_ERROR);
225 return IRQ_HANDLED; 225 return IRQ_HANDLED;
226 } 226 }
227
228 if (!pe_data->mm) {
229 /*
230 * translation fault from a kernel context - an OpenCAPI
231 * device tried to access a bad kernel address
232 */
233 rcu_read_unlock();
234 pr_warn("Unresolved OpenCAPI xsl fault in kernel context\n");
235 ack_irq(spa, ADDRESS_ERROR);
236 return IRQ_HANDLED;
237 }
227 WARN_ON(pe_data->mm->context.id != pid); 238 WARN_ON(pe_data->mm->context.id != pid);
228 239
229 if (mmget_not_zero(pe_data->mm)) { 240 if (mmget_not_zero(pe_data->mm)) {
@@ -523,7 +534,13 @@ int ocxl_link_add_pe(void *link_handle, int pasid, u32 pidr, u32 tidr,
523 pe->amr = cpu_to_be64(amr); 534 pe->amr = cpu_to_be64(amr);
524 pe->software_state = cpu_to_be32(SPA_PE_VALID); 535 pe->software_state = cpu_to_be32(SPA_PE_VALID);
525 536
526 mm_context_add_copro(mm); 537 /*
538 * For user contexts, register a copro so that TLBIs are seen
539 * by the nest MMU. If we have a kernel context, TLBIs are
540 * already global.
541 */
542 if (mm)
543 mm_context_add_copro(mm);
527 /* 544 /*
528 * Barrier is to make sure PE is visible in the SPA before it 545 * Barrier is to make sure PE is visible in the SPA before it
529 * is used by the device. It also helps with the global TLBI 546 * is used by the device. It also helps with the global TLBI
@@ -546,7 +563,8 @@ int ocxl_link_add_pe(void *link_handle, int pasid, u32 pidr, u32 tidr,
546 * have a reference on mm_users. Incrementing mm_count solves 563 * have a reference on mm_users. Incrementing mm_count solves
547 * the problem. 564 * the problem.
548 */ 565 */
549 mmgrab(mm); 566 if (mm)
567 mmgrab(mm);
550 trace_ocxl_context_add(current->pid, spa->spa_mem, pasid, pidr, tidr); 568 trace_ocxl_context_add(current->pid, spa->spa_mem, pasid, pidr, tidr);
551unlock: 569unlock:
552 mutex_unlock(&spa->spa_lock); 570 mutex_unlock(&spa->spa_lock);
@@ -652,8 +670,10 @@ int ocxl_link_remove_pe(void *link_handle, int pasid)
652 if (!pe_data) { 670 if (!pe_data) {
653 WARN(1, "Couldn't find pe data when removing PE\n"); 671 WARN(1, "Couldn't find pe data when removing PE\n");
654 } else { 672 } else {
655 mm_context_remove_copro(pe_data->mm); 673 if (pe_data->mm) {
656 mmdrop(pe_data->mm); 674 mm_context_remove_copro(pe_data->mm);
675 mmdrop(pe_data->mm);
676 }
657 kfree_rcu(pe_data, rcu); 677 kfree_rcu(pe_data, rcu);
658 } 678 }
659unlock: 679unlock: