[Skiboot] [PATCH 2/2] phb4: set PBCQ Tunnel BAR for tunneled operations

Philippe Bergheaud felix at linux.vnet.ibm.com
Tue Oct 24 00:08:30 AEDT 2017


P9 supports PCI tunneled operations (atomics and as_notify) that require
setting the PBCQ Tunnel BAR Response register with an address mask.

This register is currently initialized by enable_capi_mode(). As tunneled
operations may also operate in PCI mode, a new API is required to set the
PBCQ Tunnel BAR Response register without switching to CAPI mode.

This patch provides two new OPAL calls to get/set the PBCQ Tunnel BAR
Response register.

This new API aims at letting devices drivers set the PBCQ Tunnel BAR.
Compatibility with older kernel versions is made by enable_capi_mode().

Signed-off-by: Philippe Bergheaud <felix at linux.vnet.ibm.com>
---
 core/pci-opal.c    | 33 +++++++++++++++++++++++++++
 hw/phb4.c          | 65 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 include/opal-api.h |  4 +++-
 include/pci.h      |  4 ++++
 4 files changed, 100 insertions(+), 6 deletions(-)

diff --git a/core/pci-opal.c b/core/pci-opal.c
index bbbbcd5d..d7f4230a 100644
--- a/core/pci-opal.c
+++ b/core/pci-opal.c
@@ -1052,3 +1052,36 @@ static int64_t opal_pci_set_phb_cmpm(uint64_t phb_id, uint64_t phb_reg,
 	return rc;
 }
 opal_call(OPAL_PCI_SET_PHB_CMPM, opal_pci_set_phb_cmpm, 3);
+
+static int64_t opal_pci_get_pbcq_tunnel_bar(uint64_t phb_id, uint64_t *addr)
+{
+	struct phb *phb = pci_get_phb(phb_id);
+
+	if (!phb)
+		return OPAL_PARAMETER;
+	if (!phb->ops->get_tunnel_bar)
+		return OPAL_UNSUPPORTED;
+
+	phb_lock(phb);
+	phb->ops->get_tunnel_bar(phb, addr);
+	phb_unlock(phb);
+	return OPAL_SUCCESS;
+}
+opal_call(OPAL_PCI_GET_PBCQ_TUNNEL_BAR, opal_pci_get_pbcq_tunnel_bar, 2);
+
+static int64_t opal_pci_set_pbcq_tunnel_bar(uint64_t phb_id, uint64_t addr)
+{
+	struct phb *phb = pci_get_phb(phb_id);
+	int64_t rc;
+
+	if (!phb)
+		return OPAL_PARAMETER;
+	if (!phb->ops->set_tunnel_bar)
+		return OPAL_UNSUPPORTED;
+
+	phb_lock(phb);
+	rc = phb->ops->set_tunnel_bar(phb, addr);
+	phb_unlock(phb);
+	return rc;
+}
+opal_call(OPAL_PCI_SET_PBCQ_TUNNEL_BAR, opal_pci_set_pbcq_tunnel_bar, 2);
diff --git a/hw/phb4.c b/hw/phb4.c
index 1add8a75..54dd9fac 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -3751,12 +3751,18 @@ static int64_t enable_capi_mode(struct phb4 *p, uint64_t pe_number,
 			out_be64(p->regs + PHB_ASN_CMPM, reg);
 		}
 
-		/* PBCQ Tunnel Bar Register
-		 * Write Tunnel register to match PSL TNR register
+		/*
+		 * PBCQ Tunnel Bar Register
+		 * If unset, then use PSL_TNR_ADDR[TNR_Addr] reset value.
 		 */
-		xscom_write(p->chip_id,
-			    p->pe_stk_xscom + XPEC_NEST_STK_TUNNEL_BAR,
-			    0x020000E000000000);
+		xscom_read(p->chip_id,
+			   p->pe_stk_xscom + XPEC_NEST_STK_TUNNEL_BAR, &reg);
+		if (!reg) {
+			reg = 0x020000e000000000ull;
+			xscom_write(p->chip_id,
+				    p->pe_stk_xscom + XPEC_NEST_STK_TUNNEL_BAR,
+				    reg);
+		}
 
 		/* PB AIB Hardware Control Register
 		 * Wait 32 PCI clocks for a credit to become available
@@ -4092,6 +4098,53 @@ static int64_t phb4_set_cmpm(struct phb *phb, uint64_t phb_reg, uint64_t ind)
 	return OPAL_SUCCESS;
 }
 
+/*
+ * Return the address out of a PBCQ Tunnel Bar register.
+ */
+static void phb4_get_tunnel_bar(struct phb *phb, uint64_t *addr)
+{
+	struct phb4 *p = phb_to_phb4(phb);
+	uint64_t val;
+
+	xscom_read(p->chip_id, p->pe_stk_xscom + XPEC_NEST_STK_TUNNEL_BAR,
+		   &val);
+	*addr = val >> 8;
+}
+
+/*
+ * Set PBCQ Tunnel Bar register.
+ * Store addr bits [8:50] in PBCQ Tunnel Bar register bits [0:42].
+ * Note that addr bits [8:50] must also match PSL_TNR_ADDR[8:50].
+ * Reset register if val == 0.
+ *
+ * This interface is required to let device drivers set the Tunnel Bar
+ * value of their choice.
+ *
+ * Compatibility with older versions of linux, that do not set the
+ * Tunnel Bar with phb4_set_tunnel_bar(), is ensured by enable_capi_mode(),
+ * that will set the default value that used to be assumed.
+ */
+static int64_t phb4_set_tunnel_bar(struct phb *phb, uint64_t addr)
+{
+	struct phb4 *p = phb_to_phb4(phb);
+	uint64_t mask = 0x00ffffffffffe000ull;
+
+	if (! addr) {
+		/* Reset register */
+		xscom_write(p->chip_id,
+			    p->pe_stk_xscom + XPEC_NEST_STK_TUNNEL_BAR, addr);
+		return OPAL_SUCCESS;
+	}
+	if ((addr & ~mask))
+		return OPAL_PARAMETER;
+	if (!(addr & mask))
+		return OPAL_PARAMETER;
+
+	xscom_write(p->chip_id, p->pe_stk_xscom + XPEC_NEST_STK_TUNNEL_BAR,
+		    (addr & mask) << 8);
+	return OPAL_SUCCESS;
+}
+
 static const struct phb_ops phb4_ops = {
 	.cfg_read8		= phb4_pcicfg_read8,
 	.cfg_read16		= phb4_pcicfg_read16,
@@ -4129,6 +4182,8 @@ static const struct phb_ops phb4_ops = {
 	.set_capp_recovery	= phb4_set_capp_recovery,
 	.get_cmpm		= phb4_get_cmpm,
 	.set_cmpm		= phb4_set_cmpm,
+	.get_tunnel_bar		= phb4_get_tunnel_bar,
+	.set_tunnel_bar		= phb4_set_tunnel_bar,
 };
 
 static void phb4_init_ioda3(struct phb4 *p)
diff --git a/include/opal-api.h b/include/opal-api.h
index ce948136..1e9715ee 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -216,7 +216,9 @@
 #define OPAL_PCI_SET_P2P			157
 #define OPAL_PCI_GET_PHB_CMPM			158
 #define OPAL_PCI_SET_PHB_CMPM			159
-#define OPAL_LAST				159
+#define OPAL_PCI_GET_PBCQ_TUNNEL_BAR		160
+#define OPAL_PCI_SET_PBCQ_TUNNEL_BAR		161
+#define OPAL_LAST				161
 
 /* Device tree flags */
 
diff --git a/include/pci.h b/include/pci.h
index cdf82ee8..5276b574 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -337,6 +337,10 @@ struct phb_ops {
 	/* Get/set PHB Compare/Mask registers */
 	int64_t (*get_cmpm)(struct phb *phb, uint64_t phb_reg, uint64_t *ind);
 	int64_t (*set_cmpm)(struct phb *phb, uint64_t phb_reg, uint64_t ind);
+
+	/* Get/set PBCQ Tunnel BAR register */
+	void (*get_tunnel_bar)(struct phb *phb, uint64_t *addr);
+	int64_t (*set_tunnel_bar)(struct phb *phb, uint64_t addr);
 };
 
 enum phb_type {
-- 
2.14.2



More information about the Skiboot mailing list