|
33 | 33 | #define COMMAND_COPY BIT(5) |
34 | 34 | #define COMMAND_ENABLE_DOORBELL BIT(6) |
35 | 35 | #define COMMAND_DISABLE_DOORBELL BIT(7) |
| 36 | +#define COMMAND_BAR_SUBRANGE_SETUP BIT(8) |
| 37 | +#define COMMAND_BAR_SUBRANGE_CLEAR BIT(9) |
36 | 38 |
|
37 | 39 | #define STATUS_READ_SUCCESS BIT(0) |
38 | 40 | #define STATUS_READ_FAIL BIT(1) |
|
48 | 50 | #define STATUS_DOORBELL_ENABLE_FAIL BIT(11) |
49 | 51 | #define STATUS_DOORBELL_DISABLE_SUCCESS BIT(12) |
50 | 52 | #define STATUS_DOORBELL_DISABLE_FAIL BIT(13) |
| 53 | +#define STATUS_BAR_SUBRANGE_SETUP_SUCCESS BIT(14) |
| 54 | +#define STATUS_BAR_SUBRANGE_SETUP_FAIL BIT(15) |
| 55 | +#define STATUS_BAR_SUBRANGE_CLEAR_SUCCESS BIT(16) |
| 56 | +#define STATUS_BAR_SUBRANGE_CLEAR_FAIL BIT(17) |
51 | 57 |
|
52 | 58 | #define FLAG_USE_DMA BIT(0) |
53 | 59 |
|
|
57 | 63 | #define CAP_MSI BIT(1) |
58 | 64 | #define CAP_MSIX BIT(2) |
59 | 65 | #define CAP_INTX BIT(3) |
| 66 | +#define CAP_SUBRANGE_MAPPING BIT(4) |
| 67 | + |
| 68 | +#define PCI_EPF_TEST_BAR_SUBRANGE_NSUB 2 |
60 | 69 |
|
61 | 70 | static struct workqueue_struct *kpcitest_workqueue; |
62 | 71 |
|
@@ -102,7 +111,7 @@ static struct pci_epf_header test_header = { |
102 | 111 | .interrupt_pin = PCI_INTERRUPT_INTA, |
103 | 112 | }; |
104 | 113 |
|
105 | | -static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 }; |
| 114 | +static size_t bar_size[] = { 131072, 131072, 131072, 131072, 131072, 1048576 }; |
106 | 115 |
|
107 | 116 | static void pci_epf_test_dma_callback(void *param) |
108 | 117 | { |
@@ -806,6 +815,155 @@ static void pci_epf_test_disable_doorbell(struct pci_epf_test *epf_test, |
806 | 815 | reg->status = cpu_to_le32(status); |
807 | 816 | } |
808 | 817 |
|
| 818 | +static u8 pci_epf_test_subrange_sig_byte(enum pci_barno barno, |
| 819 | + unsigned int subno) |
| 820 | +{ |
| 821 | + return 0x50 + (barno * 8) + subno; |
| 822 | +} |
| 823 | + |
| 824 | +static void pci_epf_test_bar_subrange_setup(struct pci_epf_test *epf_test, |
| 825 | + struct pci_epf_test_reg *reg) |
| 826 | +{ |
| 827 | + struct pci_epf_bar_submap *submap, *old_submap; |
| 828 | + struct pci_epf *epf = epf_test->epf; |
| 829 | + struct pci_epc *epc = epf->epc; |
| 830 | + struct pci_epf_bar *bar; |
| 831 | + unsigned int nsub = PCI_EPF_TEST_BAR_SUBRANGE_NSUB, old_nsub; |
| 832 | + /* reg->size carries BAR number for BAR_SUBRANGE_* commands. */ |
| 833 | + enum pci_barno barno = le32_to_cpu(reg->size); |
| 834 | + u32 status = le32_to_cpu(reg->status); |
| 835 | + unsigned int i, phys_idx; |
| 836 | + size_t sub_size; |
| 837 | + u8 *addr; |
| 838 | + int ret; |
| 839 | + |
| 840 | + if (barno >= PCI_STD_NUM_BARS) { |
| 841 | + dev_err(&epf->dev, "Invalid barno: %d\n", barno); |
| 842 | + goto err; |
| 843 | + } |
| 844 | + |
| 845 | + /* Host side should've avoided test_reg_bar, this is a safeguard. */ |
| 846 | + if (barno == epf_test->test_reg_bar) { |
| 847 | + dev_err(&epf->dev, "test_reg_bar cannot be used for subrange test\n"); |
| 848 | + goto err; |
| 849 | + } |
| 850 | + |
| 851 | + if (!epf_test->epc_features->dynamic_inbound_mapping || |
| 852 | + !epf_test->epc_features->subrange_mapping) { |
| 853 | + dev_err(&epf->dev, "epc driver does not support subrange mapping\n"); |
| 854 | + goto err; |
| 855 | + } |
| 856 | + |
| 857 | + bar = &epf->bar[barno]; |
| 858 | + if (!bar->size || !bar->addr) { |
| 859 | + dev_err(&epf->dev, "bar size/addr (%zu/%p) is invalid\n", |
| 860 | + bar->size, bar->addr); |
| 861 | + goto err; |
| 862 | + } |
| 863 | + |
| 864 | + if (bar->size % nsub) { |
| 865 | + dev_err(&epf->dev, "BAR size %zu is not divisible by %u\n", |
| 866 | + bar->size, nsub); |
| 867 | + goto err; |
| 868 | + } |
| 869 | + |
| 870 | + sub_size = bar->size / nsub; |
| 871 | + |
| 872 | + submap = kcalloc(nsub, sizeof(*submap), GFP_KERNEL); |
| 873 | + if (!submap) |
| 874 | + goto err; |
| 875 | + |
| 876 | + for (i = 0; i < nsub; i++) { |
| 877 | + /* Swap the two halves so RC can verify ordering. */ |
| 878 | + phys_idx = i ^ 1; |
| 879 | + submap[i].phys_addr = bar->phys_addr + (phys_idx * sub_size); |
| 880 | + submap[i].size = sub_size; |
| 881 | + } |
| 882 | + |
| 883 | + old_submap = bar->submap; |
| 884 | + old_nsub = bar->num_submap; |
| 885 | + |
| 886 | + bar->submap = submap; |
| 887 | + bar->num_submap = nsub; |
| 888 | + |
| 889 | + ret = pci_epc_set_bar(epc, epf->func_no, epf->vfunc_no, bar); |
| 890 | + if (ret) { |
| 891 | + dev_err(&epf->dev, "pci_epc_set_bar() failed: %d\n", ret); |
| 892 | + bar->submap = old_submap; |
| 893 | + bar->num_submap = old_nsub; |
| 894 | + kfree(submap); |
| 895 | + goto err; |
| 896 | + } |
| 897 | + kfree(old_submap); |
| 898 | + |
| 899 | + /* |
| 900 | + * Fill deterministic signatures into the physical regions that |
| 901 | + * each BAR subrange maps to. RC verifies these to ensure the |
| 902 | + * submap order is really applied. |
| 903 | + */ |
| 904 | + addr = (u8 *)bar->addr; |
| 905 | + for (i = 0; i < nsub; i++) { |
| 906 | + phys_idx = i ^ 1; |
| 907 | + memset(addr + (phys_idx * sub_size), |
| 908 | + pci_epf_test_subrange_sig_byte(barno, i), |
| 909 | + sub_size); |
| 910 | + } |
| 911 | + |
| 912 | + status |= STATUS_BAR_SUBRANGE_SETUP_SUCCESS; |
| 913 | + reg->status = cpu_to_le32(status); |
| 914 | + return; |
| 915 | + |
| 916 | +err: |
| 917 | + status |= STATUS_BAR_SUBRANGE_SETUP_FAIL; |
| 918 | + reg->status = cpu_to_le32(status); |
| 919 | +} |
| 920 | + |
| 921 | +static void pci_epf_test_bar_subrange_clear(struct pci_epf_test *epf_test, |
| 922 | + struct pci_epf_test_reg *reg) |
| 923 | +{ |
| 924 | + struct pci_epf *epf = epf_test->epf; |
| 925 | + struct pci_epf_bar_submap *submap; |
| 926 | + struct pci_epc *epc = epf->epc; |
| 927 | + /* reg->size carries BAR number for BAR_SUBRANGE_* commands. */ |
| 928 | + enum pci_barno barno = le32_to_cpu(reg->size); |
| 929 | + u32 status = le32_to_cpu(reg->status); |
| 930 | + struct pci_epf_bar *bar; |
| 931 | + unsigned int nsub; |
| 932 | + int ret; |
| 933 | + |
| 934 | + if (barno >= PCI_STD_NUM_BARS) { |
| 935 | + dev_err(&epf->dev, "Invalid barno: %d\n", barno); |
| 936 | + goto err; |
| 937 | + } |
| 938 | + |
| 939 | + bar = &epf->bar[barno]; |
| 940 | + submap = bar->submap; |
| 941 | + nsub = bar->num_submap; |
| 942 | + |
| 943 | + if (!submap || !nsub) |
| 944 | + goto err; |
| 945 | + |
| 946 | + bar->submap = NULL; |
| 947 | + bar->num_submap = 0; |
| 948 | + |
| 949 | + ret = pci_epc_set_bar(epc, epf->func_no, epf->vfunc_no, bar); |
| 950 | + if (ret) { |
| 951 | + bar->submap = submap; |
| 952 | + bar->num_submap = nsub; |
| 953 | + dev_err(&epf->dev, "pci_epc_set_bar() failed: %d\n", ret); |
| 954 | + goto err; |
| 955 | + } |
| 956 | + kfree(submap); |
| 957 | + |
| 958 | + status |= STATUS_BAR_SUBRANGE_CLEAR_SUCCESS; |
| 959 | + reg->status = cpu_to_le32(status); |
| 960 | + return; |
| 961 | + |
| 962 | +err: |
| 963 | + status |= STATUS_BAR_SUBRANGE_CLEAR_FAIL; |
| 964 | + reg->status = cpu_to_le32(status); |
| 965 | +} |
| 966 | + |
809 | 967 | static void pci_epf_test_cmd_handler(struct work_struct *work) |
810 | 968 | { |
811 | 969 | u32 command; |
@@ -861,6 +1019,14 @@ static void pci_epf_test_cmd_handler(struct work_struct *work) |
861 | 1019 | pci_epf_test_disable_doorbell(epf_test, reg); |
862 | 1020 | pci_epf_test_raise_irq(epf_test, reg); |
863 | 1021 | break; |
| 1022 | + case COMMAND_BAR_SUBRANGE_SETUP: |
| 1023 | + pci_epf_test_bar_subrange_setup(epf_test, reg); |
| 1024 | + pci_epf_test_raise_irq(epf_test, reg); |
| 1025 | + break; |
| 1026 | + case COMMAND_BAR_SUBRANGE_CLEAR: |
| 1027 | + pci_epf_test_bar_subrange_clear(epf_test, reg); |
| 1028 | + pci_epf_test_raise_irq(epf_test, reg); |
| 1029 | + break; |
864 | 1030 | default: |
865 | 1031 | dev_err(dev, "Invalid command 0x%x\n", command); |
866 | 1032 | break; |
@@ -933,6 +1099,10 @@ static void pci_epf_test_set_capabilities(struct pci_epf *epf) |
933 | 1099 | if (epf_test->epc_features->intx_capable) |
934 | 1100 | caps |= CAP_INTX; |
935 | 1101 |
|
| 1102 | + if (epf_test->epc_features->dynamic_inbound_mapping && |
| 1103 | + epf_test->epc_features->subrange_mapping) |
| 1104 | + caps |= CAP_SUBRANGE_MAPPING; |
| 1105 | + |
936 | 1106 | reg->caps = cpu_to_le32(caps); |
937 | 1107 | } |
938 | 1108 |
|
|
0 commit comments