1 /* 2 * Copyright 2014 IBM Corp. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 */ 9 10 #include <linux/module.h> 11 #include <linux/rcupdate.h> 12 #include <asm/errno.h> 13 #include <misc/cxl.h> 14 #include "cxl.h" 15 16 /* protected by rcu */ 17 static struct cxl_calls *cxl_calls; 18 19 atomic_t cxl_use_count = ATOMIC_INIT(0); 20 EXPORT_SYMBOL(cxl_use_count); 21 22 #ifdef CONFIG_CXL_MODULE 23 24 static inline struct cxl_calls *cxl_calls_get(void) 25 { 26 struct cxl_calls *calls = NULL; 27 28 rcu_read_lock(); 29 calls = rcu_dereference(cxl_calls); 30 if (calls && !try_module_get(calls->owner)) 31 calls = NULL; 32 rcu_read_unlock(); 33 34 return calls; 35 } 36 37 static inline void cxl_calls_put(struct cxl_calls *calls) 38 { 39 BUG_ON(calls != cxl_calls); 40 41 /* we don't need to rcu this, as we hold a reference to the module */ 42 module_put(cxl_calls->owner); 43 } 44 45 #else /* !defined CONFIG_CXL_MODULE */ 46 47 static inline struct cxl_calls *cxl_calls_get(void) 48 { 49 return cxl_calls; 50 } 51 52 static inline void cxl_calls_put(struct cxl_calls *calls) { } 53 54 #endif /* CONFIG_CXL_MODULE */ 55 56 void cxl_slbia(struct mm_struct *mm) 57 { 58 struct cxl_calls *calls; 59 60 calls = cxl_calls_get(); 61 if (!calls) 62 return; 63 64 if (cxl_ctx_in_use()) 65 calls->cxl_slbia(mm); 66 67 cxl_calls_put(calls); 68 } 69 70 int register_cxl_calls(struct cxl_calls *calls) 71 { 72 if (cxl_calls) 73 return -EBUSY; 74 75 rcu_assign_pointer(cxl_calls, calls); 76 return 0; 77 } 78 EXPORT_SYMBOL_GPL(register_cxl_calls); 79 80 void unregister_cxl_calls(struct cxl_calls *calls) 81 { 82 BUG_ON(cxl_calls->owner != calls->owner); 83 RCU_INIT_POINTER(cxl_calls, NULL); 84 synchronize_rcu(); 85 } 86 EXPORT_SYMBOL_GPL(unregister_cxl_calls); 87