linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/5] powerpc/powernv: PHB3 Support
@ 2013-04-23 11:03 Gavin Shan
  2013-04-23 11:03 ` [PATCH 1/5] powerpc/powernv: Supports PHB3 Gavin Shan
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Gavin Shan @ 2013-04-23 11:03 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan

The patchset includes minimal support for PHB3. Initially, flag "PNV_PHB_IODA2"
is introduced to differentiate IODA2 compliant PHB3 from other types of PHBs and
do initialization accordingly for PHB3. Besides, variable IODA2 tables reside in
system memory and we allocate them in kernel, then pass them to f/w and enable
the corresponding BARs through OPAL API. The P/Q bits of IVE should be handled
on PHB3 by software and the patchset intends to cover that as well.

NOTE: The first patch comes from Ben.

v1 -> v2
	* Introduce CONFIG_POWERNV_MSI, which is similiar to CONFIG_PSERIES_MSI
	* Enable CONFIG_PPC_MSI_BITMAP while selecting CONFIG_POWERNV_MSI
	* Eleminate (struct pnv_phb::msi_count) since it has been removed in
	  linux-next
	* Replace (CONFIG_PPC_POWERNV && CONFIG_PCI_MSI) with CONFIG_POWERNV_MSI
	* Move declaration of pnv_pci_msi_eoi() to asm/xics.h
	* Remove unnecessary "#ifdef ... #endif" in icp-native.c
	* Add support to invalidate TCE
	* Let the IODA2 table allocated by firmware and kernel to retrieve them
	  through device-tree

---

arch/powerpc/include/asm/iommu.h            |    1 +
arch/powerpc/include/asm/opal.h             |    5 +-
arch/powerpc/include/asm/xics.h             |    3 +
arch/powerpc/platforms/powernv/Kconfig      |    5 +
arch/powerpc/platforms/powernv/pci-ioda.c   |  209 +++++++++++++++++++++++----
arch/powerpc/platforms/powernv/pci-p5ioc2.c |    2 +
arch/powerpc/platforms/powernv/pci.c        |   74 ++++------
arch/powerpc/platforms/powernv/pci.h        |   24 +++-
arch/powerpc/sysdev/Kconfig                 |    1 +
arch/powerpc/sysdev/xics/icp-native.c       |   27 ++++-
10 files changed, 267 insertions(+), 84 deletions(-)

Thanks,
Gavin

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

* [PATCH 1/5] powerpc/powernv: Supports PHB3
  2013-04-23 11:03 [PATCH v2 0/5] powerpc/powernv: PHB3 Support Gavin Shan
@ 2013-04-23 11:03 ` Gavin Shan
  2013-04-23 15:19   ` Benjamin Herrenschmidt
  2013-04-23 11:03 ` [PATCH 2/5] powerpc/powernv: Retrieve IODA2 tables explicitly Gavin Shan
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Gavin Shan @ 2013-04-23 11:03 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan

The patch intends to initialize PHB3 during system boot stage. The
flag "PNV_PHB_MODEL_PHB3" is introduced to differentiate IODA2
compatible PHB3 from other types of PHBs.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/platforms/powernv/pci-ioda.c |   62 +++++++++++++++--------------
 arch/powerpc/platforms/powernv/pci.c      |    7 +++-
 arch/powerpc/platforms/powernv/pci.h      |    8 ++-
 3 files changed, 43 insertions(+), 34 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index a5c5f15..3d4e958 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -852,18 +852,19 @@ static u32 pnv_ioda_bdfn_to_pe(struct pnv_phb *phb, struct pci_bus *bus,
 	return phb->ioda.pe_rmap[(bus->number << 8) | devfn];
 }
 
-void __init pnv_pci_init_ioda1_phb(struct device_node *np)
+void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type)
 {
 	struct pci_controller *hose;
 	static int primary = 1;
 	struct pnv_phb *phb;
 	unsigned long size, m32map_off, iomap_off, pemap_off;
 	const u64 *prop64;
+	const u32 *prop32;
 	u64 phb_id;
 	void *aux;
 	long rc;
 
-	pr_info(" Initializing IODA OPAL PHB %s\n", np->full_name);
+	pr_info(" Initializing IODA%d OPAL PHB %s\n", ioda_type, np->full_name);
 
 	prop64 = of_get_property(np, "ibm,opal-phbid", NULL);
 	if (!prop64) {
@@ -890,37 +891,34 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
 	hose->last_busno = 0xff;
 	hose->private_data = phb;
 	phb->opal_id = phb_id;
-	phb->type = PNV_PHB_IODA1;
+	phb->type = ioda_type;
 
 	/* Detect specific models for error handling */
 	if (of_device_is_compatible(np, "ibm,p7ioc-pciex"))
 		phb->model = PNV_PHB_MODEL_P7IOC;
+	else if (of_device_is_compatible(np, "ibm,p8-pciex"))
+		phb->model = PNV_PHB_MODEL_PHB3;
 	else
 		phb->model = PNV_PHB_MODEL_UNKNOWN;
 
-	/* We parse "ranges" now since we need to deduce the register base
-	 * from the IO base
-	 */
+	/* Parse 32-bit and IO ranges (if any) */
 	pci_process_bridge_OF_ranges(phb->hose, np, primary);
 	primary = 0;
 
-	/* Magic formula from Milton */
+	/* Get registers */
 	phb->regs = of_iomap(np, 0);
 	if (phb->regs == NULL)
 		pr_err("  Failed to map registers !\n");
 
-
-	/* XXX This is hack-a-thon. This needs to be changed so that:
-	 *  - we obtain stuff like PE# etc... from device-tree
-	 *  - we properly re-allocate M32 ourselves
-	 *    (the OFW one isn't very good)
-	 */
-
 	/* Initialize more IODA stuff */
-	phb->ioda.total_pe = 128;
+	prop32 = of_get_property(np, "ibm,opal-num-pes", NULL);
+	if (!prop32)
+		phb->ioda.total_pe = 1;
+	else
+		phb->ioda.total_pe = *prop32;
 
 	phb->ioda.m32_size = resource_size(&hose->mem_resources[0]);
-	/* OFW Has already off top 64k of M32 space (MSI space) */
+	/* FW Has already off top 64k of M32 space (MSI space) */
 	phb->ioda.m32_size += 0x10000;
 
 	phb->ioda.m32_segsize = phb->ioda.m32_size / phb->ioda.total_pe;
@@ -930,7 +928,10 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
 	phb->ioda.io_segsize = phb->ioda.io_size / phb->ioda.total_pe;
 	phb->ioda.io_pci_base = 0; /* XXX calculate this ? */
 
-	/* Allocate aux data & arrays */
+	/* Allocate aux data & arrays
+	 *
+	 * XXX TODO: Don't allocate io segmap on PHB3
+	 */
 	size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long));
 	m32map_off = size;
 	size += phb->ioda.total_pe * sizeof(phb->ioda.m32_segmap[0]);
@@ -960,7 +961,7 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
 	hose->mem_resources[2].start = 0;
 	hose->mem_resources[2].end = 0;
 
-#if 0
+#if 0 /* We should really do that ... */
 	rc = opal_pci_set_phb_mem_window(opal->phb_id,
 					 window_type,
 					 window_num,
@@ -974,16 +975,6 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
 		phb->ioda.m32_size, phb->ioda.m32_segsize,
 		phb->ioda.io_size, phb->ioda.io_segsize);
 
-	if (phb->regs)  {
-		pr_devel(" BUID     = 0x%016llx\n", in_be64(phb->regs + 0x100));
-		pr_devel(" PHB2_CR  = 0x%016llx\n", in_be64(phb->regs + 0x160));
-		pr_devel(" IO_BAR   = 0x%016llx\n", in_be64(phb->regs + 0x170));
-		pr_devel(" IO_BAMR  = 0x%016llx\n", in_be64(phb->regs + 0x178));
-		pr_devel(" IO_SAR   = 0x%016llx\n", in_be64(phb->regs + 0x180));
-		pr_devel(" M32_BAR  = 0x%016llx\n", in_be64(phb->regs + 0x190));
-		pr_devel(" M32_BAMR = 0x%016llx\n", in_be64(phb->regs + 0x198));
-		pr_devel(" M32_SAR  = 0x%016llx\n", in_be64(phb->regs + 0x1a0));
-	}
 	phb->hose->ops = &pnv_pci_ops;
 
 	/* Setup RID -> PE mapping function */
@@ -1011,7 +1002,18 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
 	rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, OPAL_ASSERT_RESET);
 	if (rc)
 		pr_warning("  OPAL Error %ld performing IODA table reset !\n", rc);
-	opal_pci_set_pe(phb_id, 0, 0, 7, 1, 1 , OPAL_MAP_PE);
+
+	/*
+	 * On IODA1 map everything to PE#0, on IODA2 we assume the IODA reset
+	 * has cleared the RTT which has the same effect
+	 */
+	if (ioda_type == PNV_PHB_IODA1)
+		opal_pci_set_pe(phb_id, 0, 0, 7, 1, 1 , OPAL_MAP_PE);
+}
+
+void pnv_pci_init_ioda2_phb(struct device_node *np)
+{
+	pnv_pci_init_ioda_phb(np, PNV_PHB_IODA2);
 }
 
 void __init pnv_pci_init_ioda_hub(struct device_node *np)
@@ -1034,6 +1036,6 @@ void __init pnv_pci_init_ioda_hub(struct device_node *np)
 	for_each_child_of_node(np, phbn) {
 		/* Look for IODA1 PHBs */
 		if (of_device_is_compatible(phbn, "ibm,ioda-phb"))
-			pnv_pci_init_ioda1_phb(phbn);
+			pnv_pci_init_ioda_phb(phbn, PNV_PHB_IODA1);
 	}
 }
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index 42eee93..83514dc 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -492,12 +492,13 @@ static void pnv_pci_dma_dev_setup(struct pci_dev *pdev)
 		pnv_pci_dma_fallback_setup(hose, pdev);
 }
 
-/* Fixup wrong class code in p7ioc root complex */
+/* Fixup wrong class code in p7ioc and p8 root complex */
 static void pnv_p7ioc_rc_quirk(struct pci_dev *dev)
 {
 	dev->class = PCI_CLASS_BRIDGE_PCI << 8;
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM, 0x3b9, pnv_p7ioc_rc_quirk);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM, 0x2da, pnv_p7ioc_rc_quirk);
 
 static int pnv_pci_probe_mode(struct pci_bus *bus)
 {
@@ -558,6 +559,10 @@ void __init pnv_pci_init(void)
 		if (!found_ioda)
 			for_each_compatible_node(np, NULL, "ibm,p5ioc2")
 				pnv_pci_init_p5ioc2_hub(np);
+
+		/* Look for ioda2 built-in PHB3's */
+		for_each_compatible_node(np, NULL, "ibm,ioda2-phb")
+			pnv_pci_init_ioda2_phb(np);
 	}
 
 	/* Setup the linkage between OF nodes and PHBs */
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 42ddfba..f6314d6 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -4,9 +4,9 @@
 struct pci_dn;
 
 enum pnv_phb_type {
-	PNV_PHB_P5IOC2,
-	PNV_PHB_IODA1,
-	PNV_PHB_IODA2,
+	PNV_PHB_P5IOC2	= 0,
+	PNV_PHB_IODA1	= 1,
+	PNV_PHB_IODA2	= 2,
 };
 
 /* Precise PHB model for error management */
@@ -14,6 +14,7 @@ enum pnv_phb_model {
 	PNV_PHB_MODEL_UNKNOWN,
 	PNV_PHB_MODEL_P5IOC2,
 	PNV_PHB_MODEL_P7IOC,
+	PNV_PHB_MODEL_PHB3,
 };
 
 #define PNV_PCI_DIAG_BUF_SIZE	4096
@@ -148,6 +149,7 @@ extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
 				      u64 dma_offset);
 extern void pnv_pci_init_p5ioc2_hub(struct device_node *np);
 extern void pnv_pci_init_ioda_hub(struct device_node *np);
+extern void pnv_pci_init_ioda2_phb(struct device_node *np);
 
 
 #endif /* __POWERNV_PCI_H */
-- 
1.7.5.4

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

* [PATCH 2/5] powerpc/powernv: Retrieve IODA2 tables explicitly
  2013-04-23 11:03 [PATCH v2 0/5] powerpc/powernv: PHB3 Support Gavin Shan
  2013-04-23 11:03 ` [PATCH 1/5] powerpc/powernv: Supports PHB3 Gavin Shan
@ 2013-04-23 11:03 ` Gavin Shan
  2013-04-23 11:03 ` [PATCH 3/5] powerpc/powernv: Add option CONFIG_POWERNV_MSI Gavin Shan
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Gavin Shan @ 2013-04-23 11:03 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan

The PHB3, which is compatible with IODA2, have lots of tables (RTT/
PETLV/PEST/IVT/RBA) in system memory and have corresponding BARs to
trace the system memory address. The tables have been allocated in
firmware and exported through device-tree. The patch retrieves the
tables explicitly.

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/opal.h           |    5 +--
 arch/powerpc/platforms/powernv/pci-ioda.c |   35 +++++++++++++++++++++++++++++
 arch/powerpc/platforms/powernv/pci.h      |   13 ++++++++++
 3 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index a4b28f1..0af7ba0 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -491,9 +491,8 @@ int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number,
 				    uint16_t window_type, uint16_t window_num,
 				    uint16_t segment_num);
 int64_t opal_pci_set_phb_table_memory(uint64_t phb_id, uint64_t rtt_addr,
-				      uint64_t ivt_addr, uint64_t ivt_len,
-				      uint64_t reject_array_addr,
-				      uint64_t peltv_addr);
+				      uint64_t peltv_addr, uint64_t pest_addr,
+				      uint64_t ivt_addr, uint64_t rba_addr);
 int64_t opal_pci_set_pe(uint64_t phb_id, uint64_t pe_number, uint64_t bus_dev_func,
 			uint8_t bus_compare, uint8_t dev_compare, uint8_t func_compare,
 			uint8_t pe_action);
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 3d4e958..0c15870 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -852,6 +852,23 @@ static u32 pnv_ioda_bdfn_to_pe(struct pnv_phb *phb, struct pci_bus *bus,
 	return phb->ioda.pe_rmap[(bus->number << 8) | devfn];
 }
 
+static void __init pnv_pci_get_ioda2_table(struct device_node *np,
+					   const char *name,
+					   void **table,
+					   unsigned int *len)
+{
+	const u32 *prop32;
+	u64 base;
+
+	prop32 = of_get_property(np, name, NULL);
+	if (prop32) {
+		base = be32_to_cpup(prop32);
+		base = base << 32 | be32_to_cpup(prop32 + 1);
+		*table = __va(base);
+		*len = be32_to_cpup(prop32 + 2);
+	}
+}
+
 void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type)
 {
 	struct pci_controller *hose;
@@ -998,6 +1015,24 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type)
 	ppc_md.pcibios_window_alignment = pnv_pci_window_alignment;
 	pci_add_flags(PCI_REASSIGN_ALL_RSRC);
 
+	/* Retrieve variable IODA2 tables */
+	if (ioda_type == PNV_PHB_IODA2) {
+		pnv_pci_get_ioda2_table(np, "ibm,opal-rtt-table",
+				&phb->ioda.tbl_rtt, &phb->ioda.rtt_len);
+		pnv_pci_get_ioda2_table(np, "ibm,opal-peltv-table",
+				&phb->ioda.tbl_peltv, &phb->ioda.peltv_len);
+		pnv_pci_get_ioda2_table(np, "ibm,opal-pest-table",
+				&phb->ioda.tbl_pest, &phb->ioda.pest_len);
+		pnv_pci_get_ioda2_table(np, "ibm,opal-ivt-table",
+				&phb->ioda.tbl_ivt, &phb->ioda.ivt_len);
+		pnv_pci_get_ioda2_table(np, "ibm,opal-rba-table",
+				&phb->ioda.tbl_rba, &phb->ioda.rba_len);
+		/* Get IVE stride */
+		prop32 = of_get_property(np, "ibm,opal-ive-stride", NULL);
+		if (prop32)
+			phb->ioda.ive_stride = be32_to_cpup(prop32);
+	}
+
 	/* Reset IODA tables to a clean state */
 	rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, OPAL_ASSERT_RESET);
 	if (rc)
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index f6314d6..c048c29 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -100,6 +100,19 @@ struct pnv_phb {
 			unsigned int		io_segsize;
 			unsigned int		io_pci_base;
 
+			/* Variable tables for IODA2 */
+			void			*tbl_rtt;
+			void			*tbl_peltv;
+			void			*tbl_pest;
+			void			*tbl_ivt;
+			void			*tbl_rba;
+			unsigned int		ive_stride;
+			unsigned int		rtt_len;
+			unsigned int		peltv_len;
+			unsigned int		pest_len;
+			unsigned int		ivt_len;
+			unsigned int		rba_len;
+
 			/* PE allocation bitmap */
 			unsigned long		*pe_alloc;
 
-- 
1.7.5.4

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

* [PATCH 3/5] powerpc/powernv: Add option CONFIG_POWERNV_MSI
  2013-04-23 11:03 [PATCH v2 0/5] powerpc/powernv: PHB3 Support Gavin Shan
  2013-04-23 11:03 ` [PATCH 1/5] powerpc/powernv: Supports PHB3 Gavin Shan
  2013-04-23 11:03 ` [PATCH 2/5] powerpc/powernv: Retrieve IODA2 tables explicitly Gavin Shan
@ 2013-04-23 11:03 ` Gavin Shan
  2013-04-23 11:03 ` [PATCH 4/5] powerpc/powernv: Patch MSI EOI handler on P8 Gavin Shan
  2013-04-23 11:03 ` [PATCH 5/5] powerpc/powernv: TCE invalidation for PHB3 Gavin Shan
  4 siblings, 0 replies; 12+ messages in thread
From: Gavin Shan @ 2013-04-23 11:03 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan

As Michael Ellerman suggested, to add CONFIG_POWERNV_MSI for PowerNV
platform. That's similar to CONFIG_PSERIES_MSI for pSeries platform.
For now, we don't make it dependent on CONFIG_EEH since it's not ready
to enable that yet.

Apart from that, we also enable CONFIG_PPC_MSI_BITMAP on selecting
CONFIG_POWERNV_MSI.

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/powernv/Kconfig |    5 +++++
 arch/powerpc/sysdev/Kconfig            |    1 +
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig
index 74fea5c..d3e840d 100644
--- a/arch/powerpc/platforms/powernv/Kconfig
+++ b/arch/powerpc/platforms/powernv/Kconfig
@@ -8,6 +8,11 @@ config PPC_POWERNV
 	select PPC_PCI_CHOICE if EMBEDDED
 	default y
 
+config POWERNV_MSI
+	bool "Support PCI MSI on PowerNV platform"
+	depends on PCI_MSI
+	default y
+
 config PPC_POWERNV_RTAS
 	depends on PPC_POWERNV
 	bool "Support for RTAS based PowerNV platforms such as BML"
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index a84fecf..ab4cb54 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -19,6 +19,7 @@ config PPC_MSI_BITMAP
 	default y if MPIC
 	default y if FSL_PCI
 	default y if PPC4xx_MSI
+	default y if POWERNV_MSI
 
 source "arch/powerpc/sysdev/xics/Kconfig"
 
-- 
1.7.5.4

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

* [PATCH 4/5] powerpc/powernv: Patch MSI EOI handler on P8
  2013-04-23 11:03 [PATCH v2 0/5] powerpc/powernv: PHB3 Support Gavin Shan
                   ` (2 preceding siblings ...)
  2013-04-23 11:03 ` [PATCH 3/5] powerpc/powernv: Add option CONFIG_POWERNV_MSI Gavin Shan
@ 2013-04-23 11:03 ` Gavin Shan
  2013-04-23 15:21   ` Benjamin Herrenschmidt
  2013-04-23 11:03 ` [PATCH 5/5] powerpc/powernv: TCE invalidation for PHB3 Gavin Shan
  4 siblings, 1 reply; 12+ messages in thread
From: Gavin Shan @ 2013-04-23 11:03 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan

The EOI handler of MSI/MSI-X interrupts for P8 (PHB3) need additional
steps to handle the P/Q bits in IVE before EOIing the corresponding
interrupt. The patch changes the EOI handler to cover that.

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/xics.h           |    3 ++
 arch/powerpc/platforms/powernv/pci-ioda.c |   33 +++++++++++++++++++++++++++++
 arch/powerpc/platforms/powernv/pci.c      |   19 ++++++++++++++++
 arch/powerpc/platforms/powernv/pci.h      |    1 +
 arch/powerpc/sysdev/xics/icp-native.c     |   27 ++++++++++++++++++++++-
 5 files changed, 82 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/include/asm/xics.h b/arch/powerpc/include/asm/xics.h
index 4ae9a09..c4b364b 100644
--- a/arch/powerpc/include/asm/xics.h
+++ b/arch/powerpc/include/asm/xics.h
@@ -72,6 +72,9 @@ extern int ics_opal_init(void);
 static inline int ics_opal_init(void) { return -ENODEV; }
 #endif
 
+/* Extra EOI handler for PHB3 */
+extern int pnv_pci_msi_eoi(unsigned int hw_irq);
+
 /* ICS instance, hooked up to chip_data of an irq */
 struct ics {
 	struct list_head link;
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 0c15870..8ec77a7 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -646,6 +646,37 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
 	return 0;
 }
 
+static int pnv_pci_ioda_msi_eoi(struct pnv_phb *phb, unsigned int hw_irq)
+{
+	u8 p_bit = 1, q_bit = 1;
+	long rc;
+
+	while (p_bit || q_bit) {
+		rc = opal_pci_get_xive_reissue(phb->opal_id,
+				hw_irq - phb->msi_base, &p_bit, &q_bit);
+		if (rc) {
+			pr_warning("%s: Failed to get P/Q bits of IRQ#%d "
+				   "on PHB#%d, rc=%ld\n", __func__, hw_irq,
+				   phb->hose->global_number, rc);
+			return -EIO;
+		}
+		if (!p_bit && !q_bit)
+			break;
+
+		rc = opal_pci_set_xive_reissue(phb->opal_id,
+				hw_irq - phb->msi_base, p_bit, q_bit);
+		if (rc) {
+			pr_warning("%s: Failed to clear P/Q (%01d/%01d) of "
+				   "IRQ#%d on PHB#%d, rc=%ld\n", __func__,
+				   p_bit, q_bit, hw_irq,
+				   phb->hose->global_number, rc);
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
 static void pnv_pci_init_ioda_msis(struct pnv_phb *phb)
 {
 	unsigned int count;
@@ -667,6 +698,8 @@ static void pnv_pci_init_ioda_msis(struct pnv_phb *phb)
 	}
 
 	phb->msi_setup = pnv_pci_ioda_msi_setup;
+	if (phb->type == PNV_PHB_IODA2)
+		phb->msi_eoi = pnv_pci_ioda_msi_eoi;
 	phb->msi32_support = 1;
 	pr_info("  Allocated bitmap for %d MSIs (base IRQ 0x%x)\n",
 		count, phb->msi_base);
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index 83514dc..1a03f42 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -115,6 +115,25 @@ static void pnv_teardown_msi_irqs(struct pci_dev *pdev)
 		irq_dispose_mapping(entry->irq);
 	}
 }
+
+int pnv_pci_msi_eoi(unsigned int hw_irq)
+{
+	struct pci_controller *hose, *tmp;
+	struct pnv_phb *phb = NULL;
+
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+		phb = hose->private_data;
+		if (hw_irq >= phb->msi_base &&
+		    hw_irq < phb->msi_base + phb->msi_bmp.irq_count) {
+			if (!phb->msi_eoi)
+				return -EEXIST;
+			return phb->msi_eoi(phb, hw_irq);
+		}
+	}
+
+	/* For LSI interrupts, we needn't do it */
+	return 0;
+}
 #endif /* CONFIG_PCI_MSI */
 
 static void pnv_pci_dump_p7ioc_diag_data(struct pnv_phb *phb)
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index c048c29..c6690b3 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -81,6 +81,7 @@ struct pnv_phb {
 	int (*msi_setup)(struct pnv_phb *phb, struct pci_dev *dev,
 			 unsigned int hwirq, unsigned int is_64,
 			 struct msi_msg *msg);
+	int (*msi_eoi)(struct pnv_phb *phb, unsigned int hw_irq);
 	void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev);
 	void (*fixup_phb)(struct pci_controller *hose);
 	u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn);
diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c
index 48861d3..38dd2b1 100644
--- a/arch/powerpc/sysdev/xics/icp-native.c
+++ b/arch/powerpc/sysdev/xics/icp-native.c
@@ -89,6 +89,22 @@ static void icp_native_eoi(struct irq_data *d)
 	icp_native_set_xirr((xics_pop_cppr() << 24) | hw_irq);
 }
 
+static void icp_p8_native_eoi(struct irq_data *d)
+{
+	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+	int ret;
+
+	/* Let firmware handle P/Q bits */
+	if (hw_irq != XICS_IPI) {
+		ret = pnv_pci_msi_eoi(hw_irq);
+		WARN_ON_ONCE(ret);
+	}
+
+	/* EOI on ICP */
+	iosync();
+	icp_native_set_xirr((xics_pop_cppr() << 24) | hw_irq);
+}
+
 static void icp_native_teardown_cpu(void)
 {
 	int cpu = smp_processor_id();
@@ -264,7 +280,7 @@ static int __init icp_native_init_one_node(struct device_node *np,
 	return 0;
 }
 
-static const struct icp_ops icp_native_ops = {
+static struct icp_ops icp_native_ops = {
 	.get_irq	= icp_native_get_irq,
 	.eoi		= icp_native_eoi,
 	.set_priority	= icp_native_set_cpu_priority,
@@ -296,6 +312,15 @@ int __init icp_native_init(void)
 	if (found == 0)
 		return -ENODEV;
 
+	/* Change the EOI handler for P8 */
+#ifdef CONFIG_POWERNV_MSI
+	np = of_find_compatible_node(NULL, NULL, "ibm,power8-xicp");
+	if (np) {
+		icp_native_ops.eoi = icp_p8_native_eoi;
+		of_node_put(np);
+	}
+#endif
+
 	icp_ops = &icp_native_ops;
 
 	return 0;
-- 
1.7.5.4

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

* [PATCH 5/5] powerpc/powernv: TCE invalidation for PHB3
  2013-04-23 11:03 [PATCH v2 0/5] powerpc/powernv: PHB3 Support Gavin Shan
                   ` (3 preceding siblings ...)
  2013-04-23 11:03 ` [PATCH 4/5] powerpc/powernv: Patch MSI EOI handler on P8 Gavin Shan
@ 2013-04-23 11:03 ` Gavin Shan
  2013-04-23 15:25   ` Benjamin Herrenschmidt
  4 siblings, 1 reply; 12+ messages in thread
From: Gavin Shan @ 2013-04-23 11:03 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan

The TCE should be invalidated while it's created or free'd. The
approach to do that for IODA1 and IODA2 compliant PHBs are different.
So the patch differentiate them with virtualized interface hooked
to the PHB. It's notable that the PCI address is used to invalidate
the corresponding TCE on IODA2 compliant PHB3.

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/iommu.h            |    1 +
 arch/powerpc/platforms/powernv/pci-ioda.c   |   79 ++++++++++++++++++++++++++-
 arch/powerpc/platforms/powernv/pci-p5ioc2.c |    2 +
 arch/powerpc/platforms/powernv/pci.c        |   48 ++---------------
 arch/powerpc/platforms/powernv/pci.h        |    2 +
 5 files changed, 86 insertions(+), 46 deletions(-)

diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h
index cbfe678..0db308e 100644
--- a/arch/powerpc/include/asm/iommu.h
+++ b/arch/powerpc/include/asm/iommu.h
@@ -76,6 +76,7 @@ struct iommu_table {
 	struct iommu_pool large_pool;
 	struct iommu_pool pools[IOMMU_NR_POOLS];
 	unsigned long *it_map;       /* A simple allocation bitmap for now */
+	void *sysdata;
 };
 
 struct scatterlist;
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 8ec77a7..a4b1c9a 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -448,6 +448,73 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus)
 	}
 }
 
+static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl,
+					 u64 *startp, u64 *endp)
+{
+	u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index;
+	unsigned long start, end, inc;
+
+	start = __pa(startp);
+	end = __pa(endp);
+
+	/* BML uses this case for p6/p7/galaxy2: Shift addr and put in node */
+	if (tbl->it_busno) {
+		start <<= 12;
+		end <<= 12;
+		inc = 128 << 12;
+		start |= tbl->it_busno;
+		end |= tbl->it_busno;
+	} else if (tbl->it_type & TCE_PCI_SWINV_PAIR) {
+		/* p7ioc-style invalidation, 2 TCEs per write */
+		start |= (1ull << 63);
+		end |= (1ull << 63);
+		inc = 16;
+        } else {
+		/* Default (older HW) */
+                inc = 128;
+	}
+
+        end |= inc - 1;	/* round up end to be different than start */
+
+        mb(); /* Ensure above stores are visible */
+        while (start <= end) {
+                __raw_writeq(start, invalidate);
+                start += inc;
+        }
+
+	/*
+	 * The iommu layer will do another mb() for us on build()
+	 * and we don't care on free()
+	 */
+}
+
+static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl,
+					 u64 *startp, u64 *endp)
+{
+	unsigned long start, end, inc;
+	u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index;
+	struct pnv_ioda_pe *pe = container_of(tbl, struct pnv_ioda_pe,
+					      tce32_table);
+
+	/* We'll invalidate DMA address in PE scope */
+	start = 0x2ul << 60;
+	start |= (pe->pe_number & 0xFF);
+	end = start;
+
+	/* Figure out the start, end and step */
+	inc = tbl->it_offset + (((u64)startp - tbl->it_base) / sizeof(u64));
+	start |= (inc << 12);
+	inc = tbl->it_offset + (((u64)endp - tbl->it_base) / sizeof(u64));
+	end |= (inc << 12);
+	inc = (0x1ul << 12);
+	mb();
+
+	while (start <= end) {
+		__raw_writeq(start, invalidate);
+		start += inc;
+	}
+}
+
 static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
 				      struct pnv_ioda_pe *pe, unsigned int base,
 				      unsigned int segs)
@@ -509,6 +576,9 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
 	pnv_pci_setup_iommu_table(tbl, addr, TCE32_TABLE_SIZE * segs,
 				  base << 28);
 
+	/* Hook the IOMMU table to PHB */
+	tbl->sysdata = phb;
+
 	/* OPAL variant of P7IOC SW invalidated TCEs */
 	swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL);
 	if (swinvp) {
@@ -519,8 +589,9 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
 		 */
 		tbl->it_busno = 0;
 		tbl->it_index = (unsigned long)ioremap(be64_to_cpup(swinvp), 8);
-		tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE
-			| TCE_PCI_SWINV_PAIR;
+		tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE;
+		if (phb->type == PNV_PHB_IODA1)
+			tbl->it_type |= TCE_PCI_SWINV_PAIR;
 	}
 	iommu_init_table(tbl, phb->hose->node);
 
@@ -1032,6 +1103,10 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type)
 
 	/* Setup TCEs */
 	phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup;
+	if (ioda_type == PNV_PHB_IODA1)
+		phb->dma_tce_invalidate = pnv_pci_ioda1_tce_invalidate;
+	else
+		phb->dma_tce_invalidate = pnv_pci_ioda2_tce_invalidate;
 
 	/* Setup MSI support */
 	pnv_pci_init_ioda_msis(phb);
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
index d5c066e..a5f791b 100644
--- a/arch/powerpc/platforms/powernv/pci-p5ioc2.c
+++ b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
@@ -167,6 +167,8 @@ static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np,
 
 	/* Setup TCEs */
 	phb->dma_dev_setup = pnv_pci_p5ioc2_dma_dev_setup;
+	phb->dma_tce_invalidate = NULL;
+	phb->p5ioc2.iommu_table.sysdata = phb;
 	pnv_pci_setup_iommu_table(&phb->p5ioc2.iommu_table,
 				  tce_mem, tce_size, 0);
 }
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index 1a03f42..d406cc0 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -348,52 +348,11 @@ struct pci_ops pnv_pci_ops = {
 	.write = pnv_pci_write_config,
 };
 
-
-static void pnv_tce_invalidate(struct iommu_table *tbl,
-			       u64 *startp, u64 *endp)
-{
-	u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index;
-	unsigned long start, end, inc;
-
-	start = __pa(startp);
-	end = __pa(endp);
-
-
-	/* BML uses this case for p6/p7/galaxy2: Shift addr and put in node */
-	if (tbl->it_busno) {
-		start <<= 12;
-		end <<= 12;
-		inc = 128 << 12;
-		start |= tbl->it_busno;
-		end |= tbl->it_busno;
-	}
-	/* p7ioc-style invalidation, 2 TCEs per write */
-	else if (tbl->it_type & TCE_PCI_SWINV_PAIR) {
-		start |= (1ull << 63);
-		end |= (1ull << 63);
-		inc = 16;
-	}
-	/* Default (older HW) */
-	else
-		inc = 128;
-
-	end |= inc - 1;		/* round up end to be different than start */
-
-	mb(); /* Ensure above stores are visible */
-	while (start <= end) {
-		__raw_writeq(start, invalidate);
-		start += inc;
-	}
-	/* The iommu layer will do another mb() for us on build() and
-	 * we don't care on free()
-	 */
-}
-
-
 static int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
 			 unsigned long uaddr, enum dma_data_direction direction,
 			 struct dma_attrs *attrs)
 {
+	struct pnv_phb *phb = tbl->sysdata;
 	u64 proto_tce;
 	u64 *tcep, *tces;
 	u64 rpn;
@@ -414,13 +373,14 @@ static int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
 	 * of flags if that becomes the case
 	 */
 	if (tbl->it_type & TCE_PCI_SWINV_CREATE)
-		pnv_tce_invalidate(tbl, tces, tcep - 1);
+		phb->dma_tce_invalidate(tbl, tces, tcep - 1);
 
 	return 0;
 }
 
 static void pnv_tce_free(struct iommu_table *tbl, long index, long npages)
 {
+	struct pnv_phb *phb = tbl->sysdata;
 	u64 *tcep, *tces;
 
 	tces = tcep = ((u64 *)tbl->it_base) + index - tbl->it_offset;
@@ -429,7 +389,7 @@ static void pnv_tce_free(struct iommu_table *tbl, long index, long npages)
 		*(tcep++) = 0;
 
 	if (tbl->it_type & TCE_PCI_SWINV_FREE)
-		pnv_tce_invalidate(tbl, tces, tcep - 1);
+		phb->dma_tce_invalidate(tbl, tces, tcep - 1);
 }
 
 static unsigned long pnv_tce_get(struct iommu_table *tbl, long index)
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index c6690b3..79a725e 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -83,6 +83,8 @@ struct pnv_phb {
 			 struct msi_msg *msg);
 	int (*msi_eoi)(struct pnv_phb *phb, unsigned int hw_irq);
 	void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev);
+	void (*dma_tce_invalidate)(struct iommu_table *tbl,
+				   u64 *startp, u64 *endp);
 	void (*fixup_phb)(struct pci_controller *hose);
 	u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn);
 
-- 
1.7.5.4

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

* Re: [PATCH 1/5] powerpc/powernv: Supports PHB3
  2013-04-23 11:03 ` [PATCH 1/5] powerpc/powernv: Supports PHB3 Gavin Shan
@ 2013-04-23 15:19   ` Benjamin Herrenschmidt
  2013-04-24  1:29     ` Gavin Shan
  0 siblings, 1 reply; 12+ messages in thread
From: Benjamin Herrenschmidt @ 2013-04-23 15:19 UTC (permalink / raw)
  To: Gavin Shan; +Cc: linuxppc-dev

On Tue, 2013-04-23 at 19:03 +0800, Gavin Shan wrote:
> -/* Fixup wrong class code in p7ioc root complex */
> +/* Fixup wrong class code in p7ioc and p8 root complex */
>  static void pnv_p7ioc_rc_quirk(struct pci_dev *dev)
>  {
>         dev->class = PCI_CLASS_BRIDGE_PCI << 8;
>  }
>  DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM, 0x3b9, pnv_p7ioc_rc_quirk);
> +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM, 0x2da, pnv_p7ioc_rc_quirk);
>  
This can go away from the normal patch, it is only necessary to work
around a problem in the simulator. The real PHB3 doesn't need the
workaround (p7ioc still does).

Cheers,
Ben.

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

* Re: [PATCH 4/5] powerpc/powernv: Patch MSI EOI handler on P8
  2013-04-23 11:03 ` [PATCH 4/5] powerpc/powernv: Patch MSI EOI handler on P8 Gavin Shan
@ 2013-04-23 15:21   ` Benjamin Herrenschmidt
  2013-04-24  1:31     ` Gavin Shan
  0 siblings, 1 reply; 12+ messages in thread
From: Benjamin Herrenschmidt @ 2013-04-23 15:21 UTC (permalink / raw)
  To: Gavin Shan; +Cc: linuxppc-dev

On Tue, 2013-04-23 at 19:03 +0800, Gavin Shan wrote:
> 
> +static int pnv_pci_ioda_msi_eoi(struct pnv_phb *phb, unsigned int hw_irq)
> +{
> +       u8 p_bit = 1, q_bit = 1;
> +       long rc;
> +
> +       while (p_bit || q_bit) {
> +               rc = opal_pci_get_xive_reissue(phb->opal_id,
> +                               hw_irq - phb->msi_base, &p_bit, &q_bit);
> +               if (rc) {
> +                       pr_warning("%s: Failed to get P/Q bits of IRQ#%d "
> +                                  "on PHB#%d, rc=%ld\n", __func__, hw_irq,
> +                                  phb->hose->global_number, rc);
> +                       return -EIO;
> +               }
> +               if (!p_bit && !q_bit)
> +                       break;
> +
> +               rc = opal_pci_set_xive_reissue(phb->opal_id,
> +                               hw_irq - phb->msi_base, p_bit, q_bit);
> +               if (rc) {
> +                       pr_warning("%s: Failed to clear P/Q (%01d/%01d) of "
> +                                  "IRQ#%d on PHB#%d, rc=%ld\n", __func__,
> +                                  p_bit, q_bit, hw_irq,
> +                                  phb->hose->global_number, rc);
> +                       return -EIO;
> +               }
> +       }
> +
> +       return 0;
> +}

Can you turn that into a single opal_pci_msi_eoi() ? This means that a
single MSI will trigger only one OPAL call rather than two which is
better for performances.

We will later implement an "optimized" variant using direct MMIO based
on knowing specifically the HW type but not now.

Cheers,
Ben.

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

* Re: [PATCH 5/5] powerpc/powernv: TCE invalidation for PHB3
  2013-04-23 11:03 ` [PATCH 5/5] powerpc/powernv: TCE invalidation for PHB3 Gavin Shan
@ 2013-04-23 15:25   ` Benjamin Herrenschmidt
  2013-04-24  1:32     ` Gavin Shan
  0 siblings, 1 reply; 12+ messages in thread
From: Benjamin Herrenschmidt @ 2013-04-23 15:25 UTC (permalink / raw)
  To: Gavin Shan; +Cc: linuxppc-dev

On Tue, 2013-04-23 at 19:03 +0800, Gavin Shan wrote:
>          * of flags if that becomes the case
>          */
>         if (tbl->it_type & TCE_PCI_SWINV_CREATE)
> -               pnv_tce_invalidate(tbl, tces, tcep - 1);
> +               phb->dma_tce_invalidate(tbl, tces, tcep - 1);
>  
>         return 0;
>  }

TCE invalidate is very performance sensitive, we might be better off
doing the if (ioda_type == PNV_PHB_IODA1) ... else ... here (which
the CPU can generally predict) rather than a function pointer call
which can be more tricky.

Cheers,
Ben.

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

* Re: [PATCH 1/5] powerpc/powernv: Supports PHB3
  2013-04-23 15:19   ` Benjamin Herrenschmidt
@ 2013-04-24  1:29     ` Gavin Shan
  0 siblings, 0 replies; 12+ messages in thread
From: Gavin Shan @ 2013-04-24  1:29 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Gavin Shan

On Wed, Apr 24, 2013 at 01:19:00AM +1000, Benjamin Herrenschmidt wrote:
>On Tue, 2013-04-23 at 19:03 +0800, Gavin Shan wrote:
>> -/* Fixup wrong class code in p7ioc root complex */
>> +/* Fixup wrong class code in p7ioc and p8 root complex */
>>  static void pnv_p7ioc_rc_quirk(struct pci_dev *dev)
>>  {
>>         dev->class = PCI_CLASS_BRIDGE_PCI << 8;
>>  }
>>  DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM, 0x3b9, pnv_p7ioc_rc_quirk);
>> +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM, 0x2da, pnv_p7ioc_rc_quirk);
>>  
>This can go away from the normal patch, it is only necessary to work
>around a problem in the simulator. The real PHB3 doesn't need the
>workaround (p7ioc still does).
>

Ok. I'll remove it in next version ;-)

Thanks,
Gavin

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

* Re: [PATCH 4/5] powerpc/powernv: Patch MSI EOI handler on P8
  2013-04-23 15:21   ` Benjamin Herrenschmidt
@ 2013-04-24  1:31     ` Gavin Shan
  0 siblings, 0 replies; 12+ messages in thread
From: Gavin Shan @ 2013-04-24  1:31 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Gavin Shan

On Wed, Apr 24, 2013 at 01:21:53AM +1000, Benjamin Herrenschmidt wrote:
>On Tue, 2013-04-23 at 19:03 +0800, Gavin Shan wrote:
>> 
>> +static int pnv_pci_ioda_msi_eoi(struct pnv_phb *phb, unsigned int hw_irq)
>> +{
>> +       u8 p_bit = 1, q_bit = 1;
>> +       long rc;
>> +
>> +       while (p_bit || q_bit) {
>> +               rc = opal_pci_get_xive_reissue(phb->opal_id,
>> +                               hw_irq - phb->msi_base, &p_bit, &q_bit);
>> +               if (rc) {
>> +                       pr_warning("%s: Failed to get P/Q bits of IRQ#%d "
>> +                                  "on PHB#%d, rc=%ld\n", __func__, hw_irq,
>> +                                  phb->hose->global_number, rc);
>> +                       return -EIO;
>> +               }
>> +               if (!p_bit && !q_bit)
>> +                       break;
>> +
>> +               rc = opal_pci_set_xive_reissue(phb->opal_id,
>> +                               hw_irq - phb->msi_base, p_bit, q_bit);
>> +               if (rc) {
>> +                       pr_warning("%s: Failed to clear P/Q (%01d/%01d) of "
>> +                                  "IRQ#%d on PHB#%d, rc=%ld\n", __func__,
>> +                                  p_bit, q_bit, hw_irq,
>> +                                  phb->hose->global_number, rc);
>> +                       return -EIO;
>> +               }
>> +       }
>> +
>> +       return 0;
>> +}
>
>Can you turn that into a single opal_pci_msi_eoi() ? This means that a
>single MSI will trigger only one OPAL call rather than two which is
>better for performances.
>

Ok. I will add new OPAL API opal_pci_msi_eoi() and use that in next version.

>We will later implement an "optimized" variant using direct MMIO based
>on knowing specifically the HW type but not now.
>

Ok :-)

Thanks,
Gavin

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

* Re: [PATCH 5/5] powerpc/powernv: TCE invalidation for PHB3
  2013-04-23 15:25   ` Benjamin Herrenschmidt
@ 2013-04-24  1:32     ` Gavin Shan
  0 siblings, 0 replies; 12+ messages in thread
From: Gavin Shan @ 2013-04-24  1:32 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Gavin Shan

On Wed, Apr 24, 2013 at 01:25:08AM +1000, Benjamin Herrenschmidt wrote:
>On Tue, 2013-04-23 at 19:03 +0800, Gavin Shan wrote:
>>          * of flags if that becomes the case
>>          */
>>         if (tbl->it_type & TCE_PCI_SWINV_CREATE)
>> -               pnv_tce_invalidate(tbl, tces, tcep - 1);
>> +               phb->dma_tce_invalidate(tbl, tces, tcep - 1);
>>  
>>         return 0;
>>  }
>
>TCE invalidate is very performance sensitive, we might be better off
>doing the if (ioda_type == PNV_PHB_IODA1) ... else ... here (which
>the CPU can generally predict) rather than a function pointer call
>which can be more tricky.
>

Ok. I'll change it in next version ;-)

Thanks,
Gavin

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

end of thread, other threads:[~2013-04-24  1:32 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-23 11:03 [PATCH v2 0/5] powerpc/powernv: PHB3 Support Gavin Shan
2013-04-23 11:03 ` [PATCH 1/5] powerpc/powernv: Supports PHB3 Gavin Shan
2013-04-23 15:19   ` Benjamin Herrenschmidt
2013-04-24  1:29     ` Gavin Shan
2013-04-23 11:03 ` [PATCH 2/5] powerpc/powernv: Retrieve IODA2 tables explicitly Gavin Shan
2013-04-23 11:03 ` [PATCH 3/5] powerpc/powernv: Add option CONFIG_POWERNV_MSI Gavin Shan
2013-04-23 11:03 ` [PATCH 4/5] powerpc/powernv: Patch MSI EOI handler on P8 Gavin Shan
2013-04-23 15:21   ` Benjamin Herrenschmidt
2013-04-24  1:31     ` Gavin Shan
2013-04-23 11:03 ` [PATCH 5/5] powerpc/powernv: TCE invalidation for PHB3 Gavin Shan
2013-04-23 15:25   ` Benjamin Herrenschmidt
2013-04-24  1:32     ` Gavin Shan

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).