Skip to content

Commit eefb837

Browse files
nxpfranklibjorn-helgaas
authored andcommitted
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
1 parent eff0c28 commit eefb837

2 files changed

Lines changed: 84 additions & 0 deletions

File tree

drivers/misc/pci_endpoint_test.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
#define COMMAND_READ BIT(3)
3838
#define COMMAND_WRITE BIT(4)
3939
#define COMMAND_COPY BIT(5)
40+
#define COMMAND_ENABLE_DOORBELL BIT(6)
41+
#define COMMAND_DISABLE_DOORBELL BIT(7)
4042

4143
#define PCI_ENDPOINT_TEST_STATUS 0x8
4244
#define STATUS_READ_SUCCESS BIT(0)
@@ -48,6 +50,11 @@
4850
#define STATUS_IRQ_RAISED BIT(6)
4951
#define STATUS_SRC_ADDR_INVALID BIT(7)
5052
#define STATUS_DST_ADDR_INVALID BIT(8)
53+
#define STATUS_DOORBELL_SUCCESS BIT(9)
54+
#define STATUS_DOORBELL_ENABLE_SUCCESS BIT(10)
55+
#define STATUS_DOORBELL_ENABLE_FAIL BIT(11)
56+
#define STATUS_DOORBELL_DISABLE_SUCCESS BIT(12)
57+
#define STATUS_DOORBELL_DISABLE_FAIL BIT(13)
5158

5259
#define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0x0c
5360
#define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10
@@ -62,6 +69,7 @@
6269
#define PCI_ENDPOINT_TEST_IRQ_NUMBER 0x28
6370

6471
#define PCI_ENDPOINT_TEST_FLAGS 0x2c
72+
6573
#define FLAG_USE_DMA BIT(0)
6674

6775
#define PCI_ENDPOINT_TEST_CAPS 0x30
@@ -70,6 +78,10 @@
7078
#define CAP_MSIX BIT(2)
7179
#define CAP_INTX BIT(3)
7280

81+
#define PCI_ENDPOINT_TEST_DB_BAR 0x34
82+
#define PCI_ENDPOINT_TEST_DB_OFFSET 0x38
83+
#define PCI_ENDPOINT_TEST_DB_DATA 0x3c
84+
7385
#define PCI_DEVICE_ID_TI_AM654 0xb00c
7486
#define PCI_DEVICE_ID_TI_J7200 0xb00f
7587
#define PCI_DEVICE_ID_TI_AM64 0xb010
@@ -100,6 +112,7 @@ enum pci_barno {
100112
BAR_3,
101113
BAR_4,
102114
BAR_5,
115+
NO_BAR = -1,
103116
};
104117

105118
struct pci_endpoint_test {
@@ -841,6 +854,73 @@ static int pci_endpoint_test_set_irq(struct pci_endpoint_test *test,
841854
return 0;
842855
}
843856

857+
static int pci_endpoint_test_doorbell(struct pci_endpoint_test *test)
858+
{
859+
struct pci_dev *pdev = test->pdev;
860+
struct device *dev = &pdev->dev;
861+
int irq_type = test->irq_type;
862+
enum pci_barno bar;
863+
u32 data, status;
864+
u32 addr;
865+
int left;
866+
867+
if (irq_type < PCITEST_IRQ_TYPE_INTX ||
868+
irq_type > PCITEST_IRQ_TYPE_MSIX) {
869+
dev_err(dev, "Invalid IRQ type\n");
870+
return -EINVAL;
871+
}
872+
873+
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type);
874+
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1);
875+
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
876+
COMMAND_ENABLE_DOORBELL);
877+
878+
left = wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000));
879+
880+
status = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
881+
if (!left || (status & STATUS_DOORBELL_ENABLE_FAIL)) {
882+
dev_err(dev, "Failed to enable doorbell\n");
883+
return -EINVAL;
884+
}
885+
886+
data = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_DATA);
887+
addr = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_OFFSET);
888+
bar = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_BAR);
889+
890+
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type);
891+
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1);
892+
893+
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS, 0);
894+
895+
bar = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_BAR);
896+
897+
writel(data, test->bar[bar] + addr);
898+
899+
left = wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000));
900+
901+
status = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
902+
903+
if (!left || !(status & STATUS_DOORBELL_SUCCESS))
904+
dev_err(dev, "Failed to trigger doorbell in endpoint\n");
905+
906+
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
907+
COMMAND_DISABLE_DOORBELL);
908+
909+
wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000));
910+
911+
status |= pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
912+
913+
if (status & STATUS_DOORBELL_DISABLE_FAIL) {
914+
dev_err(dev, "Failed to disable doorbell\n");
915+
return -EINVAL;
916+
}
917+
918+
if (!(status & STATUS_DOORBELL_SUCCESS))
919+
return -EINVAL;
920+
921+
return 0;
922+
}
923+
844924
static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
845925
unsigned long arg)
846926
{
@@ -891,6 +971,9 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
891971
case PCITEST_CLEAR_IRQ:
892972
ret = pci_endpoint_test_clear_irq(test);
893973
break;
974+
case PCITEST_DOORBELL:
975+
ret = pci_endpoint_test_doorbell(test);
976+
break;
894977
}
895978

896979
ret:

include/uapi/linux/pcitest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#define PCITEST_SET_IRQTYPE _IOW('P', 0x8, int)
2222
#define PCITEST_GET_IRQTYPE _IO('P', 0x9)
2323
#define PCITEST_BARS _IO('P', 0xa)
24+
#define PCITEST_DOORBELL _IO('P', 0xb)
2425
#define PCITEST_CLEAR_IRQ _IO('P', 0x10)
2526

2627
#define PCITEST_IRQ_TYPE_UNDEFINED -1

0 commit comments

Comments
 (0)