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)
qdf_cpuhp_legacy_handler(struct notifier_block * block,unsigned long state,void * hcpu)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
qdf_cpuhp_register_callbacks(void)65 static inline void qdf_cpuhp_register_callbacks(void)
66 {
67 register_hotcpu_notifier(&qdf_cpuhp_notifier_block);
68 }
69
qdf_cpuhp_unregister_callbacks(void)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
qdf_cpuhp_up_handler(unsigned int cpu)77 static int qdf_cpuhp_up_handler(unsigned int cpu)
78 {
79 __qdf_cpuhp_on_up(cpu);
80
81 return 0;
82 }
83
qdf_cpuhp_down_handler(unsigned int cpu)84 static int qdf_cpuhp_down_handler(unsigned int cpu)
85 {
86 __qdf_cpuhp_on_down(cpu);
87
88 return 0;
89 }
90
qdf_cpuhp_register_callbacks(void)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
qdf_cpuhp_unregister_callbacks(void)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
__qdf_cpuhp_os_init(__qdf_cpuhp_emit on_up,__qdf_cpuhp_emit on_down)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
__qdf_cpuhp_os_deinit(void)115 void __qdf_cpuhp_os_deinit(void)
116 {
117 qdf_cpuhp_unregister_callbacks();
118 }
119
120