--- v3
+++ v5
@@ -1,143 +1,131 @@
Implement vas_init() and vas_exit() functions for a new VAS module.
This VAS module is essentially a library for other device drivers
and kernel users of the NX coprocessors like NX-842 and NX-GZIP.
+In the future this will be extended to add support for user space
+to access the NX coprocessors.
+
+VAS is currently only supported with 64K page size.
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
+Changelog[v5]:
+ - [Ben Herrenschmidt]: Create and use platform device tree nodes,
+ fix up the "reg" properties for the VAS DT node and use the
+ platform device helpers to parse the reg properties; Use linked
+ list of VAS instances (don't assume vasids are sequential);
+ Use CONFIG_PPC_VAS instead of CONFIG_VAS.
+
+Changelog[v4]:
+ - [Michael Neuling] Fix some accidental deletions; fix help text
+ in Kconfig; change vas_initialized to a function; move from
+ drivers/misc to arch/powerpc/kernel
+ - Drop the vas_window_reset() interface. It is not needed as
+ window will be initialized before each use.
+ - Add a "depends on PPC_64K_PAGES"
+
Changelog[v3]:
- Zero vas_instances memory on allocation
- [Haren Myneni] Fix description in Kconfig
Changelog[v2]:
- Get HVWC, UWC and window address parameters from device tree.
---
- MAINTAINERS | 8 ++-
- arch/powerpc/include/asm/reg.h | 1 +
- drivers/misc/Kconfig | 1 +
- drivers/misc/Makefile | 1 +
- drivers/misc/vas/Kconfig | 21 ++++++
- drivers/misc/vas/Makefile | 3 +
- drivers/misc/vas/vas-internal.h | 3 +
- drivers/misc/vas/vas-window.c | 19 +++++
- drivers/misc/vas/vas.c | 155 ++++++++++++++++++++++++++++++++++++++++
- 9 files changed, 210 insertions(+), 2 deletions(-)
- create mode 100644 drivers/misc/vas/Kconfig
- create mode 100644 drivers/misc/vas/Makefile
- create mode 100644 drivers/misc/vas/vas-window.c
- create mode 100644 drivers/misc/vas/vas.c
-
+ .../devicetree/bindings/powerpc/ibm,vas.txt | 24 +++
+ MAINTAINERS | 8 +
+ arch/powerpc/platforms/powernv/Kconfig | 14 ++
+ arch/powerpc/platforms/powernv/Makefile | 1 +
+ arch/powerpc/platforms/powernv/vas-window.c | 19 +++
+ arch/powerpc/platforms/powernv/vas.c | 183 +++++++++++++++++++++
+ arch/powerpc/platforms/powernv/vas.h | 10 +-
+ 7 files changed, 257 insertions(+), 2 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/powerpc/ibm,vas.txt
+ create mode 100644 arch/powerpc/platforms/powernv/vas-window.c
+ create mode 100644 arch/powerpc/platforms/powernv/vas.c
+
+diff --git a/Documentation/devicetree/bindings/powerpc/ibm,vas.txt b/Documentation/devicetree/bindings/powerpc/ibm,vas.txt
+new file mode 100644
+index 0000000..8468a3a
+--- /dev/null
++++ b/Documentation/devicetree/bindings/powerpc/ibm,vas.txt
+@@ -0,0 +1,24 @@
++* IBM Powerpc Virtual Accelerator Switchboard (VAS)
++
++VAS is a hardware mechanism that allows ekrnel subsystems and user processes
++to directly submit compression and other requests to Nest accelerators (NX)
++or other coprocessors functions.
++
++Required properties:
++- compatible : should be "ibm,vas" or "ibm,power9-vas"
++- ibm,vas-id : A unique identifier for each instance of VAS in the system
++- reg : Should contain 4 pairs of 64-bit fields specifying the Hypervisor
++ window context start and length, OS/User window context start and length,
++ "Paste address" start and length, "Paste window id" start bit and number
++ of bits)
++- name : "vas"
++
++Example:
++
++ vas@6019100000000 {
++ compatible = "ibm,vas", "ibm,power9-vas";
++ reg = <0x6019100000000 0x2000000 0x6019000000000 0x100000000 0x8000000000000 0x100000000 0x20 0x10>;
++ name = "vas";
++ ibm,vas-id = <0x1>;
++ };
++
diff --git a/MAINTAINERS b/MAINTAINERS
-index 2a910c9..4037252 100644
+index 9e98464..4c4f05e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -3673,8 +3673,6 @@ F: arch/powerpc/platforms/powernv/pci-cxl.c
- F: drivers/misc/cxl/
- F: include/misc/cxl*
- F: include/uapi/misc/cxl.h
--F: Documentation/powerpc/cxl.txt
--F: Documentation/ABI/testing/sysfs-class-cxl
+@@ -6331,6 +6331,14 @@ F: drivers/crypto/nx/nx.*
+ F: drivers/crypto/nx/nx_csbcpb.h
+ F: drivers/crypto/nx/nx_debugfs.h
- CXLFLASH (IBM Coherent Accelerator Processor Interface CAPI Flash) SCSI DRIVER
- M: Manoj N. Kumar <manoj@linux.vnet.ibm.com>
-@@ -3686,6 +3684,12 @@ F: drivers/scsi/cxlflash/
- F: include/uapi/scsi/cxlflash_ioctls.h
- F: Documentation/powerpc/cxlflash.txt
-
-+VAS (IBM Virtual Accelerator Switch) DRIVER
-+M: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
++IBM Power Virtual Accelerator Switchboard
++M: Sukadev Bhattiprolu
+L: linuxppc-dev@lists.ozlabs.org
+S: Supported
-+F: drivers/misc/vas/
-+
- STMMAC ETHERNET DRIVER
- M: Giuseppe Cavallaro <peppe.cavallaro@st.com>
- M: Alexandre Torgue <alexandre.torgue@st.com>
-diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
-index fc879fd..7a45ff7 100644
---- a/arch/powerpc/include/asm/reg.h
-+++ b/arch/powerpc/include/asm/reg.h
-@@ -1225,6 +1225,7 @@
- #define PVR_POWER8E 0x004B
- #define PVR_POWER8NVL 0x004C
- #define PVR_POWER8 0x004D
-+#define PVR_POWER9 0x004E
- #define PVR_BE 0x0070
- #define PVR_PA6T 0x0090
-
-diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
-index c290990..97d652e 100644
---- a/drivers/misc/Kconfig
-+++ b/drivers/misc/Kconfig
-@@ -783,4 +783,5 @@ source "drivers/misc/mic/Kconfig"
- source "drivers/misc/genwqe/Kconfig"
- source "drivers/misc/echo/Kconfig"
- source "drivers/misc/cxl/Kconfig"
-+source "drivers/misc/vas/Kconfig"
- endmenu
-diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
-index 7a3ea89..5201ffd 100644
---- a/drivers/misc/Makefile
-+++ b/drivers/misc/Makefile
-@@ -53,6 +53,7 @@ obj-$(CONFIG_GENWQE) += genwqe/
- obj-$(CONFIG_ECHO) += echo/
- obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
- obj-$(CONFIG_CXL_BASE) += cxl/
-+obj-$(CONFIG_VAS) += vas/
- obj-$(CONFIG_PANEL) += panel.o
-
- lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o
-diff --git a/drivers/misc/vas/Kconfig b/drivers/misc/vas/Kconfig
-new file mode 100644
-index 0000000..43cedda
---- /dev/null
-+++ b/drivers/misc/vas/Kconfig
-@@ -0,0 +1,21 @@
-+#
-+# IBM Virtual Accelarator Switchboard (VAS) compatible devices
-+#depends on PPC_POWERNV && PCI_MSI && EEH
-+#
-+
-+config VAS
-+ tristate "Support for IBM Virtual Accelerator Switchboard (VAS)"
-+ depends on PPC_POWERNV
++F: arch/powerpc/platforms/powernv/vas*
++F: arch/powerpc/include/asm/vas.h
++F: arch/powerpc/include/uapi/asm/vas.h
++
+ IBM Power 842 compression accelerator
+ M: Haren Myneni <haren@us.ibm.com>
+ S: Supported
+diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig
+index 6a6f4ef..f565454 100644
+--- a/arch/powerpc/platforms/powernv/Kconfig
++++ b/arch/powerpc/platforms/powernv/Kconfig
+@@ -30,3 +30,17 @@ config OPAL_PRD
+ help
+ This enables the opal-prd driver, a facility to run processor
+ recovery diagnostics on OpenPower machines
++
++config PPC_VAS
++ bool "IBM Virtual Accelerator Switchboard (VAS)"
++ depends on PPC_POWERNV && PPC_64K_PAGES
+ default n
+ help
-+ Select this option to enable driver support for IBM Virtual
-+ Accelerator Switchboard (VAS).
-+
-+ VAS allows accelerators in co processors like NX-842 to be
-+ directly available to a user process. This driver enables
-+ userspace programs to access these accelerators via device
-+ nodes like /dev/crypto/nx-gzip.
++ This enables support for IBM Virtual Accelerator Switchboard (VAS).
++
++ VAS allows accelerators in co-processors like NX-GZIP and NX-842
++ to be accessible to kernel subsystems and user processes.
+
+ VAS adapters are found in POWER9 based systems.
+
+ If unsure, say N.
-diff --git a/drivers/misc/vas/Makefile b/drivers/misc/vas/Makefile
+diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
+index b5d98cb..e4db292 100644
+--- a/arch/powerpc/platforms/powernv/Makefile
++++ b/arch/powerpc/platforms/powernv/Makefile
+@@ -12,3 +12,4 @@ obj-$(CONFIG_PPC_SCOM) += opal-xscom.o
+ obj-$(CONFIG_MEMORY_FAILURE) += opal-memory-errors.o
+ obj-$(CONFIG_TRACEPOINTS) += opal-tracepoints.o
+ obj-$(CONFIG_OPAL_PRD) += opal-prd.o
++obj-$(CONFIG_PPC_VAS) += vas.o vas-window.o
+diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c
new file mode 100644
-index 0000000..7dd7139
+index 0000000..6156fbe
--- /dev/null
-+++ b/drivers/misc/vas/Makefile
-@@ -0,0 +1,3 @@
-+ccflags-y := $(call cc-disable-warning, unused-const-variable)
-+ccflags-$(CONFIG_PPC_WERROR) += -Werror
-+obj-$(CONFIG_VAS) += vas.o vas-window.o
-diff --git a/drivers/misc/vas/vas-internal.h b/drivers/misc/vas/vas-internal.h
-index ce48f14..15b62e0 100644
---- a/drivers/misc/vas/vas-internal.h
-+++ b/drivers/misc/vas/vas-internal.h
-@@ -389,4 +389,7 @@ struct vas_winctx {
- enum vas_notify_after_count notify_after_count;
- };
-
-+extern int vas_initialized;
-+extern int vas_window_reset(struct vas_instance *vinst, int winid);
-+extern struct vas_instance *find_vas_instance(int vasid);
- #endif
-diff --git a/drivers/misc/vas/vas-window.c b/drivers/misc/vas/vas-window.c
-new file mode 100644
-index 0000000..468f3bf
---- /dev/null
-+++ b/drivers/misc/vas/vas-window.c
++++ b/arch/powerpc/platforms/powernv/vas-window.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 IBM Corp.
@@ -150,20 +138,20 @@
+
+#include <linux/types.h>
+#include <linux/mutex.h>
-+#include <asm/vas.h>
-+#include "vas-internal.h"
++
++#include "vas.h"
+
+/* stub for now */
-+int vas_window_reset(struct vas_instance *vinst, int winid)
-+{
-+ return 0;
-+}
-diff --git a/drivers/misc/vas/vas.c b/drivers/misc/vas/vas.c
++int vas_win_close(struct vas_window *window)
++{
++ return -1;
++}
+diff --git a/arch/powerpc/platforms/powernv/vas.c b/arch/powerpc/platforms/powernv/vas.c
new file mode 100644
-index 0000000..75e55f9
+index 0000000..556156b
--- /dev/null
-+++ b/drivers/misc/vas/vas.c
-@@ -0,0 +1,155 @@
++++ b/arch/powerpc/platforms/powernv/vas.c
+@@ -0,0 +1,183 @@
+/*
+ * Copyright 2016 IBM Corp.
+ *
@@ -178,64 +166,67 @@
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/slab.h>
++#include <linux/platform_device.h>
++#include <linux/of_platform.h>
++#include <linux/of_address.h>
+#include <linux/of.h>
-+#include <asm/vas.h>
-+#include "vas-internal.h"
-+
-+int vas_initialized;
-+int vas_num_instances;
-+struct vas_instance *vas_instances;
-+
-+static void init_vas_chip(struct vas_instance *vinst)
-+{
-+ int i;
-+
-+ for (i = 0; i < VAS_MAX_WINDOWS_PER_CHIP; i++)
-+ vas_window_reset(vinst, i);
-+}
-+
-+static int init_vas_instance(struct device_node *dn,
-+ struct vas_instance *vinst)
-+{
-+ int rc;
-+ const __be32 *p;
-+
++
++#include "vas.h"
++
++static bool init_done;
++LIST_HEAD(vas_instances);
++
++static int init_vas_instance(struct platform_device *pdev)
++{
++ int rc, vasid;
++ struct vas_instance *vinst;
++ struct device_node *dn = pdev->dev.of_node;
++ struct resource *res;
++
++ rc = of_property_read_u32(dn, "ibm,vas-id", &vasid);
++ if (rc) {
++ pr_err("VAS: No ibm,vas-id property for %s?\n", pdev->name);
++ return -ENODEV;
++ }
++
++ if (pdev->num_resources != 4) {
++ pr_err("VAS: Unexpected DT configuration for [%s, %d]\n",
++ pdev->name, vasid);
++ return -ENODEV;
++ }
++
++ vinst = kcalloc(1, sizeof(*vinst), GFP_KERNEL);
++ if (!vinst)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&vinst->node);
+ ida_init(&vinst->ida);
+ mutex_init(&vinst->mutex);
-+
-+ p = of_get_property(dn, "vas-id", NULL);
-+ if (!p) {
-+ pr_err("VAS: NULL vas-id? %p\n", p);
-+ return -ENODEV;
-+ }
-+
-+ vinst->vas_id = of_read_number(p, 1);
-+
-+ rc = of_property_read_u64(dn, "hvwc-bar-start", &vinst->hvwc_bar_start);
-+ if (rc)
-+ return rc;
-+
-+ rc = of_property_read_u64(dn, "hvwc-bar-size", &vinst->hvwc_bar_len);
-+ if (rc)
-+ return rc;
-+
-+ rc = of_property_read_u64(dn, "uwc-bar-start", &vinst->uwc_bar_start);
-+ if (rc)
-+ return rc;
-+
-+ rc = of_property_read_u64(dn, "uwc-bar-size", &vinst->uwc_bar_len);
-+ if (rc)
-+ return rc;
-+
-+ rc = of_property_read_u64(dn, "window-base", &vinst->win_base_addr);
-+ if (rc)
-+ return rc;
-+
-+ rc = of_property_read_u64(dn, "window-shift", &vinst->win_id_shift);
-+ if (rc)
-+ return rc;
-+
-+ init_vas_chip(vinst);
++ vinst->vas_id = vasid;
++ vinst->pdev = pdev;
++
++ res = &pdev->resource[0];
++ vinst->hvwc_bar_start = res->start;
++ vinst->hvwc_bar_len = res->end - res->start + 1;
++
++ res = &pdev->resource[1];
++ vinst->uwc_bar_start = res->start;
++ vinst->uwc_bar_len = res->end - res->start + 1;
++
++ res = &pdev->resource[2];
++ vinst->paste_base_addr = res->start;
++
++ res = &pdev->resource[3];
++ vinst->paste_win_id_shift = 63 - res->end;
++
++ pr_devel("VAS: Initialized instance [%s, %d], paste_base 0x%llx, "
++ "paste_win_id_shift 0x%llx\n", pdev->name, vasid,
++ vinst->paste_base_addr, vinst->paste_win_id_shift);
++
++ vinst->ready = true;
++ list_add(&vinst->node, &vas_instances);
++
++ dev_set_drvdata(&pdev->dev, vinst);
+
+ return 0;
+}
@@ -246,78 +237,135 @@
+ */
+struct vas_instance *find_vas_instance(int vasid)
+{
-+ int i;
++ struct list_head *ent;
+ struct vas_instance *vinst;
+
-+ for (i = 0; i < vas_num_instances; i++) {
-+ vinst = &vas_instances[i];
++ list_for_each(ent, &vas_instances) {
++ vinst = list_entry(ent, struct vas_instance, node);
+ if (vinst->vas_id == vasid)
+ return vinst;
+ }
-+ pr_err("VAS instance for vas-id %d not found\n", vasid);
-+ WARN_ON_ONCE(1);
++
++ pr_devel("VAS: Instance %d not found\n", vasid);
+ return NULL;
+}
+
++bool vas_initialized(void)
++{
++ return init_done;
++}
++
++static int vas_probe(struct platform_device *pdev)
++{
++ if (!pdev || !pdev->dev.of_node)
++ return -ENODEV;
++
++ return init_vas_instance(pdev);
++}
++
++static void free_inst(struct vas_instance *vinst)
++{
++ list_del(&vinst->node);
++
++ kfree(vinst);
++}
++
++static int vas_remove(struct platform_device *pdev)
++{
++ struct vas_instance *vinst;
++
++ vinst = dev_get_drvdata(&pdev->dev);
++
++ pr_devel("VAS: Removed instance [%s, %d]\n", pdev->name,
++ vinst->vas_id);
++ free_inst(vinst);
++
++ return 0;
++}
++static const struct of_device_id powernv_vas_match[] = {
++ { .compatible = "ibm,vas",},
++ {},
++};
++
++static struct platform_driver vas_driver = {
++ .driver = {
++ .name = "vas",
++ .of_match_table = powernv_vas_match,
++ },
++ .probe = vas_probe,
++ .remove = vas_remove,
++};
++
++module_platform_driver(vas_driver);
+
+int vas_init(void)
+{
-+ int rc;
++ int found = 0;
+ struct device_node *dn;
++
++ for_each_compatible_node(dn, NULL, "ibm,vas") {
++ of_platform_device_create(dn, NULL, NULL);
++ found++;
++ }
++
++ if (!found)
++ return -ENODEV;
++
++ pr_devel("VAS: Found %d instances\n", found);
++ init_done = true;
++
++ return 0;
++}
++
++void vas_exit(void)
++{
++ struct list_head *ent;
+ struct vas_instance *vinst;
+
-+ if (!pvr_version_is(PVR_POWER9))
-+ return -ENODEV;
-+
-+ vas_num_instances = 0;
-+ for_each_node_by_name(dn, "vas")
-+ vas_num_instances++;
-+
-+ if (!vas_num_instances)
-+ return -ENODEV;
-+
-+ vas_instances = kcalloc(vas_num_instances, sizeof(*vinst), GFP_KERNEL);
-+ if (!vas_instances)
-+ return -ENOMEM;
-+
-+ vinst = &vas_instances[0];
-+ for_each_node_by_name(dn, "vas") {
-+ rc = init_vas_instance(dn, vinst);
-+ if (rc) {
-+ pr_err("Error %d initializing VAS instance %ld\n", rc,
-+ (vinst-&vas_instances[0]));
-+ goto cleanup;
-+ }
-+ vinst++;
-+ }
-+
-+ rc = -ENODEV;
-+ if (vinst == &vas_instances[0]) {
-+ /* Should not happen as we saw some above. */
-+ pr_err("VAS: Did not find any VAS DT nodes now!\n");
-+ goto cleanup;
-+ }
-+
-+ pr_devel("VAS: Initialized %d instances\n", vas_num_instances);
-+ vas_initialized = 1;
-+
-+ return 0;
-+
-+cleanup:
-+ kfree(vas_instances);
-+ return rc;
-+}
-+
-+void vas_exit(void)
-+{
-+ vas_initialized = 0;
-+ kfree(vas_instances);
++ list_for_each(ent, &vas_instances) {
++ vinst = list_entry(ent, struct vas_instance, node);
++ of_platform_depopulate(&vinst->pdev->dev);
++ }
++
++ init_done = false;
+}
+
+module_init(vas_init);
+module_exit(vas_exit);
-+MODULE_DESCRIPTION("IBM Virtual Accelerator Switchboard");
++MODULE_DESCRIPTION("Bare metal IBM Virtual Accelerator Switchboard");
+MODULE_AUTHOR("Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>");
+MODULE_LICENSE("GPL");
+diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h
+index c6bcc0c..12c6380 100644
+--- a/arch/powerpc/platforms/powernv/vas.h
++++ b/arch/powerpc/platforms/powernv/vas.h
+@@ -291,14 +291,17 @@ enum vas_notify_after_count {
+ */
+ struct vas_instance {
+ int vas_id;
++ bool ready;
+ struct ida ida;
++ struct list_head node;
++ struct platform_device *pdev;
+
+ u64 hvwc_bar_start;
+ u64 hvwc_bar_len;
+ u64 uwc_bar_start;
+ u64 uwc_bar_len;
+- u64 win_base_addr;
+- u64 win_id_shift;
++ u64 paste_base_addr;
++ u64 paste_win_id_shift;
+
+ struct mutex mutex;
+ struct vas_window *rxwin[VAS_COP_TYPE_MAX];
+@@ -376,4 +379,7 @@ struct vas_winctx {
+ enum vas_notify_after_count notify_after_count;
+ };
+
++extern bool vas_initialized(void);
++extern struct vas_instance *find_vas_instance(int vasid);
++
+ #endif /* _VAS_H */
--
2.7.4