[Skiboot] [PATCH V4 3/5] NX: Add P9 NX support for 842 compression engine

Haren Myneni haren at linux.vnet.ibm.com
Tue Jul 18 12:48:57 AEST 2017


This patch adds changes needed for 842 compression engine on power 9.
Virtual Accelerator Switch (VAS) is used to access NX 842 engine on P9
and the channel setup will be done with receive FIFO. So RxFIFO
address, logical partition ID (lpid), process ID (pid) and thread ID
(tid) are used for this setup. p9 NX supports high and normal priority
FIFOs. skiboot is not involved to process data with 842 engine, but
configures User Mode Access Control (UMAC) noitify match register with
these values and export them to kernel with device-tree entries.

Also configure registers to setup and enable / disable the engine with
the appropriate registers. Creates the following device-tree entries to
provide RxFIFO address, RxFIFO size, Fifo priority, lpid, pid and tid
values so that kernel can drive P9 NX 842 engine.

The following nodes are located under an xscom node:
/xscom@<xscom_addr>/nx@<nx_addr>

   /ibm,842-high-fifo	: High priority 842 RxFIFO
   /ibm,842-normal-fifo	: Normal priority 842 RxFIFO

Each RxFIFO node contains:
   compatible		: ibm,p9-nx-842
   priority		: High or Normal
   rx-fifo-address	: RxFIFO address
   rx-fifo-size		: RXFIFO size
   lpid			: 0xfff (1's for 12 bits set in UMAC notify
					match register)
   pid			: 842 coprocessor type
   tid			: Counter for 842

Signed-off-by: Haren Myneni <haren at us.ibm.com>
---
 hw/nx-842.c      |   63 +++++++++++++++-
 hw/nx-compress.c |  215 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 include/nx.h     |    5 +
 3 files changed, 277 insertions(+), 6 deletions(-)

diff --git a/hw/nx-842.c b/hw/nx-842.c
index 031de03..21bc2fd 100644
--- a/hw/nx-842.c
+++ b/hw/nx-842.c
@@ -20,6 +20,7 @@
 #include <io.h>
 #include <cpu.h>
 #include <nx.h>
+#include <vas.h>
 
 /* Configuration settings */
 #define CFG_842_FC_ENABLE	(0x1f) /* enable all 842 functions */
@@ -85,6 +86,32 @@ static int nx_cfg_842(u32 gcid, u64 xcfg)
 	return rc;
 }
 
+static int nx_cfg_842_umac(struct dt_node *node, u32 gcid, u32 pb_base)
+{
+	int rc;
+	u64 umac_bar, umac_notify;
+	struct dt_node *nx_node;
+	static u32 nx842_tid = 1; /* tid counter within coprocessor type */
+
+	nx_node = dt_new(node, "ibm,842-high-fifo");
+	umac_bar = pb_base + NX_P9_842_HIGH_PRI_RX_FIFO_BAR;
+	umac_notify = pb_base + NX_P9_842_HIGH_PRI_RX_FIFO_NOTIFY_MATCH;
+	rc = nx_cfg_rx_fifo(nx_node, "ibm,p9-nx-842", "High", gcid,
+				NX_CT_842, nx842_tid++, umac_bar,
+				umac_notify);
+	if (rc)
+		return rc;
+
+	nx_node = dt_new(node, "ibm,842-normal-fifo");
+	umac_bar = pb_base + NX_P9_842_NORMAL_PRI_RX_FIFO_BAR;
+	umac_notify = pb_base + NX_P9_842_NORMAL_PRI_RX_FIFO_NOTIFY_MATCH;
+	rc = nx_cfg_rx_fifo(nx_node, "ibm,p9-nx-842", "Normal", gcid,
+				NX_CT_842, nx842_tid++, umac_bar,
+				umac_notify);
+
+	return rc;
+}
+
 static int nx_cfg_842_dma(u32 gcid, u64 xcfg)
 {
 	u64 cfg;
@@ -94,7 +121,7 @@ static int nx_cfg_842_dma(u32 gcid, u64 xcfg)
 	if (rc)
 		return rc;
 
-	if (proc_gen == proc_gen_p8) {
+	if (proc_gen >= proc_gen_p8) {
 		cfg = SETFIELD(NX_DMA_CFG_842_COMPRESS_PREFETCH, cfg,
 			       DMA_COMPRESS_PREFETCH);
 		cfg = SETFIELD(NX_DMA_CFG_842_DECOMPRESS_PREFETCH, cfg,
@@ -107,14 +134,16 @@ static int nx_cfg_842_dma(u32 gcid, u64 xcfg)
 		       DMA_DECOMPRESS_MAX_RR);
 	cfg = SETFIELD(NX_DMA_CFG_842_SPBC, cfg,
 		       DMA_SPBC);
-	cfg = SETFIELD(NX_DMA_CFG_842_CSB_WR, cfg,
+	if (proc_gen < proc_gen_p9) {
+		cfg = SETFIELD(NX_DMA_CFG_842_CSB_WR, cfg,
 		       DMA_CSB_WR);
-	cfg = SETFIELD(NX_DMA_CFG_842_COMPLETION_MODE, cfg,
+		cfg = SETFIELD(NX_DMA_CFG_842_COMPLETION_MODE, cfg,
 		       DMA_COMPLETION_MODE);
-	cfg = SETFIELD(NX_DMA_CFG_842_CPB_WR, cfg,
+		cfg = SETFIELD(NX_DMA_CFG_842_CPB_WR, cfg,
 		       DMA_CPB_WR);
-	cfg = SETFIELD(NX_DMA_CFG_842_OUTPUT_DATA_WR, cfg,
+		cfg = SETFIELD(NX_DMA_CFG_842_OUTPUT_DATA_WR, cfg,
 		       DMA_OUTPUT_DATA_WR);
+	}
 
 	rc = xscom_write(gcid, xcfg, cfg);
 	if (rc)
@@ -183,3 +212,27 @@ void nx_enable_842(struct dt_node *node, u32 gcid, u32 pb_base)
 	dt_add_property_cells(node, "ibm,842-coprocessor-type", NX_CT_842);
 	dt_add_property_cells(node, "ibm,842-coprocessor-instance", gcid + 1);
 }
+
+void p9_nx_enable_842(struct dt_node *node, u32 gcid, u32 pb_base)
+{
+	u64 cfg_dma, cfg_ee;
+	int rc;
+
+	cfg_dma = pb_base + NX_P9_DMA_CFG;
+	cfg_ee = pb_base + NX_P9_EE_CFG;
+
+	rc = nx_cfg_842_dma(gcid, cfg_dma);
+	if (rc)
+		return;
+
+	rc = nx_cfg_842_umac(node, gcid, pb_base);
+	if (rc)
+		return;
+
+	rc = nx_cfg_842_ee(gcid, cfg_ee);
+	if (rc)
+		return;
+
+	prlog(PR_INFO, "NX%d: 842 Coprocessor Enabled\n", gcid);
+
+}
diff --git a/hw/nx-compress.c b/hw/nx-compress.c
index 2ea2734..313f38e 100644
--- a/hw/nx-compress.c
+++ b/hw/nx-compress.c
@@ -20,15 +20,228 @@
 #include <io.h>
 #include <cpu.h>
 #include <nx.h>
+#include <vas.h>
+
+static int nx_cfg_umac_tx_wc(u32 gcid, u64 xcfg)
+{
+	int rc = 0;
+	u64 cfg;
+
+	cfg = vas_get_wcbs_bar(gcid);
+	if (!cfg) {
+		prerror("NX%d: ERROR finding WC Backing store BAR\n", gcid);
+		return -ENOMEM;
+	}
+
+	/*
+	 * NOTE: Write the entire bar address to SCOM. VAS/NX will extract
+	 *       the relevant (NX_P9_UMAC_TX_WINDOW_CONTEXT_ADDR) bits.
+	 *       IOW, _don't_ just write the bit field like:
+	 *
+	 *       cfg = SETFIELD(NX_P9_UMAC_TX_WINDOW_CONTEXT_ADDR, 0ULL, cfg);
+	 */
+	rc = xscom_write(gcid, xcfg, cfg);
+
+	if (rc)
+		prerror("NX%d: ERROR: UMAC SEND WC BAR, %d\n", gcid, rc);
+	else
+		prlog(PR_DEBUG, "NX%d: UMAC SEND WC BAR, 0x%016lx, "
+				"xcfg 0x%llx\n",
+			gcid, (unsigned long)cfg, xcfg);
+
+	return rc;
+}
+
+static int nx_cfg_dma_vas_mmio(u32 gcid, u64 xcfg)
+{
+	int rc = 0;
+	u64 cfg;
+
+	cfg = vas_get_hvwc_mmio_bar(gcid);
+	/*
+	 * NOTE: Write the entire bar address to SCOM. VAS/NX will extract
+	 *       the relevant (NX_P9_UMAC_VAS_MMIO_ADDR) bits. IOW, _don't_
+	 *       just write the bit field like:
+	 *
+	 *	cfg = SETFIELD(NX_P9_DMA_VAS_MMIO_ADDR, 0ULL, cfg);
+	 */
+	rc = xscom_write(gcid, xcfg, cfg);
+
+	if (rc)
+		prerror("NX%d: ERROR: DMA VAS MMIO BAR, %d\n", gcid, rc);
+	else
+		prerror("NX%d: DMA VAS MMIO BAR, 0x%016lx, xcfg 0x%llx\n",
+			gcid, (unsigned long)cfg, xcfg);
+
+	return rc;
+}
+
+static int nx_cfg_umac_vas_mmio(u32 gcid, u64 xcfg)
+{
+	int rc = 0;
+	u64 cfg;
+
+	cfg = vas_get_hvwc_mmio_bar(gcid);
+	/*
+	 * NOTE: Write the entire bar address to SCOM. VAS/NX will extract
+	 *       the relevant (NX_P9_UMAC_VAS_MMIO_ADDR) bits. IOW, _don't_
+	 *	 just write the bit field like:
+	 *
+	 *       cfg = SETFIELD(NX_P9_UMAC_VAS_MMIO_ADDR, 0ULL, cfg);
+	 */
+	rc = xscom_write(gcid, xcfg, cfg);
+
+	if (rc)
+		prerror("NX%d: ERROR: UMAC VAS MMIO BAR, %d\n", gcid, rc);
+	else
+		prlog(PR_DEBUG, "NX%d: UMAC VAS MMIO BAR, 0x%016lx, "
+				"xcfg 0x%llx\n",
+			gcid, (unsigned long)cfg, xcfg);
+
+	return rc;
+}
+
+static int nx_cfg_umac_status_ctrl(u32 gcid, u64 xcfg)
+{
+	u64 uctrl;
+	int rc;
+#define CRB_ENABLE	1
+
+	rc = xscom_read(gcid, xcfg, &uctrl);
+	if (rc)
+		return rc;
+
+	uctrl = SETFIELD(NX_P9_UMAC_STATUS_CTRL_CRB_ENABLE, uctrl, CRB_ENABLE);
+	rc = xscom_write(gcid, xcfg, uctrl);
+	if (rc)
+		prerror("NX%d: ERROR: Setting UMAC Status Control failure %d\n",
+			gcid, rc);
+	else
+		prlog(PR_DEBUG, "NX%d: Setting UMAC Status Control 0x%016lx\n",
+			gcid, (unsigned long)uctrl);
+
+	return rc;
+}
+
+int nx_cfg_rx_fifo(struct dt_node *node, const char *compat,
+			const char *priority, u32 gcid, u32 pid, u32 tid,
+			u64 umac_bar, u64 umac_notify)
+{
+	u64 cfg;
+	int rc, size;
+	uint64_t fifo;
+	u32 lpid = 0xfff; /* All 1's for 12 bits in UMAC notify match reg */
+#define MATCH_ENABLE    1
+
+	fifo = (uint64_t) local_alloc(gcid, RX_FIFO_SIZE, RX_FIFO_SIZE);
+	assert(fifo);
+
+	/*
+	 * When configuring the address of the Rx FIFO into the Receive FIFO
+	 * BAR, we should _NOT_ shift the address into bits 8:53. Instead we
+	 * should copy the address as is and VAS/NX will extract relevant bits.
+	 */
+	/*
+	 * Section 5.21 of P9 NX Workbook Version 2.42 shows Receive FIFO BAR
+	 * 54:56 represents FIFO size
+	 * 000 = 1KB, 8 CRBs
+	 * 001 = 2KB, 16 CRBs
+	 * 010 = 4KB, 32 CRBs
+	 * 011 = 8KB, 64 CRBs
+	 * 100 = 16KB, 128 CRBs
+	 * 101 = 32KB, 256 CRBs
+	 * 110 = 111 reserved
+	 */
+	size = RX_FIFO_SIZE / 1024;
+	cfg = SETFIELD(NX_P9_RX_FIFO_BAR_SIZE, fifo, ilog2(size));
+
+	rc = xscom_write(gcid, umac_bar, cfg);
+	if (rc) {
+		prerror("NX%d: ERROR: Setting UMAC FIFO bar failure %d\n",
+			gcid, rc);
+		return rc;
+	} else
+		prlog(PR_DEBUG, "NX%d: Setting UMAC FIFO bar 0x%016lx\n",
+			gcid, (unsigned long)cfg);
+
+	rc = xscom_read(gcid, umac_notify, &cfg);
+	if (rc)
+		return rc;
+
+	/*
+	 * VAS issues asb_notify with the unique ID to identify the target
+	 * co-processor/engine. Logical partition ID (lpid), process ID (pid),
+	 * and thread ID (tid) combination is used to define the unique ID
+	 * in the system. Export these values in device-tree such that the
+	 * driver configure RxFIFO with VAS. Set these values in RxFIFO notify
+	 * match register for each engine which compares the ID with each
+	 * request.
+	 * To define unique indentification, 0xfff (1's for 12 bits),
+	 * co-processor type, and counter within coprocessor type are used
+	 * for lpid, pid, and tid respectively.
+	 */
+	cfg = SETFIELD(NX_P9_RX_FIFO_NOTIFY_MATCH_LPID, cfg, lpid);
+	cfg = SETFIELD(NX_P9_RX_FIFO_NOTIFY_MATCH_PID, cfg, pid);
+	cfg = SETFIELD(NX_P9_RX_FIFO_NOTIFY_MATCH_TID, cfg, tid);
+	cfg = SETFIELD(NX_P9_RX_FIFO_NOTIFY_MATCH_MATCH_ENABLE, cfg,
+			MATCH_ENABLE);
+
+	rc = xscom_write(gcid, umac_notify, cfg);
+	if (rc) {
+		prerror("NX%d: ERROR: Setting UMAC notify match failure %d\n",
+			gcid, rc);
+		return rc;
+	} else
+		prlog(PR_DEBUG, "NX%d: Setting UMAC notify match 0x%016lx\n",
+				gcid, (unsigned long)cfg);
+
+	dt_add_property_string(node, "compatible", compat);
+	dt_add_property_string(node, "priority", priority);
+	dt_add_property_u64(node, "rx-fifo-address", fifo);
+	dt_add_property_cells(node, "rx-fifo-size", RX_FIFO_SIZE);
+	dt_add_property_cells(node, "lpid", lpid);
+	dt_add_property_cells(node, "pid", pid);
+	dt_add_property_cells(node, "tid", tid);
+
+	return 0;
+}
 
 void nx_create_compress_node(struct dt_node *node)
 {
 	u32 gcid, pb_base;
+	int rc;
 
 	gcid = dt_get_chip_id(node);
 	pb_base = dt_get_address(node, 0, NULL);
 
 	prlog(PR_INFO, "NX%d: 842 at 0x%x\n", gcid, pb_base);
 
-	nx_enable_842(node, gcid, pb_base);
+	if (dt_node_is_compatible(node, "ibm,power9-nx")) {
+		u64 cfg_mmio, cfg_txwc, cfg_uctrl, cfg_dma;
+
+		printf("Found ibm,power9-nx\n");
+		cfg_mmio = pb_base + NX_P9_UMAC_VAS_MMIO_BAR;
+		cfg_dma = pb_base + NX_P9_DMA_VAS_MMIO_BAR;
+		cfg_txwc = pb_base + NX_P9_UMAC_TX_WINDOW_CONTEXT_BAR;
+		cfg_uctrl = pb_base + NX_P9_UMAC_STATUS_CTRL;
+
+		rc = nx_cfg_umac_vas_mmio(gcid, cfg_mmio);
+		if (rc)
+			return;
+
+		rc = nx_cfg_dma_vas_mmio(gcid, cfg_dma);
+		if (rc)
+			return;
+
+		rc = nx_cfg_umac_tx_wc(gcid, cfg_txwc);
+		if (rc)
+			return;
+
+		rc = nx_cfg_umac_status_ctrl(gcid, cfg_uctrl);
+		if (rc)
+			return;
+
+		p9_nx_enable_842(node, gcid, pb_base);
+	} else
+		nx_enable_842(node, gcid, pb_base);
 }
diff --git a/include/nx.h b/include/nx.h
index 0cf4633..ff2e2a0 100644
--- a/include/nx.h
+++ b/include/nx.h
@@ -394,6 +394,11 @@ extern void nx_create_crypto_node(struct dt_node *);
 extern void nx_create_compress_node(struct dt_node *);
 
 extern void nx_enable_842(struct dt_node *node, u32 gcid, u32 pb_base);
+extern void p9_nx_enable_842(struct dt_node *node, u32 gcid, u32 pb_base);
+
+extern int nx_cfg_rx_fifo(struct dt_node *node, const char *compat,
+			const char *priority, u32 gcid, u32 pid, u32 tid,
+			u64 umac_bar, u64 umac_notify);
 
 extern void nx_init(void);
 
-- 
1.7.1





More information about the Skiboot mailing list