[RFC PATCH 03/11] VAS: Define helpers for access MMIO regions

Sukadev Bhattiprolu sukadev at linux.vnet.ibm.com
Sat Nov 12 04:02:48 AEDT 2016


Define some helper functions to access the MMIO regions. We use these
in a follow-on patches to read/write VAS hardware registers. These
helpers are also used to later issue 'paste' instructions to submit
requests to the NX hardware engines.

Signed-off-by: Sukadev Bhattiprolu <sukadev at linux.vnet.ibm.com>
---
 drivers/misc/vas/vas-window.c | 182 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 182 insertions(+)

diff --git a/drivers/misc/vas/vas-window.c b/drivers/misc/vas/vas-window.c
index 468f3bf..2c220a3 100644
--- a/drivers/misc/vas/vas-window.c
+++ b/drivers/misc/vas/vas-window.c
@@ -9,9 +9,191 @@
 
 #include <linux/types.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/io.h>
 #include <asm/vas.h>
 #include "vas-internal.h"
 
+/*
+ * Using the node, chip and window id for the send winow identified by
+ * @window, compute and return the Power Bus address to which a sender
+ * could issue a paste instruction for this window.
+ *
+ * Refer to Tables 1.1 through 1.4 in Section 1.3.3.1 (Send Message w/Paste
+ * Commands (cl_rma_w)) of VAS P9 Workbook for the PowerBus Address usage
+ * in VAS.
+ *
+ * With 64K mode and Large SMP Mode the bits are used as follows:
+ *
+ *	Bits	Values		Comments
+ *	--------------------------------------
+ *	0:7     0b 0000_0000    Reserved
+ *	8:12    0b 0000_1       System id/Foreign Index 0:4
+ *	13:14   0b 00           Foreign Index 5:6
+ *
+ *	15:18   0 throuh 15     Node id (0 through 15)
+ *	19:21   0 through 7     Chip id (0 throuh 7)
+ *	22:23   0b 00           Unused, Foreign index 7:8
+ *
+ *	24:31   0b 0000_0000    RPN 0:7, Reserved
+ *	32:47   0 through 64K   Send Window Id
+ *	48:51   0b 0000         Spare
+ *
+ *	52      0b 0            Reserved
+ *	53      0b 1            Report Enable (Set to 1 for NX).
+ *	54      0b 0            Reserved
+ *
+ *	55:56   0b 00           Snoop Bus
+ *	57:63   0b 0000_000     Reserved
+ *
+ * Except for a few bits, the small SMP mode computation is similar.
+ *
+ * TODO: Detect and compute address for small SMP mode.
+ *
+ * Example: For Node 0, Chip 0, Window id 4, Report Enable 1:
+ *
+ *     Byte0    Byte1    Byte2    Byte3    Byte4    Byte5    Byte6    Byte7
+ *     00000000 00001000 00000000 00000000 00000000 00000100 00000100 00000000
+ *                                         |               |      |
+ *                                         +-------+-------+      v
+ *                                                 |          Report Enable
+ *                                                 v
+ *                                             Window id 4
+ *
+ *     Thus, the paste address is 0x00080000_00040400.
+ */
+#define RMA_LSMP_64K_SYS_ID	PPC_BITMASK(8, 12)
+#define RMA_LSMP_64K_NODE_ID	PPC_BITMASK(15, 18)
+#define RMA_LSMP_64K_CHIP_ID	PPC_BITMASK(19, 21)
+#define RMA_LSMP_64K_TX_WIN_ID	PPC_BITMASK(32, 47)
+#define RMA_LSMP_REPORT_ENABLE	PPC_BIT(53)
+
+uint64_t compute_paste_address(struct vas_window *window, int *size)
+{
+	int node, chip, winid;
+	uint64_t val = 0ULL;
+
+	node = window->vinst->node;
+	chip = window->vinst->chip;
+	winid = window->winid;
+
+	*size = PAGE_SIZE;
+
+	val = SET_FIELD(RMA_LSMP_64K_SYS_ID, val, 1);
+	val = SET_FIELD(RMA_LSMP_64K_NODE_ID, val, node);
+	val = SET_FIELD(RMA_LSMP_64K_CHIP_ID, val, chip);
+	val = SET_FIELD(RMA_LSMP_64K_TX_WIN_ID, val, winid);
+	val = SET_FIELD(RMA_LSMP_REPORT_ENABLE, val, 1);
+	pr_debug("%swin #%d: Paste address 0x%llx\n",
+			window->txwin ? "Tx" : "Rx",  winid, val);
+	return val;
+}
+
+static void get_hvwc_mmio_bar(struct vas_window *window,
+			uint64_t *start, int *len)
+{
+	uint64_t pbaddr;
+	int instance;
+
+	instance = window->vinst->node * 8 + window->vinst->chip;
+	pbaddr = VAS_HVWC_MMIO_BAR_BASE + instance * VAS_HVWC_MMIO_BAR_SIZE;
+
+	*start = pbaddr + window->winid * VAS_HVWC_SIZE;
+	*len = VAS_HVWC_SIZE;
+}
+
+static void get_uwc_mmio_bar(struct vas_window *window,
+			uint64_t *start, int *len)
+{
+	uint64_t pbaddr;
+	int instance;
+
+	instance = window->vinst->node * 8 + window->vinst->chip;
+	pbaddr = VAS_UWC_MMIO_BAR_BASE + instance * VAS_UWC_MMIO_BAR_SIZE;
+
+	*start = pbaddr + window->winid * VAS_UWC_SIZE;
+	*len = VAS_UWC_SIZE;
+}
+
+static void *map_mmio_region(char *name, uint64_t start, int len)
+{
+	void *map;
+
+	if (!request_mem_region(start, len, name)) {
+		pr_devel("%s(): request_mem_region(0x%llx, %d) failed\n",
+				__func__, start, len);
+		return NULL;
+	}
+
+	map = __ioremap(start, len, pgprot_val(pgprot_cached(__pgprot(0))));
+	if (!map) {
+		pr_devel("%s(): ioremap(0x%llx, %d) failed\n", __func__, start,
+				len);
+		return NULL;
+	}
+
+	return map;
+}
+
+/*
+ * Unmap the MMIO regions for a window.
+ */
+void unmap_wc_mmio_bars(struct vas_window *window)
+{
+	int len;
+	uint64_t busaddr_start;
+
+	if (window->paste_kaddr) {
+		iounmap(window->paste_kaddr);
+		busaddr_start = compute_paste_address(window, &len);
+		pr_debug("Releasing pbaddr region [0x%llx, %d]\n",
+				busaddr_start, len);
+		release_mem_region((phys_addr_t)busaddr_start, len);
+	}
+
+	if (window->hvwc_map) {
+		iounmap(window->hvwc_map);
+		get_hvwc_mmio_bar(window, &busaddr_start, &len);
+		release_mem_region((phys_addr_t)busaddr_start, len);
+	}
+
+	if (window->uwc_map) {
+		iounmap(window->uwc_map);
+		get_uwc_mmio_bar(window, &busaddr_start, &len);
+		release_mem_region((phys_addr_t)busaddr_start, len);
+	}
+}
+
+/*
+ * Find the Hypervisor Window Context (HVWC) MMIO Base Address Region and the
+ * OS/User Window Context (UWC) MMIO Base Address Region for the given window.
+ * Map these bus addresses and save the mapped kernel addresses in @window.
+ */
+int map_wc_mmio_bars(struct vas_window *window)
+{
+	int len;
+	uint64_t start;
+
+	window->hvwc_map = window->uwc_map = NULL;
+
+	get_hvwc_mmio_bar(window, &start, &len);
+	window->hvwc_map = map_mmio_region("HVWCM_Window", start, len);
+
+	pr_debug("Win #%d: Map hvwc 0x%p -> [0x%llx,%d]\n", window->winid,
+			window->hvwc_map, start, len);
+
+	get_uwc_mmio_bar(window, &start, &len);
+	window->uwc_map = map_mmio_region("UWCM_Window", start, len);
+
+	pr_debug("Win #%d: Map uvwc 0x%p -> [0x%llx,%d]\n", window->winid,
+			window->uwc_map, start, len);
+
+	if (!window->hvwc_map || !window->uwc_map)
+		return -1;
+
+	return 0;
+}
+
 /* stub for now */
 int vas_window_reset(struct vas_instance *vinst, int winid)
 {
-- 
1.8.3.1



More information about the Linuxppc-dev mailing list