1 /* 2 * Copyright (c) 2017 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: qdf_cpuhp 21 * This file provides OS dependent QDF CPU hotplug APIs 22 */ 23 24 #include "i_qdf_cpuhp.h" 25 #include "qdf_trace.h" 26 #include "linux/cpu.h" 27 #include "linux/notifier.h" 28 #include "linux/version.h" 29 30 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) 31 #include "linux/cpuhotplug.h" 32 #endif 33 34 static __qdf_cpuhp_emit __qdf_cpuhp_on_up; 35 static __qdf_cpuhp_emit __qdf_cpuhp_on_down; 36 37 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) 38 static int qdf_cpuhp_legacy_handler(struct notifier_block *block, 39 unsigned long state, 40 void *hcpu) 41 { 42 unsigned long cpu = (unsigned long)hcpu; 43 44 switch (state) { 45 case CPU_ONLINE: 46 __qdf_cpuhp_on_up(cpu); 47 break; 48 49 case CPU_DOWN_PREPARE: 50 case CPU_DOWN_PREPARE_FROZEN: 51 __qdf_cpuhp_on_down(cpu); 52 break; 53 54 default: 55 break; 56 } 57 58 return NOTIFY_OK; 59 } 60 61 static struct notifier_block qdf_cpuhp_notifier_block = { 62 .notifier_call = qdf_cpuhp_legacy_handler, 63 }; 64 65 static inline void qdf_cpuhp_register_callbacks(void) 66 { 67 register_hotcpu_notifier(&qdf_cpuhp_notifier_block); 68 } 69 70 static inline void qdf_cpuhp_unregister_callbacks(void) 71 { 72 unregister_hotcpu_notifier(&qdf_cpuhp_notifier_block); 73 } 74 #else 75 static enum cpuhp_state registered_hotplug_state; 76 77 static int qdf_cpuhp_up_handler(unsigned int cpu) 78 { 79 __qdf_cpuhp_on_up(cpu); 80 81 return 0; 82 } 83 84 static int qdf_cpuhp_down_handler(unsigned int cpu) 85 { 86 __qdf_cpuhp_on_down(cpu); 87 88 return 0; 89 } 90 91 static inline void qdf_cpuhp_register_callbacks(void) 92 { 93 registered_hotplug_state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, 94 "wlan/qca-qdf:online", 95 qdf_cpuhp_up_handler, 96 qdf_cpuhp_down_handler); 97 } 98 99 static inline void qdf_cpuhp_unregister_callbacks(void) 100 { 101 QDF_BUG(registered_hotplug_state); 102 if (registered_hotplug_state) 103 cpuhp_remove_state(registered_hotplug_state); 104 } 105 #endif /* KERNEL_VERSION(4, 6, 0) */ 106 107 void __qdf_cpuhp_os_init(__qdf_cpuhp_emit on_up, __qdf_cpuhp_emit on_down) 108 { 109 __qdf_cpuhp_on_up = on_up; 110 __qdf_cpuhp_on_down = on_down; 111 112 qdf_cpuhp_register_callbacks(); 113 } 114 115 void __qdf_cpuhp_os_deinit(void) 116 { 117 qdf_cpuhp_unregister_callbacks(); 118 } 119 120