linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core
@ 2019-12-11 12:46 Kishon Vijay Abraham I
  2019-12-11 12:46 ` [PATCH 1/4] PCI: endpoint: Fix ->set_msix() to take BIR and offset as arguments Kishon Vijay Abraham I
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Kishon Vijay Abraham I @ 2019-12-11 12:46 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Andrew Murray, Bjorn Helgaas, Gustavo Pimentel
  Cc: Murali Karicheri, Jingoo Han, Kishon Vijay Abraham I, linux-pci,
	linux-kernel, linux-arm-kernel, Xiaowei Bao

Existing MSI-X support in Endpoint core has limitations:
 1) MSIX table (which is mapped to a BAR) is not allocated by
    anyone. Ideally this should be allocated by endpoint
    function driver.
 2) Endpoint controller can choose any random BARs for MSIX
    table (irrespective of whether the endpoint function driver
    has allocated memory for it or not)

In order to avoid these limitations, pci_epc_set_msix() is
modified to include BAR Indicator register (BIR) configuration
and MSIX table offset as arguments. This series also fixed MSIX
support in dwc driver and add MSI-X support in Cadence PCIe driver.

The previous version of Cadence EP MSI-X support is @ [1].
This series is created on top of [2]

[1] -> https://patchwork.ozlabs.org/patch/971160/
[2] -> http://lore.kernel.org/r/20191209092147.22901-1-kishon@ti.com

Alan Douglas (1):
  PCI: cadence: Add MSI-X support to Endpoint driver

Kishon Vijay Abraham I (3):
  PCI: endpoint: Fix ->set_msix() to take BIR and offset as arguments
  PCI: dwc: Fix dw_pcie_ep_raise_msix_irq() to get correct MSIX table
    address
  PCI: keystone: Add AM654 PCIe Endpoint to raise MSIX interrupt

 .../pci/controller/cadence/pcie-cadence-ep.c  | 112 +++++++++++++++++-
 drivers/pci/controller/cadence/pcie-cadence.h |  10 ++
 drivers/pci/controller/dwc/pci-keystone.c     |   5 +-
 .../pci/controller/dwc/pcie-designware-ep.c   |  61 +++++-----
 drivers/pci/controller/dwc/pcie-designware.h  |   1 +
 drivers/pci/endpoint/functions/pci-epf-test.c |  31 ++++-
 drivers/pci/endpoint/pci-epc-core.c           |   7 +-
 drivers/pci/endpoint/pci-epf-core.c           |   2 +
 include/linux/pci-epc.h                       |   6 +-
 include/linux/pci-epf.h                       |  15 +++
 10 files changed, 207 insertions(+), 43 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/4] PCI: endpoint: Fix ->set_msix() to take BIR and offset as arguments
  2019-12-11 12:46 [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core Kishon Vijay Abraham I
@ 2019-12-11 12:46 ` Kishon Vijay Abraham I
  2019-12-11 12:46 ` [PATCH 2/4] PCI: dwc: Fix dw_pcie_ep_raise_msix_irq() to get correct MSIX table address Kishon Vijay Abraham I
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Kishon Vijay Abraham I @ 2019-12-11 12:46 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Andrew Murray, Bjorn Helgaas, Gustavo Pimentel
  Cc: Murali Karicheri, Jingoo Han, Kishon Vijay Abraham I, linux-pci,
	linux-kernel, linux-arm-kernel, Xiaowei Bao

commit 8963106eabdc5691 ("PCI: endpoint: Add MSI-X interfaces") while
adding support to raise MSIX interrupts from endpoint didn't include
BAR Indicator register (BIR) configuration and MSIX table offset as
arguments in pci_epc_set_msix(). This would result in endpoint
controller register using random BAR indicator register, the memory
for which might not be allocated by the endpoint function driver.
Add BAR indicator register and MSIX table offset as arguments in
pci_epc_set_msix() and allocate space for MSIX table and pending
bit array (PBA) in pci-epf-test endpoint function driver.

Fixes: commit 8963106eabdc5691 ("PCI: endpoint: Add MSI-X interfaces")
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../pci/controller/dwc/pcie-designware-ep.c   | 15 +++++++--
 drivers/pci/endpoint/functions/pci-epf-test.c | 31 +++++++++++++++----
 drivers/pci/endpoint/pci-epc-core.c           |  7 +++--
 include/linux/pci-epc.h                       |  6 ++--
 4 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 3dd2e2697294..4cd3193c9c7c 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -269,7 +269,8 @@ static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no)
 	return val;
 }
 
-static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts)
+static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts,
+			       enum pci_barno bir, u32 offset)
 {
 	struct dw_pcie_ep *ep = epc_get_drvdata(epc);
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
@@ -278,12 +279,22 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts)
 	if (!ep->msix_cap)
 		return -EINVAL;
 
+	dw_pcie_dbi_ro_wr_en(pci);
+
 	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);
+
+	reg = ep->msix_cap + PCI_MSIX_TABLE;
+	val = offset | bir;
+	dw_pcie_writel_dbi(pci, reg, val);
+
+	reg = ep->msix_cap + PCI_MSIX_PBA;
+	val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
+	dw_pcie_writel_dbi(pci, reg, val);
+
 	dw_pcie_dbi_ro_wr_dis(pci);
 
 	return 0;
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
index 5d74f81ddfe4..f4bd3200cd74 100644
--- a/drivers/pci/endpoint/functions/pci-epf-test.c
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -47,6 +47,7 @@ struct pci_epf_test {
 	void			*reg[PCI_STD_NUM_BARS];
 	struct pci_epf		*epf;
 	enum pci_barno		test_reg_bar;
+	size_t			msix_table_offset;
 	struct delayed_work	cmd_handler;
 	const struct pci_epc_features *epc_features;
 };
@@ -429,6 +430,10 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
 	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
 	struct device *dev = &epf->dev;
 	struct pci_epf_bar *epf_bar;
+	size_t msix_table_size = 0;
+	size_t test_reg_bar_size;
+	size_t pba_size = 0;
+	bool msix_capable;
 	void *base;
 	int bar, add;
 	enum pci_barno test_reg_bar = epf_test->test_reg_bar;
@@ -437,13 +442,25 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
 
 	epc_features = epf_test->epc_features;
 
-	if (epc_features->bar_fixed_size[test_reg_bar])
+	test_reg_bar_size = ALIGN(sizeof(struct pci_epf_test_reg), 128);
+
+	msix_capable = epc_features->msix_capable;
+	if (msix_capable) {
+		msix_table_size = PCI_MSIX_ENTRY_SIZE * epf->msix_interrupts;
+		epf_test->msix_table_offset = test_reg_bar_size;
+		/* Align to QWORD or 8 Bytes */
+		pba_size = ALIGN(DIV_ROUND_UP(epf->msix_interrupts, 8), 8);
+	}
+	test_reg_size = test_reg_bar_size + msix_table_size + pba_size;
+
+	if (epc_features->bar_fixed_size[test_reg_bar]) {
+		if (test_reg_size > bar_size[test_reg_bar])
+			return -ENOMEM;
 		test_reg_size = bar_size[test_reg_bar];
-	else
-		test_reg_size = sizeof(struct pci_epf_test_reg);
+	}
 
-	base = pci_epf_alloc_space(epf, test_reg_size,
-				   test_reg_bar, epc_features->align);
+	base = pci_epf_alloc_space(epf, test_reg_size, test_reg_bar,
+				   epc_features->align);
 	if (!base) {
 		dev_err(dev, "Failed to allocated register space\n");
 		return -ENOMEM;
@@ -539,7 +556,9 @@ static int pci_epf_test_bind(struct pci_epf *epf)
 	}
 
 	if (msix_capable) {
-		ret = pci_epc_set_msix(epc, epf->func_no, epf->msix_interrupts);
+		ret = pci_epc_set_msix(epc, epf->func_no, epf->msix_interrupts,
+				       epf_test->test_reg_bar,
+				       epf_test->msix_table_offset);
 		if (ret) {
 			dev_err(dev, "MSI-X configuration failed\n");
 			return ret;
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
index 2091508c1620..3b278fb99206 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -305,10 +305,13 @@ EXPORT_SYMBOL_GPL(pci_epc_get_msix);
  * @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
+ * @bir: BAR where the MSI-X table resides
+ * @offset: Offset pointing to the start of MSI-X table
  *
  * 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 pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts,
+		     enum pci_barno bir, u32 offset)
 {
 	int ret;
 	unsigned long flags;
@@ -321,7 +324,7 @@ int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts)
 		return 0;
 
 	spin_lock_irqsave(&epc->lock, flags);
-	ret = epc->ops->set_msix(epc, func_no, interrupts - 1);
+	ret = epc->ops->set_msix(epc, func_no, interrupts - 1, bir, offset);
 	spin_unlock_irqrestore(&epc->lock, flags);
 
 	return ret;
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index 56f1846b9d39..4e2bed5fd39c 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -53,7 +53,8 @@ struct pci_epc_ops {
 			      phys_addr_t addr);
 	int	(*set_msi)(struct pci_epc *epc, u8 func_no, u8 interrupts);
 	int	(*get_msi)(struct pci_epc *epc, u8 func_no);
-	int	(*set_msix)(struct pci_epc *epc, u8 func_no, u16 interrupts);
+	int	(*set_msix)(struct pci_epc *epc, u8 func_no, u16 interrupts,
+			    enum pci_barno, u32 offset);
 	int	(*get_msix)(struct pci_epc *epc, u8 func_no);
 	int	(*raise_irq)(struct pci_epc *epc, u8 func_no,
 			     enum pci_epc_irq_type type, u16 interrupt_num);
@@ -165,7 +166,8 @@ void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no,
 			phys_addr_t phys_addr);
 int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts);
 int pci_epc_get_msi(struct pci_epc *epc, u8 func_no);
-int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts);
+int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts,
+		     enum pci_barno, u32 offset);
 int pci_epc_get_msix(struct pci_epc *epc, u8 func_no);
 int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no,
 		      enum pci_epc_irq_type type, u16 interrupt_num);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/4] PCI: dwc: Fix dw_pcie_ep_raise_msix_irq() to get correct MSIX table address
  2019-12-11 12:46 [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core Kishon Vijay Abraham I
  2019-12-11 12:46 ` [PATCH 1/4] PCI: endpoint: Fix ->set_msix() to take BIR and offset as arguments Kishon Vijay Abraham I
@ 2019-12-11 12:46 ` Kishon Vijay Abraham I
  2019-12-11 12:46 ` [PATCH 3/4] PCI: keystone: Allow AM654 PCIe Endpoint to raise MSIX interrupt Kishon Vijay Abraham I
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Kishon Vijay Abraham I @ 2019-12-11 12:46 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Andrew Murray, Bjorn Helgaas, Gustavo Pimentel
  Cc: Murali Karicheri, Jingoo Han, Kishon Vijay Abraham I, linux-pci,
	linux-kernel, linux-arm-kernel, Xiaowei Bao

commit beb4641a787df79a14 ("PCI: dwc: Add MSI-X callbacks handler"),
in order to raise MSIX interrupt, obtained MSIX table address from
Base Address Register (BAR). However BAR only holds PCI address
programmed by the host whereas the MSIX table should be in the local
memory.

Store the MSIX table address (virtual address) as part of ->set_bar()
callback and use that to get the message address and message data
here.

Fixes: commit beb4641a787df79a14 ("PCI: dwc: Add MSI-X callbacks
handler")

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../pci/controller/dwc/pcie-designware-ep.c   | 46 +++++++------------
 drivers/pci/controller/dwc/pcie-designware.h  |  1 +
 drivers/pci/endpoint/pci-epf-core.c           |  2 +
 include/linux/pci-epf.h                       | 15 ++++++
 4 files changed, 35 insertions(+), 29 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 4cd3193c9c7c..b61e47365456 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -125,6 +125,7 @@ static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no,
 
 	dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_INBOUND);
 	clear_bit(atu_index, ep->ib_window_map);
+	ep->epf_bar[bar] = NULL;
 }
 
 static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no,
@@ -158,6 +159,7 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no,
 		dw_pcie_writel_dbi(pci, reg + 4, 0);
 	}
 
+	ep->epf_bar[bar] = epf_bar;
 	dw_pcie_dbi_ro_wr_dis(pci);
 
 	return 0;
@@ -420,55 +422,41 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
 			     u16 interrupt_num)
 {
 	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+	struct pci_epf_msix_tbl *msix_tbl;
 	struct pci_epc *epc = ep->epc;
-	u16 tbl_offset, bir;
-	u32 bar_addr_upper, bar_addr_lower;
-	u32 msg_addr_upper, msg_addr_lower;
+	struct pci_epf_bar *epf_bar;
 	u32 reg, msg_data, vec_ctrl;
-	u64 tbl_addr, msg_addr, reg_u64;
-	void __iomem *msix_tbl;
+	unsigned int aligned_offset;
+	u32 tbl_offset;
+	u64 msg_addr;
 	int ret;
+	u8 bir;
 
 	reg = ep->msix_cap + PCI_MSIX_TABLE;
 	tbl_offset = dw_pcie_readl_dbi(pci, reg);
 	bir = (tbl_offset & PCI_MSIX_TABLE_BIR);
 	tbl_offset &= PCI_MSIX_TABLE_OFFSET;
 
-	reg = PCI_BASE_ADDRESS_0 + (4 * bir);
-	bar_addr_upper = 0;
-	bar_addr_lower = dw_pcie_readl_dbi(pci, reg);
-	reg_u64 = (bar_addr_lower & PCI_BASE_ADDRESS_MEM_TYPE_MASK);
-	if (reg_u64 == PCI_BASE_ADDRESS_MEM_TYPE_64)
-		bar_addr_upper = dw_pcie_readl_dbi(pci, reg + 4);
+	epf_bar = ep->epf_bar[bir];
+	msix_tbl = epf_bar->addr;
+	msix_tbl = (struct pci_epf_msix_tbl *)((char *)msix_tbl + tbl_offset);
 
-	tbl_addr = ((u64) bar_addr_upper) << 32 | bar_addr_lower;
-	tbl_addr += (tbl_offset + ((interrupt_num - 1) * PCI_MSIX_ENTRY_SIZE));
-	tbl_addr &= PCI_BASE_ADDRESS_MEM_MASK;
-
-	msix_tbl = ioremap_nocache(ep->phys_base + tbl_addr,
-				   PCI_MSIX_ENTRY_SIZE);
-	if (!msix_tbl)
-		return -EINVAL;
-
-	msg_addr_lower = readl(msix_tbl + PCI_MSIX_ENTRY_LOWER_ADDR);
-	msg_addr_upper = readl(msix_tbl + PCI_MSIX_ENTRY_UPPER_ADDR);
-	msg_addr = ((u64) msg_addr_upper) << 32 | msg_addr_lower;
-	msg_data = readl(msix_tbl + PCI_MSIX_ENTRY_DATA);
-	vec_ctrl = readl(msix_tbl + PCI_MSIX_ENTRY_VECTOR_CTRL);
-
-	iounmap(msix_tbl);
+	msg_addr = msix_tbl[(interrupt_num - 1)].msg_addr;
+	msg_data = msix_tbl[(interrupt_num - 1)].msg_data;
+	vec_ctrl = msix_tbl[(interrupt_num - 1)].vector_ctrl;
 
 	if (vec_ctrl & PCI_MSIX_ENTRY_CTRL_MASKBIT) {
 		dev_dbg(pci->dev, "MSI-X entry ctrl set\n");
 		return -EPERM;
 	}
 
-	ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr,
+	aligned_offset = msg_addr & (epc->mem->page_size - 1);
+	ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys,  msg_addr,
 				  epc->mem->page_size);
 	if (ret)
 		return ret;
 
-	writel(msg_data, ep->msi_mem);
+	writel(msg_data, ep->msi_mem + aligned_offset);
 
 	dw_pcie_ep_unmap_addr(epc, func_no, ep->msi_mem_phys);
 
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 5accdd6bc388..6c7fcd867581 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -224,6 +224,7 @@ struct dw_pcie_ep {
 	phys_addr_t		msi_mem_phys;
 	u8			msi_cap;	/* MSI capability offset */
 	u8			msix_cap;	/* MSI-X capability offset */
+	struct pci_epf_bar	*epf_bar[PCI_STD_NUM_BARS];
 };
 
 struct dw_pcie_ops {
diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c
index fb1306de8f40..93ebe916949e 100644
--- a/drivers/pci/endpoint/pci-epf-core.c
+++ b/drivers/pci/endpoint/pci-epf-core.c
@@ -99,6 +99,7 @@ void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar)
 			  epf->bar[bar].phys_addr);
 
 	epf->bar[bar].phys_addr = 0;
+	epf->bar[bar].addr = NULL;
 	epf->bar[bar].size = 0;
 	epf->bar[bar].barno = 0;
 	epf->bar[bar].flags = 0;
@@ -135,6 +136,7 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
 	}
 
 	epf->bar[bar].phys_addr = phys_addr;
+	epf->bar[bar].addr = space;
 	epf->bar[bar].size = size;
 	epf->bar[bar].barno = bar;
 	epf->bar[bar].flags |= upper_32_bits(size) ?
diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h
index 2d6f07556682..bc5ce7afd79a 100644
--- a/include/linux/pci-epf.h
+++ b/include/linux/pci-epf.h
@@ -92,10 +92,12 @@ struct pci_epf_driver {
 /**
  * struct pci_epf_bar - represents the BAR of EPF device
  * @phys_addr: physical address that should be mapped to the BAR
+ * @addr: virtual address corresponding to the @phys_addr
  * @size: the size of the address space present in BAR
  */
 struct pci_epf_bar {
 	dma_addr_t	phys_addr;
+	void		*addr;
 	size_t		size;
 	enum pci_barno	barno;
 	int		flags;
@@ -127,6 +129,19 @@ struct pci_epf {
 	struct list_head	list;
 };
 
+/**
+ * struct pci_epf_msix_tbl - represents the MSIX table entry structure
+ * @msg_addr: Writes to this address will trigger MSIX interrupt in host
+ * @msg_data: Data that should be written to @msg_addr to trigger MSIX interrupt
+ * @vector_ctrl: Identifies if the function is prohibited from sending a message
+ * using this MSIX table entry
+ */
+struct pci_epf_msix_tbl {
+	u64 msg_addr;
+	u32 msg_data;
+	u32 vector_ctrl;
+};
+
 #define to_pci_epf(epf_dev) container_of((epf_dev), struct pci_epf, dev)
 
 #define pci_epf_register_driver(driver)    \
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/4] PCI: keystone: Allow AM654 PCIe Endpoint to raise MSIX interrupt
  2019-12-11 12:46 [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core Kishon Vijay Abraham I
  2019-12-11 12:46 ` [PATCH 1/4] PCI: endpoint: Fix ->set_msix() to take BIR and offset as arguments Kishon Vijay Abraham I
  2019-12-11 12:46 ` [PATCH 2/4] PCI: dwc: Fix dw_pcie_ep_raise_msix_irq() to get correct MSIX table address Kishon Vijay Abraham I
@ 2019-12-11 12:46 ` Kishon Vijay Abraham I
  2019-12-11 12:46 ` [PATCH 4/4] PCI: cadence: Add MSI-X support to Endpoint driver Kishon Vijay Abraham I
  2019-12-11 22:46 ` [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core Bjorn Helgaas
  4 siblings, 0 replies; 10+ messages in thread
From: Kishon Vijay Abraham I @ 2019-12-11 12:46 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Andrew Murray, Bjorn Helgaas, Gustavo Pimentel
  Cc: Murali Karicheri, Jingoo Han, Kishon Vijay Abraham I, linux-pci,
	linux-kernel, linux-arm-kernel, Xiaowei Bao

AM654 PCIe EP controller has MSIX capability register and has the
ability to raise MSIX interrupt. Add support in pci-keystone.c
for PCIe endpoint controller in AM654 to raise MSIX interrupts.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/pci/controller/dwc/pci-keystone.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index af677254a072..dbe31589eb61 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -959,6 +959,9 @@ static int ks_pcie_am654_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
 	case PCI_EPC_IRQ_MSI:
 		dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
 		break;
+	case PCI_EPC_IRQ_MSIX:
+		dw_pcie_ep_raise_msix_irq(ep, func_no, interrupt_num);
+		break;
 	default:
 		dev_err(pci->dev, "UNKNOWN IRQ type\n");
 		return -EINVAL;
@@ -970,7 +973,7 @@ static int ks_pcie_am654_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
 static const struct pci_epc_features ks_pcie_am654_epc_features = {
 	.linkup_notifier = false,
 	.msi_capable = true,
-	.msix_capable = false,
+	.msix_capable = true,
 	.reserved_bar = 1 << BAR_0 | 1 << BAR_1,
 	.bar_fixed_64bit = 1 << BAR_0,
 	.bar_fixed_size[2] = SZ_1M,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/4] PCI: cadence: Add MSI-X support to Endpoint driver
  2019-12-11 12:46 [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core Kishon Vijay Abraham I
                   ` (2 preceding siblings ...)
  2019-12-11 12:46 ` [PATCH 3/4] PCI: keystone: Allow AM654 PCIe Endpoint to raise MSIX interrupt Kishon Vijay Abraham I
@ 2019-12-11 12:46 ` Kishon Vijay Abraham I
  2020-01-23 22:10   ` Ramon Fried
  2019-12-11 22:46 ` [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core Bjorn Helgaas
  4 siblings, 1 reply; 10+ messages in thread
From: Kishon Vijay Abraham I @ 2019-12-11 12:46 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Andrew Murray, Bjorn Helgaas, Gustavo Pimentel
  Cc: Murali Karicheri, Jingoo Han, Kishon Vijay Abraham I, linux-pci,
	linux-kernel, linux-arm-kernel, Xiaowei Bao

From: Alan Douglas <adouglas@cadence.com>

Implement ->set_msix() and ->get_msix() callback functions in order
to configure MSIX capability in the PCIe endpoint controller.

Add cdns_pcie_ep_send_msix_irq() to send MSIX interrupts to Host.
cdns_pcie_ep_send_msix_irq() gets the MSIX table address (virtual
address) from "struct cdns_pcie_epf" that gets initialized in
->set_bar() call back function.

[kishon@ti.com: Re-implement MSIX support in accordance with the
 re-designed core MSI-X interfaces]
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Alan Douglas <adouglas@cadence.com>
---
 .../pci/controller/cadence/pcie-cadence-ep.c  | 112 +++++++++++++++++-
 drivers/pci/controller/cadence/pcie-cadence.h |  10 ++
 2 files changed, 121 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
index 088394b6be04..c3081e8e52a4 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
@@ -52,6 +52,7 @@ static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 fn,
 				struct pci_epf_bar *epf_bar)
 {
 	struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
+	struct cdns_pcie_epf *epf = &ep->epf[fn];
 	struct cdns_pcie *pcie = &ep->pcie;
 	dma_addr_t bar_phys = epf_bar->phys_addr;
 	enum pci_barno bar = epf_bar->barno;
@@ -112,6 +113,8 @@ static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 fn,
 		CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL(b, ctrl));
 	cdns_pcie_writel(pcie, reg, cfg);
 
+	epf->epf_bar[bar] = epf_bar;
+
 	return 0;
 }
 
@@ -119,6 +122,7 @@ static void cdns_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn,
 				   struct pci_epf_bar *epf_bar)
 {
 	struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
+	struct cdns_pcie_epf *epf = &ep->epf[fn];
 	struct cdns_pcie *pcie = &ep->pcie;
 	enum pci_barno bar = epf_bar->barno;
 	u32 reg, cfg, b, ctrl;
@@ -140,6 +144,8 @@ static void cdns_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn,
 
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar), 0);
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar), 0);
+
+	epf->epf_bar[bar] = NULL;
 }
 
 static int cdns_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, phys_addr_t addr,
@@ -225,6 +231,50 @@ static int cdns_pcie_ep_get_msi(struct pci_epc *epc, u8 fn)
 	return mme;
 }
 
+static int cdns_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no)
+{
+	struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
+	struct cdns_pcie *pcie = &ep->pcie;
+	u32 cap = CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET;
+	u32 val, reg;
+
+	reg = cap + PCI_MSIX_FLAGS;
+	val = cdns_pcie_ep_fn_readw(pcie, func_no, reg);
+	if (!(val & PCI_MSIX_FLAGS_ENABLE))
+		return -EINVAL;
+
+	val &= PCI_MSIX_FLAGS_QSIZE;
+
+	return val;
+}
+
+static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u16 interrupts,
+				 enum pci_barno bir, u32 offset)
+{
+	struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
+	struct cdns_pcie *pcie = &ep->pcie;
+	u32 cap = CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET;
+	u32 val, reg;
+
+	reg = cap + PCI_MSIX_FLAGS;
+	val = cdns_pcie_ep_fn_readw(pcie, fn, reg);
+	val &= ~PCI_MSIX_FLAGS_QSIZE;
+	val |= interrupts;
+	cdns_pcie_ep_fn_writew(pcie, fn, reg, val);
+
+	/* Set MSIX BAR and offset */
+	reg = cap + PCI_MSIX_TABLE;
+	val = offset | bir;
+	cdns_pcie_ep_fn_writel(pcie, fn, reg, val);
+
+	/* Set PBA BAR and offset.  BAR must match MSIX BAR */
+	reg = cap + PCI_MSIX_PBA;
+	val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
+	cdns_pcie_ep_fn_writel(pcie, fn, reg, val);
+
+	return 0;
+}
+
 static void cdns_pcie_ep_assert_intx(struct cdns_pcie_ep *ep, u8 fn,
 				     u8 intx, bool is_asserted)
 {
@@ -331,6 +381,56 @@ static int cdns_pcie_ep_send_msi_irq(struct cdns_pcie_ep *ep, u8 fn,
 	return 0;
 }
 
+static int cdns_pcie_ep_send_msix_irq(struct cdns_pcie_ep *ep, u8 fn,
+				      u16 interrupt_num)
+{
+	u32 cap = CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET;
+	u32 tbl_offset, msg_data, reg, vec_ctrl;
+	struct cdns_pcie *pcie = &ep->pcie;
+	struct pci_epf_msix_tbl *msix_tbl;
+	struct pci_epf_bar *epf_bar;
+	struct cdns_pcie_epf *epf;
+	u64 pci_addr_mask = 0xff;
+	u64 msg_addr;
+	u16 flags;
+	u8 bir;
+
+	/* Check whether the MSI-X feature has been enabled by the PCI host. */
+	flags = cdns_pcie_ep_fn_readw(pcie, fn, cap + PCI_MSIX_FLAGS);
+	if (!(flags & PCI_MSIX_FLAGS_ENABLE))
+		return -EINVAL;
+
+	reg = cap + PCI_MSIX_TABLE;
+	tbl_offset = cdns_pcie_ep_fn_readl(pcie, fn, reg);
+	bir = tbl_offset & PCI_MSIX_TABLE_BIR;
+	tbl_offset &= PCI_MSIX_TABLE_OFFSET;
+
+	epf = &ep->epf[fn];
+	epf_bar = epf->epf_bar[bir];
+	msix_tbl = epf_bar->addr;
+	msix_tbl = (struct pci_epf_msix_tbl *)((char *)msix_tbl + tbl_offset);
+
+	msg_addr = msix_tbl[(interrupt_num - 1)].msg_addr;
+	msg_data = msix_tbl[(interrupt_num - 1)].msg_data;
+	vec_ctrl = msix_tbl[(interrupt_num - 1)].vector_ctrl;
+
+	/* Set the outbound region if needed. */
+	if (unlikely(ep->irq_pci_addr != (msg_addr & ~pci_addr_mask) ||
+		     ep->irq_pci_fn != fn)) {
+		/* First region was reserved for IRQ writes. */
+		cdns_pcie_set_outbound_region(pcie, fn, 0,
+					      false,
+					      ep->irq_phys_addr,
+					      msg_addr & ~pci_addr_mask,
+					      pci_addr_mask + 1);
+		ep->irq_pci_addr = (msg_addr & ~pci_addr_mask);
+		ep->irq_pci_fn = fn;
+	}
+	writel(msg_data, ep->irq_cpu_addr + (msg_addr & pci_addr_mask));
+
+	return 0;
+}
+
 static int cdns_pcie_ep_raise_irq(struct pci_epc *epc, u8 fn,
 				  enum pci_epc_irq_type type,
 				  u16 interrupt_num)
@@ -344,6 +444,9 @@ static int cdns_pcie_ep_raise_irq(struct pci_epc *epc, u8 fn,
 	case PCI_EPC_IRQ_MSI:
 		return cdns_pcie_ep_send_msi_irq(ep, fn, interrupt_num);
 
+	case PCI_EPC_IRQ_MSIX:
+		return cdns_pcie_ep_send_msix_irq(ep, fn, interrupt_num);
+
 	default:
 		break;
 	}
@@ -381,7 +484,7 @@ static int cdns_pcie_ep_start(struct pci_epc *epc)
 static const struct pci_epc_features cdns_pcie_epc_features = {
 	.linkup_notifier = false,
 	.msi_capable = true,
-	.msix_capable = false,
+	.msix_capable = true,
 };
 
 static const struct pci_epc_features*
@@ -398,6 +501,8 @@ static const struct pci_epc_ops cdns_pcie_epc_ops = {
 	.unmap_addr	= cdns_pcie_ep_unmap_addr,
 	.set_msi	= cdns_pcie_ep_set_msi,
 	.get_msi	= cdns_pcie_ep_get_msi,
+	.set_msix	= cdns_pcie_ep_set_msix,
+	.get_msix	= cdns_pcie_ep_get_msix,
 	.raise_irq	= cdns_pcie_ep_raise_irq,
 	.start		= cdns_pcie_ep_start,
 	.get_features	= cdns_pcie_ep_get_features,
@@ -457,6 +562,11 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
 	if (of_property_read_u8(np, "max-functions", &epc->max_functions) < 0)
 		epc->max_functions = 1;
 
+	ep->epf = devm_kcalloc(dev, epc->max_functions, sizeof(*ep->epf),
+			       GFP_KERNEL);
+	if (!ep->epf)
+		return -ENOMEM;
+
 	ret = pci_epc_mem_init(epc, pcie->mem_res->start,
 			       resource_size(pcie->mem_res));
 	if (ret < 0) {
diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
index ffa8b9f78ff8..207d6ba03f70 100644
--- a/drivers/pci/controller/cadence/pcie-cadence.h
+++ b/drivers/pci/controller/cadence/pcie-cadence.h
@@ -99,6 +99,7 @@
 #define CDNS_PCIE_EP_FUNC_BASE(fn)	(((fn) << 12) & GENMASK(19, 12))
 
 #define CDNS_PCIE_EP_FUNC_MSI_CAP_OFFSET	0x90
+#define CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET	0xb0
 
 /*
  * Root Port Registers (PCI configuration space for the root port function)
@@ -281,6 +282,14 @@ struct cdns_pcie_rc {
 	u16			device_id;
 };
 
+/**
+ * struct cdns_pcie_epf - Structure to hold info about endpoint function
+ * @epf_bar: reference to the pci_epf_bar for the six Base Address Registers
+ */
+struct cdns_pcie_epf {
+	struct pci_epf_bar *epf_bar[PCI_STD_NUM_BARS];
+};
+
 /**
  * struct cdns_pcie_ep - private data for this PCIe endpoint controller driver
  * @pcie: Cadence PCIe controller
@@ -308,6 +317,7 @@ struct cdns_pcie_ep {
 	u64			irq_pci_addr;
 	u8			irq_pci_fn;
 	u8			irq_pending;
+	struct cdns_pcie_epf	*epf;
 };
 
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core
  2019-12-11 12:46 [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core Kishon Vijay Abraham I
                   ` (3 preceding siblings ...)
  2019-12-11 12:46 ` [PATCH 4/4] PCI: cadence: Add MSI-X support to Endpoint driver Kishon Vijay Abraham I
@ 2019-12-11 22:46 ` Bjorn Helgaas
  2020-01-09 10:19   ` Kishon Vijay Abraham I
  4 siblings, 1 reply; 10+ messages in thread
From: Bjorn Helgaas @ 2019-12-11 22:46 UTC (permalink / raw)
  To: Kishon Vijay Abraham I
  Cc: Lorenzo Pieralisi, Andrew Murray, Gustavo Pimentel,
	Murali Karicheri, Jingoo Han, linux-pci, linux-kernel,
	linux-arm-kernel, Xiaowei Bao

On Wed, Dec 11, 2019 at 06:16:04PM +0530, Kishon Vijay Abraham I wrote:
> Existing MSI-X support in Endpoint core has limitations:
>  1) MSIX table (which is mapped to a BAR) is not allocated by
>     anyone. Ideally this should be allocated by endpoint
>     function driver.
>  2) Endpoint controller can choose any random BARs for MSIX
>     table (irrespective of whether the endpoint function driver
>     has allocated memory for it or not)
> 
> In order to avoid these limitations, pci_epc_set_msix() is
> modified to include BAR Indicator register (BIR) configuration
> and MSIX table offset as arguments. This series also fixed MSIX
> support in dwc driver and add MSI-X support in Cadence PCIe driver.
> 
> The previous version of Cadence EP MSI-X support is @ [1].
> This series is created on top of [2]
> 
> [1] -> https://patchwork.ozlabs.org/patch/971160/
> [2] -> http://lore.kernel.org/r/20191209092147.22901-1-kishon@ti.com
> 
> Alan Douglas (1):
>   PCI: cadence: Add MSI-X support to Endpoint driver
> 
> Kishon Vijay Abraham I (3):
>   PCI: endpoint: Fix ->set_msix() to take BIR and offset as arguments
>   PCI: dwc: Fix dw_pcie_ep_raise_msix_irq() to get correct MSIX table
>     address
>   PCI: keystone: Add AM654 PCIe Endpoint to raise MSIX interrupt

Trivial nits:

  - There's a mix of "MSI-X" and "MSIX" in the subjects, commit logs,
    and comments.  I prefer "MSI-X" to match usage in the spec.

  - "Fixes:" tags need not include "commit".  It doesn't *hurt*
    anything, but it takes up space that could be used for the
    subject.

  - Commit references typically use a 12-char SHA1.  Again, doesn't
    hurt anything.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core
  2019-12-11 22:46 ` [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core Bjorn Helgaas
@ 2020-01-09 10:19   ` Kishon Vijay Abraham I
  2020-01-09 10:20     ` Xiaowei Bao
  2020-01-09 10:33     ` Gustavo Pimentel
  0 siblings, 2 replies; 10+ messages in thread
From: Kishon Vijay Abraham I @ 2020-01-09 10:19 UTC (permalink / raw)
  To: Bjorn Helgaas, Gustavo Pimentel, Xiaowei Bao
  Cc: Lorenzo Pieralisi, Andrew Murray, Murali Karicheri, Jingoo Han,
	linux-pci, linux-kernel, linux-arm-kernel

Hi,

On 12/12/19 4:16 AM, Bjorn Helgaas wrote:
> On Wed, Dec 11, 2019 at 06:16:04PM +0530, Kishon Vijay Abraham I wrote:
>> Existing MSI-X support in Endpoint core has limitations:
>>  1) MSIX table (which is mapped to a BAR) is not allocated by
>>     anyone. Ideally this should be allocated by endpoint
>>     function driver.
>>  2) Endpoint controller can choose any random BARs for MSIX
>>     table (irrespective of whether the endpoint function driver
>>     has allocated memory for it or not)
>>
>> In order to avoid these limitations, pci_epc_set_msix() is
>> modified to include BAR Indicator register (BIR) configuration
>> and MSIX table offset as arguments. This series also fixed MSIX
>> support in dwc driver and add MSI-X support in Cadence PCIe driver.
>>
>> The previous version of Cadence EP MSI-X support is @ [1].
>> This series is created on top of [2]
>>
>> [1] -> https://patchwork.ozlabs.org/patch/971160/
>> [2] -> http://lore.kernel.org/r/20191209092147.22901-1-kishon@ti.com
>>
>> Alan Douglas (1):
>>   PCI: cadence: Add MSI-X support to Endpoint driver
>>
>> Kishon Vijay Abraham I (3):
>>   PCI: endpoint: Fix ->set_msix() to take BIR and offset as arguments
>>   PCI: dwc: Fix dw_pcie_ep_raise_msix_irq() to get correct MSIX table
>>     address
>>   PCI: keystone: Add AM654 PCIe Endpoint to raise MSIX interrupt
> 
> Trivial nits:
> 
>   - There's a mix of "MSI-X" and "MSIX" in the subjects, commit logs,
>     and comments.  I prefer "MSI-X" to match usage in the spec.
> 
>   - "Fixes:" tags need not include "commit".  It doesn't *hurt*
>     anything, but it takes up space that could be used for the
>     subject.
> 
>   - Commit references typically use a 12-char SHA1.  Again, doesn't
>     hurt anything.

I'll fix all this in my next revision.

Xiaowei, Gustavo,

The issues we discussed in  [1] should be fixed with this series. Can
you help test this in your platforms?

[1] -> https://lkml.org/lkml/2019/11/6/678

Thanks
Kishon
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core
  2020-01-09 10:19   ` Kishon Vijay Abraham I
@ 2020-01-09 10:20     ` Xiaowei Bao
  2020-01-09 10:33     ` Gustavo Pimentel
  1 sibling, 0 replies; 10+ messages in thread
From: Xiaowei Bao @ 2020-01-09 10:20 UTC (permalink / raw)
  To: Kishon Vijay Abraham I, Bjorn Helgaas, Gustavo Pimentel
  Cc: Lorenzo Pieralisi, Andrew Murray, Murali Karicheri, Jingoo Han,
	linux-pci, linux-kernel, linux-arm-kernel



> -----Original Message-----
> From: Kishon Vijay Abraham I <kishon@ti.com>
> Sent: 2020年1月9日 18:19
> To: Bjorn Helgaas <helgaas@kernel.org>; Gustavo Pimentel
> <gustavo.pimentel@synopsys.com>; Xiaowei Bao <xiaowei.bao@nxp.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>; Andrew Murray
> <andrew.murray@arm.com>; Murali Karicheri <m-karicheri2@ti.com>; Jingoo
> Han <jingoohan1@gmail.com>; linux-pci@vger.kernel.org;
> linux-kernel@vger.kernel.org; linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core
> 
> Hi,
> 
> On 12/12/19 4:16 AM, Bjorn Helgaas wrote:
> > On Wed, Dec 11, 2019 at 06:16:04PM +0530, Kishon Vijay Abraham I wrote:
> >> Existing MSI-X support in Endpoint core has limitations:
> >>  1) MSIX table (which is mapped to a BAR) is not allocated by
> >>     anyone. Ideally this should be allocated by endpoint
> >>     function driver.
> >>  2) Endpoint controller can choose any random BARs for MSIX
> >>     table (irrespective of whether the endpoint function driver
> >>     has allocated memory for it or not)
> >>
> >> In order to avoid these limitations, pci_epc_set_msix() is modified
> >> to include BAR Indicator register (BIR) configuration and MSIX table
> >> offset as arguments. This series also fixed MSIX support in dwc
> >> driver and add MSI-X support in Cadence PCIe driver.
> >>
> >> The previous version of Cadence EP MSI-X support is @ [1].
> >> This series is created on top of [2]
> >>
> >> [1] ->
> >> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpat
> >>
> chwork.ozlabs.org%2Fpatch%2F971160%2F&amp;data=02%7C01%7Cxiaowei
> .bao%
> >>
> 40nxp.com%7Ca1c78017032c4f4882b708d794ed1e9c%7C686ea1d3bc2b4c6
> fa92cd9
> >>
> 9c5c301635%7C0%7C0%7C637141618459605704&amp;sdata=o1gFrMe%2B
> DERcNIVjK
> >> 5ZRJnDmO1QfAKQostQci05%2BrJA%3D&amp;reserved=0
> >> [2] ->
> >> https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Flore
> >> .kernel.org%2Fr%2F20191209092147.22901-1-kishon%40ti.com&amp;dat
> a=02%
> >>
> 7C01%7Cxiaowei.bao%40nxp.com%7Ca1c78017032c4f4882b708d794ed1e9
> c%7C686
> >>
> ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637141618459605704&a
> mp;sdata=
> >>
> fdZEFSCBc89vBEZlCUpuoIjZqrsqWPdNaNt3nMFdO0I%3D&amp;reserved=0
> >>
> >> Alan Douglas (1):
> >>   PCI: cadence: Add MSI-X support to Endpoint driver
> >>
> >> Kishon Vijay Abraham I (3):
> >>   PCI: endpoint: Fix ->set_msix() to take BIR and offset as arguments
> >>   PCI: dwc: Fix dw_pcie_ep_raise_msix_irq() to get correct MSIX table
> >>     address
> >>   PCI: keystone: Add AM654 PCIe Endpoint to raise MSIX interrupt
> >
> > Trivial nits:
> >
> >   - There's a mix of "MSI-X" and "MSIX" in the subjects, commit logs,
> >     and comments.  I prefer "MSI-X" to match usage in the spec.
> >
> >   - "Fixes:" tags need not include "commit".  It doesn't *hurt*
> >     anything, but it takes up space that could be used for the
> >     subject.
> >
> >   - Commit references typically use a 12-char SHA1.  Again, doesn't
> >     hurt anything.
> 
> I'll fix all this in my next revision.
> 
> Xiaowei, Gustavo,
> 
> The issues we discussed in  [1] should be fixed with this series. Can you help
> test this in your platforms?

OK, I will test it when I am free, and give the feedback to you.

Thanks
Xiaowei

> 
> [1] ->
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.or
> g%2Flkml%2F2019%2F11%2F6%2F678&amp;data=02%7C01%7Cxiaowei.bao
> %40nxp.com%7Ca1c78017032c4f4882b708d794ed1e9c%7C686ea1d3bc2b4c
> 6fa92cd99c5c301635%7C0%7C0%7C637141618459605704&amp;sdata=nmJ
> GiBLcEUnBFTaaoJUOhL290cmA7F%2F2uBnTpvw9ugo%3D&amp;reserved=0
> 
> Thanks
> Kishon
> >

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core
  2020-01-09 10:19   ` Kishon Vijay Abraham I
  2020-01-09 10:20     ` Xiaowei Bao
@ 2020-01-09 10:33     ` Gustavo Pimentel
  1 sibling, 0 replies; 10+ messages in thread
From: Gustavo Pimentel @ 2020-01-09 10:33 UTC (permalink / raw)
  To: Kishon Vijay Abraham I, Bjorn Helgaas, Xiaowei Bao
  Cc: Lorenzo Pieralisi, Andrew Murray, Murali Karicheri, Jingoo Han,
	linux-pci, linux-kernel, linux-arm-kernel

Hi Kishon,

On Thu, Jan 9, 2020 at 10:19:17, Kishon Vijay Abraham I <kishon@ti.com> 
wrote:

> Hi,
> 
> On 12/12/19 4:16 AM, Bjorn Helgaas wrote:
> > On Wed, Dec 11, 2019 at 06:16:04PM +0530, Kishon Vijay Abraham I wrote:
> >> Existing MSI-X support in Endpoint core has limitations:
> >>  1) MSIX table (which is mapped to a BAR) is not allocated by
> >>     anyone. Ideally this should be allocated by endpoint
> >>     function driver.
> >>  2) Endpoint controller can choose any random BARs for MSIX
> >>     table (irrespective of whether the endpoint function driver
> >>     has allocated memory for it or not)
> >>
> >> In order to avoid these limitations, pci_epc_set_msix() is
> >> modified to include BAR Indicator register (BIR) configuration
> >> and MSIX table offset as arguments. This series also fixed MSIX
> >> support in dwc driver and add MSI-X support in Cadence PCIe driver.
> >>
> >> The previous version of Cadence EP MSI-X support is @ [1].
> >> This series is created on top of [2]
> >>
> >> [1] -> https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.ozlabs.org_patch_971160_&d=DwICaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=bkWxpLoW-f-E3EdiDCCa0_h0PicsViasSlvIpzZvPxs&m=mDuurD6XufzL6j14X2LHC1ulMbU5dbmCtVUYVtCxNFM&s=IEKU31dHkOuXDfERPV1_QZ0U_BsjgCFgLwoE2ipAhFU&e= 
> >> [2] -> https://urldefense.proofpoint.com/v2/url?u=http-3A__lore.kernel.org_r_20191209092147.22901-2D1-2Dkishon-40ti.com&d=DwICaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=bkWxpLoW-f-E3EdiDCCa0_h0PicsViasSlvIpzZvPxs&m=mDuurD6XufzL6j14X2LHC1ulMbU5dbmCtVUYVtCxNFM&s=9-DXCyz6iyuFk67BCnXeBt8HtJ-OOczk6ug_0ZZBgVE&e= 
> >>
> >> Alan Douglas (1):
> >>   PCI: cadence: Add MSI-X support to Endpoint driver
> >>
> >> Kishon Vijay Abraham I (3):
> >>   PCI: endpoint: Fix ->set_msix() to take BIR and offset as arguments
> >>   PCI: dwc: Fix dw_pcie_ep_raise_msix_irq() to get correct MSIX table
> >>     address
> >>   PCI: keystone: Add AM654 PCIe Endpoint to raise MSIX interrupt
> > 
> > Trivial nits:
> > 
> >   - There's a mix of "MSI-X" and "MSIX" in the subjects, commit logs,
> >     and comments.  I prefer "MSI-X" to match usage in the spec.
> > 
> >   - "Fixes:" tags need not include "commit".  It doesn't *hurt*
> >     anything, but it takes up space that could be used for the
> >     subject.
> > 
> >   - Commit references typically use a 12-char SHA1.  Again, doesn't
> >     hurt anything.
> 
> I'll fix all this in my next revision.
> 
> Xiaowei, Gustavo,
> 
> The issues we discussed in  [1] should be fixed with this series. Can
> you help test this in your platforms?

I didn't forget this, but unfortunately, I still don't have the HW 
prototype required to be able to test this (there are some resources and 
roadmap constraints that are blocking this).
To avoid blocking you and Xiaomi, I 'd suggest (assuming this MSI-X API 
rework is working for layerscape and keystone drivers) to continue with 
this patch series and take it to the mainline. If I get some problem with 
my setup (as soon as I get the required conditions to test) I'll deal 
with it then.

Regards
Gustavo

> 
> [1] -> https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.org_lkml_2019_11_6_678&d=DwICaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=bkWxpLoW-f-E3EdiDCCa0_h0PicsViasSlvIpzZvPxs&m=mDuurD6XufzL6j14X2LHC1ulMbU5dbmCtVUYVtCxNFM&s=CbZ63jR-UW-NMY3U39htnXhperbQxlQX6dMQ9zpvBXg&e= 
> 
> Thanks
> Kishon
> > 



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] PCI: cadence: Add MSI-X support to Endpoint driver
  2019-12-11 12:46 ` [PATCH 4/4] PCI: cadence: Add MSI-X support to Endpoint driver Kishon Vijay Abraham I
@ 2020-01-23 22:10   ` Ramon Fried
  0 siblings, 0 replies; 10+ messages in thread
From: Ramon Fried @ 2020-01-23 22:10 UTC (permalink / raw)
  To: Kishon Vijay Abraham I
  Cc: Lorenzo Pieralisi, Andrew Murray, Bjorn Helgaas,
	Gustavo Pimentel, Murali Karicheri, Jingoo Han, linux-pci,
	linux-kernel, linux-arm-kernel, Xiaowei Bao

On Wed, Dec 11, 2019 at 2:47 PM Kishon Vijay Abraham I <kishon@ti.com> wrote:
>
> From: Alan Douglas <adouglas@cadence.com>
>
> Implement ->set_msix() and ->get_msix() callback functions in order
> to configure MSIX capability in the PCIe endpoint controller.
>
> Add cdns_pcie_ep_send_msix_irq() to send MSIX interrupts to Host.
> cdns_pcie_ep_send_msix_irq() gets the MSIX table address (virtual
> address) from "struct cdns_pcie_epf" that gets initialized in
> ->set_bar() call back function.
>
> [kishon@ti.com: Re-implement MSIX support in accordance with the
>  re-designed core MSI-X interfaces]
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> Signed-off-by: Alan Douglas <adouglas@cadence.com>
> ---
>  .../pci/controller/cadence/pcie-cadence-ep.c  | 112 +++++++++++++++++-
>  drivers/pci/controller/cadence/pcie-cadence.h |  10 ++
>  2 files changed, 121 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> index 088394b6be04..c3081e8e52a4 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
> +++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> @@ -52,6 +52,7 @@ static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 fn,
>                                 struct pci_epf_bar *epf_bar)
>  {
>         struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
> +       struct cdns_pcie_epf *epf = &ep->epf[fn];
>         struct cdns_pcie *pcie = &ep->pcie;
>         dma_addr_t bar_phys = epf_bar->phys_addr;
>         enum pci_barno bar = epf_bar->barno;
> @@ -112,6 +113,8 @@ static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 fn,
>                 CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL(b, ctrl));
>         cdns_pcie_writel(pcie, reg, cfg);
>
> +       epf->epf_bar[bar] = epf_bar;
> +
>         return 0;
>  }
>
> @@ -119,6 +122,7 @@ static void cdns_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn,
>                                    struct pci_epf_bar *epf_bar)
>  {
>         struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
> +       struct cdns_pcie_epf *epf = &ep->epf[fn];
>         struct cdns_pcie *pcie = &ep->pcie;
>         enum pci_barno bar = epf_bar->barno;
>         u32 reg, cfg, b, ctrl;
> @@ -140,6 +144,8 @@ static void cdns_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn,
>
>         cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar), 0);
>         cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar), 0);
> +
> +       epf->epf_bar[bar] = NULL;
>  }
>
>  static int cdns_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, phys_addr_t addr,
> @@ -225,6 +231,50 @@ static int cdns_pcie_ep_get_msi(struct pci_epc *epc, u8 fn)
>         return mme;
>  }
>
> +static int cdns_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no)
> +{
> +       struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
> +       struct cdns_pcie *pcie = &ep->pcie;
> +       u32 cap = CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET;
> +       u32 val, reg;
> +
> +       reg = cap + PCI_MSIX_FLAGS;
> +       val = cdns_pcie_ep_fn_readw(pcie, func_no, reg);
> +       if (!(val & PCI_MSIX_FLAGS_ENABLE))
> +               return -EINVAL;
> +
> +       val &= PCI_MSIX_FLAGS_QSIZE;
> +
> +       return val;
> +}
> +
> +static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u16 interrupts,
> +                                enum pci_barno bir, u32 offset)
> +{
> +       struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
> +       struct cdns_pcie *pcie = &ep->pcie;
> +       u32 cap = CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET;
> +       u32 val, reg;
> +
> +       reg = cap + PCI_MSIX_FLAGS;
> +       val = cdns_pcie_ep_fn_readw(pcie, fn, reg);
> +       val &= ~PCI_MSIX_FLAGS_QSIZE;
> +       val |= interrupts;
> +       cdns_pcie_ep_fn_writew(pcie, fn, reg, val);
> +
> +       /* Set MSIX BAR and offset */
> +       reg = cap + PCI_MSIX_TABLE;
> +       val = offset | bir;
> +       cdns_pcie_ep_fn_writel(pcie, fn, reg, val);
> +
> +       /* Set PBA BAR and offset.  BAR must match MSIX BAR */
> +       reg = cap + PCI_MSIX_PBA;
> +       val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
> +       cdns_pcie_ep_fn_writel(pcie, fn, reg, val);
> +
> +       return 0;
> +}
> +
>  static void cdns_pcie_ep_assert_intx(struct cdns_pcie_ep *ep, u8 fn,
>                                      u8 intx, bool is_asserted)
>  {
> @@ -331,6 +381,56 @@ static int cdns_pcie_ep_send_msi_irq(struct cdns_pcie_ep *ep, u8 fn,
>         return 0;
>  }
>
> +static int cdns_pcie_ep_send_msix_irq(struct cdns_pcie_ep *ep, u8 fn,
> +                                     u16 interrupt_num)
> +{
> +       u32 cap = CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET;
> +       u32 tbl_offset, msg_data, reg, vec_ctrl;
> +       struct cdns_pcie *pcie = &ep->pcie;
> +       struct pci_epf_msix_tbl *msix_tbl;
> +       struct pci_epf_bar *epf_bar;
> +       struct cdns_pcie_epf *epf;
> +       u64 pci_addr_mask = 0xff;
> +       u64 msg_addr;
> +       u16 flags;
> +       u8 bir;
> +
> +       /* Check whether the MSI-X feature has been enabled by the PCI host. */
> +       flags = cdns_pcie_ep_fn_readw(pcie, fn, cap + PCI_MSIX_FLAGS);
> +       if (!(flags & PCI_MSIX_FLAGS_ENABLE))
> +               return -EINVAL;
> +
> +       reg = cap + PCI_MSIX_TABLE;
> +       tbl_offset = cdns_pcie_ep_fn_readl(pcie, fn, reg);
> +       bir = tbl_offset & PCI_MSIX_TABLE_BIR;
> +       tbl_offset &= PCI_MSIX_TABLE_OFFSET;
> +
> +       epf = &ep->epf[fn];
> +       epf_bar = epf->epf_bar[bir];
> +       msix_tbl = epf_bar->addr;
> +       msix_tbl = (struct pci_epf_msix_tbl *)((char *)msix_tbl + tbl_offset);
> +
> +       msg_addr = msix_tbl[(interrupt_num - 1)].msg_addr;
> +       msg_data = msix_tbl[(interrupt_num - 1)].msg_data;
> +       vec_ctrl = msix_tbl[(interrupt_num - 1)].vector_ctrl;
> +
> +       /* Set the outbound region if needed. */
> +       if (unlikely(ep->irq_pci_addr != (msg_addr & ~pci_addr_mask) ||
I'm not sure about this _unlikely_, because unlike MSI, msg_addr will
be different for every vector.
It's interesting if safe to assume that host will allocate all message
address in linear fashion,
in that case maybe it's wiser to map all the the area at once and just
offset into it.

Thanks,
Ramon.

> +                    ep->irq_pci_fn != fn)) {
> +               /* First region was reserved for IRQ writes. */
> +               cdns_pcie_set_outbound_region(pcie, fn, 0,
> +                                             false,
> +                                             ep->irq_phys_addr,
> +                                             msg_addr & ~pci_addr_mask,
> +                                             pci_addr_mask + 1);
> +               ep->irq_pci_addr = (msg_addr & ~pci_addr_mask);
> +               ep->irq_pci_fn = fn;
> +       }
> +       writel(msg_data, ep->irq_cpu_addr + (msg_addr & pci_addr_mask));
> +
> +       return 0;
> +}
> +
>  static int cdns_pcie_ep_raise_irq(struct pci_epc *epc, u8 fn,
>                                   enum pci_epc_irq_type type,
>                                   u16 interrupt_num)
> @@ -344,6 +444,9 @@ static int cdns_pcie_ep_raise_irq(struct pci_epc *epc, u8 fn,
>         case PCI_EPC_IRQ_MSI:
>                 return cdns_pcie_ep_send_msi_irq(ep, fn, interrupt_num);
>
> +       case PCI_EPC_IRQ_MSIX:
> +               return cdns_pcie_ep_send_msix_irq(ep, fn, interrupt_num);
> +
>         default:
>                 break;
>         }
> @@ -381,7 +484,7 @@ static int cdns_pcie_ep_start(struct pci_epc *epc)
>  static const struct pci_epc_features cdns_pcie_epc_features = {
>         .linkup_notifier = false,
>         .msi_capable = true,
> -       .msix_capable = false,
> +       .msix_capable = true,
>  };
>
>  static const struct pci_epc_features*
> @@ -398,6 +501,8 @@ static const struct pci_epc_ops cdns_pcie_epc_ops = {
>         .unmap_addr     = cdns_pcie_ep_unmap_addr,
>         .set_msi        = cdns_pcie_ep_set_msi,
>         .get_msi        = cdns_pcie_ep_get_msi,
> +       .set_msix       = cdns_pcie_ep_set_msix,
> +       .get_msix       = cdns_pcie_ep_get_msix,
>         .raise_irq      = cdns_pcie_ep_raise_irq,
>         .start          = cdns_pcie_ep_start,
>         .get_features   = cdns_pcie_ep_get_features,
> @@ -457,6 +562,11 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
>         if (of_property_read_u8(np, "max-functions", &epc->max_functions) < 0)
>                 epc->max_functions = 1;
>
> +       ep->epf = devm_kcalloc(dev, epc->max_functions, sizeof(*ep->epf),
> +                              GFP_KERNEL);
> +       if (!ep->epf)
> +               return -ENOMEM;
> +
>         ret = pci_epc_mem_init(epc, pcie->mem_res->start,
>                                resource_size(pcie->mem_res));
>         if (ret < 0) {
> diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
> index ffa8b9f78ff8..207d6ba03f70 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence.h
> +++ b/drivers/pci/controller/cadence/pcie-cadence.h
> @@ -99,6 +99,7 @@
>  #define CDNS_PCIE_EP_FUNC_BASE(fn)     (((fn) << 12) & GENMASK(19, 12))
>
>  #define CDNS_PCIE_EP_FUNC_MSI_CAP_OFFSET       0x90
> +#define CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET      0xb0
>
>  /*
>   * Root Port Registers (PCI configuration space for the root port function)
> @@ -281,6 +282,14 @@ struct cdns_pcie_rc {
>         u16                     device_id;
>  };
>
> +/**
> + * struct cdns_pcie_epf - Structure to hold info about endpoint function
> + * @epf_bar: reference to the pci_epf_bar for the six Base Address Registers
> + */
> +struct cdns_pcie_epf {
> +       struct pci_epf_bar *epf_bar[PCI_STD_NUM_BARS];
> +};
> +
>  /**
>   * struct cdns_pcie_ep - private data for this PCIe endpoint controller driver
>   * @pcie: Cadence PCIe controller
> @@ -308,6 +317,7 @@ struct cdns_pcie_ep {
>         u64                     irq_pci_addr;
>         u8                      irq_pci_fn;
>         u8                      irq_pending;
> +       struct cdns_pcie_epf    *epf;
>  };
>
>
> --
> 2.17.1
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-01-23 22:10 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-11 12:46 [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core Kishon Vijay Abraham I
2019-12-11 12:46 ` [PATCH 1/4] PCI: endpoint: Fix ->set_msix() to take BIR and offset as arguments Kishon Vijay Abraham I
2019-12-11 12:46 ` [PATCH 2/4] PCI: dwc: Fix dw_pcie_ep_raise_msix_irq() to get correct MSIX table address Kishon Vijay Abraham I
2019-12-11 12:46 ` [PATCH 3/4] PCI: keystone: Allow AM654 PCIe Endpoint to raise MSIX interrupt Kishon Vijay Abraham I
2019-12-11 12:46 ` [PATCH 4/4] PCI: cadence: Add MSI-X support to Endpoint driver Kishon Vijay Abraham I
2020-01-23 22:10   ` Ramon Fried
2019-12-11 22:46 ` [PATCH 0/4] Redesign MSI-X support in PCIe Endpoint Core Bjorn Helgaas
2020-01-09 10:19   ` Kishon Vijay Abraham I
2020-01-09 10:20     ` Xiaowei Bao
2020-01-09 10:33     ` Gustavo Pimentel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).