cxl: Add base builtin support
authorIan Munsie <imunsie@au1.ibm.com>
Wed, 8 Oct 2014 08:55:01 +0000 (19:55 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 8 Oct 2014 09:15:56 +0000 (20:15 +1100)
This adds the base cxl support that cannot be built as a module. Specifically
it adds the cxl callbacks that are called from the core powerpc mm code which
must always exist irrespective of if the cxl module is loaded or not. This is
similar to how cell works with CONFIG_SPU_BASE.

This adds a cxl_slbia() call (similar to spu_flush_all_slbs()) which checks if
the cxl module is loaded and in use, returning immediately if it is not. If it
is in use it calls into the cxl SLB invalidation code.

Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/cxl/Kconfig [new file with mode: 0644]
drivers/misc/cxl/Makefile [new file with mode: 0644]
drivers/misc/cxl/base.c [new file with mode: 0644]

index b841180c7c742f57f63f1345453720b4bb9725a3..bbeb4516facf239b7bce979f6993ae38f1e4e459 100644 (file)
@@ -527,4 +527,5 @@ source "drivers/misc/vmw_vmci/Kconfig"
 source "drivers/misc/mic/Kconfig"
 source "drivers/misc/genwqe/Kconfig"
 source "drivers/misc/echo/Kconfig"
+source "drivers/misc/cxl/Kconfig"
 endmenu
index 5497d026e651f47ffdaaf8bcac9a67cd30c4b2a9..7d5c4cd118c44fbf052425d2d61e3ec3cc1ae455 100644 (file)
@@ -55,3 +55,4 @@ obj-y                         += mic/
 obj-$(CONFIG_GENWQE)           += genwqe/
 obj-$(CONFIG_ECHO)             += echo/
 obj-$(CONFIG_VEXPRESS_SYSCFG)  += vexpress-syscfg.o
+obj-$(CONFIG_CXL_BASE)         += cxl/
diff --git a/drivers/misc/cxl/Kconfig b/drivers/misc/cxl/Kconfig
new file mode 100644 (file)
index 0000000..5cdd319
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# IBM Coherent Accelerator (CXL) compatible devices
+#
+
+config CXL_BASE
+       bool
+       default n
+       select PPC_COPRO_BASE
diff --git a/drivers/misc/cxl/Makefile b/drivers/misc/cxl/Makefile
new file mode 100644 (file)
index 0000000..e30ad0a
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_CXL_BASE)         += base.o
diff --git a/drivers/misc/cxl/base.c b/drivers/misc/cxl/base.c
new file mode 100644 (file)
index 0000000..0654ad8
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2014 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/rcupdate.h>
+#include <asm/errno.h>
+#include <misc/cxl.h>
+#include "cxl.h"
+
+/* protected by rcu */
+static struct cxl_calls *cxl_calls;
+
+atomic_t cxl_use_count = ATOMIC_INIT(0);
+EXPORT_SYMBOL(cxl_use_count);
+
+#ifdef CONFIG_CXL_MODULE
+
+static inline struct cxl_calls *cxl_calls_get(void)
+{
+       struct cxl_calls *calls = NULL;
+
+       rcu_read_lock();
+       calls = rcu_dereference(cxl_calls);
+       if (calls && !try_module_get(calls->owner))
+               calls = NULL;
+       rcu_read_unlock();
+
+       return calls;
+}
+
+static inline void cxl_calls_put(struct cxl_calls *calls)
+{
+       BUG_ON(calls != cxl_calls);
+
+       /* we don't need to rcu this, as we hold a reference to the module */
+       module_put(cxl_calls->owner);
+}
+
+#else /* !defined CONFIG_CXL_MODULE */
+
+static inline struct cxl_calls *cxl_calls_get(void)
+{
+       return cxl_calls;
+}
+
+static inline void cxl_calls_put(struct cxl_calls *calls) { }
+
+#endif /* CONFIG_CXL_MODULE */
+
+void cxl_slbia(struct mm_struct *mm)
+{
+       struct cxl_calls *calls;
+
+       calls = cxl_calls_get();
+       if (!calls)
+               return;
+
+       if (cxl_ctx_in_use())
+           calls->cxl_slbia(mm);
+
+       cxl_calls_put(calls);
+}
+
+int register_cxl_calls(struct cxl_calls *calls)
+{
+       if (cxl_calls)
+               return -EBUSY;
+
+       rcu_assign_pointer(cxl_calls, calls);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(register_cxl_calls);
+
+void unregister_cxl_calls(struct cxl_calls *calls)
+{
+       BUG_ON(cxl_calls->owner != calls->owner);
+       RCU_INIT_POINTER(cxl_calls, NULL);
+       synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(unregister_cxl_calls);