diff options
Diffstat (limited to 'drivers/misc/cxl/pci.c')
-rw-r--r-- | drivers/misc/cxl/pci.c | 95 |
1 files changed, 57 insertions, 38 deletions
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 23b84c5d9453..fb4fd45e8744 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c | |||
@@ -90,8 +90,8 @@ | |||
90 | 90 | ||
91 | /* This works a little different than the p1/p2 register accesses to make it | 91 | /* This works a little different than the p1/p2 register accesses to make it |
92 | * easier to pull out individual fields */ | 92 | * easier to pull out individual fields */ |
93 | #define AFUD_READ(afu, off) in_be64(afu->afu_desc_mmio + off) | 93 | #define AFUD_READ(afu, off) in_be64(afu->native->afu_desc_mmio + off) |
94 | #define AFUD_READ_LE(afu, off) in_le64(afu->afu_desc_mmio + off) | 94 | #define AFUD_READ_LE(afu, off) in_le64(afu->native->afu_desc_mmio + off) |
95 | #define EXTRACT_PPC_BIT(val, bit) (!!(val & PPC_BIT(bit))) | 95 | #define EXTRACT_PPC_BIT(val, bit) (!!(val & PPC_BIT(bit))) |
96 | #define EXTRACT_PPC_BITS(val, bs, be) ((val & PPC_BITMASK(bs, be)) >> PPC_BITLSHIFT(be)) | 96 | #define EXTRACT_PPC_BITS(val, bs, be) ((val & PPC_BITMASK(bs, be)) >> PPC_BITLSHIFT(be)) |
97 | 97 | ||
@@ -550,15 +550,15 @@ static int pci_map_slice_regs(struct cxl_afu *afu, struct cxl *adapter, struct p | |||
550 | 550 | ||
551 | p1n_base = p1_base(dev) + 0x10000 + (afu->slice * p1n_size); | 551 | p1n_base = p1_base(dev) + 0x10000 + (afu->slice * p1n_size); |
552 | p2n_base = p2_base(dev) + (afu->slice * p2n_size); | 552 | p2n_base = p2_base(dev) + (afu->slice * p2n_size); |
553 | afu->psn_phys = p2_base(dev) + (adapter->ps_off + (afu->slice * adapter->ps_size)); | 553 | afu->psn_phys = p2_base(dev) + (adapter->native->ps_off + (afu->slice * adapter->ps_size)); |
554 | afu_desc = p2_base(dev) + adapter->afu_desc_off + (afu->slice * adapter->afu_desc_size); | 554 | afu_desc = p2_base(dev) + adapter->native->afu_desc_off + (afu->slice * adapter->native->afu_desc_size); |
555 | 555 | ||
556 | if (!(afu->p1n_mmio = ioremap(p1n_base, p1n_size))) | 556 | if (!(afu->native->p1n_mmio = ioremap(p1n_base, p1n_size))) |
557 | goto err; | 557 | goto err; |
558 | if (!(afu->p2n_mmio = ioremap(p2n_base, p2n_size))) | 558 | if (!(afu->p2n_mmio = ioremap(p2n_base, p2n_size))) |
559 | goto err1; | 559 | goto err1; |
560 | if (afu_desc) { | 560 | if (afu_desc) { |
561 | if (!(afu->afu_desc_mmio = ioremap(afu_desc, adapter->afu_desc_size))) | 561 | if (!(afu->native->afu_desc_mmio = ioremap(afu_desc, adapter->native->afu_desc_size))) |
562 | goto err2; | 562 | goto err2; |
563 | } | 563 | } |
564 | 564 | ||
@@ -566,7 +566,7 @@ static int pci_map_slice_regs(struct cxl_afu *afu, struct cxl *adapter, struct p | |||
566 | err2: | 566 | err2: |
567 | iounmap(afu->p2n_mmio); | 567 | iounmap(afu->p2n_mmio); |
568 | err1: | 568 | err1: |
569 | iounmap(afu->p1n_mmio); | 569 | iounmap(afu->native->p1n_mmio); |
570 | err: | 570 | err: |
571 | dev_err(&afu->dev, "Error mapping AFU MMIO regions\n"); | 571 | dev_err(&afu->dev, "Error mapping AFU MMIO regions\n"); |
572 | return -ENOMEM; | 572 | return -ENOMEM; |
@@ -578,13 +578,13 @@ static void pci_unmap_slice_regs(struct cxl_afu *afu) | |||
578 | iounmap(afu->p2n_mmio); | 578 | iounmap(afu->p2n_mmio); |
579 | afu->p2n_mmio = NULL; | 579 | afu->p2n_mmio = NULL; |
580 | } | 580 | } |
581 | if (afu->p1n_mmio) { | 581 | if (afu->native->p1n_mmio) { |
582 | iounmap(afu->p1n_mmio); | 582 | iounmap(afu->native->p1n_mmio); |
583 | afu->p1n_mmio = NULL; | 583 | afu->native->p1n_mmio = NULL; |
584 | } | 584 | } |
585 | if (afu->afu_desc_mmio) { | 585 | if (afu->native->afu_desc_mmio) { |
586 | iounmap(afu->afu_desc_mmio); | 586 | iounmap(afu->native->afu_desc_mmio); |
587 | afu->afu_desc_mmio = NULL; | 587 | afu->native->afu_desc_mmio = NULL; |
588 | } | 588 | } |
589 | } | 589 | } |
590 | 590 | ||
@@ -597,6 +597,7 @@ void cxl_pci_release_afu(struct device *dev) | |||
597 | idr_destroy(&afu->contexts_idr); | 597 | idr_destroy(&afu->contexts_idr); |
598 | cxl_release_spa(afu); | 598 | cxl_release_spa(afu); |
599 | 599 | ||
600 | kfree(afu->native); | ||
600 | kfree(afu); | 601 | kfree(afu); |
601 | } | 602 | } |
602 | 603 | ||
@@ -621,7 +622,7 @@ static int cxl_read_afu_descriptor(struct cxl_afu *afu) | |||
621 | afu->pp_size = AFUD_PPPSA_LEN(val) * 4096; | 622 | afu->pp_size = AFUD_PPPSA_LEN(val) * 4096; |
622 | afu->psa = AFUD_PPPSA_PSA(val); | 623 | afu->psa = AFUD_PPPSA_PSA(val); |
623 | if ((afu->pp_psa = AFUD_PPPSA_PP(val))) | 624 | if ((afu->pp_psa = AFUD_PPPSA_PP(val))) |
624 | afu->pp_offset = AFUD_READ_PPPSA_OFF(afu); | 625 | afu->native->pp_offset = AFUD_READ_PPPSA_OFF(afu); |
625 | 626 | ||
626 | val = AFUD_READ_CR(afu); | 627 | val = AFUD_READ_CR(afu); |
627 | afu->crs_len = AFUD_CR_LEN(val) * 256; | 628 | afu->crs_len = AFUD_CR_LEN(val) * 256; |
@@ -652,7 +653,7 @@ static int cxl_afu_descriptor_looks_ok(struct cxl_afu *afu) | |||
652 | u32 val; | 653 | u32 val; |
653 | 654 | ||
654 | if (afu->psa && afu->adapter->ps_size < | 655 | if (afu->psa && afu->adapter->ps_size < |
655 | (afu->pp_offset + afu->pp_size*afu->max_procs_virtualised)) { | 656 | (afu->native->pp_offset + afu->pp_size*afu->max_procs_virtualised)) { |
656 | dev_err(&afu->dev, "per-process PSA can't fit inside the PSA!\n"); | 657 | dev_err(&afu->dev, "per-process PSA can't fit inside the PSA!\n"); |
657 | return -ENODEV; | 658 | return -ENODEV; |
658 | } | 659 | } |
@@ -737,7 +738,7 @@ ssize_t cxl_pci_afu_read_err_buffer(struct cxl_afu *afu, char *buf, | |||
737 | loff_t aligned_start, aligned_end; | 738 | loff_t aligned_start, aligned_end; |
738 | size_t aligned_length; | 739 | size_t aligned_length; |
739 | void *tbuf; | 740 | void *tbuf; |
740 | const void __iomem *ebuf = afu->afu_desc_mmio + afu->eb_offset; | 741 | const void __iomem *ebuf = afu->native->afu_desc_mmio + afu->eb_offset; |
741 | 742 | ||
742 | if (count == 0 || off < 0 || (size_t)off >= afu->eb_len) | 743 | if (count == 0 || off < 0 || (size_t)off >= afu->eb_len) |
743 | return 0; | 744 | return 0; |
@@ -819,19 +820,25 @@ static void pci_deconfigure_afu(struct cxl_afu *afu) | |||
819 | static int pci_init_afu(struct cxl *adapter, int slice, struct pci_dev *dev) | 820 | static int pci_init_afu(struct cxl *adapter, int slice, struct pci_dev *dev) |
820 | { | 821 | { |
821 | struct cxl_afu *afu; | 822 | struct cxl_afu *afu; |
822 | int rc; | 823 | int rc = -ENOMEM; |
823 | 824 | ||
824 | afu = cxl_alloc_afu(adapter, slice); | 825 | afu = cxl_alloc_afu(adapter, slice); |
825 | if (!afu) | 826 | if (!afu) |
826 | return -ENOMEM; | 827 | return -ENOMEM; |
827 | 828 | ||
829 | afu->native = kzalloc(sizeof(struct cxl_afu_native), GFP_KERNEL); | ||
830 | if (!afu->native) | ||
831 | goto err_free_afu; | ||
832 | |||
833 | mutex_init(&afu->native->spa_mutex); | ||
834 | |||
828 | rc = dev_set_name(&afu->dev, "afu%i.%i", adapter->adapter_num, slice); | 835 | rc = dev_set_name(&afu->dev, "afu%i.%i", adapter->adapter_num, slice); |
829 | if (rc) | 836 | if (rc) |
830 | goto err_free; | 837 | goto err_free_native; |
831 | 838 | ||
832 | rc = pci_configure_afu(afu, adapter, dev); | 839 | rc = pci_configure_afu(afu, adapter, dev); |
833 | if (rc) | 840 | if (rc) |
834 | goto err_free; | 841 | goto err_free_native; |
835 | 842 | ||
836 | /* Don't care if this fails */ | 843 | /* Don't care if this fails */ |
837 | cxl_debugfs_afu_add(afu); | 844 | cxl_debugfs_afu_add(afu); |
@@ -859,7 +866,9 @@ err_put1: | |||
859 | device_unregister(&afu->dev); | 866 | device_unregister(&afu->dev); |
860 | return rc; | 867 | return rc; |
861 | 868 | ||
862 | err_free: | 869 | err_free_native: |
870 | kfree(afu->native); | ||
871 | err_free_afu: | ||
863 | kfree(afu); | 872 | kfree(afu); |
864 | return rc; | 873 | return rc; |
865 | 874 | ||
@@ -920,17 +929,17 @@ static int cxl_map_adapter_regs(struct cxl *adapter, struct pci_dev *dev) | |||
920 | pr_devel("cxl_map_adapter_regs: p1: %#016llx %#llx, p2: %#016llx %#llx", | 929 | pr_devel("cxl_map_adapter_regs: p1: %#016llx %#llx, p2: %#016llx %#llx", |
921 | p1_base(dev), p1_size(dev), p2_base(dev), p2_size(dev)); | 930 | p1_base(dev), p1_size(dev), p2_base(dev), p2_size(dev)); |
922 | 931 | ||
923 | if (!(adapter->p1_mmio = ioremap(p1_base(dev), p1_size(dev)))) | 932 | if (!(adapter->native->p1_mmio = ioremap(p1_base(dev), p1_size(dev)))) |
924 | goto err3; | 933 | goto err3; |
925 | 934 | ||
926 | if (!(adapter->p2_mmio = ioremap(p2_base(dev), p2_size(dev)))) | 935 | if (!(adapter->native->p2_mmio = ioremap(p2_base(dev), p2_size(dev)))) |
927 | goto err4; | 936 | goto err4; |
928 | 937 | ||
929 | return 0; | 938 | return 0; |
930 | 939 | ||
931 | err4: | 940 | err4: |
932 | iounmap(adapter->p1_mmio); | 941 | iounmap(adapter->native->p1_mmio); |
933 | adapter->p1_mmio = NULL; | 942 | adapter->native->p1_mmio = NULL; |
934 | err3: | 943 | err3: |
935 | pci_release_region(dev, 0); | 944 | pci_release_region(dev, 0); |
936 | err2: | 945 | err2: |
@@ -941,14 +950,14 @@ err1: | |||
941 | 950 | ||
942 | static void cxl_unmap_adapter_regs(struct cxl *adapter) | 951 | static void cxl_unmap_adapter_regs(struct cxl *adapter) |
943 | { | 952 | { |
944 | if (adapter->p1_mmio) { | 953 | if (adapter->native->p1_mmio) { |
945 | iounmap(adapter->p1_mmio); | 954 | iounmap(adapter->native->p1_mmio); |
946 | adapter->p1_mmio = NULL; | 955 | adapter->native->p1_mmio = NULL; |
947 | pci_release_region(to_pci_dev(adapter->dev.parent), 2); | 956 | pci_release_region(to_pci_dev(adapter->dev.parent), 2); |
948 | } | 957 | } |
949 | if (adapter->p2_mmio) { | 958 | if (adapter->native->p2_mmio) { |
950 | iounmap(adapter->p2_mmio); | 959 | iounmap(adapter->native->p2_mmio); |
951 | adapter->p2_mmio = NULL; | 960 | adapter->native->p2_mmio = NULL; |
952 | pci_release_region(to_pci_dev(adapter->dev.parent), 0); | 961 | pci_release_region(to_pci_dev(adapter->dev.parent), 0); |
953 | } | 962 | } |
954 | } | 963 | } |
@@ -989,10 +998,10 @@ static int cxl_read_vsec(struct cxl *adapter, struct pci_dev *dev) | |||
989 | 998 | ||
990 | /* Convert everything to bytes, because there is NO WAY I'd look at the | 999 | /* Convert everything to bytes, because there is NO WAY I'd look at the |
991 | * code a month later and forget what units these are in ;-) */ | 1000 | * code a month later and forget what units these are in ;-) */ |
992 | adapter->ps_off = ps_off * 64 * 1024; | 1001 | adapter->native->ps_off = ps_off * 64 * 1024; |
993 | adapter->ps_size = ps_size * 64 * 1024; | 1002 | adapter->ps_size = ps_size * 64 * 1024; |
994 | adapter->afu_desc_off = afu_desc_off * 64 * 1024; | 1003 | adapter->native->afu_desc_off = afu_desc_off * 64 * 1024; |
995 | adapter->afu_desc_size = afu_desc_size *64 * 1024; | 1004 | adapter->native->afu_desc_size = afu_desc_size * 64 * 1024; |
996 | 1005 | ||
997 | /* Total IRQs - 1 PSL ERROR - #AFU*(1 slice error + 1 DSI) */ | 1006 | /* Total IRQs - 1 PSL ERROR - #AFU*(1 slice error + 1 DSI) */ |
998 | adapter->user_irqs = pnv_cxl_get_irq_count(dev) - 1 - 2*adapter->slices; | 1007 | adapter->user_irqs = pnv_cxl_get_irq_count(dev) - 1 - 2*adapter->slices; |
@@ -1043,15 +1052,15 @@ static int cxl_vsec_looks_ok(struct cxl *adapter, struct pci_dev *dev) | |||
1043 | return -EINVAL; | 1052 | return -EINVAL; |
1044 | } | 1053 | } |
1045 | 1054 | ||
1046 | if (!adapter->afu_desc_off || !adapter->afu_desc_size) { | 1055 | if (!adapter->native->afu_desc_off || !adapter->native->afu_desc_size) { |
1047 | dev_err(&dev->dev, "ABORTING: VSEC shows no AFU descriptors\n"); | 1056 | dev_err(&dev->dev, "ABORTING: VSEC shows no AFU descriptors\n"); |
1048 | return -EINVAL; | 1057 | return -EINVAL; |
1049 | } | 1058 | } |
1050 | 1059 | ||
1051 | if (adapter->ps_size > p2_size(dev) - adapter->ps_off) { | 1060 | if (adapter->ps_size > p2_size(dev) - adapter->native->ps_off) { |
1052 | dev_err(&dev->dev, "ABORTING: Problem state size larger than " | 1061 | dev_err(&dev->dev, "ABORTING: Problem state size larger than " |
1053 | "available in BAR2: 0x%llx > 0x%llx\n", | 1062 | "available in BAR2: 0x%llx > 0x%llx\n", |
1054 | adapter->ps_size, p2_size(dev) - adapter->ps_off); | 1063 | adapter->ps_size, p2_size(dev) - adapter->native->ps_off); |
1055 | return -EINVAL; | 1064 | return -EINVAL; |
1056 | } | 1065 | } |
1057 | 1066 | ||
@@ -1066,6 +1075,7 @@ static void cxl_release_adapter(struct device *dev) | |||
1066 | 1075 | ||
1067 | cxl_remove_adapter_nr(adapter); | 1076 | cxl_remove_adapter_nr(adapter); |
1068 | 1077 | ||
1078 | kfree(adapter->native); | ||
1069 | kfree(adapter); | 1079 | kfree(adapter); |
1070 | } | 1080 | } |
1071 | 1081 | ||
@@ -1162,6 +1172,12 @@ static struct cxl *cxl_pci_init_adapter(struct pci_dev *dev) | |||
1162 | if (!adapter) | 1172 | if (!adapter) |
1163 | return ERR_PTR(-ENOMEM); | 1173 | return ERR_PTR(-ENOMEM); |
1164 | 1174 | ||
1175 | adapter->native = kzalloc(sizeof(struct cxl_native), GFP_KERNEL); | ||
1176 | if (!adapter->native) { | ||
1177 | rc = -ENOMEM; | ||
1178 | goto err_release; | ||
1179 | } | ||
1180 | |||
1165 | /* Set defaults for parameters which need to persist over | 1181 | /* Set defaults for parameters which need to persist over |
1166 | * configure/reconfigure | 1182 | * configure/reconfigure |
1167 | */ | 1183 | */ |
@@ -1171,8 +1187,7 @@ static struct cxl *cxl_pci_init_adapter(struct pci_dev *dev) | |||
1171 | rc = cxl_configure_adapter(adapter, dev); | 1187 | rc = cxl_configure_adapter(adapter, dev); |
1172 | if (rc) { | 1188 | if (rc) { |
1173 | pci_disable_device(dev); | 1189 | pci_disable_device(dev); |
1174 | cxl_release_adapter(&adapter->dev); | 1190 | goto err_release; |
1175 | return ERR_PTR(rc); | ||
1176 | } | 1191 | } |
1177 | 1192 | ||
1178 | /* Don't care if this one fails: */ | 1193 | /* Don't care if this one fails: */ |
@@ -1198,6 +1213,10 @@ err_put1: | |||
1198 | cxl_deconfigure_adapter(adapter); | 1213 | cxl_deconfigure_adapter(adapter); |
1199 | device_unregister(&adapter->dev); | 1214 | device_unregister(&adapter->dev); |
1200 | return ERR_PTR(rc); | 1215 | return ERR_PTR(rc); |
1216 | |||
1217 | err_release: | ||
1218 | cxl_release_adapter(&adapter->dev); | ||
1219 | return ERR_PTR(rc); | ||
1201 | } | 1220 | } |
1202 | 1221 | ||
1203 | static void cxl_pci_remove_adapter(struct cxl *adapter) | 1222 | static void cxl_pci_remove_adapter(struct cxl *adapter) |