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

misc: pci_endpoint_test: Add doorbell test case

Add doorbell support with the help of three new registers:
PCIE_ENDPOINT_TEST_DB_BAR, PCIE_ENDPOINT_TEST_DB_ADDR, and
PCIE_ENDPOINT_TEST_DB_DATA.

The testcase works by triggering the doorbell in Endpoint by writing the
value from PCI_ENDPOINT_TEST_DB_DATA register to the address provided by
PCI_ENDPOINT_TEST_DB_OFFSET register of the BAR indicated by the
PCIE_ENDPOINT_TEST_DB_BAR register and waiting for the completion status
from the Endpoint.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
[mani: removed one spurious change and reworded the commit message]
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Niklas Cassel <cassel@kernel.org>
Link: https://patch.msgid.link/20250710-ep-msi-v21-7-57683fc7fb25@nxp.com

authored by

Frank Li and committed by
Bjorn Helgaas
eefb8379 eff0c286

+84
+83
drivers/misc/pci_endpoint_test.c
··· 37 37 #define COMMAND_READ BIT(3) 38 38 #define COMMAND_WRITE BIT(4) 39 39 #define COMMAND_COPY BIT(5) 40 + #define COMMAND_ENABLE_DOORBELL BIT(6) 41 + #define COMMAND_DISABLE_DOORBELL BIT(7) 40 42 41 43 #define PCI_ENDPOINT_TEST_STATUS 0x8 42 44 #define STATUS_READ_SUCCESS BIT(0) ··· 50 48 #define STATUS_IRQ_RAISED BIT(6) 51 49 #define STATUS_SRC_ADDR_INVALID BIT(7) 52 50 #define STATUS_DST_ADDR_INVALID BIT(8) 51 + #define STATUS_DOORBELL_SUCCESS BIT(9) 52 + #define STATUS_DOORBELL_ENABLE_SUCCESS BIT(10) 53 + #define STATUS_DOORBELL_ENABLE_FAIL BIT(11) 54 + #define STATUS_DOORBELL_DISABLE_SUCCESS BIT(12) 55 + #define STATUS_DOORBELL_DISABLE_FAIL BIT(13) 53 56 54 57 #define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0x0c 55 58 #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10 ··· 69 62 #define PCI_ENDPOINT_TEST_IRQ_NUMBER 0x28 70 63 71 64 #define PCI_ENDPOINT_TEST_FLAGS 0x2c 65 + 72 66 #define FLAG_USE_DMA BIT(0) 73 67 74 68 #define PCI_ENDPOINT_TEST_CAPS 0x30 ··· 77 69 #define CAP_MSI BIT(1) 78 70 #define CAP_MSIX BIT(2) 79 71 #define CAP_INTX BIT(3) 72 + 73 + #define PCI_ENDPOINT_TEST_DB_BAR 0x34 74 + #define PCI_ENDPOINT_TEST_DB_OFFSET 0x38 75 + #define PCI_ENDPOINT_TEST_DB_DATA 0x3c 80 76 81 77 #define PCI_DEVICE_ID_TI_AM654 0xb00c 82 78 #define PCI_DEVICE_ID_TI_J7200 0xb00f ··· 112 100 BAR_3, 113 101 BAR_4, 114 102 BAR_5, 103 + NO_BAR = -1, 115 104 }; 116 105 117 106 struct pci_endpoint_test { ··· 854 841 return 0; 855 842 } 856 843 844 + static int pci_endpoint_test_doorbell(struct pci_endpoint_test *test) 845 + { 846 + struct pci_dev *pdev = test->pdev; 847 + struct device *dev = &pdev->dev; 848 + int irq_type = test->irq_type; 849 + enum pci_barno bar; 850 + u32 data, status; 851 + u32 addr; 852 + int left; 853 + 854 + if (irq_type < PCITEST_IRQ_TYPE_INTX || 855 + irq_type > PCITEST_IRQ_TYPE_MSIX) { 856 + dev_err(dev, "Invalid IRQ type\n"); 857 + return -EINVAL; 858 + } 859 + 860 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); 861 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); 862 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 863 + COMMAND_ENABLE_DOORBELL); 864 + 865 + left = wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000)); 866 + 867 + status = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS); 868 + if (!left || (status & STATUS_DOORBELL_ENABLE_FAIL)) { 869 + dev_err(dev, "Failed to enable doorbell\n"); 870 + return -EINVAL; 871 + } 872 + 873 + data = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_DATA); 874 + addr = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_OFFSET); 875 + bar = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_BAR); 876 + 877 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); 878 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); 879 + 880 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS, 0); 881 + 882 + bar = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_BAR); 883 + 884 + writel(data, test->bar[bar] + addr); 885 + 886 + left = wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000)); 887 + 888 + status = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS); 889 + 890 + if (!left || !(status & STATUS_DOORBELL_SUCCESS)) 891 + dev_err(dev, "Failed to trigger doorbell in endpoint\n"); 892 + 893 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 894 + COMMAND_DISABLE_DOORBELL); 895 + 896 + wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000)); 897 + 898 + status |= pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS); 899 + 900 + if (status & STATUS_DOORBELL_DISABLE_FAIL) { 901 + dev_err(dev, "Failed to disable doorbell\n"); 902 + return -EINVAL; 903 + } 904 + 905 + if (!(status & STATUS_DOORBELL_SUCCESS)) 906 + return -EINVAL; 907 + 908 + return 0; 909 + } 910 + 857 911 static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, 858 912 unsigned long arg) 859 913 { ··· 970 890 break; 971 891 case PCITEST_CLEAR_IRQ: 972 892 ret = pci_endpoint_test_clear_irq(test); 893 + break; 894 + case PCITEST_DOORBELL: 895 + ret = pci_endpoint_test_doorbell(test); 973 896 break; 974 897 } 975 898
+1
include/uapi/linux/pcitest.h
··· 21 21 #define PCITEST_SET_IRQTYPE _IOW('P', 0x8, int) 22 22 #define PCITEST_GET_IRQTYPE _IO('P', 0x9) 23 23 #define PCITEST_BARS _IO('P', 0xa) 24 + #define PCITEST_DOORBELL _IO('P', 0xb) 24 25 #define PCITEST_CLEAR_IRQ _IO('P', 0x10) 25 26 26 27 #define PCITEST_IRQ_TYPE_UNDEFINED -1