Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

PCI: endpoint: pci-epf-test: Add BAR subrange mapping test support

Extend pci-epf-test so that pci_endpoint_test can exercise BAR subrange
mapping end-to-end.

Add BAR_SUBRANGE_SETUP/CLEAR commands that program (and tear down) a
simple 2-subrange layout for a selected BAR. The endpoint deliberately
permutes the physical backing regions (swap the halves) and writes a
deterministic signature byte per subrange. This allows the RC to verify
that the submap order is actually applied, not just that reads/writes
work with an identity mapping.

Advertise CAP_SUBRANGE_MAPPING only when the underlying EPC supports
dynamic_inbound_mapping and subrange_mapping. Also bump the default BAR
sizes (BAR0-4) to 128 KiB so that split subranges are large enough to
satisfy common inbound-translation alignment constraints. E.g. for DWC
EP, the default and maximum CX_ATU_MIN_REGION_SIZE is 64 kB, so 128 KiB
is sufficient for DWC-based EP platforms for 2-subrange testing.

Signed-off-by: Koichiro Den <den@valinux.co.jp>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20260124145012.2794108-7-den@valinux.co.jp

authored by

Koichiro Den and committed by
Bjorn Helgaas
6c5e6101 dd3ce166

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