Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright 2014 IBM Corp.
  4 */
  5
  6#include <linux/module.h>
  7#include <linux/rcupdate.h>
  8#include <asm/errno.h>
  9#include <misc/cxl-base.h>
 10#include <linux/of_platform.h>
 11#include "cxl.h"
 12
 13/* protected by rcu */
 14static struct cxl_calls *cxl_calls;
 15
 16atomic_t cxl_use_count = ATOMIC_INIT(0);
 17EXPORT_SYMBOL(cxl_use_count);
 18
 19#ifdef CONFIG_CXL_MODULE
 20
 21static inline struct cxl_calls *cxl_calls_get(void)
 22{
 23	struct cxl_calls *calls = NULL;
 24
 25	rcu_read_lock();
 26	calls = rcu_dereference(cxl_calls);
 27	if (calls && !try_module_get(calls->owner))
 28		calls = NULL;
 29	rcu_read_unlock();
 30
 31	return calls;
 32}
 33
 34static inline void cxl_calls_put(struct cxl_calls *calls)
 35{
 36	BUG_ON(calls != cxl_calls);
 37
 38	/* we don't need to rcu this, as we hold a reference to the module */
 39	module_put(cxl_calls->owner);
 40}
 41
 42#else /* !defined CONFIG_CXL_MODULE */
 43
 44static inline struct cxl_calls *cxl_calls_get(void)
 45{
 46	return cxl_calls;
 47}
 48
 49static inline void cxl_calls_put(struct cxl_calls *calls) { }
 50
 51#endif /* CONFIG_CXL_MODULE */
 52
 53/* AFU refcount management */
 54struct cxl_afu *cxl_afu_get(struct cxl_afu *afu)
 55{
 56	return (get_device(&afu->dev) == NULL) ? NULL : afu;
 57}
 58EXPORT_SYMBOL_GPL(cxl_afu_get);
 59
 60void cxl_afu_put(struct cxl_afu *afu)
 61{
 62	put_device(&afu->dev);
 63}
 64EXPORT_SYMBOL_GPL(cxl_afu_put);
 65
 66void cxl_slbia(struct mm_struct *mm)
 67{
 68	struct cxl_calls *calls;
 69
 70	calls = cxl_calls_get();
 71	if (!calls)
 72		return;
 73
 74	if (cxl_ctx_in_use())
 75	    calls->cxl_slbia(mm);
 76
 77	cxl_calls_put(calls);
 78}
 79
 80int register_cxl_calls(struct cxl_calls *calls)
 81{
 82	if (cxl_calls)
 83		return -EBUSY;
 84
 85	rcu_assign_pointer(cxl_calls, calls);
 86	return 0;
 87}
 88EXPORT_SYMBOL_GPL(register_cxl_calls);
 89
 90void unregister_cxl_calls(struct cxl_calls *calls)
 91{
 92	BUG_ON(cxl_calls->owner != calls->owner);
 93	RCU_INIT_POINTER(cxl_calls, NULL);
 94	synchronize_rcu();
 95}
 96EXPORT_SYMBOL_GPL(unregister_cxl_calls);
 97
 98int cxl_update_properties(struct device_node *dn,
 99			  struct property *new_prop)
100{
101	return of_update_property(dn, new_prop);
102}
103EXPORT_SYMBOL_GPL(cxl_update_properties);
104
105static int __init cxl_base_init(void)
106{
107	struct device_node *np;
108	struct platform_device *dev;
109	int count = 0;
110
111	/*
112	 * Scan for compatible devices in guest only
113	 */
114	if (cpu_has_feature(CPU_FTR_HVMODE))
115		return 0;
116
117	for_each_compatible_node(np, NULL, "ibm,coherent-platform-facility") {
118		dev = of_platform_device_create(np, NULL, NULL);
119		if (dev)
120			count++;
121	}
122	pr_devel("Found %d cxl device(s)\n", count);
123	return 0;
124}
125device_initcall(cxl_base_init);