On Mon, Jun 09, 2025 at 12:34:18PM GMT, Frank Li wrote: > Add three registers: PCIE_ENDPOINT_TEST_DB_BAR, PCIE_ENDPOINT_TEST_DB_ADDR, > and PCIE_ENDPOINT_TEST_DB_DATA. > > Trigger the doorbell by writing data from PCI_ENDPOINT_TEST_DB_DATA to the > address provided by PCI_ENDPOINT_TEST_DB_OFFSET and wait for endpoint > feedback. > > Add two command to COMMAND_ENABLE_DOORBELL and COMMAND_DISABLE_DOORBELL > to enable EP side's doorbell support and avoid compatible problem, which > host side driver miss-match with endpoint side function driver. See below > table: > > Host side new driver Host side old driver > EP: new driver S F > EP: old driver F F > > S: If EP side support MSI, 'pci_endpoint_test -f pcie_ep_doorbell' return > success. > If EP side doesn't support MSI, the same to 'F'. > > F: 'pci_endpoint_test -f pcie_ep_doorbell' return failure, other case as > usual. > > Tested-by: Niklas Cassel <cassel@xxxxxxxxxx> > Signed-off-by: Frank Li <Frank.Li@xxxxxxx> > --- > change from v14 to v16 > - none > > Change from v13 to v14 > - update to use pci_endpoint_test -f pcie_ep_doorbell > - change ioctrl id to fix conflict > > Change from v9 to v13 > - none > > Change from v8 to v9 > - change PCITEST_DOORBELL to 0xa > > Change form v6 to v8 > - none > > Change from v5 to v6 > - %s/PCI_ENDPOINT_TEST_DB_ADDR/PCI_ENDPOINT_TEST_DB_OFFSET/g > > Change from v4 to v5 > - remove unused varible > - add irq_type at pci_endpoint_test_doorbell(); > > change from v3 to v4 > - Add COMMAND_ENABLE_DOORBELL and COMMAND_DISABLE_DOORBELL. > - Remove new DID requirement. > --- > drivers/misc/pci_endpoint_test.c | 82 ++++++++++++++++++++++++++++++++++++++++ > include/uapi/linux/pcitest.h | 1 + > 2 files changed, 83 insertions(+) > > diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c > index c4e5e2c977be2..0f3af7adea107 100644 > --- a/drivers/misc/pci_endpoint_test.c > +++ b/drivers/misc/pci_endpoint_test.c > @@ -37,6 +37,8 @@ > #define COMMAND_READ BIT(3) > #define COMMAND_WRITE BIT(4) > #define COMMAND_COPY BIT(5) > +#define COMMAND_ENABLE_DOORBELL BIT(6) > +#define COMMAND_DISABLE_DOORBELL BIT(7) > > #define PCI_ENDPOINT_TEST_STATUS 0x8 > #define STATUS_READ_SUCCESS BIT(0) > @@ -48,6 +50,11 @@ > #define STATUS_IRQ_RAISED BIT(6) > #define STATUS_SRC_ADDR_INVALID BIT(7) > #define STATUS_DST_ADDR_INVALID BIT(8) > +#define STATUS_DOORBELL_SUCCESS BIT(9) > +#define STATUS_DOORBELL_ENABLE_SUCCESS BIT(10) > +#define STATUS_DOORBELL_ENABLE_FAIL BIT(11) > +#define STATUS_DOORBELL_DISABLE_SUCCESS BIT(12) > +#define STATUS_DOORBELL_DISABLE_FAIL BIT(13) > > #define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0x0c > #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10 > @@ -62,6 +69,7 @@ > #define PCI_ENDPOINT_TEST_IRQ_NUMBER 0x28 > > #define PCI_ENDPOINT_TEST_FLAGS 0x2c > + > #define FLAG_USE_DMA BIT(0) > > #define PCI_ENDPOINT_TEST_CAPS 0x30 > @@ -70,6 +78,10 @@ > #define CAP_MSIX BIT(2) > #define CAP_INTX BIT(3) > > +#define PCI_ENDPOINT_TEST_DB_BAR 0x34 > +#define PCI_ENDPOINT_TEST_DB_OFFSET 0x38 > +#define PCI_ENDPOINT_TEST_DB_DATA 0x3c > + > #define PCI_DEVICE_ID_TI_AM654 0xb00c > #define PCI_DEVICE_ID_TI_J7200 0xb00f > #define PCI_DEVICE_ID_TI_AM64 0xb010 > @@ -100,6 +112,7 @@ enum pci_barno { > BAR_3, > BAR_4, > BAR_5, > + NO_BAR = -1, > }; > > struct pci_endpoint_test { > @@ -841,6 +854,72 @@ static int pci_endpoint_test_set_irq(struct pci_endpoint_test *test, > return 0; > } > > +static int pci_endpoint_test_doorbell(struct pci_endpoint_test *test) > +{ > + struct pci_dev *pdev = test->pdev; > + struct device *dev = &pdev->dev; > + int irq_type = test->irq_type; > + enum pci_barno bar; > + u32 data, status; > + u32 addr; > + > + if (irq_type < PCITEST_IRQ_TYPE_INTX || > + irq_type > PCITEST_IRQ_TYPE_MSIX) { > + dev_err(dev, "Invalid IRQ type option\n"); 'Invalid IRQ type\n' > + return -EINVAL; > + } > + > + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); > + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); > + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, > + COMMAND_ENABLE_DOORBELL); > + > + wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000)); You should check for the timeout here and below. > + > + status = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS); > + if (status & STATUS_DOORBELL_ENABLE_FAIL) { > + dev_err(dev, "Failed to enable doorbell\n"); > + return -EINVAL; > + } > + > + data = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_DATA); > + addr = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_OFFSET); > + bar = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_BAR); > + > + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); > + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); > + > + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS, 0); > + > + bar = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_DB_BAR); > + > + writel(data, test->bar[bar] + addr); > + > + wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000)); > + > + status = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS); > + > + if (!(status & STATUS_DOORBELL_SUCCESS)) > + dev_err(dev, "Endpoint have not received Doorbell\n"); 'Failed to trigger doorbell in endpoint\n' - Mani -- மணிவண்ணன் சதாசிவம்