aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/cxl/native.c
diff options
context:
space:
mode:
authorFrederic Barrat <fbarrat@linux.vnet.ibm.com>2016-03-04 06:26:26 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2016-03-08 21:05:39 -0500
commitd56d301b51746e71f7bdaaba10973f054c3c736e (patch)
treecf1ec59764c3012335d55d5ed620a1973e6b3f6c /drivers/misc/cxl/native.c
parent8633186209e35dfafc27c3d0f0d5e702ab47265f (diff)
cxl: Move bare-metal specific code to specialized files
Move a few functions around to better separate code specific to bare-metal environment from code which will be commonly used between guest and bare-metal. Code specific to bare-metal is meant to be in native.c or pci.c only. It's basically anything which touches the card p1 registers, some p2 registers not needed from a guest and the PCI interface. Co-authored-by: Christophe Lombard <clombard@linux.vnet.ibm.com> Signed-off-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com> Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com> Reviewed-by: Manoj Kumar <manoj@linux.vnet.ibm.com> Acked-by: Ian Munsie <imunsie@au1.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'drivers/misc/cxl/native.c')
-rw-r--r--drivers/misc/cxl/native.c240
1 files changed, 239 insertions, 1 deletions
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index 0b0a4c8a27d0..3103e3327ea6 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -712,7 +712,7 @@ int cxl_detach_process(struct cxl_context *ctx)
712 return detach_process_native_afu_directed(ctx); 712 return detach_process_native_afu_directed(ctx);
713} 713}
714 714
715int cxl_get_irq(struct cxl_afu *afu, struct cxl_irq_info *info) 715static int cxl_get_irq(struct cxl_afu *afu, struct cxl_irq_info *info)
716{ 716{
717 u64 pidtid; 717 u64 pidtid;
718 718
@@ -734,6 +734,208 @@ int cxl_get_irq(struct cxl_afu *afu, struct cxl_irq_info *info)
734 return 0; 734 return 0;
735} 735}
736 736
737irqreturn_t handle_psl_slice_error(struct cxl_context *ctx, u64 dsisr, u64 errstat)
738{
739 u64 fir1, fir2, fir_slice, serr, afu_debug;
740
741 fir1 = cxl_p1_read(ctx->afu->adapter, CXL_PSL_FIR1);
742 fir2 = cxl_p1_read(ctx->afu->adapter, CXL_PSL_FIR2);
743 fir_slice = cxl_p1n_read(ctx->afu, CXL_PSL_FIR_SLICE_An);
744 serr = cxl_p1n_read(ctx->afu, CXL_PSL_SERR_An);
745 afu_debug = cxl_p1n_read(ctx->afu, CXL_AFU_DEBUG_An);
746
747 dev_crit(&ctx->afu->dev, "PSL ERROR STATUS: 0x%016llx\n", errstat);
748 dev_crit(&ctx->afu->dev, "PSL_FIR1: 0x%016llx\n", fir1);
749 dev_crit(&ctx->afu->dev, "PSL_FIR2: 0x%016llx\n", fir2);
750 dev_crit(&ctx->afu->dev, "PSL_SERR_An: 0x%016llx\n", serr);
751 dev_crit(&ctx->afu->dev, "PSL_FIR_SLICE_An: 0x%016llx\n", fir_slice);
752 dev_crit(&ctx->afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%016llx\n", afu_debug);
753
754 dev_crit(&ctx->afu->dev, "STOPPING CXL TRACE\n");
755 cxl_stop_trace(ctx->afu->adapter);
756
757 return cxl_ack_irq(ctx, 0, errstat);
758}
759
760static irqreturn_t fail_psl_irq(struct cxl_afu *afu, struct cxl_irq_info *irq_info)
761{
762 if (irq_info->dsisr & CXL_PSL_DSISR_TRANS)
763 cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE);
764 else
765 cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A);
766
767 return IRQ_HANDLED;
768}
769
770static irqreturn_t cxl_irq_multiplexed(int irq, void *data)
771{
772 struct cxl_afu *afu = data;
773 struct cxl_context *ctx;
774 struct cxl_irq_info irq_info;
775 int ph = cxl_p2n_read(afu, CXL_PSL_PEHandle_An) & 0xffff;
776 int ret;
777
778 if ((ret = cxl_get_irq(afu, &irq_info))) {
779 WARN(1, "Unable to get CXL IRQ Info: %i\n", ret);
780 return fail_psl_irq(afu, &irq_info);
781 }
782
783 rcu_read_lock();
784 ctx = idr_find(&afu->contexts_idr, ph);
785 if (ctx) {
786 ret = cxl_irq(irq, ctx, &irq_info);
787 rcu_read_unlock();
788 return ret;
789 }
790 rcu_read_unlock();
791
792 WARN(1, "Unable to demultiplex CXL PSL IRQ for PE %i DSISR %016llx DAR"
793 " %016llx\n(Possible AFU HW issue - was a term/remove acked"
794 " with outstanding transactions?)\n", ph, irq_info.dsisr,
795 irq_info.dar);
796 return fail_psl_irq(afu, &irq_info);
797}
798
799static irqreturn_t cxl_slice_irq_err(int irq, void *data)
800{
801 struct cxl_afu *afu = data;
802 u64 fir_slice, errstat, serr, afu_debug;
803
804 WARN(irq, "CXL SLICE ERROR interrupt %i\n", irq);
805
806 serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
807 fir_slice = cxl_p1n_read(afu, CXL_PSL_FIR_SLICE_An);
808 errstat = cxl_p2n_read(afu, CXL_PSL_ErrStat_An);
809 afu_debug = cxl_p1n_read(afu, CXL_AFU_DEBUG_An);
810 dev_crit(&afu->dev, "PSL_SERR_An: 0x%016llx\n", serr);
811 dev_crit(&afu->dev, "PSL_FIR_SLICE_An: 0x%016llx\n", fir_slice);
812 dev_crit(&afu->dev, "CXL_PSL_ErrStat_An: 0x%016llx\n", errstat);
813 dev_crit(&afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%016llx\n", afu_debug);
814
815 cxl_p1n_write(afu, CXL_PSL_SERR_An, serr);
816
817 return IRQ_HANDLED;
818}
819
820static irqreturn_t cxl_irq_err(int irq, void *data)
821{
822 struct cxl *adapter = data;
823 u64 fir1, fir2, err_ivte;
824
825 WARN(1, "CXL ERROR interrupt %i\n", irq);
826
827 err_ivte = cxl_p1_read(adapter, CXL_PSL_ErrIVTE);
828 dev_crit(&adapter->dev, "PSL_ErrIVTE: 0x%016llx\n", err_ivte);
829
830 dev_crit(&adapter->dev, "STOPPING CXL TRACE\n");
831 cxl_stop_trace(adapter);
832
833 fir1 = cxl_p1_read(adapter, CXL_PSL_FIR1);
834 fir2 = cxl_p1_read(adapter, CXL_PSL_FIR2);
835
836 dev_crit(&adapter->dev, "PSL_FIR1: 0x%016llx\nPSL_FIR2: 0x%016llx\n", fir1, fir2);
837
838 return IRQ_HANDLED;
839}
840
841int cxl_register_psl_err_irq(struct cxl *adapter)
842{
843 int rc;
844
845 adapter->irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err",
846 dev_name(&adapter->dev));
847 if (!adapter->irq_name)
848 return -ENOMEM;
849
850 if ((rc = cxl_register_one_irq(adapter, cxl_irq_err, adapter,
851 &adapter->err_hwirq,
852 &adapter->err_virq,
853 adapter->irq_name))) {
854 kfree(adapter->irq_name);
855 adapter->irq_name = NULL;
856 return rc;
857 }
858
859 cxl_p1_write(adapter, CXL_PSL_ErrIVTE, adapter->err_hwirq & 0xffff);
860
861 return 0;
862}
863
864void cxl_release_psl_err_irq(struct cxl *adapter)
865{
866 if (adapter->err_virq != irq_find_mapping(NULL, adapter->err_hwirq))
867 return;
868
869 cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000);
870 cxl_unmap_irq(adapter->err_virq, adapter);
871 cxl_release_one_irq(adapter, adapter->err_hwirq);
872 kfree(adapter->irq_name);
873}
874
875int cxl_register_serr_irq(struct cxl_afu *afu)
876{
877 u64 serr;
878 int rc;
879
880 afu->err_irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err",
881 dev_name(&afu->dev));
882 if (!afu->err_irq_name)
883 return -ENOMEM;
884
885 if ((rc = cxl_register_one_irq(afu->adapter, cxl_slice_irq_err, afu,
886 &afu->serr_hwirq,
887 &afu->serr_virq, afu->err_irq_name))) {
888 kfree(afu->err_irq_name);
889 afu->err_irq_name = NULL;
890 return rc;
891 }
892
893 serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
894 serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff);
895 cxl_p1n_write(afu, CXL_PSL_SERR_An, serr);
896
897 return 0;
898}
899
900void cxl_release_serr_irq(struct cxl_afu *afu)
901{
902 if (afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
903 return;
904
905 cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000);
906 cxl_unmap_irq(afu->serr_virq, afu);
907 cxl_release_one_irq(afu->adapter, afu->serr_hwirq);
908 kfree(afu->err_irq_name);
909}
910
911int cxl_register_psl_irq(struct cxl_afu *afu)
912{
913 int rc;
914
915 afu->psl_irq_name = kasprintf(GFP_KERNEL, "cxl-%s",
916 dev_name(&afu->dev));
917 if (!afu->psl_irq_name)
918 return -ENOMEM;
919
920 if ((rc = cxl_register_one_irq(afu->adapter, cxl_irq_multiplexed, afu,
921 &afu->psl_hwirq, &afu->psl_virq,
922 afu->psl_irq_name))) {
923 kfree(afu->psl_irq_name);
924 afu->psl_irq_name = NULL;
925 }
926 return rc;
927}
928
929void cxl_release_psl_irq(struct cxl_afu *afu)
930{
931 if (afu->psl_virq != irq_find_mapping(NULL, afu->psl_hwirq))
932 return;
933
934 cxl_unmap_irq(afu->psl_virq, afu);
935 cxl_release_one_irq(afu->adapter, afu->psl_hwirq);
936 kfree(afu->psl_irq_name);
937}
938
737static void recover_psl_err(struct cxl_afu *afu, u64 errstat) 939static void recover_psl_err(struct cxl_afu *afu, u64 errstat)
738{ 940{
739 u64 dsisr; 941 u64 dsisr;
@@ -763,3 +965,39 @@ int cxl_check_error(struct cxl_afu *afu)
763{ 965{
764 return (cxl_p1n_read(afu, CXL_PSL_SCNTL_An) == ~0ULL); 966 return (cxl_p1n_read(afu, CXL_PSL_SCNTL_An) == ~0ULL);
765} 967}
968
969u64 cxl_afu_cr_read64(struct cxl_afu *afu, int cr, u64 off)
970{
971 if (likely(cxl_adapter_link_ok(afu->adapter)))
972 return in_le64((afu)->afu_desc_mmio + (afu)->crs_offset +
973 ((cr) * (afu)->crs_len) + (off));
974 else
975 return ~0ULL;
976}
977
978u32 cxl_afu_cr_read32(struct cxl_afu *afu, int cr, u64 off)
979{
980 if (likely(cxl_adapter_link_ok(afu->adapter)))
981 return in_le32((afu)->afu_desc_mmio + (afu)->crs_offset +
982 ((cr) * (afu)->crs_len) + (off));
983 else
984 return 0xffffffff;
985}
986
987u16 cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off)
988{
989 u64 aligned_off = off & ~0x3L;
990 u32 val;
991
992 val = cxl_afu_cr_read32(afu, cr, aligned_off);
993 return (val >> ((off & 0x2) * 8)) & 0xffff;
994}
995
996u8 cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off)
997{
998 u64 aligned_off = off & ~0x3L;
999 u32 val;
1000
1001 val = cxl_afu_cr_read32(afu, cr, aligned_off);
1002 return (val >> ((off & 0x3) * 8)) & 0xff;
1003}