--- v4
+++ v5
@@ -1,79 +1,371 @@
-Move the GET_FIELD and SET_FIELD macros to vas.h as VAS and other
-users of VAS, including NX-842 can use those macros.
-
-There is a lot of related code between the VAS/NX kernel drivers
-and skiboot. For consistency switch the order of parameters in
-SET_FIELD to match the order in skiboot.
+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>
-Reviewed-by: Dan Streetman <ddstreet@ieee.org>
---
-
-Changelog[v3]
- - Fix order of parameters in nx-842 driver.
+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.
---
- arch/powerpc/include/uapi/asm/vas.h | 8 ++++++++
- drivers/crypto/nx/nx-842-powernv.c | 7 ++++---
- drivers/crypto/nx/nx-842.h | 5 -----
- 3 files changed, 12 insertions(+), 8 deletions(-)
-
-diff --git a/arch/powerpc/include/uapi/asm/vas.h b/arch/powerpc/include/uapi/asm/vas.h
-index ddfe046..21249f5 100644
---- a/arch/powerpc/include/uapi/asm/vas.h
-+++ b/arch/powerpc/include/uapi/asm/vas.h
-@@ -22,4 +22,12 @@
- #define VAS_THRESH_FIFO_GT_QTR_FULL 2
- #define VAS_THRESH_FIFO_GT_EIGHTH_FULL 3
+ .../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 9e98464..4c4f05e 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -6331,6 +6331,14 @@ F: drivers/crypto/nx/nx.*
+ F: drivers/crypto/nx/nx_csbcpb.h
+ F: drivers/crypto/nx/nx_debugfs.h
++IBM Power Virtual Accelerator Switchboard
++M: Sukadev Bhattiprolu
++L: linuxppc-dev@lists.ozlabs.org
++S: Supported
++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
++ 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/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..6156fbe
+--- /dev/null
++++ b/arch/powerpc/platforms/powernv/vas-window.c
+@@ -0,0 +1,19 @@
+/*
-+ * Get/Set bit fields
++ * Copyright 2016 IBM Corp.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
+ */
-+#define GET_FIELD(m, v) (((v) & (m)) >> MASK_LSH(m))
-+#define MASK_LSH(m) (__builtin_ffsl(m) - 1)
-+#define SET_FIELD(m, v, val) \
-+ (((v) & ~(m)) | ((((typeof(v))(val)) << MASK_LSH(m)) & (m)))
-+
- #endif /* _UAPI_MISC_VAS_H */
-diff --git a/drivers/crypto/nx/nx-842-powernv.c b/drivers/crypto/nx/nx-842-powernv.c
-index 1710f80..3abb045 100644
---- a/drivers/crypto/nx/nx-842-powernv.c
-+++ b/drivers/crypto/nx/nx-842-powernv.c
-@@ -22,6 +22,7 @@
++
++#include <linux/types.h>
++#include <linux/mutex.h>
++
++#include "vas.h"
++
++/* stub for now */
++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..556156b
+--- /dev/null
++++ b/arch/powerpc/platforms/powernv/vas.c
+@@ -0,0 +1,183 @@
++/*
++ * Copyright 2016 IBM Corp.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#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 "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);
++ 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;
++}
++
++/*
++ * Although this is read/used multiple times, it is written to only
++ * during initialization.
++ */
++struct vas_instance *find_vas_instance(int vasid)
++{
++ struct list_head *ent;
++ struct vas_instance *vinst;
++
++ list_for_each(ent, &vas_instances) {
++ vinst = list_entry(ent, struct vas_instance, node);
++ if (vinst->vas_id == vasid)
++ return vinst;
++ }
++
++ 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 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;
++
++ 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("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;
- #include <asm/prom.h>
- #include <asm/icswx.h>
-+#include <asm/vas.h>
+ 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;
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");
-@@ -424,9 +425,9 @@ static int nx842_powernv_function(const unsigned char *in, unsigned int inlen,
+ 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;
+ };
- /* set up CCW */
- ccw = 0;
-- ccw = SET_FIELD(ccw, CCW_CT, nx842_ct);
-- ccw = SET_FIELD(ccw, CCW_CI_842, 0); /* use 0 for hw auto-selection */
-- ccw = SET_FIELD(ccw, CCW_FC_842, fc);
-+ ccw = SET_FIELD(CCW_CT, ccw, nx842_ct);
-+ ccw = SET_FIELD(CCW_CI_842, ccw, 0); /* use 0 for hw auto-selection */
-+ ccw = SET_FIELD(CCW_FC_842, ccw, fc);
-
- /* set up CRB's CSB addr */
- csb_addr = nx842_get_pa(csb) & CRB_CSB_ADDRESS;
-diff --git a/drivers/crypto/nx/nx-842.h b/drivers/crypto/nx/nx-842.h
-index a4eee3b..30929bd 100644
---- a/drivers/crypto/nx/nx-842.h
-+++ b/drivers/crypto/nx/nx-842.h
-@@ -100,11 +100,6 @@ static inline unsigned long nx842_get_pa(void *addr)
- return page_to_phys(vmalloc_to_page(addr)) + offset_in_page(addr);
- }
-
--/* Get/Set bit fields */
--#define MASK_LSH(m) (__builtin_ffsl(m) - 1)
--#define GET_FIELD(v, m) (((v) & (m)) >> MASK_LSH(m))
--#define SET_FIELD(v, m, val) (((v) & ~(m)) | (((val) << MASK_LSH(m)) & (m)))
--
- /**
- * This provides the driver's constraints. Different nx842 implementations
- * may have varying requirements. The constraints are:
++extern bool vas_initialized(void);
++extern struct vas_instance *find_vas_instance(int vasid);
++
+ #endif /* _VAS_H */
--
2.7.4