diff options
Diffstat (limited to 'drivers/misc/cxl/native.c')
-rw-r--r-- | drivers/misc/cxl/native.c | 224 |
1 files changed, 213 insertions, 11 deletions
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c index 193769f56075..194c58ec83b8 100644 --- a/drivers/misc/cxl/native.c +++ b/drivers/misc/cxl/native.c | |||
@@ -120,6 +120,7 @@ int cxl_psl_purge(struct cxl_afu *afu) | |||
120 | u64 AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); | 120 | u64 AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An); |
121 | u64 dsisr, dar; | 121 | u64 dsisr, dar; |
122 | u64 start, end; | 122 | u64 start, end; |
123 | u64 trans_fault = 0x0ULL; | ||
123 | unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); | 124 | unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); |
124 | int rc = 0; | 125 | int rc = 0; |
125 | 126 | ||
@@ -127,6 +128,11 @@ int cxl_psl_purge(struct cxl_afu *afu) | |||
127 | 128 | ||
128 | pr_devel("PSL purge request\n"); | 129 | pr_devel("PSL purge request\n"); |
129 | 130 | ||
131 | if (cxl_is_psl8(afu)) | ||
132 | trans_fault = CXL_PSL_DSISR_TRANS; | ||
133 | if (cxl_is_psl9(afu)) | ||
134 | trans_fault = CXL_PSL9_DSISR_An_TF; | ||
135 | |||
130 | if (!cxl_ops->link_ok(afu->adapter, afu)) { | 136 | if (!cxl_ops->link_ok(afu->adapter, afu)) { |
131 | dev_warn(&afu->dev, "PSL Purge called with link down, ignoring\n"); | 137 | dev_warn(&afu->dev, "PSL Purge called with link down, ignoring\n"); |
132 | rc = -EIO; | 138 | rc = -EIO; |
@@ -158,7 +164,7 @@ int cxl_psl_purge(struct cxl_afu *afu) | |||
158 | pr_devel_ratelimited("PSL purging... PSL_CNTL: 0x%016llx PSL_DSISR: 0x%016llx\n", | 164 | pr_devel_ratelimited("PSL purging... PSL_CNTL: 0x%016llx PSL_DSISR: 0x%016llx\n", |
159 | PSL_CNTL, dsisr); | 165 | PSL_CNTL, dsisr); |
160 | 166 | ||
161 | if (dsisr & CXL_PSL_DSISR_TRANS) { | 167 | if (dsisr & trans_fault) { |
162 | dar = cxl_p2n_read(afu, CXL_PSL_DAR_An); | 168 | dar = cxl_p2n_read(afu, CXL_PSL_DAR_An); |
163 | dev_notice(&afu->dev, "PSL purge terminating pending translation, DSISR: 0x%016llx, DAR: 0x%016llx\n", | 169 | dev_notice(&afu->dev, "PSL purge terminating pending translation, DSISR: 0x%016llx, DAR: 0x%016llx\n", |
164 | dsisr, dar); | 170 | dsisr, dar); |
@@ -200,7 +206,7 @@ static int spa_max_procs(int spa_size) | |||
200 | return ((spa_size / 8) - 96) / 17; | 206 | return ((spa_size / 8) - 96) / 17; |
201 | } | 207 | } |
202 | 208 | ||
203 | int cxl_alloc_spa(struct cxl_afu *afu) | 209 | static int cxl_alloc_spa(struct cxl_afu *afu, int mode) |
204 | { | 210 | { |
205 | unsigned spa_size; | 211 | unsigned spa_size; |
206 | 212 | ||
@@ -213,7 +219,8 @@ int cxl_alloc_spa(struct cxl_afu *afu) | |||
213 | if (spa_size > 0x100000) { | 219 | if (spa_size > 0x100000) { |
214 | dev_warn(&afu->dev, "num_of_processes too large for the SPA, limiting to %i (0x%x)\n", | 220 | dev_warn(&afu->dev, "num_of_processes too large for the SPA, limiting to %i (0x%x)\n", |
215 | afu->native->spa_max_procs, afu->native->spa_size); | 221 | afu->native->spa_max_procs, afu->native->spa_size); |
216 | afu->num_procs = afu->native->spa_max_procs; | 222 | if (mode != CXL_MODE_DEDICATED) |
223 | afu->num_procs = afu->native->spa_max_procs; | ||
217 | break; | 224 | break; |
218 | } | 225 | } |
219 | 226 | ||
@@ -262,6 +269,36 @@ void cxl_release_spa(struct cxl_afu *afu) | |||
262 | } | 269 | } |
263 | } | 270 | } |
264 | 271 | ||
272 | /* | ||
273 | * Invalidation of all ERAT entries is no longer required by CAIA2. Use | ||
274 | * only for debug. | ||
275 | */ | ||
276 | int cxl_invalidate_all_psl9(struct cxl *adapter) | ||
277 | { | ||
278 | unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); | ||
279 | u64 ierat; | ||
280 | |||
281 | pr_devel("CXL adapter - invalidation of all ERAT entries\n"); | ||
282 | |||
283 | /* Invalidates all ERAT entries for Radix or HPT */ | ||
284 | ierat = CXL_XSL9_IERAT_IALL; | ||
285 | if (radix_enabled()) | ||
286 | ierat |= CXL_XSL9_IERAT_INVR; | ||
287 | cxl_p1_write(adapter, CXL_XSL9_IERAT, ierat); | ||
288 | |||
289 | while (cxl_p1_read(adapter, CXL_XSL9_IERAT) & CXL_XSL9_IERAT_IINPROG) { | ||
290 | if (time_after_eq(jiffies, timeout)) { | ||
291 | dev_warn(&adapter->dev, | ||
292 | "WARNING: CXL adapter invalidation of all ERAT entries timed out!\n"); | ||
293 | return -EBUSY; | ||
294 | } | ||
295 | if (!cxl_ops->link_ok(adapter, NULL)) | ||
296 | return -EIO; | ||
297 | cpu_relax(); | ||
298 | } | ||
299 | return 0; | ||
300 | } | ||
301 | |||
265 | int cxl_invalidate_all_psl8(struct cxl *adapter) | 302 | int cxl_invalidate_all_psl8(struct cxl *adapter) |
266 | { | 303 | { |
267 | unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); | 304 | unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); |
@@ -498,7 +535,7 @@ static int activate_afu_directed(struct cxl_afu *afu) | |||
498 | 535 | ||
499 | afu->num_procs = afu->max_procs_virtualised; | 536 | afu->num_procs = afu->max_procs_virtualised; |
500 | if (afu->native->spa == NULL) { | 537 | if (afu->native->spa == NULL) { |
501 | if (cxl_alloc_spa(afu)) | 538 | if (cxl_alloc_spa(afu, CXL_MODE_DIRECTED)) |
502 | return -ENOMEM; | 539 | return -ENOMEM; |
503 | } | 540 | } |
504 | attach_spa(afu); | 541 | attach_spa(afu); |
@@ -548,10 +585,19 @@ static u64 calculate_sr(struct cxl_context *ctx) | |||
548 | sr |= (mfmsr() & MSR_SF) | CXL_PSL_SR_An_HV; | 585 | sr |= (mfmsr() & MSR_SF) | CXL_PSL_SR_An_HV; |
549 | } else { | 586 | } else { |
550 | sr |= CXL_PSL_SR_An_PR | CXL_PSL_SR_An_R; | 587 | sr |= CXL_PSL_SR_An_PR | CXL_PSL_SR_An_R; |
551 | sr &= ~(CXL_PSL_SR_An_HV); | 588 | if (radix_enabled()) |
589 | sr |= CXL_PSL_SR_An_HV; | ||
590 | else | ||
591 | sr &= ~(CXL_PSL_SR_An_HV); | ||
552 | if (!test_tsk_thread_flag(current, TIF_32BIT)) | 592 | if (!test_tsk_thread_flag(current, TIF_32BIT)) |
553 | sr |= CXL_PSL_SR_An_SF; | 593 | sr |= CXL_PSL_SR_An_SF; |
554 | } | 594 | } |
595 | if (cxl_is_psl9(ctx->afu)) { | ||
596 | if (radix_enabled()) | ||
597 | sr |= CXL_PSL_SR_An_XLAT_ror; | ||
598 | else | ||
599 | sr |= CXL_PSL_SR_An_XLAT_hpt; | ||
600 | } | ||
555 | return sr; | 601 | return sr; |
556 | } | 602 | } |
557 | 603 | ||
@@ -584,6 +630,70 @@ static void update_ivtes_directed(struct cxl_context *ctx) | |||
584 | WARN_ON(add_process_element(ctx)); | 630 | WARN_ON(add_process_element(ctx)); |
585 | } | 631 | } |
586 | 632 | ||
633 | static int process_element_entry_psl9(struct cxl_context *ctx, u64 wed, u64 amr) | ||
634 | { | ||
635 | u32 pid; | ||
636 | |||
637 | cxl_assign_psn_space(ctx); | ||
638 | |||
639 | ctx->elem->ctxtime = 0; /* disable */ | ||
640 | ctx->elem->lpid = cpu_to_be32(mfspr(SPRN_LPID)); | ||
641 | ctx->elem->haurp = 0; /* disable */ | ||
642 | |||
643 | if (ctx->kernel) | ||
644 | pid = 0; | ||
645 | else { | ||
646 | if (ctx->mm == NULL) { | ||
647 | pr_devel("%s: unable to get mm for pe=%d pid=%i\n", | ||
648 | __func__, ctx->pe, pid_nr(ctx->pid)); | ||
649 | return -EINVAL; | ||
650 | } | ||
651 | pid = ctx->mm->context.id; | ||
652 | } | ||
653 | |||
654 | ctx->elem->common.tid = 0; | ||
655 | ctx->elem->common.pid = cpu_to_be32(pid); | ||
656 | |||
657 | ctx->elem->sr = cpu_to_be64(calculate_sr(ctx)); | ||
658 | |||
659 | ctx->elem->common.csrp = 0; /* disable */ | ||
660 | |||
661 | cxl_prefault(ctx, wed); | ||
662 | |||
663 | /* | ||
664 | * Ensure we have the multiplexed PSL interrupt set up to take faults | ||
665 | * for kernel contexts that may not have allocated any AFU IRQs at all: | ||
666 | */ | ||
667 | if (ctx->irqs.range[0] == 0) { | ||
668 | ctx->irqs.offset[0] = ctx->afu->native->psl_hwirq; | ||
669 | ctx->irqs.range[0] = 1; | ||
670 | } | ||
671 | |||
672 | ctx->elem->common.amr = cpu_to_be64(amr); | ||
673 | ctx->elem->common.wed = cpu_to_be64(wed); | ||
674 | |||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | int cxl_attach_afu_directed_psl9(struct cxl_context *ctx, u64 wed, u64 amr) | ||
679 | { | ||
680 | int result; | ||
681 | |||
682 | /* fill the process element entry */ | ||
683 | result = process_element_entry_psl9(ctx, wed, amr); | ||
684 | if (result) | ||
685 | return result; | ||
686 | |||
687 | update_ivtes_directed(ctx); | ||
688 | |||
689 | /* first guy needs to enable */ | ||
690 | result = cxl_ops->afu_check_and_enable(ctx->afu); | ||
691 | if (result) | ||
692 | return result; | ||
693 | |||
694 | return add_process_element(ctx); | ||
695 | } | ||
696 | |||
587 | int cxl_attach_afu_directed_psl8(struct cxl_context *ctx, u64 wed, u64 amr) | 697 | int cxl_attach_afu_directed_psl8(struct cxl_context *ctx, u64 wed, u64 amr) |
588 | { | 698 | { |
589 | u32 pid; | 699 | u32 pid; |
@@ -594,7 +704,7 @@ int cxl_attach_afu_directed_psl8(struct cxl_context *ctx, u64 wed, u64 amr) | |||
594 | ctx->elem->ctxtime = 0; /* disable */ | 704 | ctx->elem->ctxtime = 0; /* disable */ |
595 | ctx->elem->lpid = cpu_to_be32(mfspr(SPRN_LPID)); | 705 | ctx->elem->lpid = cpu_to_be32(mfspr(SPRN_LPID)); |
596 | ctx->elem->haurp = 0; /* disable */ | 706 | ctx->elem->haurp = 0; /* disable */ |
597 | ctx->elem->sdr = cpu_to_be64(mfspr(SPRN_SDR1)); | 707 | ctx->elem->u.sdr = cpu_to_be64(mfspr(SPRN_SDR1)); |
598 | 708 | ||
599 | pid = current->pid; | 709 | pid = current->pid; |
600 | if (ctx->kernel) | 710 | if (ctx->kernel) |
@@ -605,13 +715,13 @@ int cxl_attach_afu_directed_psl8(struct cxl_context *ctx, u64 wed, u64 amr) | |||
605 | ctx->elem->sr = cpu_to_be64(calculate_sr(ctx)); | 715 | ctx->elem->sr = cpu_to_be64(calculate_sr(ctx)); |
606 | 716 | ||
607 | ctx->elem->common.csrp = 0; /* disable */ | 717 | ctx->elem->common.csrp = 0; /* disable */ |
608 | ctx->elem->common.aurp0 = 0; /* disable */ | 718 | ctx->elem->common.u.psl8.aurp0 = 0; /* disable */ |
609 | ctx->elem->common.aurp1 = 0; /* disable */ | 719 | ctx->elem->common.u.psl8.aurp1 = 0; /* disable */ |
610 | 720 | ||
611 | cxl_prefault(ctx, wed); | 721 | cxl_prefault(ctx, wed); |
612 | 722 | ||
613 | ctx->elem->common.sstp0 = cpu_to_be64(ctx->sstp0); | 723 | ctx->elem->common.u.psl8.sstp0 = cpu_to_be64(ctx->sstp0); |
614 | ctx->elem->common.sstp1 = cpu_to_be64(ctx->sstp1); | 724 | ctx->elem->common.u.psl8.sstp1 = cpu_to_be64(ctx->sstp1); |
615 | 725 | ||
616 | /* | 726 | /* |
617 | * Ensure we have the multiplexed PSL interrupt set up to take faults | 727 | * Ensure we have the multiplexed PSL interrupt set up to take faults |
@@ -677,6 +787,32 @@ static int deactivate_afu_directed(struct cxl_afu *afu) | |||
677 | return 0; | 787 | return 0; |
678 | } | 788 | } |
679 | 789 | ||
790 | int cxl_activate_dedicated_process_psl9(struct cxl_afu *afu) | ||
791 | { | ||
792 | dev_info(&afu->dev, "Activating dedicated process mode\n"); | ||
793 | |||
794 | /* | ||
795 | * If XSL is set to dedicated mode (Set in PSL_SCNTL reg), the | ||
796 | * XSL and AFU are programmed to work with a single context. | ||
797 | * The context information should be configured in the SPA area | ||
798 | * index 0 (so PSL_SPAP must be configured before enabling the | ||
799 | * AFU). | ||
800 | */ | ||
801 | afu->num_procs = 1; | ||
802 | if (afu->native->spa == NULL) { | ||
803 | if (cxl_alloc_spa(afu, CXL_MODE_DEDICATED)) | ||
804 | return -ENOMEM; | ||
805 | } | ||
806 | attach_spa(afu); | ||
807 | |||
808 | cxl_p1n_write(afu, CXL_PSL_SCNTL_An, CXL_PSL_SCNTL_An_PM_Process); | ||
809 | cxl_p1n_write(afu, CXL_PSL_ID_An, CXL_PSL_ID_An_F | CXL_PSL_ID_An_L); | ||
810 | |||
811 | afu->current_mode = CXL_MODE_DEDICATED; | ||
812 | |||
813 | return cxl_chardev_d_afu_add(afu); | ||
814 | } | ||
815 | |||
680 | int cxl_activate_dedicated_process_psl8(struct cxl_afu *afu) | 816 | int cxl_activate_dedicated_process_psl8(struct cxl_afu *afu) |
681 | { | 817 | { |
682 | dev_info(&afu->dev, "Activating dedicated process mode\n"); | 818 | dev_info(&afu->dev, "Activating dedicated process mode\n"); |
@@ -700,6 +836,16 @@ int cxl_activate_dedicated_process_psl8(struct cxl_afu *afu) | |||
700 | return cxl_chardev_d_afu_add(afu); | 836 | return cxl_chardev_d_afu_add(afu); |
701 | } | 837 | } |
702 | 838 | ||
839 | void cxl_update_dedicated_ivtes_psl9(struct cxl_context *ctx) | ||
840 | { | ||
841 | int r; | ||
842 | |||
843 | for (r = 0; r < CXL_IRQ_RANGES; r++) { | ||
844 | ctx->elem->ivte_offsets[r] = cpu_to_be16(ctx->irqs.offset[r]); | ||
845 | ctx->elem->ivte_ranges[r] = cpu_to_be16(ctx->irqs.range[r]); | ||
846 | } | ||
847 | } | ||
848 | |||
703 | void cxl_update_dedicated_ivtes_psl8(struct cxl_context *ctx) | 849 | void cxl_update_dedicated_ivtes_psl8(struct cxl_context *ctx) |
704 | { | 850 | { |
705 | struct cxl_afu *afu = ctx->afu; | 851 | struct cxl_afu *afu = ctx->afu; |
@@ -716,6 +862,26 @@ void cxl_update_dedicated_ivtes_psl8(struct cxl_context *ctx) | |||
716 | ((u64)ctx->irqs.range[3] & 0xffff)); | 862 | ((u64)ctx->irqs.range[3] & 0xffff)); |
717 | } | 863 | } |
718 | 864 | ||
865 | int cxl_attach_dedicated_process_psl9(struct cxl_context *ctx, u64 wed, u64 amr) | ||
866 | { | ||
867 | struct cxl_afu *afu = ctx->afu; | ||
868 | int result; | ||
869 | |||
870 | /* fill the process element entry */ | ||
871 | result = process_element_entry_psl9(ctx, wed, amr); | ||
872 | if (result) | ||
873 | return result; | ||
874 | |||
875 | if (ctx->afu->adapter->native->sl_ops->update_dedicated_ivtes) | ||
876 | afu->adapter->native->sl_ops->update_dedicated_ivtes(ctx); | ||
877 | |||
878 | result = cxl_ops->afu_reset(afu); | ||
879 | if (result) | ||
880 | return result; | ||
881 | |||
882 | return afu_enable(afu); | ||
883 | } | ||
884 | |||
719 | int cxl_attach_dedicated_process_psl8(struct cxl_context *ctx, u64 wed, u64 amr) | 885 | int cxl_attach_dedicated_process_psl8(struct cxl_context *ctx, u64 wed, u64 amr) |
720 | { | 886 | { |
721 | struct cxl_afu *afu = ctx->afu; | 887 | struct cxl_afu *afu = ctx->afu; |
@@ -887,6 +1053,21 @@ static int native_get_irq_info(struct cxl_afu *afu, struct cxl_irq_info *info) | |||
887 | return 0; | 1053 | return 0; |
888 | } | 1054 | } |
889 | 1055 | ||
1056 | void cxl_native_irq_dump_regs_psl9(struct cxl_context *ctx) | ||
1057 | { | ||
1058 | u64 fir1, fir2, serr; | ||
1059 | |||
1060 | fir1 = cxl_p1_read(ctx->afu->adapter, CXL_PSL9_FIR1); | ||
1061 | fir2 = cxl_p1_read(ctx->afu->adapter, CXL_PSL9_FIR2); | ||
1062 | |||
1063 | dev_crit(&ctx->afu->dev, "PSL_FIR1: 0x%016llx\n", fir1); | ||
1064 | dev_crit(&ctx->afu->dev, "PSL_FIR2: 0x%016llx\n", fir2); | ||
1065 | if (ctx->afu->adapter->native->sl_ops->register_serr_irq) { | ||
1066 | serr = cxl_p1n_read(ctx->afu, CXL_PSL_SERR_An); | ||
1067 | cxl_afu_decode_psl_serr(ctx->afu, serr); | ||
1068 | } | ||
1069 | } | ||
1070 | |||
890 | void cxl_native_irq_dump_regs_psl8(struct cxl_context *ctx) | 1071 | void cxl_native_irq_dump_regs_psl8(struct cxl_context *ctx) |
891 | { | 1072 | { |
892 | u64 fir1, fir2, fir_slice, serr, afu_debug; | 1073 | u64 fir1, fir2, fir_slice, serr, afu_debug; |
@@ -923,9 +1104,20 @@ static irqreturn_t native_handle_psl_slice_error(struct cxl_context *ctx, | |||
923 | return cxl_ops->ack_irq(ctx, 0, errstat); | 1104 | return cxl_ops->ack_irq(ctx, 0, errstat); |
924 | } | 1105 | } |
925 | 1106 | ||
1107 | static bool cxl_is_translation_fault(struct cxl_afu *afu, u64 dsisr) | ||
1108 | { | ||
1109 | if ((cxl_is_psl8(afu)) && (dsisr & CXL_PSL_DSISR_TRANS)) | ||
1110 | return true; | ||
1111 | |||
1112 | if ((cxl_is_psl9(afu)) && (dsisr & CXL_PSL9_DSISR_An_TF)) | ||
1113 | return true; | ||
1114 | |||
1115 | return false; | ||
1116 | } | ||
1117 | |||
926 | irqreturn_t cxl_fail_irq_psl(struct cxl_afu *afu, struct cxl_irq_info *irq_info) | 1118 | irqreturn_t cxl_fail_irq_psl(struct cxl_afu *afu, struct cxl_irq_info *irq_info) |
927 | { | 1119 | { |
928 | if (irq_info->dsisr & CXL_PSL_DSISR_TRANS) | 1120 | if (cxl_is_translation_fault(afu, irq_info->dsisr)) |
929 | cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE); | 1121 | cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE); |
930 | else | 1122 | else |
931 | cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A); | 1123 | cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A); |
@@ -994,6 +1186,9 @@ static void native_irq_wait(struct cxl_context *ctx) | |||
994 | if (cxl_is_psl8(ctx->afu) && | 1186 | if (cxl_is_psl8(ctx->afu) && |
995 | ((dsisr & CXL_PSL_DSISR_PENDING) == 0)) | 1187 | ((dsisr & CXL_PSL_DSISR_PENDING) == 0)) |
996 | return; | 1188 | return; |
1189 | if (cxl_is_psl9(ctx->afu) && | ||
1190 | ((dsisr & CXL_PSL9_DSISR_PENDING) == 0)) | ||
1191 | return; | ||
997 | /* | 1192 | /* |
998 | * We are waiting for the workqueue to process our | 1193 | * We are waiting for the workqueue to process our |
999 | * irq, so need to let that run here. | 1194 | * irq, so need to let that run here. |
@@ -1122,6 +1317,13 @@ int cxl_native_register_serr_irq(struct cxl_afu *afu) | |||
1122 | serr = cxl_p1n_read(afu, CXL_PSL_SERR_An); | 1317 | serr = cxl_p1n_read(afu, CXL_PSL_SERR_An); |
1123 | if (cxl_is_power8()) | 1318 | if (cxl_is_power8()) |
1124 | serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff); | 1319 | serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff); |
1320 | if (cxl_is_power9()) { | ||
1321 | /* | ||
1322 | * By default, all errors are masked. So don't set all masks. | ||
1323 | * Slice errors will be transfered. | ||
1324 | */ | ||
1325 | serr = (serr & ~0xff0000007fffffffULL) | (afu->serr_hwirq & 0xffff); | ||
1326 | } | ||
1125 | cxl_p1n_write(afu, CXL_PSL_SERR_An, serr); | 1327 | cxl_p1n_write(afu, CXL_PSL_SERR_An, serr); |
1126 | 1328 | ||
1127 | return 0; | 1329 | return 0; |