[PATCH 01/10] PCI: endpoint: Add MSI-X interfaces
Add PCI_EPC_IRQ_MSIX type. Add MSI-X callbacks signatures to ops structure. Add sysfs interface for set/get MSI-X capability maximum number. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/pci/endpoint/pci-ep-cfs.c | 24 drivers/pci/endpoint/pci-epc-core.c | 57 + include/linux/pci-epc.h | 11 ++- include/linux/pci-epf.h | 1 + 4 files changed, 92 insertions(+), 1 deletion(-) diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c index 018ea34..d1288a0 100644 --- a/drivers/pci/endpoint/pci-ep-cfs.c +++ b/drivers/pci/endpoint/pci-ep-cfs.c @@ -286,6 +286,28 @@ static ssize_t pci_epf_msi_interrupts_show(struct config_item *item, to_pci_epf_group(item)->epf->msi_interrupts); } +static ssize_t pci_epf_msix_interrupts_store(struct config_item *item, +const char *page, size_t len) +{ + u16 val; + int ret; + + ret = kstrtou16(page, 0, ); + if (ret) + return ret; + + to_pci_epf_group(item)->epf->msix_interrupts = val; + + return len; +} + +static ssize_t pci_epf_msix_interrupts_show(struct config_item *item, + char *page) +{ + return sprintf(page, "%d\n", + to_pci_epf_group(item)->epf->msix_interrupts); +} + PCI_EPF_HEADER_R(vendorid) PCI_EPF_HEADER_W_u16(vendorid) @@ -327,6 +349,7 @@ CONFIGFS_ATTR(pci_epf_, subsys_vendor_id); CONFIGFS_ATTR(pci_epf_, subsys_id); CONFIGFS_ATTR(pci_epf_, interrupt_pin); CONFIGFS_ATTR(pci_epf_, msi_interrupts); +CONFIGFS_ATTR(pci_epf_, msix_interrupts); static struct configfs_attribute *pci_epf_attrs[] = { _epf_attr_vendorid, @@ -340,6 +363,7 @@ static struct configfs_attribute *pci_epf_attrs[] = { _epf_attr_subsys_id, _epf_attr_interrupt_pin, _epf_attr_msi_interrupts, + _epf_attr_msix_interrupts, NULL, }; diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index b0ee427..7d77bd0 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -218,6 +218,63 @@ int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts) EXPORT_SYMBOL_GPL(pci_epc_set_msi); /** + * pci_epc_get_msix() - get the number of MSI-X interrupt numbers allocated + * @epc: the EPC device to which MSI-X interrupts was requested + * @func_no: the endpoint function number in the EPC device + * + * Invoke to get the number of MSI-X interrupts allocated by the RC + */ +int pci_epc_get_msix(struct pci_epc *epc, u8 func_no) +{ + int interrupt; + unsigned long flags; + + if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) + return 0; + + if (!epc->ops->get_msix) + return 0; + + spin_lock_irqsave(>lock, flags); + interrupt = epc->ops->get_msix(epc, func_no); + spin_unlock_irqrestore(>lock, flags); + + if (interrupt < 0) + return 0; + + return interrupt + 1; +} +EXPORT_SYMBOL_GPL(pci_epc_get_msix); + +/** + * pci_epc_set_msix() - set the number of MSI-X interrupt numbers required + * @epc: the EPC device on which MSI-X has to be configured + * @func_no: the endpoint function number in the EPC device + * @interrupts: number of MSI-X interrupts required by the EPF + * + * Invoke to set the required number of MSI-X interrupts. + */ +int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts) +{ + int ret; + unsigned long flags; + + if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || + interrupts < 1 || interrupts > 2048) + return -EINVAL; + + if (!epc->ops->set_msix) + return 0; + + spin_lock_irqsave(>lock, flags); + ret = epc->ops->set_msix(epc, func_no, interrupts - 1); + spin_unlock_irqrestore(>lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(pci_epc_set_msix); + +/** * pci_epc_unmap_addr() - unmap CPU address from PCI address * @epc: the EPC device on which address is allocated * @func_no: the endpoint function number in the EPC device diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index af657ca..32e8961 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -17,6 +17,7 @@ enum pci_epc_irq_type { PCI_EPC_IRQ_UNKNOWN, PCI_EPC_IRQ_LEGACY, PCI_EPC_IRQ_MSI, + PCI_EPC_IRQ_MSIX, }; /** @@ -30,6 +31,10 @@ enum pci_epc_irq_type { * capability register * @get_msi: ops to get the number of MSI interrupts allocated by the RC from * the MSI capability register + * @set_msix: ops to set the requested number of MSI-X interrupts in the + * MSI-X capability register + *
[PATCH 09/10] tools: PCI: Add MSI-X support
Add MSI-X support to pcitest tool. Modify pcitest.sh script to accomodate MSI-X interrupt tests. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- include/uapi/linux/pcitest.h | 1 + tools/pci/pcitest.c | 18 +- tools/pci/pcitest.sh | 25 + 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/pcitest.h b/include/uapi/linux/pcitest.h index 953cf03..d746fb1 100644 --- a/include/uapi/linux/pcitest.h +++ b/include/uapi/linux/pcitest.h @@ -16,5 +16,6 @@ #define PCITEST_WRITE _IOW('P', 0x4, unsigned long) #define PCITEST_READ _IOW('P', 0x5, unsigned long) #define PCITEST_COPY _IOW('P', 0x6, unsigned long) +#define PCITEST_MSIX _IOW('P', 0x7, int) #endif /* __UAPI_LINUX_PCITEST_H */ diff --git a/tools/pci/pcitest.c b/tools/pci/pcitest.c index 9074b47..9d145a3 100644 --- a/tools/pci/pcitest.c +++ b/tools/pci/pcitest.c @@ -37,6 +37,7 @@ struct pci_test { charbarnum; boollegacyirq; unsigned intmsinum; + unsigned intmsixnum; boolread; boolwrite; boolcopy; @@ -83,6 +84,15 @@ static int run_test(struct pci_test *test) fprintf(stdout, "%s\n", result[ret]); } + if (test->msixnum > 0 && test->msixnum <= 2048) { + ret = ioctl(fd, PCITEST_MSIX, test->msixnum); + fprintf(stdout, "MSI-X%d:\t\t", test->msixnum); + if (ret < 0) + fprintf(stdout, "TEST FAILED\n"); + else + fprintf(stdout, "%s\n", result[ret]); + } + if (test->write) { ret = ioctl(fd, PCITEST_WRITE, test->size); fprintf(stdout, "WRITE (%7ld bytes):\t\t", test->size); @@ -133,7 +143,7 @@ int main(int argc, char **argv) /* set default endpoint device */ test->device = "/dev/pci-endpoint-test.0"; - while ((c = getopt(argc, argv, "D:b:m:lrwcs:")) != EOF) + while ((c = getopt(argc, argv, "D:b:m:x:lrwcs:")) != EOF) switch (c) { case 'D': test->device = optarg; @@ -151,6 +161,11 @@ int main(int argc, char **argv) if (test->msinum < 1 || test->msinum > 32) goto usage; continue; + case 'x': + test->msixnum = atoi(optarg); + if (test->msixnum < 1 || test->msixnum > 2048) + goto usage; + continue; case 'r': test->read = true; continue; @@ -173,6 +188,7 @@ int main(int argc, char **argv) "\t-D PCI endpoint test device {default: /dev/pci-endpoint-test.0}\n" "\t-b BAR test (bar number between 0..5)\n" "\t-m MSI test (msi number between 1..32)\n" + "\t-x MSI-X test (msix number between 1..2048)\n" "\t-l Legacy IRQ test\n" "\t-r Read buffer test\n" "\t-w Write buffer test\n" diff --git a/tools/pci/pcitest.sh b/tools/pci/pcitest.sh index 77e8c85..86709a2 100644 --- a/tools/pci/pcitest.sh +++ b/tools/pci/pcitest.sh @@ -4,6 +4,8 @@ echo "BAR tests" echo +modprobe pci_endpoint_test +sleep 2 bar=0 while [ $bar -lt 6 ] @@ -16,7 +18,14 @@ echo echo "Interrupt tests" echo +rmmod pci_endpoint_test +sleep 2 +modprobe pci_endpoint_test irq_type=0 pcitest -l + +rmmod pci_endpoint_test +sleep 2 +modprobe pci_endpoint_test irq_type=1 msi=1 while [ $msi -lt 33 ] @@ -26,9 +35,25 @@ do done echo +rmmod pci_endpoint_test +sleep 2 +modprobe pci_endpoint_test irq_type=2 +msix=1 + +while [ $msix -lt 2049 ] +do +pcitest -x $msix +msix=`expr $msix + 1` +done +echo + echo "Read Tests" echo +rmmod pci_endpoint_test +sleep 2 +modprobe pci_endpoint_test irq_type=1 + pcitest -r -s 1 pcitest -r -s 1024 pcitest -r -s 1025 -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 02/10] PCI: dwc: Add MSI-X callbacks handler
Change pcie_raise_irq() signature, namely the interrupt_num variable type from u8 to u16 to accommodate the 2048 maximum MSI-X interrupts. Add PCIe config space capability search function. Add sysfs set/get interface to allow to change of EP MSI-X maximum number. Add EP MSI-X callback for triggering interruptions. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/pci/dwc/pci-dra7xx.c | 2 +- drivers/pci/dwc/pcie-artpec6.c | 2 +- drivers/pci/dwc/pcie-designware-ep.c | 143 - drivers/pci/dwc/pcie-designware-plat.c | 4 +- drivers/pci/dwc/pcie-designware.h | 14 +++- 5 files changed, 160 insertions(+), 5 deletions(-) diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c index ed8558d..5265725 100644 --- a/drivers/pci/dwc/pci-dra7xx.c +++ b/drivers/pci/dwc/pci-dra7xx.c @@ -369,7 +369,7 @@ static void dra7xx_pcie_raise_msi_irq(struct dra7xx_pcie *dra7xx, } static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, -enum pci_epc_irq_type type, u8 interrupt_num) +enum pci_epc_irq_type type, u16 interrupt_num) { struct dw_pcie *pci = to_dw_pcie_from_ep(ep); struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index e66cede..96dc259 100644 --- a/drivers/pci/dwc/pcie-artpec6.c +++ b/drivers/pci/dwc/pcie-artpec6.c @@ -428,7 +428,7 @@ static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep) } static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, - enum pci_epc_irq_type type, u8 interrupt_num) + enum pci_epc_irq_type type, u16 interrupt_num) { struct dw_pcie *pci = to_dw_pcie_from_ep(ep); diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index 15b22a6..9b0d396 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@ -40,6 +40,39 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar) __dw_pcie_ep_reset_bar(pci, bar, 0); } +u8 __dw_pcie_ep_find_next_cap(struct dw_pcie *pci, u8 cap_ptr, + u8 cap) +{ + u8 cap_id, next_cap_ptr; + u16 reg; + + reg = dw_pcie_readw_dbi(pci, cap_ptr); + next_cap_ptr = (reg & 0xff00) >> 8; + cap_id = (reg & 0x00ff); + + if (!next_cap_ptr || cap_id > PCI_CAP_ID_MAX) + return 0; + + if (cap_id == cap) + return cap_ptr; + + return __dw_pcie_ep_find_next_cap(pci, next_cap_ptr, cap); +} + +u8 dw_pcie_ep_find_capability(struct dw_pcie *pci, u8 cap) +{ + u8 next_cap_ptr; + u16 reg; + + reg = dw_pcie_readw_dbi(pci, PCI_CAPABILITY_LIST); + next_cap_ptr = (reg & 0x00ff); + + if (!next_cap_ptr) + return 0; + + return __dw_pcie_ep_find_next_cap(pci, next_cap_ptr, cap); +} + static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, struct pci_epf_header *hdr) { @@ -241,8 +274,47 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 encode_int) return 0; } +static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no) +{ + struct dw_pcie_ep *ep = epc_get_drvdata(epc); + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + u32 val, reg; + + if (!ep->msix_cap) + return 0; + + reg = ep->msix_cap + PCI_MSIX_FLAGS; + val = dw_pcie_readw_dbi(pci, reg); + if (!(val & PCI_MSIX_FLAGS_ENABLE)) + return -EINVAL; + + val &= PCI_MSIX_FLAGS_QSIZE; + + return val; +} + +static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts) +{ + struct dw_pcie_ep *ep = epc_get_drvdata(epc); + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + u32 val, reg; + + if (!ep->msix_cap) + return 0; + + reg = ep->msix_cap + PCI_MSIX_FLAGS; + val = dw_pcie_readw_dbi(pci, reg); + val &= ~PCI_MSIX_FLAGS_QSIZE; + val |= interrupts; + dw_pcie_dbi_ro_wr_en(pci); + dw_pcie_writew_dbi(pci, reg, val); + dw_pcie_dbi_ro_wr_dis(pci); + + return 0; +} + static int dw_pcie_ep_raise_irq(struct pci_epc *epc, u8 func_no, - enum pci_epc_irq_type type, u8 interrupt_num) + enum pci_epc_irq_type type, u16 interrupt_num) { struct dw_pcie_ep *ep = epc_get_drvdata(epc); @@ -282,6 +354,8 @@ static const struct pci_epc_ops epc_ops = { .unmap_addr = dw_pcie_ep_unmap_addr, .set_msi= dw_pcie_ep_set_msi, .get_msi= dw_pcie_ep_get_msi, + .set_msix = dw_pcie_ep_set_msix, +
[PATCH 03/10] PCI: cadence: Update cdns_pcie_ep_raise_irq function signature
Change cdns_pcie_ep_raise_irq() signature, namely the interrupt_num variable type from u8 to u16 to accommodate the 2048 maximum MSI-X interrupts. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> Acked-by: Alan Douglas <adoug...@cadence.com> --- drivers/pci/cadence/pcie-cadence-ep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/cadence/pcie-cadence-ep.c b/drivers/pci/cadence/pcie-cadence-ep.c index 3d8283e..6d6322c 100644 --- a/drivers/pci/cadence/pcie-cadence-ep.c +++ b/drivers/pci/cadence/pcie-cadence-ep.c @@ -363,7 +363,7 @@ static int cdns_pcie_ep_send_msi_irq(struct cdns_pcie_ep *ep, u8 fn, } static int cdns_pcie_ep_raise_irq(struct pci_epc *epc, u8 fn, - enum pci_epc_irq_type type, u8 interrupt_num) + enum pci_epc_irq_type type, u16 interrupt_num) { struct cdns_pcie_ep *ep = epc_get_drvdata(epc); -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 06/10] misc: pci_endpoint_test: Add MSI-X support
Add MSI-X support and update driver documentation accordingly. Add new driver parameter to allow interruption type selection. Modify the Legacy/MSI/MSI-X test process, by: - Add and use a specific register located in a BAR, which defines the interrupt type is been triggered. - Move the interrupt ID number from the command section to a register located in a BAR. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- Documentation/misc-devices/pci-endpoint-test.txt | 3 + drivers/misc/pci_endpoint_test.c | 121 +++ drivers/pci/endpoint/functions/pci-epf-test.c| 78 +++ 3 files changed, 143 insertions(+), 59 deletions(-) diff --git a/Documentation/misc-devices/pci-endpoint-test.txt b/Documentation/misc-devices/pci-endpoint-test.txt index 4ebc359..fdfa0f6 100644 --- a/Documentation/misc-devices/pci-endpoint-test.txt +++ b/Documentation/misc-devices/pci-endpoint-test.txt @@ -10,6 +10,7 @@ The PCI driver for the test device performs the following tests *) verifying addresses programmed in BAR *) raise legacy IRQ *) raise MSI IRQ + *) raise MSI-X IRQ *) read data *) write data *) copy data @@ -25,6 +26,8 @@ ioctl PCITEST_LEGACY_IRQ: Tests legacy IRQ PCITEST_MSI: Tests message signalled interrupts. The MSI number to be tested should be passed as argument. + PCITEST_MSIX: Tests message signalled interrupts. The MSI-X number + to be tested should be passed as argument. PCITEST_WRITE: Perform write tests. The size of the buffer should be passed as argument. PCITEST_READ: Perform read tests. The size of the buffer should be passed diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 58a88ba..b003079 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -35,38 +35,44 @@ #include -#define DRV_MODULE_NAME"pci-endpoint-test" - -#define PCI_ENDPOINT_TEST_MAGIC0x0 - -#define PCI_ENDPOINT_TEST_COMMAND 0x4 -#define COMMAND_RAISE_LEGACY_IRQ BIT(0) -#define COMMAND_RAISE_MSI_IRQ BIT(1) -#define MSI_NUMBER_SHIFT 2 -/* 6 bits for MSI number */ -#define COMMAND_READBIT(8) -#define COMMAND_WRITE BIT(9) -#define COMMAND_COPYBIT(10) - -#define PCI_ENDPOINT_TEST_STATUS 0x8 -#define STATUS_READ_SUCCESS BIT(0) -#define STATUS_READ_FAILBIT(1) -#define STATUS_WRITE_SUCCESSBIT(2) -#define STATUS_WRITE_FAIL BIT(3) -#define STATUS_COPY_SUCCESS BIT(4) -#define STATUS_COPY_FAILBIT(5) -#define STATUS_IRQ_RAISED BIT(6) -#define STATUS_SRC_ADDR_INVALID BIT(7) -#define STATUS_DST_ADDR_INVALID BIT(8) - -#define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0xc +#define DRV_MODULE_NAME"pci-endpoint-test" + +#define IRQ_TYPE_LEGACY0 +#define IRQ_TYPE_MSI 1 +#define IRQ_TYPE_MSIX 2 + +#define PCI_ENDPOINT_TEST_MAGIC0x0 + +#define PCI_ENDPOINT_TEST_COMMAND 0x4 +#define COMMAND_RAISE_LEGACY_IRQ BIT(0) +#define COMMAND_RAISE_MSI_IRQ BIT(1) +#define COMMAND_RAISE_MSIX_IRQ BIT(2) +#define COMMAND_READ BIT(3) +#define COMMAND_WRITE BIT(4) +#define COMMAND_COPY BIT(5) + +#define PCI_ENDPOINT_TEST_STATUS 0x8 +#define STATUS_READ_SUCCESSBIT(0) +#define STATUS_READ_FAIL BIT(1) +#define STATUS_WRITE_SUCCESS BIT(2) +#define STATUS_WRITE_FAIL BIT(3) +#define STATUS_COPY_SUCCESSBIT(4) +#define STATUS_COPY_FAIL BIT(5) +#define STATUS_IRQ_RAISED BIT(6) +#define STATUS_SRC_ADDR_INVALIDBIT(7) +#define STATUS_DST_ADDR_INVALIDBIT(8) + +#define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0x0c #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10 #define PCI_ENDPOINT_TEST_LOWER_DST_ADDR 0x14 #define PCI_ENDPOINT_TEST_UPPER_DST_ADDR 0x18 -#define PCI_ENDPOINT_TEST_SIZE 0x1c -#define PCI_ENDPOINT_TEST_CHECKSUM 0x20 +#define PCI_ENDPOINT_TEST_SIZE 0x1c +#define PCI_ENDPOINT_TEST_CHECKSUM 0x20 + +#define PCI_ENDPOINT_TEST_IRQ_TYPE 0x24 +#define PCI_ENDPOINT_TEST_IRQ_NUMBER 0x28 static DEFINE_IDA(pci_endpoint_test_ida); @@ -77,6 +83,10 @@ static bool no_msi; module_param(no_msi, bool, 0444); MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test"); +static int irq_type = IRQ_TYPE_MS
[PATCH 04/10] PCI: dwc: Rework MSI callbacks handler
Remove duplicate defines located on pcie-designware.h file already available on /include/uapi/linux/pci-regs.h file. Add pci_epc_set_msi() maximum 32 interrupts validation. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/pci/dwc/pcie-designware-ep.c | 49 drivers/pci/dwc/pcie-designware.h| 11 drivers/pci/endpoint/pci-epc-core.c | 3 ++- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index 9b0d396..1ba3a7f 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@ -246,29 +246,38 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 func_no) { - int val; struct dw_pcie_ep *ep = epc_get_drvdata(epc); struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + u32 val, reg; + + if (!ep->msi_cap) + return 0; - val = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); - if (!(val & MSI_CAP_MSI_EN_MASK)) + reg = ep->msi_cap + PCI_MSI_FLAGS; + val = dw_pcie_readw_dbi(pci, reg); + if (!(val & PCI_MSI_FLAGS_ENABLE)) return -EINVAL; - val = (val & MSI_CAP_MME_MASK) >> MSI_CAP_MME_SHIFT; + val = (val & PCI_MSI_FLAGS_QSIZE) >> 4; + return val; } -static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 encode_int) +static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts) { - int val; struct dw_pcie_ep *ep = epc_get_drvdata(epc); struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + u32 val, reg; - val = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); - val &= ~MSI_CAP_MMC_MASK; - val |= (encode_int << MSI_CAP_MMC_SHIFT) & MSI_CAP_MMC_MASK; + if (!ep->msi_cap) + return 0; + + reg = ep->msi_cap + PCI_MSI_FLAGS; + val = dw_pcie_readw_dbi(pci, reg); + val &= ~PCI_MSI_FLAGS_QMASK; + val |= (interrupts << 1) & PCI_MSI_FLAGS_QMASK; dw_pcie_dbi_ro_wr_en(pci); - dw_pcie_writew_dbi(pci, MSI_MESSAGE_CONTROL, val); + dw_pcie_writew_dbi(pci, reg, val); dw_pcie_dbi_ro_wr_dis(pci); return 0; @@ -367,21 +376,29 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, struct dw_pcie *pci = to_dw_pcie_from_ep(ep); struct pci_epc *epc = ep->epc; u16 msg_ctrl, msg_data; - u32 msg_addr_lower, msg_addr_upper; + u32 msg_addr_lower, msg_addr_upper, reg; u64 msg_addr; bool has_upper; int ret; + if (!ep->msi_cap) + return 0; + /* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */ - msg_ctrl = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); + reg = ep->msi_cap + PCI_MSI_FLAGS; + msg_ctrl = dw_pcie_readw_dbi(pci, reg); has_upper = !!(msg_ctrl & PCI_MSI_FLAGS_64BIT); - msg_addr_lower = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_L32); + reg = ep->msi_cap + PCI_MSI_ADDRESS_LO; + msg_addr_lower = dw_pcie_readl_dbi(pci, reg); if (has_upper) { - msg_addr_upper = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_U32); - msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_64); + reg = ep->msi_cap + PCI_MSI_ADDRESS_HI; + msg_addr_upper = dw_pcie_readl_dbi(pci, reg); + reg = ep->msi_cap + PCI_MSI_DATA_64; + msg_data = dw_pcie_readw_dbi(pci, reg); } else { msg_addr_upper = 0; - msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_32); + reg = ep->msi_cap + PCI_MSI_DATA_32; + msg_data = dw_pcie_readw_dbi(pci, reg); } msg_addr = ((u64) msg_addr_upper) << 32 | msg_addr_lower; ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr, diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h index b22c5bb..a0ab12f 100644 --- a/drivers/pci/dwc/pcie-designware.h +++ b/drivers/pci/dwc/pcie-designware.h @@ -96,17 +96,6 @@ #define PCIE_GET_ATU_INB_UNR_REG_OFFSET(region) \ ((0x3 << 20) | ((region) << 9) | (0x1 << 8)) -#define MSI_MESSAGE_CONTROL0x52 -#define MSI_CAP_MMC_SHIFT 1 -#define MSI_CAP_MMC_MASK (7 << MSI_CAP_MMC_SHIFT) -#define MSI_CAP_MME_SHIFT 4 -#define MSI_CAP_MSI_EN_MASK0x1 -#define MSI_CAP_MME_MASK (7 << MSI_CAP_MME_SHIFT) -#define MSI_MESSAGE_ADDR_L32 0x54 -#define MSI_MESSAGE_ADDR_U32 0x58 -#define MSI_MESSAGE_DATA_320x58 -#define MSI_MESSA
[PATCH 10/10] misc: pci_endpoint_test: Use pci_irq_vector function
Replace "pdev->irq + index" operation by the pci_irq_vector() call, that converts from device vector to Linux IRQ. (suggestion made by Alan Douglas). Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/misc/pci_endpoint_test.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index c9b6e26..cbdd0c6 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -220,7 +220,7 @@ static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test, if (!val) return false; - if (test->last_irq - pdev->irq == msi_num - 1) + if (pci_irq_vector(pdev, irq_num - 1) == test->last_irq) return true; return false; @@ -565,12 +565,12 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, } for (i = 1; i < irq; i++) { - err = devm_request_irq(dev, pdev->irq + i, + err = devm_request_irq(dev, pci_irq_vector(pdev, i), pci_endpoint_test_irqhandler, IRQF_SHARED, DRV_MODULE_NAME, test); if (err) dev_err(dev, "Failed to request IRQ %d for MSI%s %d\n", - pdev->irq + i, + pci_irq_vector(pdev, i), irq_type == IRQ_TYPE_MSIX ? "-X" : "", i + 1); } @@ -633,7 +633,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, } for (i = 0; i < irq; i++) - devm_free_irq(dev, pdev->irq + i, test); + devm_free_irq(>dev, pci_irq_vector(pdev, i), test); err_disable_msi: pci_disable_msi(pdev); @@ -667,7 +667,7 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) pci_iounmap(pdev, test->bar[bar]); } for (i = 0; i < test->num_irqs; i++) - devm_free_irq(>dev, pdev->irq + i, test); + devm_free_irq(>dev, pci_irq_vector(pdev, i), test); pci_disable_msi(pdev); pci_disable_msix(pdev); pci_release_regions(pdev); -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 07/10] misc: pci_endpoint_test: Replace lower into upper case characters
Replace all initial lower case character into upper case in comments and debug printks. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/misc/pci_endpoint_test.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index b003079..c9b6e26 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -250,7 +250,7 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size) orig_src_addr = dma_alloc_coherent(dev, size + alignment, _src_phys_addr, GFP_KERNEL); if (!orig_src_addr) { - dev_err(dev, "failed to allocate source buffer\n"); + dev_err(dev, "Failed to allocate source buffer\n"); ret = false; goto err; } @@ -276,7 +276,7 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size) orig_dst_addr = dma_alloc_coherent(dev, size + alignment, _dst_phys_addr, GFP_KERNEL); if (!orig_dst_addr) { - dev_err(dev, "failed to allocate destination address\n"); + dev_err(dev, "Failed to allocate destination address\n"); ret = false; goto err_orig_src_addr; } @@ -340,7 +340,7 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size) orig_addr = dma_alloc_coherent(dev, size + alignment, _phys_addr, GFP_KERNEL); if (!orig_addr) { - dev_err(dev, "failed to allocate address\n"); + dev_err(dev, "Failed to allocate address\n"); ret = false; goto err; } @@ -403,7 +403,7 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size) orig_addr = dma_alloc_coherent(dev, size + alignment, _phys_addr, GFP_KERNEL); if (!orig_addr) { - dev_err(dev, "failed to allocate destination address\n"); + dev_err(dev, "Failed to allocate destination address\n"); ret = false; goto err; } @@ -543,7 +543,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, case IRQ_TYPE_MSI: irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); if (irq < 0) - dev_err(dev, "failed to get MSI interrupts\n"); + dev_err(dev, "Failed to get MSI interrupts\n"); test->num_irqs = irq; break; case IRQ_TYPE_MSIX: @@ -560,7 +560,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, IRQF_SHARED, DRV_MODULE_NAME, test); if (err) { - dev_err(dev, "failed to request IRQ %d\n", pdev->irq); + dev_err(dev, "Failed to request IRQ %d\n", pdev->irq); goto err_disable_msi; } @@ -578,7 +578,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) { base = pci_ioremap_bar(pdev, bar); if (!base) { - dev_err(dev, "failed to read BAR%d\n", bar); + dev_err(dev, "Failed to read BAR%d\n", bar); WARN_ON(bar == test_reg_bar); } test->bar[bar] = base; @@ -598,7 +598,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, id = ida_simple_get(_endpoint_test_ida, 0, 0, GFP_KERNEL); if (id < 0) { err = id; - dev_err(dev, "unable to get id\n"); + dev_err(dev, "Unable to get id\n"); goto err_iounmap; } @@ -614,7 +614,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, err = misc_register(misc_device); if (err) { - dev_err(dev, "failed to register device\n"); + dev_err(dev, "Failed to register device\n"); goto err_kfree_name; } -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 08/10] PCI: endpoint: functions/pci-epf-test: Replace lower into upper case characters
Replace all initial lower case character into upper case in comments and debug printks. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/pci/endpoint/functions/pci-epf-test.c | 26 +- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index be5547f..e9ff4aa 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -92,7 +92,7 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) src_addr = pci_epc_mem_alloc_addr(epc, _phys_addr, reg->size); if (!src_addr) { - dev_err(dev, "failed to allocate source address\n"); + dev_err(dev, "Failed to allocate source address\n"); reg->status = STATUS_SRC_ADDR_INVALID; ret = -ENOMEM; goto err; @@ -101,14 +101,14 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) ret = pci_epc_map_addr(epc, epf->func_no, src_phys_addr, reg->src_addr, reg->size); if (ret) { - dev_err(dev, "failed to map source address\n"); + dev_err(dev, "Failed to map source address\n"); reg->status = STATUS_SRC_ADDR_INVALID; goto err_src_addr; } dst_addr = pci_epc_mem_alloc_addr(epc, _phys_addr, reg->size); if (!dst_addr) { - dev_err(dev, "failed to allocate destination address\n"); + dev_err(dev, "Failed to allocate destination address\n"); reg->status = STATUS_DST_ADDR_INVALID; ret = -ENOMEM; goto err_src_map_addr; @@ -117,7 +117,7 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) ret = pci_epc_map_addr(epc, epf->func_no, dst_phys_addr, reg->dst_addr, reg->size); if (ret) { - dev_err(dev, "failed to map destination address\n"); + dev_err(dev, "Failed to map destination address\n"); reg->status = STATUS_DST_ADDR_INVALID; goto err_dst_addr; } @@ -154,7 +154,7 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test) src_addr = pci_epc_mem_alloc_addr(epc, _addr, reg->size); if (!src_addr) { - dev_err(dev, "failed to allocate address\n"); + dev_err(dev, "Failed to allocate address\n"); reg->status = STATUS_SRC_ADDR_INVALID; ret = -ENOMEM; goto err; @@ -163,7 +163,7 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test) ret = pci_epc_map_addr(epc, epf->func_no, phys_addr, reg->src_addr, reg->size); if (ret) { - dev_err(dev, "failed to map address\n"); + dev_err(dev, "Failed to map address\n"); reg->status = STATUS_SRC_ADDR_INVALID; goto err_addr; } @@ -206,7 +206,7 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test) dst_addr = pci_epc_mem_alloc_addr(epc, _addr, reg->size); if (!dst_addr) { - dev_err(dev, "failed to allocate address\n"); + dev_err(dev, "Failed to allocate address\n"); reg->status = STATUS_DST_ADDR_INVALID; ret = -ENOMEM; goto err; @@ -215,7 +215,7 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test) ret = pci_epc_map_addr(epc, epf->func_no, phys_addr, reg->dst_addr, reg->size); if (ret) { - dev_err(dev, "failed to map address\n"); + dev_err(dev, "Failed to map address\n"); reg->status = STATUS_DST_ADDR_INVALID; goto err_addr; } @@ -409,7 +409,7 @@ static int pci_epf_test_set_bar(struct pci_epf *epf) ret = pci_epc_set_bar(epc, epf->func_no, epf_bar); if (ret) { pci_epf_free_space(epf, epf_test->reg[bar], bar); - dev_err(dev, "failed to set BAR%d\n", bar); + dev_err(dev, "Failed to set BAR%d\n", bar); if (bar == test_reg_bar) return ret; } @@ -436,7 +436,7 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf) base = pci_epf_alloc_space(epf, sizeof(struct pci_epf_test_reg), test_reg_bar); if (!base) { - dev_err(dev, "failed to allocated register space\n"); +
[PATCH 05/10] PCI: dwc: Add legacy interrupt callback handler
Add a legacy interrupt callback handler. Currently DesignWare IP don't allow triggering the legacy interrupt. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/pci/dwc/pcie-designware-ep.c | 10 ++ drivers/pci/dwc/pcie-designware-plat.c | 3 +-- drivers/pci/dwc/pcie-designware.h | 6 ++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index 1ba3a7f..b599169 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@ -370,6 +370,16 @@ static const struct pci_epc_ops epc_ops = { .stop = dw_pcie_ep_stop, }; +int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no) +{ + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + struct device *dev = pci->dev; + + dev_err(dev, "EP cannot trigger legacy IRQs\n"); + + return -EINVAL; +} + int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, u8 interrupt_num) { diff --git a/drivers/pci/dwc/pcie-designware-plat.c b/drivers/pci/dwc/pcie-designware-plat.c index 654dcb5..90a8c95 100644 --- a/drivers/pci/dwc/pcie-designware-plat.c +++ b/drivers/pci/dwc/pcie-designware-plat.c @@ -84,8 +84,7 @@ static int dw_plat_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, switch (type) { case PCI_EPC_IRQ_LEGACY: - dev_err(pci->dev, "EP cannot trigger legacy IRQs\n"); - return -EINVAL; + return dw_pcie_ep_raise_legacy_irq(ep, func_no); case PCI_EPC_IRQ_MSI: return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num); case PCI_EPC_IRQ_MSIX: diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h index a0ab12f..69e6e17 100644 --- a/drivers/pci/dwc/pcie-designware.h +++ b/drivers/pci/dwc/pcie-designware.h @@ -350,6 +350,7 @@ static inline int dw_pcie_allocate_domains(struct pcie_port *pp) void dw_pcie_ep_linkup(struct dw_pcie_ep *ep); int dw_pcie_ep_init(struct dw_pcie_ep *ep); void dw_pcie_ep_exit(struct dw_pcie_ep *ep); +int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no); int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, u8 interrupt_num); int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no, @@ -369,6 +370,11 @@ static inline void dw_pcie_ep_exit(struct dw_pcie_ep *ep) { } +static inline int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no) +{ + return 0; +} + static inline int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, u8 interrupt_num) { -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 00/10] Add MSI-X support on pcitest tool
Depends of the following serie [1]. Add MSI-X support on pcitest tool. Add new callbacks methods and handlers to trigger the MSI-X interrupts on the EP DesignWare IP driver. Allow to set/get MSI-X EP maximum capability number. Rework on set/get and triggering MSI methods on EP DesignWare IP driver. Add a new input parameter (msix) to pcitest tool to test MSI-X feature. Update the pcitest.sh script to support MSI-X feature tests. [1] -> https://lkml.org/lkml/2018/4/27/342 Gustavo Pimentel (10): PCI: endpoint: Add MSI-X interfaces PCI: dwc: Add MSI-X callbacks handler PCI: cadence: Update cdns_pcie_ep_raise_irq function signature PCI: dwc: Rework MSI callbacks handler PCI: dwc: Add legacy interrupt callback handler misc: pci_endpoint_test: Add MSI-X support misc: pci_endpoint_test: Replace lower into upper case characters PCI: endpoint: functions/pci-epf-test: Replace lower into upper case characters tools: PCI: Add MSI-X support misc: pci_endpoint_test: Use pci_irq_vector function Documentation/misc-devices/pci-endpoint-test.txt | 3 + drivers/misc/pci_endpoint_test.c | 147 +++-- drivers/pci/cadence/pcie-cadence-ep.c| 2 +- drivers/pci/dwc/pci-dra7xx.c | 2 +- drivers/pci/dwc/pcie-artpec6.c | 2 +- drivers/pci/dwc/pcie-designware-ep.c | 202 +-- drivers/pci/dwc/pcie-designware-plat.c | 7 +- drivers/pci/dwc/pcie-designware.h| 31 ++-- drivers/pci/endpoint/functions/pci-epf-test.c| 104 drivers/pci/endpoint/pci-ep-cfs.c| 24 +++ drivers/pci/endpoint/pci-epc-core.c | 60 ++- include/linux/pci-epc.h | 11 +- include/linux/pci-epf.h | 1 + include/uapi/linux/pcitest.h | 1 + tools/pci/pcitest.c | 18 +- tools/pci/pcitest.sh | 25 +++ 16 files changed, 517 insertions(+), 123 deletions(-) -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC 01/10] PCI: dwc: Add MSI-X callbacks handler
Hi Alan, Sorry for the delay on the response, I only have time to proper analyze this now. On 24/04/2018 10:15, Alan Douglas wrote: > Hi, > > On 10 April 2018 18:15 Gustavo Pimentel wrote: >> Changes the pcie_raise_irq function signature, namely the interrupt_num >> variable type from u8 to u16 to accommodate the MSI-X maximum interrupts >> of 2048. >> >> Implements a PCIe config space capability iterator function to search and >> save >> the MSI and MSI-X pointers. With this method the code becomes more >> generic and flexible. >> >> Implements MSI-X set/get functions for sysfs interface in order to change the >> EP entries number. >> >> Implements EP MSI-X interface for triggering interruptions. >> >> Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> >> --- >> drivers/pci/dwc/pci-dra7xx.c | 2 +- >> drivers/pci/dwc/pcie-artpec6.c | 2 +- >> drivers/pci/dwc/pcie-designware-ep.c | 145 >> - >> drivers/pci/dwc/pcie-designware-plat.c | 6 +- >> drivers/pci/dwc/pcie-designware.h | 23 +- >> 5 files changed, 173 insertions(+), 5 deletions(-) >> >> diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c >> index >> ed8558d..5265725 100644 >> --- a/drivers/pci/dwc/pci-dra7xx.c >> +++ b/drivers/pci/dwc/pci-dra7xx.c >> @@ -369,7 +369,7 @@ static void dra7xx_pcie_raise_msi_irq(struct >> dra7xx_pcie *dra7xx, } >> >> static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, >> - enum pci_epc_irq_type type, u8 >> interrupt_num) >> + enum pci_epc_irq_type type, u16 >> interrupt_num) >> { >> struct dw_pcie *pci = to_dw_pcie_from_ep(ep); >> struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); diff --git >> a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index >> e66cede..96dc259 100644 >> --- a/drivers/pci/dwc/pcie-artpec6.c >> +++ b/drivers/pci/dwc/pcie-artpec6.c >> @@ -428,7 +428,7 @@ static void artpec6_pcie_ep_init(struct dw_pcie_ep >> *ep) } >> >> static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, >> - enum pci_epc_irq_type type, u8 >> interrupt_num) >> + enum pci_epc_irq_type type, u16 >> interrupt_num) >> { >> struct dw_pcie *pci = to_dw_pcie_from_ep(ep); >> >> diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie- >> designware-ep.c >> index 15b22a6..874d4c2 100644 >> --- a/drivers/pci/dwc/pcie-designware-ep.c >> +++ b/drivers/pci/dwc/pcie-designware-ep.c >> @@ -40,6 +40,44 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, >> enum pci_barno bar) >> __dw_pcie_ep_reset_bar(pci, bar, 0); >> } >> >> +void dw_pcie_ep_find_cap_addr(struct dw_pcie_ep *ep) { >> +struct dw_pcie *pci = to_dw_pcie_from_ep(ep); >> +u8 next_ptr, curr_ptr, cap_id; >> +u16 reg; >> + >> +memset(>cap_addr, 0, sizeof(ep->cap_addr)); >> + >> +reg = dw_pcie_readw_dbi(pci, PCI_STATUS); >> +if (!(reg & PCI_STATUS_CAP_LIST)) >> +return; >> + >> +reg = dw_pcie_readw_dbi(pci, PCI_CAPABILITY_LIST); >> +next_ptr = (reg & 0x00ff); >> +if (!next_ptr) >> +return; >> + >> +reg = dw_pcie_readw_dbi(pci, next_ptr); >> +curr_ptr = next_ptr; >> +next_ptr = (reg & 0xff00) >> 8; >> +cap_id = (reg & 0x00ff); >> + >> +while (next_ptr && (cap_id <= PCI_CAP_ID_MAX)) { >> +switch (cap_id) { >> +case PCI_CAP_ID_MSI: >> +ep->cap_addr.msi_addr = curr_ptr; >> +break; >> +case PCI_CAP_ID_MSIX: >> +ep->cap_addr.msix_addr = curr_ptr; >> +break; >> +} >> +reg = dw_pcie_readw_dbi(pci, next_ptr); >> +curr_ptr = next_ptr; >> +next_ptr = (reg & 0xff00) >> 8; >> +cap_id = (reg & 0x00ff); >> +} >> +} >> + >> static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, >> struct pci_epf_header *hdr) >> { >> @@ -241,8 +279,47 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, >> u8 func_no, u8 encode_int) >> return 0; >> } >> >> +static int dw_pcie_ep_ge
[PATCH v2 4/7] PCI: dwc: Rework MSI callbacks handler
Remove duplicate defines located on pcie-designware.h file already available on /include/uapi/linux/pci-regs.h file. Add pci_epc_set_msi() maximum 32 interrupts validation. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- Change v1->v2: - Nothing changed, just to follow the patch set version. drivers/pci/dwc/pcie-designware-ep.c | 49 drivers/pci/dwc/pcie-designware.h| 11 drivers/pci/endpoint/pci-epc-core.c | 3 ++- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index e5f2377..a4baa0d 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@ -246,29 +246,38 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 func_no) { - int val; struct dw_pcie_ep *ep = epc_get_drvdata(epc); struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + u32 val, reg; + + if (!ep->msi_cap) + return 0; - val = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); - if (!(val & MSI_CAP_MSI_EN_MASK)) + reg = ep->msi_cap + PCI_MSI_FLAGS; + val = dw_pcie_readw_dbi(pci, reg); + if (!(val & PCI_MSI_FLAGS_ENABLE)) return -EINVAL; - val = (val & MSI_CAP_MME_MASK) >> MSI_CAP_MME_SHIFT; + val = (val & PCI_MSI_FLAGS_QSIZE) >> 4; + return val; } -static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 encode_int) +static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts) { - int val; struct dw_pcie_ep *ep = epc_get_drvdata(epc); struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + u32 val, reg; - val = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); - val &= ~MSI_CAP_MMC_MASK; - val |= (encode_int << MSI_CAP_MMC_SHIFT) & MSI_CAP_MMC_MASK; + if (!ep->msi_cap) + return 0; + + reg = ep->msi_cap + PCI_MSI_FLAGS; + val = dw_pcie_readw_dbi(pci, reg); + val &= ~PCI_MSI_FLAGS_QMASK; + val |= (interrupts << 1) & PCI_MSI_FLAGS_QMASK; dw_pcie_dbi_ro_wr_en(pci); - dw_pcie_writew_dbi(pci, MSI_MESSAGE_CONTROL, val); + dw_pcie_writew_dbi(pci, reg, val); dw_pcie_dbi_ro_wr_dis(pci); return 0; @@ -367,21 +376,29 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, struct dw_pcie *pci = to_dw_pcie_from_ep(ep); struct pci_epc *epc = ep->epc; u16 msg_ctrl, msg_data; - u32 msg_addr_lower, msg_addr_upper; + u32 msg_addr_lower, msg_addr_upper, reg; u64 msg_addr; bool has_upper; int ret; + if (!ep->msi_cap) + return 0; + /* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */ - msg_ctrl = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); + reg = ep->msi_cap + PCI_MSI_FLAGS; + msg_ctrl = dw_pcie_readw_dbi(pci, reg); has_upper = !!(msg_ctrl & PCI_MSI_FLAGS_64BIT); - msg_addr_lower = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_L32); + reg = ep->msi_cap + PCI_MSI_ADDRESS_LO; + msg_addr_lower = dw_pcie_readl_dbi(pci, reg); if (has_upper) { - msg_addr_upper = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_U32); - msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_64); + reg = ep->msi_cap + PCI_MSI_ADDRESS_HI; + msg_addr_upper = dw_pcie_readl_dbi(pci, reg); + reg = ep->msi_cap + PCI_MSI_DATA_64; + msg_data = dw_pcie_readw_dbi(pci, reg); } else { msg_addr_upper = 0; - msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_32); + reg = ep->msi_cap + PCI_MSI_DATA_32; + msg_data = dw_pcie_readw_dbi(pci, reg); } msg_addr = ((u64) msg_addr_upper) << 32 | msg_addr_lower; ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr, diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h index b22c5bb..a0ab12f 100644 --- a/drivers/pci/dwc/pcie-designware.h +++ b/drivers/pci/dwc/pcie-designware.h @@ -96,17 +96,6 @@ #define PCIE_GET_ATU_INB_UNR_REG_OFFSET(region) \ ((0x3 << 20) | ((region) << 9) | (0x1 << 8)) -#define MSI_MESSAGE_CONTROL0x52 -#define MSI_CAP_MMC_SHIFT 1 -#define MSI_CAP_MMC_MASK (7 << MSI_CAP_MMC_SHIFT) -#define MSI_CAP_MME_SHIFT 4 -#define MSI_CAP_MSI_EN_MASK0x1 -#define MSI_CAP_MME_MASK (7 << MSI_CAP_MME_SHIFT) -#define MSI_MESSAGE_ADDR_L32 0x54 -#define MSI_MESSAGE_ADDR_U32 0x58 -#d
[PATCH v2 1/7] PCI: endpoint: Add MSI-X interfaces
Add PCI_EPC_IRQ_MSIX type. Add MSI-X callbacks signatures to the ops structure. Add sysfs interface for set/get MSI-X capability maximum number. Change pci_epc_raise_irq() signature, namely the interrupt_num variable type from u8 to u16 to accommodate 2048 maximum MSI-X interrupts. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- Change v1->v2: - Nothing changed, just to follow the patch set version. drivers/pci/endpoint/pci-ep-cfs.c | 24 +++ drivers/pci/endpoint/pci-epc-core.c | 59 - include/linux/pci-epc.h | 13 ++-- include/linux/pci-epf.h | 1 + 4 files changed, 94 insertions(+), 3 deletions(-) diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c index 018ea34..d1288a0 100644 --- a/drivers/pci/endpoint/pci-ep-cfs.c +++ b/drivers/pci/endpoint/pci-ep-cfs.c @@ -286,6 +286,28 @@ static ssize_t pci_epf_msi_interrupts_show(struct config_item *item, to_pci_epf_group(item)->epf->msi_interrupts); } +static ssize_t pci_epf_msix_interrupts_store(struct config_item *item, +const char *page, size_t len) +{ + u16 val; + int ret; + + ret = kstrtou16(page, 0, ); + if (ret) + return ret; + + to_pci_epf_group(item)->epf->msix_interrupts = val; + + return len; +} + +static ssize_t pci_epf_msix_interrupts_show(struct config_item *item, + char *page) +{ + return sprintf(page, "%d\n", + to_pci_epf_group(item)->epf->msix_interrupts); +} + PCI_EPF_HEADER_R(vendorid) PCI_EPF_HEADER_W_u16(vendorid) @@ -327,6 +349,7 @@ CONFIGFS_ATTR(pci_epf_, subsys_vendor_id); CONFIGFS_ATTR(pci_epf_, subsys_id); CONFIGFS_ATTR(pci_epf_, interrupt_pin); CONFIGFS_ATTR(pci_epf_, msi_interrupts); +CONFIGFS_ATTR(pci_epf_, msix_interrupts); static struct configfs_attribute *pci_epf_attrs[] = { _epf_attr_vendorid, @@ -340,6 +363,7 @@ static struct configfs_attribute *pci_epf_attrs[] = { _epf_attr_subsys_id, _epf_attr_interrupt_pin, _epf_attr_msi_interrupts, + _epf_attr_msix_interrupts, NULL, }; diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index b0ee427..a23aa75 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -137,7 +137,7 @@ EXPORT_SYMBOL_GPL(pci_epc_start); * Invoke to raise an MSI or legacy interrupt */ int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no, - enum pci_epc_irq_type type, u8 interrupt_num) + enum pci_epc_irq_type type, u16 interrupt_num) { int ret; unsigned long flags; @@ -218,6 +218,63 @@ int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts) EXPORT_SYMBOL_GPL(pci_epc_set_msi); /** + * pci_epc_get_msix() - get the number of MSI-X interrupt numbers allocated + * @epc: the EPC device to which MSI-X interrupts was requested + * @func_no: the endpoint function number in the EPC device + * + * Invoke to get the number of MSI-X interrupts allocated by the RC + */ +int pci_epc_get_msix(struct pci_epc *epc, u8 func_no) +{ + int interrupt; + unsigned long flags; + + if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) + return 0; + + if (!epc->ops->get_msix) + return 0; + + spin_lock_irqsave(>lock, flags); + interrupt = epc->ops->get_msix(epc, func_no); + spin_unlock_irqrestore(>lock, flags); + + if (interrupt < 0) + return 0; + + return interrupt + 1; +} +EXPORT_SYMBOL_GPL(pci_epc_get_msix); + +/** + * pci_epc_set_msix() - set the number of MSI-X interrupt numbers required + * @epc: the EPC device on which MSI-X has to be configured + * @func_no: the endpoint function number in the EPC device + * @interrupts: number of MSI-X interrupts required by the EPF + * + * Invoke to set the required number of MSI-X interrupts. + */ +int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts) +{ + int ret; + unsigned long flags; + + if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || + interrupts < 1 || interrupts > 2048) + return -EINVAL; + + if (!epc->ops->set_msix) + return 0; + + spin_lock_irqsave(>lock, flags); + ret = epc->ops->set_msix(epc, func_no, interrupts - 1); + spin_unlock_irqrestore(>lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(pci_epc_set_msix); + +/** * pci_epc_unmap_addr() - unmap CPU address from PCI address * @epc: the EPC device on which address is allocated * @func_no: the endpoint function number in the EPC device diff --git a/include/linux/pci-epc.h b/include/linux/pci-e
[PATCH v2 0/7] Add MSI-X support on pcitest tool
Patch series made against Lorenzo's branches and also depends of: - pci/dwc - pci/endpoint Add MSI-X support on pcitest tool. Add new callbacks methods and handlers to trigger the MSI-X interrupts on the EP DesignWare IP driver. Allow to set/get MSI-X EP maximum capability number. Rework on set/get and triggering MSI methods on EP DesignWare IP driver. Add a new input parameter (msix) to pcitest tool to test MSI-X feature. Update the pcitest.sh script to support MSI-X feature tests. Gustavo Pimentel (7): PCI: endpoint: Add MSI-X interfaces PCI: dwc: Add MSI-X callbacks handler PCI: cadence: Update cdns_pcie_ep_raise_irq function signature PCI: dwc: Rework MSI callbacks handler PCI: dwc: Add legacy interrupt callback handler misc: pci_endpoint_test: Add MSI-X support tools: PCI: Add MSI-X support Documentation/misc-devices/pci-endpoint-test.txt | 6 + drivers/misc/pci_endpoint_test.c | 261 +-- drivers/pci/cadence/pcie-cadence-ep.c| 3 +- drivers/pci/dwc/pci-dra7xx.c | 2 +- drivers/pci/dwc/pcie-artpec6.c | 2 +- drivers/pci/dwc/pcie-designware-ep.c | 205 -- drivers/pci/dwc/pcie-designware-plat.c | 7 +- drivers/pci/dwc/pcie-designware.h| 31 +-- drivers/pci/endpoint/functions/pci-epf-test.c| 81 +-- drivers/pci/endpoint/pci-ep-cfs.c| 24 +++ drivers/pci/endpoint/pci-epc-core.c | 62 +- include/linux/pci-epc.h | 13 +- include/linux/pci-epf.h | 1 + include/uapi/linux/pcitest.h | 3 + tools/pci/pcitest.c | 51 - tools/pci/pcitest.sh | 15 ++ 16 files changed, 639 insertions(+), 128 deletions(-) -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 3/7] PCI: cadence: Update cdns_pcie_ep_raise_irq function signature
Change cdns_pcie_ep_raise_irq() signature, namely the interrupt_num variable type from u8 to u16 to accommodate 2048 maximum MSI-X interrupts. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> Acked-by: Alan Douglas <adoug...@cadence.com> --- Change v1->v2: - Nothing changed, just to follow the patch set version. drivers/pci/cadence/pcie-cadence-ep.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pci/cadence/pcie-cadence-ep.c b/drivers/pci/cadence/pcie-cadence-ep.c index 3d8283e..6b713ca 100644 --- a/drivers/pci/cadence/pcie-cadence-ep.c +++ b/drivers/pci/cadence/pcie-cadence-ep.c @@ -363,7 +363,8 @@ static int cdns_pcie_ep_send_msi_irq(struct cdns_pcie_ep *ep, u8 fn, } static int cdns_pcie_ep_raise_irq(struct pci_epc *epc, u8 fn, - enum pci_epc_irq_type type, u8 interrupt_num) + enum pci_epc_irq_type type, + u16 interrupt_num) { struct cdns_pcie_ep *ep = epc_get_drvdata(epc); -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 5/7] PCI: dwc: Add legacy interrupt callback handler
Add a legacy interrupt callback handler. Currently DesignWare IP don't allow trigger legacy interrupts. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- Change v1->v2: - Nothing changed, just to follow the patch set version. drivers/pci/dwc/pcie-designware-ep.c | 10 ++ drivers/pci/dwc/pcie-designware-plat.c | 3 +-- drivers/pci/dwc/pcie-designware.h | 6 ++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index a4baa0d..9822127 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@ -370,6 +370,16 @@ static const struct pci_epc_ops epc_ops = { .stop = dw_pcie_ep_stop, }; +int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no) +{ + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + struct device *dev = pci->dev; + + dev_err(dev, "EP cannot trigger legacy IRQs\n"); + + return -EINVAL; +} + int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, u8 interrupt_num) { diff --git a/drivers/pci/dwc/pcie-designware-plat.c b/drivers/pci/dwc/pcie-designware-plat.c index 654dcb5..90a8c95 100644 --- a/drivers/pci/dwc/pcie-designware-plat.c +++ b/drivers/pci/dwc/pcie-designware-plat.c @@ -84,8 +84,7 @@ static int dw_plat_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, switch (type) { case PCI_EPC_IRQ_LEGACY: - dev_err(pci->dev, "EP cannot trigger legacy IRQs\n"); - return -EINVAL; + return dw_pcie_ep_raise_legacy_irq(ep, func_no); case PCI_EPC_IRQ_MSI: return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num); case PCI_EPC_IRQ_MSIX: diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h index a0ab12f..69e6e17 100644 --- a/drivers/pci/dwc/pcie-designware.h +++ b/drivers/pci/dwc/pcie-designware.h @@ -350,6 +350,7 @@ static inline int dw_pcie_allocate_domains(struct pcie_port *pp) void dw_pcie_ep_linkup(struct dw_pcie_ep *ep); int dw_pcie_ep_init(struct dw_pcie_ep *ep); void dw_pcie_ep_exit(struct dw_pcie_ep *ep); +int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no); int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, u8 interrupt_num); int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no, @@ -369,6 +370,11 @@ static inline void dw_pcie_ep_exit(struct dw_pcie_ep *ep) { } +static inline int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no) +{ + return 0; +} + static inline int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, u8 interrupt_num) { -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 7/7] tools: PCI: Add MSI-X support
Add MSI-X support to pcitest tool. Add 2 new IOCTL commands: - Allow to reconfigure driver IRQ type in runtime. - Allow to retrieve current driver IRQ type configured. Modify pcitest.sh script to accommodate MSI-X interrupt tests. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- Change v1->v2: - Allow IRQ type driver reconfiguring in runtime, follwing Kishon's suggestion. include/uapi/linux/pcitest.h | 3 +++ tools/pci/pcitest.c | 51 +++- tools/pci/pcitest.sh | 15 + 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/pcitest.h b/include/uapi/linux/pcitest.h index 953cf03..cbf422e 100644 --- a/include/uapi/linux/pcitest.h +++ b/include/uapi/linux/pcitest.h @@ -16,5 +16,8 @@ #define PCITEST_WRITE _IOW('P', 0x4, unsigned long) #define PCITEST_READ _IOW('P', 0x5, unsigned long) #define PCITEST_COPY _IOW('P', 0x6, unsigned long) +#define PCITEST_MSIX _IOW('P', 0x7, int) +#define PCITEST_SET_IRQTYPE_IOW('P', 0x8, int) +#define PCITEST_GET_IRQTYPE_IO('P', 0x9) #endif /* __UAPI_LINUX_PCITEST_H */ diff --git a/tools/pci/pcitest.c b/tools/pci/pcitest.c index 9074b47..af146bb 100644 --- a/tools/pci/pcitest.c +++ b/tools/pci/pcitest.c @@ -31,12 +31,17 @@ #define BILLION 1E9 static char *result[] = { "NOT OKAY", "OKAY" }; +static char *irq[] = { "LEGACY", "MSI", "MSI-X" }; struct pci_test { char*device; charbarnum; boollegacyirq; unsigned intmsinum; + unsigned intmsixnum; + int irqtype; + boolset_irqtype; + boolget_irqtype; boolread; boolwrite; boolcopy; @@ -65,6 +70,24 @@ static int run_test(struct pci_test *test) fprintf(stdout, "%s\n", result[ret]); } + if (test->set_irqtype) { + ret = ioctl(fd, PCITEST_SET_IRQTYPE, test->irqtype); + fprintf(stdout, "SET IRQ TYPE TO %s:\t\t", irq[test->irqtype]); + if (ret < 0) + fprintf(stdout, "FAILED\n"); + else + fprintf(stdout, "%s\n", result[ret]); + } + + if (test->get_irqtype) { + ret = ioctl(fd, PCITEST_GET_IRQTYPE); + fprintf(stdout, "GET IRQ TYPE:\t\t"); + if (ret < 0) + fprintf(stdout, "FAILED\n"); + else + fprintf(stdout, "%s\n", irq[ret]); + } + if (test->legacyirq) { ret = ioctl(fd, PCITEST_LEGACY_IRQ, 0); fprintf(stdout, "LEGACY IRQ:\t"); @@ -83,6 +106,15 @@ static int run_test(struct pci_test *test) fprintf(stdout, "%s\n", result[ret]); } + if (test->msixnum > 0 && test->msixnum <= 2048) { + ret = ioctl(fd, PCITEST_MSIX, test->msixnum); + fprintf(stdout, "MSI-X%d:\t\t", test->msixnum); + if (ret < 0) + fprintf(stdout, "TEST FAILED\n"); + else + fprintf(stdout, "%s\n", result[ret]); + } + if (test->write) { ret = ioctl(fd, PCITEST_WRITE, test->size); fprintf(stdout, "WRITE (%7ld bytes):\t\t", test->size); @@ -133,7 +165,7 @@ int main(int argc, char **argv) /* set default endpoint device */ test->device = "/dev/pci-endpoint-test.0"; - while ((c = getopt(argc, argv, "D:b:m:lrwcs:")) != EOF) + while ((c = getopt(argc, argv, "D:b:m:x:i:Ilrwcs:")) != EOF) switch (c) { case 'D': test->device = optarg; @@ -151,6 +183,20 @@ int main(int argc, char **argv) if (test->msinum < 1 || test->msinum > 32) goto usage; continue; + case 'x': + test->msixnum = atoi(optarg); + if (test->msixnum < 1 || test->msixnum > 2048) + goto usage; + continue; + case 'i': + test->irqtype = atoi(optarg); + if (test->irqtype < 0 || test->irqtype > 2) + goto usage; + test->set_irqtype = true; + continue; + case 'I': + test->get_irqtype = true; + continue; case 'r': test->read = true; continue; @@ -173,6 +219,9 @@ int main(int argc, char **argv)
[PATCH v2 6/7] misc: pci_endpoint_test: Add MSI-X support
Add MSI-X support and update driver documentation accordingly. Add new driver parameter to allow interruption type selection. Add 2 new IOCTL commands: - Allow to reconfigure driver IRQ type in runtime. - Allow to retrieve current driver IRQ type configured. Change Legacy/MSI/MSI-X test process, by having in a BAR: - Interrupt type triggered (added). - Interrupt ID number (moved from the command section). Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- Change v1->v2: - Allow IRQ type driver reconfiguring in runtime, follwing Kishon's suggestion. Documentation/misc-devices/pci-endpoint-test.txt | 6 + drivers/misc/pci_endpoint_test.c | 261 +-- drivers/pci/endpoint/functions/pci-epf-test.c| 81 +-- 3 files changed, 260 insertions(+), 88 deletions(-) diff --git a/Documentation/misc-devices/pci-endpoint-test.txt b/Documentation/misc-devices/pci-endpoint-test.txt index 4ebc359..58ccca4 100644 --- a/Documentation/misc-devices/pci-endpoint-test.txt +++ b/Documentation/misc-devices/pci-endpoint-test.txt @@ -10,6 +10,7 @@ The PCI driver for the test device performs the following tests *) verifying addresses programmed in BAR *) raise legacy IRQ *) raise MSI IRQ + *) raise MSI-X IRQ *) read data *) write data *) copy data @@ -25,6 +26,11 @@ ioctl PCITEST_LEGACY_IRQ: Tests legacy IRQ PCITEST_MSI: Tests message signalled interrupts. The MSI number to be tested should be passed as argument. + PCITEST_MSIX: Tests message signalled interrupts. The MSI-X number + to be tested should be passed as argument. + PCITEST_SET_IRQTYPE: Changes driver IRQ type configuration. The IRQ type + should be passed as argument (0: Legacy, 1:MSI, 2:MSI-X). + PCITEST_GET_IRQTYPE: Gets driver IRQ type configuration. PCITEST_WRITE: Perform write tests. The size of the buffer should be passed as argument. PCITEST_READ: Perform read tests. The size of the buffer should be passed diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 7b37046..df2017f 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -35,38 +35,44 @@ #include -#define DRV_MODULE_NAME"pci-endpoint-test" - -#define PCI_ENDPOINT_TEST_MAGIC0x0 - -#define PCI_ENDPOINT_TEST_COMMAND 0x4 -#define COMMAND_RAISE_LEGACY_IRQ BIT(0) -#define COMMAND_RAISE_MSI_IRQ BIT(1) -#define MSI_NUMBER_SHIFT 2 -/* 6 bits for MSI number */ -#define COMMAND_READBIT(8) -#define COMMAND_WRITE BIT(9) -#define COMMAND_COPYBIT(10) - -#define PCI_ENDPOINT_TEST_STATUS 0x8 -#define STATUS_READ_SUCCESS BIT(0) -#define STATUS_READ_FAILBIT(1) -#define STATUS_WRITE_SUCCESSBIT(2) -#define STATUS_WRITE_FAIL BIT(3) -#define STATUS_COPY_SUCCESS BIT(4) -#define STATUS_COPY_FAILBIT(5) -#define STATUS_IRQ_RAISED BIT(6) -#define STATUS_SRC_ADDR_INVALID BIT(7) -#define STATUS_DST_ADDR_INVALID BIT(8) - -#define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0xc +#define DRV_MODULE_NAME"pci-endpoint-test" + +#define IRQ_TYPE_LEGACY0 +#define IRQ_TYPE_MSI 1 +#define IRQ_TYPE_MSIX 2 + +#define PCI_ENDPOINT_TEST_MAGIC0x0 + +#define PCI_ENDPOINT_TEST_COMMAND 0x4 +#define COMMAND_RAISE_LEGACY_IRQ BIT(0) +#define COMMAND_RAISE_MSI_IRQ BIT(1) +#define COMMAND_RAISE_MSIX_IRQ BIT(2) +#define COMMAND_READ BIT(3) +#define COMMAND_WRITE BIT(4) +#define COMMAND_COPY BIT(5) + +#define PCI_ENDPOINT_TEST_STATUS 0x8 +#define STATUS_READ_SUCCESSBIT(0) +#define STATUS_READ_FAIL BIT(1) +#define STATUS_WRITE_SUCCESS BIT(2) +#define STATUS_WRITE_FAIL BIT(3) +#define STATUS_COPY_SUCCESSBIT(4) +#define STATUS_COPY_FAIL BIT(5) +#define STATUS_IRQ_RAISED BIT(6) +#define STATUS_SRC_ADDR_INVALIDBIT(7) +#define STATUS_DST_ADDR_INVALIDBIT(8) + +#define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0x0c #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10 #define PCI_ENDPOINT_TEST_LOWER_DST_ADDR 0x14 #define PCI_ENDPOINT_TEST_UPPER_DST_ADDR 0x18 -#define PCI_ENDPOINT_TEST_SIZE 0x1c -#define PCI_ENDPOINT_TEST_CHECKSUM 0x20 +#define PCI_ENDPOINT_TEST_SIZE 0x1c +#define PCI_ENDPOINT_TEST_CHECKSU
[PATCH v2 2/7] PCI: dwc: Add MSI-X callbacks handler
Change pcie_raise_irq() signature, namely the interrupt_num variable type from u8 to u16 to accommodate 2048 maximum MSI-X interrupts. Add PCIe config space capability search function. Add sysfs set/get interface to allow the change of EP MSI-X maximum number. Add EP MSI-X callback for triggering interruptions. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- Change v1->v2: - Nothing changed, just to follow the patch set version. drivers/pci/dwc/pci-dra7xx.c | 2 +- drivers/pci/dwc/pcie-artpec6.c | 2 +- drivers/pci/dwc/pcie-designware-ep.c | 146 - drivers/pci/dwc/pcie-designware-plat.c | 4 +- drivers/pci/dwc/pcie-designware.h | 14 +++- 5 files changed, 163 insertions(+), 5 deletions(-) diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c index f688204..bdf948b 100644 --- a/drivers/pci/dwc/pci-dra7xx.c +++ b/drivers/pci/dwc/pci-dra7xx.c @@ -370,7 +370,7 @@ static void dra7xx_pcie_raise_msi_irq(struct dra7xx_pcie *dra7xx, } static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, -enum pci_epc_irq_type type, u8 interrupt_num) +enum pci_epc_irq_type type, u16 interrupt_num) { struct dw_pcie *pci = to_dw_pcie_from_ep(ep); struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index 321b56c..9a2474b 100644 --- a/drivers/pci/dwc/pcie-artpec6.c +++ b/drivers/pci/dwc/pcie-artpec6.c @@ -428,7 +428,7 @@ static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep) } static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, - enum pci_epc_irq_type type, u8 interrupt_num) + enum pci_epc_irq_type type, u16 interrupt_num) { struct dw_pcie *pci = to_dw_pcie_from_ep(ep); diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index 1eec441..e5f2377 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@ -40,6 +40,39 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar) __dw_pcie_ep_reset_bar(pci, bar, 0); } +u8 __dw_pcie_ep_find_next_cap(struct dw_pcie *pci, u8 cap_ptr, + u8 cap) +{ + u8 cap_id, next_cap_ptr; + u16 reg; + + reg = dw_pcie_readw_dbi(pci, cap_ptr); + next_cap_ptr = (reg & 0xff00) >> 8; + cap_id = (reg & 0x00ff); + + if (!next_cap_ptr || cap_id > PCI_CAP_ID_MAX) + return 0; + + if (cap_id == cap) + return cap_ptr; + + return __dw_pcie_ep_find_next_cap(pci, next_cap_ptr, cap); +} + +u8 dw_pcie_ep_find_capability(struct dw_pcie *pci, u8 cap) +{ + u8 next_cap_ptr; + u16 reg; + + reg = dw_pcie_readw_dbi(pci, PCI_CAPABILITY_LIST); + next_cap_ptr = (reg & 0x00ff); + + if (!next_cap_ptr) + return 0; + + return __dw_pcie_ep_find_next_cap(pci, next_cap_ptr, cap); +} + static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, struct pci_epf_header *hdr) { @@ -241,8 +274,47 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 encode_int) return 0; } +static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no) +{ + struct dw_pcie_ep *ep = epc_get_drvdata(epc); + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + u32 val, reg; + + if (!ep->msix_cap) + return 0; + + reg = ep->msix_cap + PCI_MSIX_FLAGS; + val = dw_pcie_readw_dbi(pci, reg); + if (!(val & PCI_MSIX_FLAGS_ENABLE)) + return -EINVAL; + + val &= PCI_MSIX_FLAGS_QSIZE; + + return val; +} + +static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts) +{ + struct dw_pcie_ep *ep = epc_get_drvdata(epc); + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + u32 val, reg; + + if (!ep->msix_cap) + return 0; + + reg = ep->msix_cap + PCI_MSIX_FLAGS; + val = dw_pcie_readw_dbi(pci, reg); + val &= ~PCI_MSIX_FLAGS_QSIZE; + val |= interrupts; + dw_pcie_dbi_ro_wr_en(pci); + dw_pcie_writew_dbi(pci, reg, val); + dw_pcie_dbi_ro_wr_dis(pci); + + return 0; +} + static int dw_pcie_ep_raise_irq(struct pci_epc *epc, u8 func_no, - enum pci_epc_irq_type type, u8 interrupt_num) + enum pci_epc_irq_type type, u16 interrupt_num) { struct dw_pcie_ep *ep = epc_get_drvdata(epc); @@ -282,6 +354,8 @@ static const struct pci_epc_ops epc_ops = { .unmap_addr = dw_pcie_ep_unmap_addr, .set_msi= dw_pcie_ep_set_msi, .get_msi= dw_pcie_ep_get_msi,
Re: [RFC 01/10] PCI: dwc: Add MSI-X callbacks handler
Hi Kishon, On 24/04/2018 12:24, Kishon Vijay Abraham I wrote: > Hi, > > On Tuesday 24 April 2018 03:06 PM, Gustavo Pimentel wrote: >> Hi Kishon, >> >> On 24/04/2018 08:07, Kishon Vijay Abraham I wrote: >>> Hi, >>> >>> On Monday 23 April 2018 03:06 PM, Gustavo Pimentel wrote: >>>> Hi Kishon, >>>> >>>> On 16/04/2018 10:29, Kishon Vijay Abraham I wrote: >>>>> Hi Gustavo, >>>>> >>>>> On Tuesday 10 April 2018 10:44 PM, Gustavo Pimentel wrote: >>>>>> Changes the pcie_raise_irq function signature, namely the interrupt_num >>>>>> variable type from u8 to u16 to accommodate the MSI-X maximum interrupts >>>>>> of 2048. >>>>>> >>>>>> Implements a PCIe config space capability iterator function to search and >>>>>> save the MSI and MSI-X pointers. With this method the code becomes more >>>>>> generic and flexible. >>>>>> >>>>>> Implements MSI-X set/get functions for sysfs interface in order to change >>>>>> the EP entries number. >>>>>> >>>>>> Implements EP MSI-X interface for triggering interruptions. >>>>>> >>>>>> Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> >>>>>> --- >>>>>> drivers/pci/dwc/pci-dra7xx.c | 2 +- >>>>>> drivers/pci/dwc/pcie-artpec6.c | 2 +- >>>>>> drivers/pci/dwc/pcie-designware-ep.c | 145 >>>>>> - >>>>>> drivers/pci/dwc/pcie-designware-plat.c | 6 +- >>>>>> drivers/pci/dwc/pcie-designware.h | 23 +- >>>>>> 5 files changed, 173 insertions(+), 5 deletions(-) >>>>>> >>>>>> diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c >>>>>> index ed8558d..5265725 100644 >>>>>> --- a/drivers/pci/dwc/pci-dra7xx.c >>>>>> +++ b/drivers/pci/dwc/pci-dra7xx.c >>>>>> @@ -369,7 +369,7 @@ static void dra7xx_pcie_raise_msi_irq(struct >>>>>> dra7xx_pcie *dra7xx, >>>>>> } >>>>>> >>>>>> static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, >>>>>> - enum pci_epc_irq_type type, u8 >>>>>> interrupt_num) >>>>>> + enum pci_epc_irq_type type, u16 >>>>>> interrupt_num) >>>>>> { >>>>>> struct dw_pcie *pci = to_dw_pcie_from_ep(ep); >>>>>> struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); >>>>>> diff --git a/drivers/pci/dwc/pcie-artpec6.c >>>>>> b/drivers/pci/dwc/pcie-artpec6.c >>>>>> index e66cede..96dc259 100644 >>>>>> --- a/drivers/pci/dwc/pcie-artpec6.c >>>>>> +++ b/drivers/pci/dwc/pcie-artpec6.c >>>>>> @@ -428,7 +428,7 @@ static void artpec6_pcie_ep_init(struct dw_pcie_ep >>>>>> *ep) >>>>>> } >>>>>> >>>>>> static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, >>>>>> - enum pci_epc_irq_type type, u8 >>>>>> interrupt_num) >>>>>> + enum pci_epc_irq_type type, u16 >>>>>> interrupt_num) >>>>>> { >>>>>> struct dw_pcie *pci = to_dw_pcie_from_ep(ep); >>>>>> >>>>>> diff --git a/drivers/pci/dwc/pcie-designware-ep.c >>>>>> b/drivers/pci/dwc/pcie-designware-ep.c >>>>>> index 15b22a6..874d4c2 100644 >>>>>> --- a/drivers/pci/dwc/pcie-designware-ep.c >>>>>> +++ b/drivers/pci/dwc/pcie-designware-ep.c >>>>>> @@ -40,6 +40,44 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum >>>>>> pci_barno bar) >>>>>> __dw_pcie_ep_reset_bar(pci, bar, 0); >>>>>> } >>>>>> >>>>>> +void dw_pcie_ep_find_cap_addr(struct dw_pcie_ep *ep) >>>>>> +{ >>>>> >>>>> This should be implemented in a generic way similar to >>>>> pci_find_capability(). >>>>> It'll be useful when we try to implement other capabilities as well. >>&
Re: [RFC 06/10] misc: pci_endpoint_test: Add MSI-X support
Hi Kishon, On 24/04/2018 12:43, Kishon Vijay Abraham I wrote: > Hi, > > On Tuesday 24 April 2018 04:27 PM, Gustavo Pimentel wrote: >> Hi Kishon, >> >> On 24/04/2018 08:19, Kishon Vijay Abraham I wrote: >>> Hi, >>> >>> On Tuesday 17 April 2018 11:08 PM, Gustavo Pimentel wrote: >>>> Hi Kishon, >>>> >>>> On 17/04/2018 11:33, Kishon Vijay Abraham I wrote: >>>>> Hi, >>>>> >>>>> On Tuesday 10 April 2018 10:44 PM, Gustavo Pimentel wrote: >>>>>> Adds the MSI-X support and updates driver documentation accordingly. >>>>>> >>>>>> Changes the driver parameter in order to allow the interruption type >>>>>> selection. >>>>>> >>>>>> Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> >>>>>> --- >>>>>> Documentation/misc-devices/pci-endpoint-test.txt | 3 + >>>>>> drivers/misc/pci_endpoint_test.c | 102 >>>>>> +-- >>>>>> 2 files changed, 79 insertions(+), 26 deletions(-) >>>>>> >>>>>> diff --git a/Documentation/misc-devices/pci-endpoint-test.txt >>>>>> b/Documentation/misc-devices/pci-endpoint-test.txt >>>>>> index 4ebc359..fdfa0f6 100644 >>>>>> --- a/Documentation/misc-devices/pci-endpoint-test.txt >>>>>> +++ b/Documentation/misc-devices/pci-endpoint-test.txt >>>>>> @@ -10,6 +10,7 @@ The PCI driver for the test device performs the >>>>>> following tests >>>>>> *) verifying addresses programmed in BAR >>>>>> *) raise legacy IRQ >>>>>> *) raise MSI IRQ >>>>>> +*) raise MSI-X IRQ >>>>>> *) read data >>>>>> *) write data >>>>>> *) copy data >>>>>> @@ -25,6 +26,8 @@ ioctl >>>>>> PCITEST_LEGACY_IRQ: Tests legacy IRQ >>>>>> PCITEST_MSI: Tests message signalled interrupts. The MSI number >>>>>>to be tested should be passed as argument. >>>>>> + PCITEST_MSIX: Tests message signalled interrupts. The MSI-X number >>>>>> + to be tested should be passed as argument. >>>>>> PCITEST_WRITE: Perform write tests. The size of the buffer should be >>>>>> passed >>>>>> as argument. >>>>>> PCITEST_READ: Perform read tests. The size of the buffer should be >>>>>> passed >>>>>> diff --git a/drivers/misc/pci_endpoint_test.c >>>>>> b/drivers/misc/pci_endpoint_test.c >>>>>> index 37db0fc..a7d9354 100644 >>>>>> --- a/drivers/misc/pci_endpoint_test.c >>>>>> +++ b/drivers/misc/pci_endpoint_test.c >>>>>> @@ -42,11 +42,16 @@ >>>>>> #define PCI_ENDPOINT_TEST_COMMAND 0x4 >>>>>> #define COMMAND_RAISE_LEGACY_IRQBIT(0) >>>>>> #define COMMAND_RAISE_MSI_IRQ BIT(1) >>>>>> -#define MSI_NUMBER_SHIFT2 >>>>>> -/* 6 bits for MSI number */ >>>>>> -#define COMMAND_READBIT(8) >>>>>> -#define COMMAND_WRITE BIT(9) >>>>>> -#define COMMAND_COPYBIT(10) >>>>>> +#define COMMAND_RAISE_MSIX_IRQ BIT(2) >>>>>> +#define IRQ_TYPE_SHIFT 3 >>>>>> +#define IRQ_TYPE_LEGACY 0 >>>>>> +#define IRQ_TYPE_MSI1 >>>>>> +#define IRQ_TYPE_MSIX 2 >>>>>> +#define MSI_NUMBER_SHIFT5 >>>>> >>>>> Now that you are anyways fixing this, add a new register entry for MSI >>>>> numbers. >>>>> Let's not keep COMMAND and MSI's together. >>>> >>>> What you suggest? >>> >>> #define PCI_ENDPOINT_TEST_COMMAND 0x4 >>> #define COMMAND_RAISE_LEGACY_IRQBIT(0) >>> #define COMMAND_RAISE_MSI_IRQ BIT(1) >>> #define COMMAND_RAISE_MSIX_IRQ BIT(2) >>> #define COMMAND_READBIT(3) >>> #define COMMAND_WRITE BIT(4) >>> #define COMMAND_COPYBIT(5) >>> >>&g
Re: [PATCH 06/10] misc: pci_endpoint_test: Add MSI-X support
Hi Alan, On 30/04/2018 16:35, Alan Douglas wrote: > Hi Gustavo, > > On April 27, 2018, 4:57 p.m. Gustavo Pimentel wrote: >> Add MSI-X support and update driver documentation accordingly. >> >> Add new driver parameter to allow interruption type selection. >> >> Modify the Legacy/MSI/MSI-X test process, by: >> - Add and use a specific register located in a BAR, which defines the >> interrupt >> type is been triggered. >> - Move the interrupt ID number from the command section to a register >> located in a BAR. >> >> Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> >> --- >> Documentation/misc-devices/pci-endpoint-test.txt | 3 + >> drivers/misc/pci_endpoint_test.c | 121 >> +++ >> drivers/pci/endpoint/functions/pci-epf-test.c| 78 +++ >> 3 files changed, 143 insertions(+), 59 deletions(-) >> > In testing these changes I found that pci_epc_raise_irq() also needs to be > updated in pci-epc-core.c, since it has interrupt_num parameter as u8 Yes, indeed. I updated it together with the pci-epc.h file. Thanks Alan, well spotted! Regards, Gustavo > > Thanks, > Alan > -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC 01/10] PCI: dwc: Add MSI-X callbacks handler
Changes the pcie_raise_irq function signature, namely the interrupt_num variable type from u8 to u16 to accommodate the MSI-X maximum interrupts of 2048. Implements a PCIe config space capability iterator function to search and save the MSI and MSI-X pointers. With this method the code becomes more generic and flexible. Implements MSI-X set/get functions for sysfs interface in order to change the EP entries number. Implements EP MSI-X interface for triggering interruptions. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/pci/dwc/pci-dra7xx.c | 2 +- drivers/pci/dwc/pcie-artpec6.c | 2 +- drivers/pci/dwc/pcie-designware-ep.c | 145 - drivers/pci/dwc/pcie-designware-plat.c | 6 +- drivers/pci/dwc/pcie-designware.h | 23 +- 5 files changed, 173 insertions(+), 5 deletions(-) diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c index ed8558d..5265725 100644 --- a/drivers/pci/dwc/pci-dra7xx.c +++ b/drivers/pci/dwc/pci-dra7xx.c @@ -369,7 +369,7 @@ static void dra7xx_pcie_raise_msi_irq(struct dra7xx_pcie *dra7xx, } static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, -enum pci_epc_irq_type type, u8 interrupt_num) +enum pci_epc_irq_type type, u16 interrupt_num) { struct dw_pcie *pci = to_dw_pcie_from_ep(ep); struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index e66cede..96dc259 100644 --- a/drivers/pci/dwc/pcie-artpec6.c +++ b/drivers/pci/dwc/pcie-artpec6.c @@ -428,7 +428,7 @@ static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep) } static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, - enum pci_epc_irq_type type, u8 interrupt_num) + enum pci_epc_irq_type type, u16 interrupt_num) { struct dw_pcie *pci = to_dw_pcie_from_ep(ep); diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index 15b22a6..874d4c2 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@ -40,6 +40,44 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar) __dw_pcie_ep_reset_bar(pci, bar, 0); } +void dw_pcie_ep_find_cap_addr(struct dw_pcie_ep *ep) +{ + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + u8 next_ptr, curr_ptr, cap_id; + u16 reg; + + memset(>cap_addr, 0, sizeof(ep->cap_addr)); + + reg = dw_pcie_readw_dbi(pci, PCI_STATUS); + if (!(reg & PCI_STATUS_CAP_LIST)) + return; + + reg = dw_pcie_readw_dbi(pci, PCI_CAPABILITY_LIST); + next_ptr = (reg & 0x00ff); + if (!next_ptr) + return; + + reg = dw_pcie_readw_dbi(pci, next_ptr); + curr_ptr = next_ptr; + next_ptr = (reg & 0xff00) >> 8; + cap_id = (reg & 0x00ff); + + while (next_ptr && (cap_id <= PCI_CAP_ID_MAX)) { + switch (cap_id) { + case PCI_CAP_ID_MSI: + ep->cap_addr.msi_addr = curr_ptr; + break; + case PCI_CAP_ID_MSIX: + ep->cap_addr.msix_addr = curr_ptr; + break; + } + reg = dw_pcie_readw_dbi(pci, next_ptr); + curr_ptr = next_ptr; + next_ptr = (reg & 0xff00) >> 8; + cap_id = (reg & 0x00ff); + } +} + static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, struct pci_epf_header *hdr) { @@ -241,8 +279,47 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 encode_int) return 0; } +static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no) +{ + struct dw_pcie_ep *ep = epc_get_drvdata(epc); + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + u32 val, reg; + + if (ep->cap_addr.msix_addr == 0) + return 0; + + reg = ep->cap_addr.msix_addr + PCI_MSIX_FLAGS; + val = dw_pcie_readw_dbi(pci, reg); + if (!(val & PCI_MSIX_FLAGS_ENABLE)) + return -EINVAL; + + val &= PCI_MSIX_FLAGS_QSIZE; + + return val; +} + +static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts) +{ + struct dw_pcie_ep *ep = epc_get_drvdata(epc); + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + u32 val, reg; + + if (ep->cap_addr.msix_addr == 0) + return 0; + + reg = ep->cap_addr.msix_addr + PCI_MSIX_FLAGS; + val = dw_pcie_readw_dbi(pci, reg); + val &= ~PCI_MSIX_FLAGS_QSIZE; + val |= interrupts; + dw_pcie_dbi_ro_wr_en(pci); + dw_pcie_writew_dbi(pci, reg, val); + dw_pcie_dbi_ro_wr_di
[RFC 07/10] misc: pci_endpoint_test: Replace lower into upper case characters
Replaces lower into upper case characters in comments and debug printks. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/misc/pci_endpoint_test.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index a7d9354..7212a7d 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -259,7 +259,7 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size) orig_src_addr = dma_alloc_coherent(dev, size + alignment, _src_phys_addr, GFP_KERNEL); if (!orig_src_addr) { - dev_err(dev, "failed to allocate source buffer\n"); + dev_err(dev, "Failed to allocate source buffer\n"); ret = false; goto err; } @@ -285,7 +285,7 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size) orig_dst_addr = dma_alloc_coherent(dev, size + alignment, _dst_phys_addr, GFP_KERNEL); if (!orig_dst_addr) { - dev_err(dev, "failed to allocate destination address\n"); + dev_err(dev, "Failed to allocate destination address\n"); ret = false; goto err_orig_src_addr; } @@ -349,7 +349,7 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size) orig_addr = dma_alloc_coherent(dev, size + alignment, _phys_addr, GFP_KERNEL); if (!orig_addr) { - dev_err(dev, "failed to allocate address\n"); + dev_err(dev, "Failed to allocate address\n"); ret = false; goto err; } @@ -412,7 +412,7 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size) orig_addr = dma_alloc_coherent(dev, size + alignment, _phys_addr, GFP_KERNEL); if (!orig_addr) { - dev_err(dev, "failed to allocate destination address\n"); + dev_err(dev, "Failed to allocate destination address\n"); ret = false; goto err; } @@ -550,7 +550,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, case IRQ_TYPE_MSI: irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); if (irq < 0) - dev_err(dev, "failed to get MSI interrupts\n"); + dev_err(dev, "Failed to get MSI interrupts\n"); test->num_irqs = irq; break; case IRQ_TYPE_MSIX: @@ -567,7 +567,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, IRQF_SHARED, DRV_MODULE_NAME, test); if (err) { - dev_err(dev, "failed to request IRQ %d\n", pdev->irq); + dev_err(dev, "Failed to request IRQ %d\n", pdev->irq); goto err_disable_msi; } @@ -585,7 +585,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) { base = pci_ioremap_bar(pdev, bar); if (!base) { - dev_err(dev, "failed to read BAR%d\n", bar); + dev_err(dev, "Failed to read BAR%d\n", bar); WARN_ON(bar == test_reg_bar); } test->bar[bar] = base; @@ -605,7 +605,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, id = ida_simple_get(_endpoint_test_ida, 0, 0, GFP_KERNEL); if (id < 0) { err = id; - dev_err(dev, "unable to get id\n"); + dev_err(dev, "Unable to get id\n"); goto err_iounmap; } @@ -621,7 +621,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, err = misc_register(misc_device); if (err) { - dev_err(dev, "failed to register device\n"); + dev_err(dev, "Failed to register device\n"); goto err_kfree_name; } -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC 05/10] PCI: dwc: Add legacy interrupt callback handler
Adds a legacy interrupt callback handler. Currently Designware IP doesn't allow triggering the legacy interrupt. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/pci/dwc/pcie-designware-ep.c | 10 ++ drivers/pci/dwc/pcie-designware-plat.c | 3 +-- drivers/pci/dwc/pcie-designware.h | 6 ++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index e352786..fb55259 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@ -375,6 +375,16 @@ static const struct pci_epc_ops epc_ops = { .stop = dw_pcie_ep_stop, }; +int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no) +{ + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + struct device *dev = pci->dev; + + dev_err(dev, "EP cannot trigger legacy IRQs\n"); + + return -EINVAL; +} + int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, u8 interrupt_num) { diff --git a/drivers/pci/dwc/pcie-designware-plat.c b/drivers/pci/dwc/pcie-designware-plat.c index c3a4707..3874b02 100644 --- a/drivers/pci/dwc/pcie-designware-plat.c +++ b/drivers/pci/dwc/pcie-designware-plat.c @@ -86,8 +86,7 @@ static int dw_plat_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, switch (type) { case PCI_EPC_IRQ_LEGACY: - dev_err(pci->dev, "EP cannot trigger legacy IRQs\n"); - return -EINVAL; + return dw_pcie_ep_raise_legacy_irq(ep, func_no); case PCI_EPC_IRQ_MSI: return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num); case PCI_EPC_IRQ_MSIX: diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h index 2acf18b0..808b280 100644 --- a/drivers/pci/dwc/pcie-designware.h +++ b/drivers/pci/dwc/pcie-designware.h @@ -354,6 +354,7 @@ static inline int dw_pcie_allocate_domains(struct pcie_port *pp) void dw_pcie_ep_linkup(struct dw_pcie_ep *ep); int dw_pcie_ep_init(struct dw_pcie_ep *ep); void dw_pcie_ep_exit(struct dw_pcie_ep *ep); +int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no); int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, u8 interrupt_num); int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no, @@ -374,6 +375,11 @@ static inline void dw_pcie_ep_exit(struct dw_pcie_ep *ep) { } +static inline int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no) +{ + return 0; +} + static inline int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, u8 interrupt_num) { -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC 04/10] PCI: dwc: MSI callbacks handler rework
Adds in pci_epc_set_msi function a maximum number of 32 interrupts validation. Removes duplicate defines located on pcie-designware.h file. Uses now the defines available on /include/uapi/linux/pci-regs.h file. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/pci/dwc/pcie-designware-ep.c | 46 +++- drivers/pci/dwc/pcie-designware.h| 11 - drivers/pci/endpoint/pci-epc-core.c | 3 ++- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index 874d4c2..e352786 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c @@ -251,29 +251,38 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 func_no) { - int val; struct dw_pcie_ep *ep = epc_get_drvdata(epc); struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + u32 val, reg; + + if (ep->cap_addr.msi_addr == 0) + return 0; - val = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); - if (!(val & MSI_CAP_MSI_EN_MASK)) + reg = ep->cap_addr.msi_addr + PCI_MSI_FLAGS; + val = dw_pcie_readw_dbi(pci, reg); + if (!(val & PCI_MSI_FLAGS_ENABLE)) return -EINVAL; - val = (val & MSI_CAP_MME_MASK) >> MSI_CAP_MME_SHIFT; + val = (val & PCI_MSI_FLAGS_QSIZE) >> 4; + return val; } -static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 encode_int) +static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts) { - int val; struct dw_pcie_ep *ep = epc_get_drvdata(epc); struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + u32 val, reg; + + if (ep->cap_addr.msi_addr == 0) + return 0; - val = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); - val &= ~MSI_CAP_MMC_MASK; - val |= (encode_int << MSI_CAP_MMC_SHIFT) & MSI_CAP_MMC_MASK; + reg = ep->cap_addr.msi_addr + PCI_MSI_FLAGS; + val = dw_pcie_readw_dbi(pci, reg); + val &= ~PCI_MSI_FLAGS_QMASK; + val |= (interrupts << 1) & PCI_MSI_FLAGS_QMASK; dw_pcie_dbi_ro_wr_en(pci); - dw_pcie_writew_dbi(pci, MSI_MESSAGE_CONTROL, val); + dw_pcie_writew_dbi(pci, reg, val); dw_pcie_dbi_ro_wr_dis(pci); return 0; @@ -372,21 +381,26 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, struct dw_pcie *pci = to_dw_pcie_from_ep(ep); struct pci_epc *epc = ep->epc; u16 msg_ctrl, msg_data; - u32 msg_addr_lower, msg_addr_upper; + u32 msg_addr_lower, msg_addr_upper, reg; u64 msg_addr; bool has_upper; int ret; /* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */ - msg_ctrl = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); + reg = ep->cap_addr.msi_addr + PCI_MSI_FLAGS; + msg_ctrl = dw_pcie_readw_dbi(pci, reg); has_upper = !!(msg_ctrl & PCI_MSI_FLAGS_64BIT); - msg_addr_lower = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_L32); + reg = ep->cap_addr.msi_addr + PCI_MSI_ADDRESS_LO; + msg_addr_lower = dw_pcie_readl_dbi(pci, reg); if (has_upper) { - msg_addr_upper = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_U32); - msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_64); + reg = ep->cap_addr.msi_addr + PCI_MSI_ADDRESS_HI; + msg_addr_upper = dw_pcie_readl_dbi(pci, reg); + reg = ep->cap_addr.msi_addr + PCI_MSI_DATA_64; + msg_data = dw_pcie_readw_dbi(pci, reg); } else { msg_addr_upper = 0; - msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_32); + reg = ep->cap_addr.msi_addr + PCI_MSI_DATA_32; + msg_data = dw_pcie_readw_dbi(pci, reg); } msg_addr = ((u64) msg_addr_upper) << 32 | msg_addr_lower; ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr, diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h index 456fd94..2acf18b0 100644 --- a/drivers/pci/dwc/pcie-designware.h +++ b/drivers/pci/dwc/pcie-designware.h @@ -96,17 +96,6 @@ #define PCIE_GET_ATU_INB_UNR_REG_OFFSET(region) \ ((0x3 << 20) | ((region) << 9) | (0x1 << 8)) -#define MSI_MESSAGE_CONTROL0x52 -#define MSI_CAP_MMC_SHIFT 1 -#define MSI_CAP_MMC_MASK (7 << MSI_CAP_MMC_SHIFT) -#define MSI_CAP_MME_SHIFT 4 -#define MSI_CAP_MSI_EN_MASK0x1 -#define MSI_CAP_MME_MASK (7 << MSI_CAP_MME_SHIFT) -#define MSI_MESSAGE_ADDR_L32 0x54 -#define MSI_MESSAGE_ADDR_U32 0x58
[RFC 02/10] PCI: cadence: Update cdns_pcie_ep_raise_irq function signature
Changes the cdns_pcie_ep_raise_irq function signature, namely the interrupt_num variable type from u8 to u16 to accommodate the MSI-X maximum interrupts of 2048. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/pci/cadence/pcie-cadence-ep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/cadence/pcie-cadence-ep.c b/drivers/pci/cadence/pcie-cadence-ep.c index 3d8283e..6d6322c 100644 --- a/drivers/pci/cadence/pcie-cadence-ep.c +++ b/drivers/pci/cadence/pcie-cadence-ep.c @@ -363,7 +363,7 @@ static int cdns_pcie_ep_send_msi_irq(struct cdns_pcie_ep *ep, u8 fn, } static int cdns_pcie_ep_raise_irq(struct pci_epc *epc, u8 fn, - enum pci_epc_irq_type type, u8 interrupt_num) + enum pci_epc_irq_type type, u16 interrupt_num) { struct cdns_pcie_ep *ep = epc_get_drvdata(epc); -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC 06/10] misc: pci_endpoint_test: Add MSI-X support
Adds the MSI-X support and updates driver documentation accordingly. Changes the driver parameter in order to allow the interruption type selection. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- Documentation/misc-devices/pci-endpoint-test.txt | 3 + drivers/misc/pci_endpoint_test.c | 102 +-- 2 files changed, 79 insertions(+), 26 deletions(-) diff --git a/Documentation/misc-devices/pci-endpoint-test.txt b/Documentation/misc-devices/pci-endpoint-test.txt index 4ebc359..fdfa0f6 100644 --- a/Documentation/misc-devices/pci-endpoint-test.txt +++ b/Documentation/misc-devices/pci-endpoint-test.txt @@ -10,6 +10,7 @@ The PCI driver for the test device performs the following tests *) verifying addresses programmed in BAR *) raise legacy IRQ *) raise MSI IRQ + *) raise MSI-X IRQ *) read data *) write data *) copy data @@ -25,6 +26,8 @@ ioctl PCITEST_LEGACY_IRQ: Tests legacy IRQ PCITEST_MSI: Tests message signalled interrupts. The MSI number to be tested should be passed as argument. + PCITEST_MSIX: Tests message signalled interrupts. The MSI-X number + to be tested should be passed as argument. PCITEST_WRITE: Perform write tests. The size of the buffer should be passed as argument. PCITEST_READ: Perform read tests. The size of the buffer should be passed diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 37db0fc..a7d9354 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -42,11 +42,16 @@ #define PCI_ENDPOINT_TEST_COMMAND 0x4 #define COMMAND_RAISE_LEGACY_IRQ BIT(0) #define COMMAND_RAISE_MSI_IRQ BIT(1) -#define MSI_NUMBER_SHIFT 2 -/* 6 bits for MSI number */ -#define COMMAND_READBIT(8) -#define COMMAND_WRITE BIT(9) -#define COMMAND_COPYBIT(10) +#define COMMAND_RAISE_MSIX_IRQ BIT(2) +#define IRQ_TYPE_SHIFT 3 +#define IRQ_TYPE_LEGACY0 +#define IRQ_TYPE_MSI 1 +#define IRQ_TYPE_MSIX 2 +#define MSI_NUMBER_SHIFT 5 +/* 12 bits for MSI number */ +#define COMMAND_READBIT(17) +#define COMMAND_WRITE BIT(18) +#define COMMAND_COPYBIT(19) #define PCI_ENDPOINT_TEST_STATUS 0x8 #define STATUS_READ_SUCCESS BIT(0) @@ -73,9 +78,9 @@ static DEFINE_IDA(pci_endpoint_test_ida); #define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \ miscdev) -static bool no_msi; -module_param(no_msi, bool, 0444); -MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test"); +static int irq_type = IRQ_TYPE_MSIX; +module_param(irq_type, int, 0444); +MODULE_PARM_DESC(irq_type, "IRQ mode selection in pci_endpoint_test (0 - Legacy, 1 - MSI, 2 - MSI-X)"); enum pci_barno { BAR_0, @@ -103,7 +108,7 @@ struct pci_endpoint_test { struct pci_endpoint_test_data { enum pci_barno test_reg_bar; size_t alignment; - bool no_msi; + int irq_type; }; static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test, @@ -177,10 +182,10 @@ static bool pci_endpoint_test_bar(struct pci_endpoint_test *test, static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test) { - u32 val; + u32 val = COMMAND_RAISE_LEGACY_IRQ; - pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, -COMMAND_RAISE_LEGACY_IRQ); + val |= (IRQ_TYPE_LEGACY << IRQ_TYPE_SHIFT); + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, val); val = wait_for_completion_timeout(>irq_raised, msecs_to_jiffies(1000)); if (!val) @@ -192,12 +197,12 @@ static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test) static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test, u8 msi_num) { - u32 val; + u32 val = COMMAND_RAISE_MSI_IRQ; struct pci_dev *pdev = test->pdev; - pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, -msi_num << MSI_NUMBER_SHIFT | -COMMAND_RAISE_MSI_IRQ); + val |= (msi_num << MSI_NUMBER_SHIFT); + val |= (IRQ_TYPE_MSI << IRQ_TYPE_SHIFT); + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, val); val = wait_for_completion_timeout(>irq_raised, msecs_to_jiffies(1000)); if (!val) @@ -209,6 +214,26 @@ static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test, return false; } +static boo
[RFC 10/10] tools: PCI: Add MSI-X support
Adds MSI-X support to the pcitest tool and modified the pcitest.sh script to accomodate this new type of interruption test. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- include/uapi/linux/pcitest.h | 1 + tools/pci/pcitest.c | 18 +- tools/pci/pcitest.sh | 25 + 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/pcitest.h b/include/uapi/linux/pcitest.h index 953cf03..d746fb1 100644 --- a/include/uapi/linux/pcitest.h +++ b/include/uapi/linux/pcitest.h @@ -16,5 +16,6 @@ #define PCITEST_WRITE _IOW('P', 0x4, unsigned long) #define PCITEST_READ _IOW('P', 0x5, unsigned long) #define PCITEST_COPY _IOW('P', 0x6, unsigned long) +#define PCITEST_MSIX _IOW('P', 0x7, int) #endif /* __UAPI_LINUX_PCITEST_H */ diff --git a/tools/pci/pcitest.c b/tools/pci/pcitest.c index 9074b47..9d145a3 100644 --- a/tools/pci/pcitest.c +++ b/tools/pci/pcitest.c @@ -37,6 +37,7 @@ struct pci_test { charbarnum; boollegacyirq; unsigned intmsinum; + unsigned intmsixnum; boolread; boolwrite; boolcopy; @@ -83,6 +84,15 @@ static int run_test(struct pci_test *test) fprintf(stdout, "%s\n", result[ret]); } + if (test->msixnum > 0 && test->msixnum <= 2048) { + ret = ioctl(fd, PCITEST_MSIX, test->msixnum); + fprintf(stdout, "MSI-X%d:\t\t", test->msixnum); + if (ret < 0) + fprintf(stdout, "TEST FAILED\n"); + else + fprintf(stdout, "%s\n", result[ret]); + } + if (test->write) { ret = ioctl(fd, PCITEST_WRITE, test->size); fprintf(stdout, "WRITE (%7ld bytes):\t\t", test->size); @@ -133,7 +143,7 @@ int main(int argc, char **argv) /* set default endpoint device */ test->device = "/dev/pci-endpoint-test.0"; - while ((c = getopt(argc, argv, "D:b:m:lrwcs:")) != EOF) + while ((c = getopt(argc, argv, "D:b:m:x:lrwcs:")) != EOF) switch (c) { case 'D': test->device = optarg; @@ -151,6 +161,11 @@ int main(int argc, char **argv) if (test->msinum < 1 || test->msinum > 32) goto usage; continue; + case 'x': + test->msixnum = atoi(optarg); + if (test->msixnum < 1 || test->msixnum > 2048) + goto usage; + continue; case 'r': test->read = true; continue; @@ -173,6 +188,7 @@ int main(int argc, char **argv) "\t-D PCI endpoint test device {default: /dev/pci-endpoint-test.0}\n" "\t-b BAR test (bar number between 0..5)\n" "\t-m MSI test (msi number between 1..32)\n" + "\t-x MSI-X test (msix number between 1..2048)\n" "\t-l Legacy IRQ test\n" "\t-r Read buffer test\n" "\t-w Write buffer test\n" diff --git a/tools/pci/pcitest.sh b/tools/pci/pcitest.sh index 77e8c85..86709a2 100644 --- a/tools/pci/pcitest.sh +++ b/tools/pci/pcitest.sh @@ -4,6 +4,8 @@ echo "BAR tests" echo +modprobe pci_endpoint_test +sleep 2 bar=0 while [ $bar -lt 6 ] @@ -16,7 +18,14 @@ echo echo "Interrupt tests" echo +rmmod pci_endpoint_test +sleep 2 +modprobe pci_endpoint_test irq_type=0 pcitest -l + +rmmod pci_endpoint_test +sleep 2 +modprobe pci_endpoint_test irq_type=1 msi=1 while [ $msi -lt 33 ] @@ -26,9 +35,25 @@ do done echo +rmmod pci_endpoint_test +sleep 2 +modprobe pci_endpoint_test irq_type=2 +msix=1 + +while [ $msix -lt 2049 ] +do +pcitest -x $msix +msix=`expr $msix + 1` +done +echo + echo "Read Tests" echo +rmmod pci_endpoint_test +sleep 2 +modprobe pci_endpoint_test irq_type=1 + pcitest -r -s 1 pcitest -r -s 1024 pcitest -r -s 1025 -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC 08/10] PCI: endpoint: functions/pci-epf-test: Add MSI-X support
Adds driver's MSI-X support. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/pci/endpoint/functions/pci-epf-test.c | 87 +-- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index 63dca44..5997c6e 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -20,11 +20,18 @@ #define COMMAND_RAISE_LEGACY_IRQ BIT(0) #define COMMAND_RAISE_MSI_IRQ BIT(1) -#define MSI_NUMBER_SHIFT 2 +#define COMMAND_RAISE_MSIX_IRQ BIT(2) +#define IRQ_TYPE_SHIFT 3 +#define MSI_NUMBER_SHIFT 5 +#define IRQ_TYPE_MASK (0x3 << IRQ_TYPE_SHIFT) +#define IRQ_TYPE_LEGACY0 +#define IRQ_TYPE_MSI 1 +#define IRQ_TYPE_MSIX 2 #define MSI_NUMBER_MASK(0x3f << MSI_NUMBER_SHIFT) -#define COMMAND_READ BIT(8) -#define COMMAND_WRITE BIT(9) -#define COMMAND_COPY BIT(10) +#define MSIX_NUMBER_MASK (0xfff << MSI_NUMBER_SHIFT) +#define COMMAND_READ BIT(17) +#define COMMAND_WRITE BIT(18) +#define COMMAND_COPY BIT(19) #define STATUS_READ_SUCCESSBIT(0) #define STATUS_READ_FAIL BIT(1) @@ -244,31 +251,44 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test) return ret; } -static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, u8 irq) +static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, u8 irq_type, + u16 irq) { - u8 msi_count; struct pci_epf *epf = epf_test->epf; + struct device *dev = >dev; struct pci_epc *epc = epf->epc; enum pci_barno test_reg_bar = epf_test->test_reg_bar; struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; reg->status |= STATUS_IRQ_RAISED; - msi_count = pci_epc_get_msi(epc, epf->func_no); - if (irq > msi_count || msi_count <= 0) - pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_LEGACY, 0); - else + + switch (irq_type) { + case IRQ_TYPE_LEGACY: + pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_LEGACY, irq); + break; + case IRQ_TYPE_MSI: pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_MSI, irq); + break; + case IRQ_TYPE_MSIX: + pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_MSIX, irq); + break; + default: + dev_err(dev, "Failed to raise IRQ, unknown type\n"); + break; + } } static void pci_epf_test_cmd_handler(struct work_struct *work) { int ret; - u8 irq; - u8 msi_count; + u16 irq; + u8 irq_type; + u16 msi_count; u32 command; struct pci_epf_test *epf_test = container_of(work, struct pci_epf_test, cmd_handler.work); struct pci_epf *epf = epf_test->epf; + struct device *dev = >dev; struct pci_epc *epc = epf->epc; enum pci_barno test_reg_bar = epf_test->test_reg_bar; struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; @@ -280,11 +300,25 @@ static void pci_epf_test_cmd_handler(struct work_struct *work) reg->command = 0; reg->status = 0; - irq = (command & MSI_NUMBER_MASK) >> MSI_NUMBER_SHIFT; + irq_type = (command & IRQ_TYPE_MASK) >> IRQ_TYPE_SHIFT; + switch (irq_type) { + case IRQ_TYPE_LEGACY: + irq = 0; + break; + case IRQ_TYPE_MSI: + irq = (command & MSI_NUMBER_MASK) >> MSI_NUMBER_SHIFT; + break; + case IRQ_TYPE_MSIX: + irq = (command & MSIX_NUMBER_MASK) >> MSI_NUMBER_SHIFT; + break; + default: + dev_err(dev, "Failed to detect IRQ type\n"); + goto reset_handler; + } if (command & COMMAND_RAISE_LEGACY_IRQ) { reg->status = STATUS_IRQ_RAISED; - pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_LEGACY, 0); + pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_LEGACY, irq); goto reset_handler; } @@ -294,7 +328,7 @@ static void pci_epf_test_cmd_handler(struct work_struct *work) reg->status |= STATUS_WRITE_FAIL; else reg->status |= STATUS_WRITE_SUCCESS; - pci_epf_test_raise_irq(epf_test, irq); + pci_epf_test_raise_irq(epf_test, irq_type, ir
[RFC 09/10] PCI: endpoint: functions/pci-epf-test: Replace lower into upper case characters
Replaces lower into upper case characters in comments and debug printks. Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> --- drivers/pci/endpoint/functions/pci-epf-test.c | 26 +- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index 5997c6e..e3d4af0 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -94,7 +94,7 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) src_addr = pci_epc_mem_alloc_addr(epc, _phys_addr, reg->size); if (!src_addr) { - dev_err(dev, "failed to allocate source address\n"); + dev_err(dev, "Failed to allocate source address\n"); reg->status = STATUS_SRC_ADDR_INVALID; ret = -ENOMEM; goto err; @@ -103,14 +103,14 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) ret = pci_epc_map_addr(epc, epf->func_no, src_phys_addr, reg->src_addr, reg->size); if (ret) { - dev_err(dev, "failed to map source address\n"); + dev_err(dev, "Failed to map source address\n"); reg->status = STATUS_SRC_ADDR_INVALID; goto err_src_addr; } dst_addr = pci_epc_mem_alloc_addr(epc, _phys_addr, reg->size); if (!dst_addr) { - dev_err(dev, "failed to allocate destination address\n"); + dev_err(dev, "Failed to allocate destination address\n"); reg->status = STATUS_DST_ADDR_INVALID; ret = -ENOMEM; goto err_src_map_addr; @@ -119,7 +119,7 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) ret = pci_epc_map_addr(epc, epf->func_no, dst_phys_addr, reg->dst_addr, reg->size); if (ret) { - dev_err(dev, "failed to map destination address\n"); + dev_err(dev, "Failed to map destination address\n"); reg->status = STATUS_DST_ADDR_INVALID; goto err_dst_addr; } @@ -156,7 +156,7 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test) src_addr = pci_epc_mem_alloc_addr(epc, _addr, reg->size); if (!src_addr) { - dev_err(dev, "failed to allocate address\n"); + dev_err(dev, "Failed to allocate address\n"); reg->status = STATUS_SRC_ADDR_INVALID; ret = -ENOMEM; goto err; @@ -165,7 +165,7 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test) ret = pci_epc_map_addr(epc, epf->func_no, phys_addr, reg->src_addr, reg->size); if (ret) { - dev_err(dev, "failed to map address\n"); + dev_err(dev, "Failed to map address\n"); reg->status = STATUS_SRC_ADDR_INVALID; goto err_addr; } @@ -208,7 +208,7 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test) dst_addr = pci_epc_mem_alloc_addr(epc, _addr, reg->size); if (!dst_addr) { - dev_err(dev, "failed to allocate address\n"); + dev_err(dev, "Failed to allocate address\n"); reg->status = STATUS_DST_ADDR_INVALID; ret = -ENOMEM; goto err; @@ -217,7 +217,7 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test) ret = pci_epc_map_addr(epc, epf->func_no, phys_addr, reg->dst_addr, reg->size); if (ret) { - dev_err(dev, "failed to map address\n"); + dev_err(dev, "Failed to map address\n"); reg->status = STATUS_DST_ADDR_INVALID; goto err_addr; } @@ -422,7 +422,7 @@ static int pci_epf_test_set_bar(struct pci_epf *epf) ret = pci_epc_set_bar(epc, epf->func_no, epf_bar); if (ret) { pci_epf_free_space(epf, epf_test->reg[bar], bar); - dev_err(dev, "failed to set BAR%d\n", bar); + dev_err(dev, "Failed to set BAR%d\n", bar); if (bar == test_reg_bar) return ret; } @@ -449,7 +449,7 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf) base = pci_epf_alloc_space(epf, sizeof(struct pci_epf_test_reg), test_reg_bar); if (!base) { - dev_err(dev, "failed to allocated register space\n"); + dev_err(dev, "Fail
Re: [RFC 03/10] PCI: endpoint: Add MSI-X interfaces
Hi Kishon, On 17/04/2018 11:24, Kishon Vijay Abraham I wrote: > Hi, > > On Tuesday 10 April 2018 10:44 PM, Gustavo Pimentel wrote: >> Implements the generic method for calling the get/set callbacks. >> >> Adds the PCI_EPC_IRQ_MSIX type. >> >> Adds the MSI-X callbacks signatures to the ops structure. >> >> Adds sysfs interface for altering the number of MSI-X entries. >> >> Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> >> --- >> drivers/pci/endpoint/pci-ep-cfs.c | 24 >> drivers/pci/endpoint/pci-epc-core.c | 57 >> + >> include/linux/pci-epc.h | 11 ++- >> include/linux/pci-epf.h | 1 + >> 4 files changed, 92 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/pci/endpoint/pci-ep-cfs.c >> b/drivers/pci/endpoint/pci-ep-cfs.c >> index 018ea34..d1288a0 100644 >> --- a/drivers/pci/endpoint/pci-ep-cfs.c >> +++ b/drivers/pci/endpoint/pci-ep-cfs.c >> @@ -286,6 +286,28 @@ static ssize_t pci_epf_msi_interrupts_show(struct >> config_item *item, >> to_pci_epf_group(item)->epf->msi_interrupts); >> } >> >> +static ssize_t pci_epf_msix_interrupts_store(struct config_item *item, >> + const char *page, size_t len) >> +{ >> +u16 val; >> +int ret; >> + >> +ret = kstrtou16(page, 0, ); >> +if (ret) >> +return ret; >> + >> +to_pci_epf_group(item)->epf->msix_interrupts = val; >> + >> +return len; >> +} >> + >> +static ssize_t pci_epf_msix_interrupts_show(struct config_item *item, >> +char *page) >> +{ >> +return sprintf(page, "%d\n", >> + to_pci_epf_group(item)->epf->msix_interrupts); >> +} >> + >> PCI_EPF_HEADER_R(vendorid) >> PCI_EPF_HEADER_W_u16(vendorid) >> >> @@ -327,6 +349,7 @@ CONFIGFS_ATTR(pci_epf_, subsys_vendor_id); >> CONFIGFS_ATTR(pci_epf_, subsys_id); >> CONFIGFS_ATTR(pci_epf_, interrupt_pin); >> CONFIGFS_ATTR(pci_epf_, msi_interrupts); >> +CONFIGFS_ATTR(pci_epf_, msix_interrupts); >> >> static struct configfs_attribute *pci_epf_attrs[] = { >> _epf_attr_vendorid, >> @@ -340,6 +363,7 @@ static struct configfs_attribute *pci_epf_attrs[] = { >> _epf_attr_subsys_id, >> _epf_attr_interrupt_pin, >> _epf_attr_msi_interrupts, >> +_epf_attr_msix_interrupts, >> NULL, >> }; >> >> diff --git a/drivers/pci/endpoint/pci-epc-core.c >> b/drivers/pci/endpoint/pci-epc-core.c >> index b0ee427..294a383 100644 >> --- a/drivers/pci/endpoint/pci-epc-core.c >> +++ b/drivers/pci/endpoint/pci-epc-core.c >> @@ -218,6 +218,63 @@ int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 >> interrupts) >> EXPORT_SYMBOL_GPL(pci_epc_set_msi); >> >> /** >> + * pci_epc_get_msix() - get the number of MSI-X interrupt numbers allocated >> + * @epc: the EPC device to which MSI-X interrupts was requested >> + * @func_no: the endpoint function number in the EPC device >> + * >> + * Invoke to get the number of MSI-X interrupts allocated by the RC >> + */ >> +int pci_epc_get_msix(struct pci_epc *epc, u8 func_no) >> +{ >> +int interrupt; >> +unsigned long flags; >> + >> +if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) >> +return 0; >> + >> +if (!epc->ops->get_msix) >> +return 0; >> + >> +spin_lock_irqsave(>lock, flags); >> +interrupt = epc->ops->get_msix(epc, func_no); >> +spin_unlock_irqrestore(>lock, flags); >> + >> +if (interrupt < 0) >> +return 0; >> + >> +return interrupt++; > > return interrupt + 1? I'll change it. >> +} >> +EXPORT_SYMBOL_GPL(pci_epc_get_msix); >> + >> +/** >> + * pci_epc_set_msix() - set the number of MSI-X interrupt numbers required >> + * @epc: the EPC device on which MSI-X has to be configured >> + * @func_no: the endpoint function number in the EPC device >> + * @interrupts: number of MSI-X interrupts required by the EPF >> + * >> + * Invoke to set the required number of MSI-X interrupts. >> + */ >> +int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts) >> +{ >> +int ret; >> +unsigned long flags; >> + >> +if (IS_ERR_OR_NULL(
Re: [RFC 10/10] tools: PCI: Add MSI-X support
Hi Alan, On 24/04/2018 10:57, Alan Douglas wrote: > Hi Gustavo, > > On 10 April 2018 18:15, Gustavo Pimentel wrote: >> Adds MSI-X support to the pcitest tool and modified the pcitest.sh script to >> accomodate this new type of interruption test. >> >> Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> >> --- >> include/uapi/linux/pcitest.h | 1 + >> tools/pci/pcitest.c | 18 +- >> tools/pci/pcitest.sh | 25 + >> 3 files changed, 43 insertions(+), 1 deletion(-) > I found some possible problems when testing with the Cadence EP driver. The > problem > is that pcitest uses the BARs for tests, but we also use one for the MSI-X > tables > > In Cadence core the MSI-X table is in BAR0 by default, but this is configured > to a size > of 0x80 in the test driver, since it is used as the test_reg_bar. So, I > changed the > configuration to use BAR4 instead, which is configured to a size of 131072 > in pci-efp-test.c, and this gives me enough space. > > However, if I run the BAR tests in pcitest before running the MSI-X tests, the > MSI-X tests fail, since the BAR content is overwritten. It's not a problem > with the > scenario in pcitest.sh, but it would be if the module wasn't re-loaded. > > So, wondering if we need to come up with some mechanism to specify that a > specific > BAR will be used for MSI-X, and that its size and content shouldn't be > modified by > pcitest? I see your point. I have bypassed the problem by doing the module load/unload (to avoid having to fight on multiple fronts). I like your suggestion. Maybe we could have a bool variable for each BARs that could be set to false if a resource have intent to use it. However this change must be accepted by Kishon. > > Regards, > Alan > Regards, Gustavo -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC 01/10] PCI: dwc: Add MSI-X callbacks handler
Hi Kishon, On 16/04/2018 10:29, Kishon Vijay Abraham I wrote: > Hi Gustavo, > > On Tuesday 10 April 2018 10:44 PM, Gustavo Pimentel wrote: >> Changes the pcie_raise_irq function signature, namely the interrupt_num >> variable type from u8 to u16 to accommodate the MSI-X maximum interrupts >> of 2048. >> >> Implements a PCIe config space capability iterator function to search and >> save the MSI and MSI-X pointers. With this method the code becomes more >> generic and flexible. >> >> Implements MSI-X set/get functions for sysfs interface in order to change >> the EP entries number. >> >> Implements EP MSI-X interface for triggering interruptions. >> >> Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> >> --- >> drivers/pci/dwc/pci-dra7xx.c | 2 +- >> drivers/pci/dwc/pcie-artpec6.c | 2 +- >> drivers/pci/dwc/pcie-designware-ep.c | 145 >> - >> drivers/pci/dwc/pcie-designware-plat.c | 6 +- >> drivers/pci/dwc/pcie-designware.h | 23 +- >> 5 files changed, 173 insertions(+), 5 deletions(-) >> >> diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c >> index ed8558d..5265725 100644 >> --- a/drivers/pci/dwc/pci-dra7xx.c >> +++ b/drivers/pci/dwc/pci-dra7xx.c >> @@ -369,7 +369,7 @@ static void dra7xx_pcie_raise_msi_irq(struct dra7xx_pcie >> *dra7xx, >> } >> >> static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, >> - enum pci_epc_irq_type type, u8 interrupt_num) >> + enum pci_epc_irq_type type, u16 interrupt_num) >> { >> struct dw_pcie *pci = to_dw_pcie_from_ep(ep); >> struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); >> diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c >> index e66cede..96dc259 100644 >> --- a/drivers/pci/dwc/pcie-artpec6.c >> +++ b/drivers/pci/dwc/pcie-artpec6.c >> @@ -428,7 +428,7 @@ static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep) >> } >> >> static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, >> - enum pci_epc_irq_type type, u8 interrupt_num) >> + enum pci_epc_irq_type type, u16 interrupt_num) >> { >> struct dw_pcie *pci = to_dw_pcie_from_ep(ep); >> >> diff --git a/drivers/pci/dwc/pcie-designware-ep.c >> b/drivers/pci/dwc/pcie-designware-ep.c >> index 15b22a6..874d4c2 100644 >> --- a/drivers/pci/dwc/pcie-designware-ep.c >> +++ b/drivers/pci/dwc/pcie-designware-ep.c >> @@ -40,6 +40,44 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum >> pci_barno bar) >> __dw_pcie_ep_reset_bar(pci, bar, 0); >> } >> >> +void dw_pcie_ep_find_cap_addr(struct dw_pcie_ep *ep) >> +{ > > This should be implemented in a generic way similar to pci_find_capability(). > It'll be useful when we try to implement other capabilities as well. Hum, what you suggest? Something implemented on the pci-epf-core? > > Thanks > Kishon > Regards, Gustavo -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC 06/10] misc: pci_endpoint_test: Add MSI-X support
Hi Kishon, On 24/04/2018 08:19, Kishon Vijay Abraham I wrote: > Hi, > > On Tuesday 17 April 2018 11:08 PM, Gustavo Pimentel wrote: >> Hi Kishon, >> >> On 17/04/2018 11:33, Kishon Vijay Abraham I wrote: >>> Hi, >>> >>> On Tuesday 10 April 2018 10:44 PM, Gustavo Pimentel wrote: >>>> Adds the MSI-X support and updates driver documentation accordingly. >>>> >>>> Changes the driver parameter in order to allow the interruption type >>>> selection. >>>> >>>> Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> >>>> --- >>>> Documentation/misc-devices/pci-endpoint-test.txt | 3 + >>>> drivers/misc/pci_endpoint_test.c | 102 >>>> +-- >>>> 2 files changed, 79 insertions(+), 26 deletions(-) >>>> >>>> diff --git a/Documentation/misc-devices/pci-endpoint-test.txt >>>> b/Documentation/misc-devices/pci-endpoint-test.txt >>>> index 4ebc359..fdfa0f6 100644 >>>> --- a/Documentation/misc-devices/pci-endpoint-test.txt >>>> +++ b/Documentation/misc-devices/pci-endpoint-test.txt >>>> @@ -10,6 +10,7 @@ The PCI driver for the test device performs the >>>> following tests >>>>*) verifying addresses programmed in BAR >>>>*) raise legacy IRQ >>>>*) raise MSI IRQ >>>> + *) raise MSI-X IRQ >>>>*) read data >>>>*) write data >>>>*) copy data >>>> @@ -25,6 +26,8 @@ ioctl >>>> PCITEST_LEGACY_IRQ: Tests legacy IRQ >>>> PCITEST_MSI: Tests message signalled interrupts. The MSI number >>>> to be tested should be passed as argument. >>>> + PCITEST_MSIX: Tests message signalled interrupts. The MSI-X number >>>> +to be tested should be passed as argument. >>>> PCITEST_WRITE: Perform write tests. The size of the buffer should be >>>> passed >>>>as argument. >>>> PCITEST_READ: Perform read tests. The size of the buffer should be passed >>>> diff --git a/drivers/misc/pci_endpoint_test.c >>>> b/drivers/misc/pci_endpoint_test.c >>>> index 37db0fc..a7d9354 100644 >>>> --- a/drivers/misc/pci_endpoint_test.c >>>> +++ b/drivers/misc/pci_endpoint_test.c >>>> @@ -42,11 +42,16 @@ >>>> #define PCI_ENDPOINT_TEST_COMMAND 0x4 >>>> #define COMMAND_RAISE_LEGACY_IRQ BIT(0) >>>> #define COMMAND_RAISE_MSI_IRQ BIT(1) >>>> -#define MSI_NUMBER_SHIFT 2 >>>> -/* 6 bits for MSI number */ >>>> -#define COMMAND_READBIT(8) >>>> -#define COMMAND_WRITE BIT(9) >>>> -#define COMMAND_COPYBIT(10) >>>> +#define COMMAND_RAISE_MSIX_IRQBIT(2) >>>> +#define IRQ_TYPE_SHIFT3 >>>> +#define IRQ_TYPE_LEGACY 0 >>>> +#define IRQ_TYPE_MSI 1 >>>> +#define IRQ_TYPE_MSIX 2 >>>> +#define MSI_NUMBER_SHIFT 5 >>> >>> Now that you are anyways fixing this, add a new register entry for MSI >>> numbers. >>> Let's not keep COMMAND and MSI's together. >> >> What you suggest? > > #define PCI_ENDPOINT_TEST_COMMAND 0x4 > #define COMMAND_RAISE_LEGACY_IRQ BIT(0) > #define COMMAND_RAISE_MSI_IRQ BIT(1) > #define COMMAND_RAISE_MSIX_IRQBIT(2) > #define COMMAND_READBIT(3) > #define COMMAND_WRITE BIT(4) > #define COMMAND_COPYBIT(5) > > #define PCI_ENDPOINT_TEST_STATUS 0x8 > #define STATUS_READ_SUCCESS BIT(0) > #define STATUS_READ_FAILBIT(1) > #define STATUS_WRITE_SUCCESSBIT(2) > #define STATUS_WRITE_FAIL BIT(3) > #define STATUS_COPY_SUCCESS BIT(4) > #define STATUS_COPY_FAILBIT(5) > #define STATUS_IRQ_RAISED BIT(6) > #define STATUS_SRC_ADDR_INVALID BIT(7) > #define STATUS_DST_ADDR_INVALID BIT(8) > > #define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0xc > #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10 > > #define PCI_ENDPOINT_TEST_LOWER_DST_ADDR 0x14 > #define PCI_ENDPOINT_TEST_UPPER_DST_ADDR 0x18 > > #define PCI_ENDPOINT_TEST_SIZE0x1c > #define PCI_ENDPOINT_TEST_CHECKSUM0x20 > > #define PCI_END
Re: [RFC 01/10] PCI: dwc: Add MSI-X callbacks handler
Hi Kishon, On 24/04/2018 08:07, Kishon Vijay Abraham I wrote: > Hi, > > On Monday 23 April 2018 03:06 PM, Gustavo Pimentel wrote: >> Hi Kishon, >> >> On 16/04/2018 10:29, Kishon Vijay Abraham I wrote: >>> Hi Gustavo, >>> >>> On Tuesday 10 April 2018 10:44 PM, Gustavo Pimentel wrote: >>>> Changes the pcie_raise_irq function signature, namely the interrupt_num >>>> variable type from u8 to u16 to accommodate the MSI-X maximum interrupts >>>> of 2048. >>>> >>>> Implements a PCIe config space capability iterator function to search and >>>> save the MSI and MSI-X pointers. With this method the code becomes more >>>> generic and flexible. >>>> >>>> Implements MSI-X set/get functions for sysfs interface in order to change >>>> the EP entries number. >>>> >>>> Implements EP MSI-X interface for triggering interruptions. >>>> >>>> Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> >>>> --- >>>> drivers/pci/dwc/pci-dra7xx.c | 2 +- >>>> drivers/pci/dwc/pcie-artpec6.c | 2 +- >>>> drivers/pci/dwc/pcie-designware-ep.c | 145 >>>> - >>>> drivers/pci/dwc/pcie-designware-plat.c | 6 +- >>>> drivers/pci/dwc/pcie-designware.h | 23 +- >>>> 5 files changed, 173 insertions(+), 5 deletions(-) >>>> >>>> diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c >>>> index ed8558d..5265725 100644 >>>> --- a/drivers/pci/dwc/pci-dra7xx.c >>>> +++ b/drivers/pci/dwc/pci-dra7xx.c >>>> @@ -369,7 +369,7 @@ static void dra7xx_pcie_raise_msi_irq(struct >>>> dra7xx_pcie *dra7xx, >>>> } >>>> >>>> static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, >>>> - enum pci_epc_irq_type type, u8 interrupt_num) >>>> + enum pci_epc_irq_type type, u16 interrupt_num) >>>> { >>>>struct dw_pcie *pci = to_dw_pcie_from_ep(ep); >>>>struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); >>>> diff --git a/drivers/pci/dwc/pcie-artpec6.c >>>> b/drivers/pci/dwc/pcie-artpec6.c >>>> index e66cede..96dc259 100644 >>>> --- a/drivers/pci/dwc/pcie-artpec6.c >>>> +++ b/drivers/pci/dwc/pcie-artpec6.c >>>> @@ -428,7 +428,7 @@ static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep) >>>> } >>>> >>>> static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, >>>> -enum pci_epc_irq_type type, u8 interrupt_num) >>>> +enum pci_epc_irq_type type, u16 interrupt_num) >>>> { >>>>struct dw_pcie *pci = to_dw_pcie_from_ep(ep); >>>> >>>> diff --git a/drivers/pci/dwc/pcie-designware-ep.c >>>> b/drivers/pci/dwc/pcie-designware-ep.c >>>> index 15b22a6..874d4c2 100644 >>>> --- a/drivers/pci/dwc/pcie-designware-ep.c >>>> +++ b/drivers/pci/dwc/pcie-designware-ep.c >>>> @@ -40,6 +40,44 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum >>>> pci_barno bar) >>>>__dw_pcie_ep_reset_bar(pci, bar, 0); >>>> } >>>> >>>> +void dw_pcie_ep_find_cap_addr(struct dw_pcie_ep *ep) >>>> +{ >>> >>> This should be implemented in a generic way similar to >>> pci_find_capability(). >>> It'll be useful when we try to implement other capabilities as well. >> >> Hum, what you suggest? Something implemented on the pci-epf-core? > > yeah, Initially thought it could be implemented as a helper function in > pci-epc-core so that both designware and cadence can use it. That would be nice, however I couldn't find out how to access the config space, through the pci_epf or pci_epc structs. So, I reworked the functions like this: (on pcie-designware-ep.c) u8 __dw_pcie_ep_find_next_cap(struct dw_pcie *pci, u8 cap_ptr, u8 cap) { u8 cap_id, next_cap_ptr; u16 reg; reg = dw_pcie_readw_dbi(pci, cap_ptr); next_cap_ptr = (reg & 0xff00) >> 8; cap_id = (reg & 0x00ff); if (!next_cap_ptr || cap_id > PCI_CAP_ID_MAX) return 0; if (cap_id == cap) return cap_ptr; return __dw_pcie_ep_find_next_cap(pci, next_cap_ptr, cap); } u8 dw_pcie_ep_find_capability(struct dw_pcie *pci,
Re: [RFC 00/10] Adds pcitest tool support for MSI-X
Hi Alan, On 24/04/2018 07:48, Alan Douglas wrote: > Hi Gustavo, > > On 10 April 2018 18:15 Gustavo Pimentel wrote: >> This patch set depends the following series: >> https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.org_lkml_2018_4_10_421=DwIFAg=DPL6_X_6JkXFx7AXWqB0tg=bkWxpLoW-f-E3EdiDCCa0_h0PicsViasSlvIpzZvPxs=R3h7a4AkN9--FFv6jtHaknKIzx6NieDdkYxyCe4obB8=J2A11L2_WwzMdaBheYSTwfjPDA7sx3_DyoGPAYsJ9A4=> >> This series aims to add pcitest tool support for MSI-X. >> >> Includes new callbacks methods and handlers to trigger the MSI-X >> interruptions on the EP Designware IP driver. >> >> Provides new methods on pci_epf_test driver that allows to set/get EP >> maximum number of MSI-X entries (similar to set/get MSI methods). >> >> Reworks on MSI set/get and triggering methods on EP Designware IP driver to >> be more generic and flexible. >> >> Adds a new input parameter (msix) and replicates the whole MSI mechanism >> applied to the MSI-X feature on pcitest tool. Also updates the pcitest script >> with the new test set applied to this new feature. >> >> Gustavo Pimentel (10): >> PCI: dwc: Add MSI-X callbacks handler >> PCI: cadence: Update cdns_pcie_ep_raise_irq function signature >> PCI: endpoint: Add MSI-X interfaces >> PCI: dwc: MSI callbacks handler rework >> PCI: dwc: Add legacy interrupt callback handler >> misc: pci_endpoint_test: Add MSI-X support >> misc: pci_endpoint_test: Replace lower into upper case characters >> PCI: endpoint: functions/pci-epf-test: Add MSI-X support >> PCI: endpoint: functions/pci-epf-test: Replace lower into upper case >> characters >> tools: PCI: Add MSI-X support >> >> Documentation/misc-devices/pci-endpoint-test.txt | 3 + >> drivers/misc/pci_endpoint_test.c | 120 ++ >> drivers/pci/cadence/pcie-cadence-ep.c| 2 +- >> drivers/pci/dwc/pci-dra7xx.c | 2 +- >> drivers/pci/dwc/pcie-artpec6.c | 2 +- >> drivers/pci/dwc/pcie-designware-ep.c | 201 >> +-- >> drivers/pci/dwc/pcie-designware-plat.c | 9 +- >> drivers/pci/dwc/pcie-designware.h| 40 +++-- >> drivers/pci/endpoint/functions/pci-epf-test.c| 113 + >> drivers/pci/endpoint/pci-ep-cfs.c| 24 +++ >> drivers/pci/endpoint/pci-epc-core.c | 60 ++- >> include/linux/pci-epc.h | 11 +- >> include/linux/pci-epf.h | 1 + >> include/uapi/linux/pcitest.h | 1 + >> tools/pci/pcitest.c | 18 +- >> tools/pci/pcitest.sh | 25 +++ >> 16 files changed, 528 insertions(+), 104 deletions(-) >> >> -- >> 2.7.4 >> > Nice set of patches. I have tested this with the Cadence EP driver after > adding MSI-X support, and found a few changes required. > I will send you comments. Ok, great news! Maybe after this patch series submission we could start a new thread about new features that could be tested/verified using pcitest. I think this could be helpful for everybody. > > Thanks, > Alan > Thanks, Gustavo -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC 06/10] misc: pci_endpoint_test: Add MSI-X support
Hi Alan, On 24/04/2018 07:59, Alan Douglas wrote: > Hi Gustavo, > > On 10 April 2018 18:15 Gustavo Pimentel wrote: >> >> Adds the MSI-X support and updates driver documentation accordingly. >> >> Changes the driver parameter in order to allow the interruption type >> selection. >> >> Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> >> --- >> Documentation/misc-devices/pci-endpoint-test.txt | 3 + >> drivers/misc/pci_endpoint_test.c | 102 >> +-- >> 2 files changed, 79 insertions(+), 26 deletions(-) >> >> diff --git a/Documentation/misc-devices/pci-endpoint-test.txt >> b/Documentation/misc-devices/pci-endpoint-test.txt >> index 4ebc359..fdfa0f6 100644 >> --- a/Documentation/misc-devices/pci-endpoint-test.txt >> +++ b/Documentation/misc-devices/pci-endpoint-test.txt >> @@ -10,6 +10,7 @@ The PCI driver for the test device performs the >> following tests >> *) verifying addresses programmed in BAR >> *) raise legacy IRQ >> *) raise MSI IRQ >> +*) raise MSI-X IRQ >> *) read data >> *) write data >> *) copy data >> @@ -25,6 +26,8 @@ ioctl >> PCITEST_LEGACY_IRQ: Tests legacy IRQ >> PCITEST_MSI: Tests message signalled interrupts. The MSI number >>to be tested should be passed as argument. >> + PCITEST_MSIX: Tests message signalled interrupts. The MSI-X number >> + to be tested should be passed as argument. >> PCITEST_WRITE: Perform write tests. The size of the buffer should be passed >> as argument. >> PCITEST_READ: Perform read tests. The size of the buffer should be passed >> diff --git a/drivers/misc/pci_endpoint_test.c >> b/drivers/misc/pci_endpoint_test.c >> index 37db0fc..a7d9354 100644 >> --- a/drivers/misc/pci_endpoint_test.c >> +++ b/drivers/misc/pci_endpoint_test.c >> @@ -42,11 +42,16 @@ >> #define PCI_ENDPOINT_TEST_COMMAND 0x4 >> #define COMMAND_RAISE_LEGACY_IRQBIT(0) >> #define COMMAND_RAISE_MSI_IRQ BIT(1) >> -#define MSI_NUMBER_SHIFT2 >> -/* 6 bits for MSI number */ >> -#define COMMAND_READBIT(8) >> -#define COMMAND_WRITE BIT(9) >> -#define COMMAND_COPYBIT(10) >> +#define COMMAND_RAISE_MSIX_IRQ BIT(2) >> +#define IRQ_TYPE_SHIFT 3 >> +#define IRQ_TYPE_LEGACY 0 >> +#define IRQ_TYPE_MSI1 >> +#define IRQ_TYPE_MSIX 2 >> +#define MSI_NUMBER_SHIFT5 >> +/* 12 bits for MSI number */ >> +#define COMMAND_READBIT(17) >> +#define COMMAND_WRITE BIT(18) >> +#define COMMAND_COPYBIT(19) >> >> #define PCI_ENDPOINT_TEST_STATUS0x8 >> #define STATUS_READ_SUCCESS BIT(0) >> @@ -73,9 +78,9 @@ static DEFINE_IDA(pci_endpoint_test_ida); >> #define to_endpoint_test(priv) container_of((priv), struct >> pci_endpoint_test, >> \ >> miscdev) >> >> -static bool no_msi; >> -module_param(no_msi, bool, 0444); >> -MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in >> pci_endpoint_test"); >> +static int irq_type = IRQ_TYPE_MSIX; >> +module_param(irq_type, int, 0444); >> +MODULE_PARM_DESC(irq_type, "IRQ mode selection in pci_endpoint_test >> (0 >> +- Legacy, 1 - MSI, 2 - MSI-X)"); >> >> enum pci_barno { >> BAR_0, >> @@ -103,7 +108,7 @@ struct pci_endpoint_test { struct >> pci_endpoint_test_data { >> enum pci_barno test_reg_bar; >> size_t alignment; >> -bool no_msi; >> +int irq_type; >> }; >> >> static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test, >> @@ -177,10 +182,10 @@ static bool pci_endpoint_test_bar(struct >> pci_endpoint_test *test, >> >> static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test) { >> -u32 val; >> +u32 val = COMMAND_RAISE_LEGACY_IRQ; >> >> -pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, >> - COMMAND_RAISE_LEGACY_IRQ); >> +val |= (IRQ_TYPE_LEGACY << IRQ_TYPE_SHIFT); >> +pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, val); >> val = wait_for_completion_timeout(>irq_raised, >>msecs_to_jiffies(1000)); >> if (!val) >> @@ -192,
Re: [RFC 01/10] PCI: dwc: Add MSI-X callbacks handler
On 24/04/2018 10:15, Alan Douglas wrote: > Hi, > > On 10 April 2018 18:15 Gustavo Pimentel wrote: >> Changes the pcie_raise_irq function signature, namely the interrupt_num >> variable type from u8 to u16 to accommodate the MSI-X maximum interrupts >> of 2048. >> >> Implements a PCIe config space capability iterator function to search and >> save >> the MSI and MSI-X pointers. With this method the code becomes more >> generic and flexible. >> >> Implements MSI-X set/get functions for sysfs interface in order to change the >> EP entries number. >> >> Implements EP MSI-X interface for triggering interruptions. >> >> Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> >> --- >> drivers/pci/dwc/pci-dra7xx.c | 2 +- >> drivers/pci/dwc/pcie-artpec6.c | 2 +- >> drivers/pci/dwc/pcie-designware-ep.c | 145 >> - >> drivers/pci/dwc/pcie-designware-plat.c | 6 +- >> drivers/pci/dwc/pcie-designware.h | 23 +- >> 5 files changed, 173 insertions(+), 5 deletions(-) >> >> diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c >> index >> ed8558d..5265725 100644 >> --- a/drivers/pci/dwc/pci-dra7xx.c >> +++ b/drivers/pci/dwc/pci-dra7xx.c >> @@ -369,7 +369,7 @@ static void dra7xx_pcie_raise_msi_irq(struct >> dra7xx_pcie *dra7xx, } >> >> static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, >> - enum pci_epc_irq_type type, u8 >> interrupt_num) >> + enum pci_epc_irq_type type, u16 >> interrupt_num) >> { >> struct dw_pcie *pci = to_dw_pcie_from_ep(ep); >> struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); diff --git >> a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index >> e66cede..96dc259 100644 >> --- a/drivers/pci/dwc/pcie-artpec6.c >> +++ b/drivers/pci/dwc/pcie-artpec6.c >> @@ -428,7 +428,7 @@ static void artpec6_pcie_ep_init(struct dw_pcie_ep >> *ep) } >> >> static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, >> - enum pci_epc_irq_type type, u8 >> interrupt_num) >> + enum pci_epc_irq_type type, u16 >> interrupt_num) >> { >> struct dw_pcie *pci = to_dw_pcie_from_ep(ep); >> >> diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie- >> designware-ep.c >> index 15b22a6..874d4c2 100644 >> --- a/drivers/pci/dwc/pcie-designware-ep.c >> +++ b/drivers/pci/dwc/pcie-designware-ep.c >> @@ -40,6 +40,44 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, >> enum pci_barno bar) >> __dw_pcie_ep_reset_bar(pci, bar, 0); >> } >> >> +void dw_pcie_ep_find_cap_addr(struct dw_pcie_ep *ep) { >> +struct dw_pcie *pci = to_dw_pcie_from_ep(ep); >> +u8 next_ptr, curr_ptr, cap_id; >> +u16 reg; >> + >> +memset(>cap_addr, 0, sizeof(ep->cap_addr)); >> + >> +reg = dw_pcie_readw_dbi(pci, PCI_STATUS); >> +if (!(reg & PCI_STATUS_CAP_LIST)) >> +return; >> + >> +reg = dw_pcie_readw_dbi(pci, PCI_CAPABILITY_LIST); >> +next_ptr = (reg & 0x00ff); >> +if (!next_ptr) >> +return; >> + >> +reg = dw_pcie_readw_dbi(pci, next_ptr); >> +curr_ptr = next_ptr; >> +next_ptr = (reg & 0xff00) >> 8; >> +cap_id = (reg & 0x00ff); >> + >> +while (next_ptr && (cap_id <= PCI_CAP_ID_MAX)) { >> +switch (cap_id) { >> +case PCI_CAP_ID_MSI: >> +ep->cap_addr.msi_addr = curr_ptr; >> +break; >> +case PCI_CAP_ID_MSIX: >> +ep->cap_addr.msix_addr = curr_ptr; >> +break; >> +} >> +reg = dw_pcie_readw_dbi(pci, next_ptr); >> +curr_ptr = next_ptr; >> +next_ptr = (reg & 0xff00) >> 8; >> +cap_id = (reg & 0x00ff); >> +} >> +} >> + >> static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, >> struct pci_epf_header *hdr) >> { >> @@ -241,8 +279,47 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, >> u8 func_no, u8 encode_int) >> return 0; >> } >> >> +static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no) { >> +struct dw_pcie_ep *ep = epc_get_drvdat
Re: [RFC 06/10] misc: pci_endpoint_test: Add MSI-X support
Hi Kishon, On 17/04/2018 11:33, Kishon Vijay Abraham I wrote: > Hi, > > On Tuesday 10 April 2018 10:44 PM, Gustavo Pimentel wrote: >> Adds the MSI-X support and updates driver documentation accordingly. >> >> Changes the driver parameter in order to allow the interruption type >> selection. >> >> Signed-off-by: Gustavo Pimentel <gustavo.pimen...@synopsys.com> >> --- >> Documentation/misc-devices/pci-endpoint-test.txt | 3 + >> drivers/misc/pci_endpoint_test.c | 102 >> +-- >> 2 files changed, 79 insertions(+), 26 deletions(-) >> >> diff --git a/Documentation/misc-devices/pci-endpoint-test.txt >> b/Documentation/misc-devices/pci-endpoint-test.txt >> index 4ebc359..fdfa0f6 100644 >> --- a/Documentation/misc-devices/pci-endpoint-test.txt >> +++ b/Documentation/misc-devices/pci-endpoint-test.txt >> @@ -10,6 +10,7 @@ The PCI driver for the test device performs the following >> tests >> *) verifying addresses programmed in BAR >> *) raise legacy IRQ >> *) raise MSI IRQ >> +*) raise MSI-X IRQ >> *) read data >> *) write data >> *) copy data >> @@ -25,6 +26,8 @@ ioctl >> PCITEST_LEGACY_IRQ: Tests legacy IRQ >> PCITEST_MSI: Tests message signalled interrupts. The MSI number >>to be tested should be passed as argument. >> + PCITEST_MSIX: Tests message signalled interrupts. The MSI-X number >> + to be tested should be passed as argument. >> PCITEST_WRITE: Perform write tests. The size of the buffer should be passed >> as argument. >> PCITEST_READ: Perform read tests. The size of the buffer should be passed >> diff --git a/drivers/misc/pci_endpoint_test.c >> b/drivers/misc/pci_endpoint_test.c >> index 37db0fc..a7d9354 100644 >> --- a/drivers/misc/pci_endpoint_test.c >> +++ b/drivers/misc/pci_endpoint_test.c >> @@ -42,11 +42,16 @@ >> #define PCI_ENDPOINT_TEST_COMMAND 0x4 >> #define COMMAND_RAISE_LEGACY_IRQBIT(0) >> #define COMMAND_RAISE_MSI_IRQ BIT(1) >> -#define MSI_NUMBER_SHIFT2 >> -/* 6 bits for MSI number */ >> -#define COMMAND_READBIT(8) >> -#define COMMAND_WRITE BIT(9) >> -#define COMMAND_COPYBIT(10) >> +#define COMMAND_RAISE_MSIX_IRQ BIT(2) >> +#define IRQ_TYPE_SHIFT 3 >> +#define IRQ_TYPE_LEGACY 0 >> +#define IRQ_TYPE_MSI1 >> +#define IRQ_TYPE_MSIX 2 >> +#define MSI_NUMBER_SHIFT5 > > Now that you are anyways fixing this, add a new register entry for MSI > numbers. > Let's not keep COMMAND and MSI's together. What you suggest? >> +/* 12 bits for MSI number */ >> +#define COMMAND_READBIT(17) >> +#define COMMAND_WRITE BIT(18) >> +#define COMMAND_COPYBIT(19) > > This change should be done along with the pci-epf-test in a single patch. To be clear, you're saying is this patch should be just be squashed into the patch number 8 [1], because there is a lot of dependencies namely the defines, that is used on the alter functions. [1] -> https://patchwork.ozlabs.org/patch/896841/ >> >> #define PCI_ENDPOINT_TEST_STATUS0x8 >> #define STATUS_READ_SUCCESS BIT(0) >> @@ -73,9 +78,9 @@ static DEFINE_IDA(pci_endpoint_test_ida); >> #define to_endpoint_test(priv) container_of((priv), struct >> pci_endpoint_test, \ >> miscdev) >> >> -static bool no_msi; >> -module_param(no_msi, bool, 0444); >> -MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test"); > > Let's not remove this just to make sure existing users doesn't get affected. Hum, by making an internal conversion? Like this no_msi = false <=> irq_type = 1 no_msi = true <=> irq_type = 0 >> +static int irq_type = IRQ_TYPE_MSIX; >> +module_param(irq_type, int, 0444); >> +MODULE_PARM_DESC(irq_type, "IRQ mode selection in pci_endpoint_test (0 - >> Legacy, 1 - MSI, 2 - MSI-X)"); >> >> enum pci_barno { >> BAR_0, >> @@ -103,7 +108,7 @@ struct pci_endpoint_test { >> struct pci_endpoint_test_data { >> enum pci_barno test_reg_bar; >> size_t alignment; >> -bool no_msi; >> +int irq_type; >> }; >> >> static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test, >> @@ -177,10 +182,10