summaryrefslogtreecommitdiff
path: root/qdf/linux/src/qdf_cpuhp.c
diff options
context:
space:
mode:
Diffstat (limited to 'qdf/linux/src/qdf_cpuhp.c')
-rw-r--r--qdf/linux/src/qdf_cpuhp.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/qdf/linux/src/qdf_cpuhp.c b/qdf/linux/src/qdf_cpuhp.c
new file mode 100644
index 000000000000..199213da32dc
--- /dev/null
+++ b/qdf/linux/src/qdf_cpuhp.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: qdf_cpuhp
+ * This file provides OS dependent QDF CPU hotplug APIs
+ */
+
+#include "i_qdf_cpuhp.h"
+#include "qdf_trace.h"
+#include "linux/cpu.h"
+#include "linux/notifier.h"
+#include "linux/version.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
+#include "linux/cpuhotplug.h"
+#endif
+
+static __qdf_cpuhp_emit __qdf_cpuhp_on_up;
+static __qdf_cpuhp_emit __qdf_cpuhp_on_down;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
+static int qdf_cpuhp_legacy_handler(struct notifier_block *block,
+ unsigned long state,
+ void *hcpu)
+{
+ unsigned long cpu = (unsigned long)hcpu;
+
+ switch (state) {
+ case CPU_ONLINE:
+ __qdf_cpuhp_on_up(cpu);
+ break;
+
+ case CPU_DOWN_PREPARE:
+ case CPU_DOWN_PREPARE_FROZEN:
+ __qdf_cpuhp_on_down(cpu);
+ break;
+
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block qdf_cpuhp_notifier_block = {
+ .notifier_call = qdf_cpuhp_legacy_handler,
+};
+
+static inline void qdf_cpuhp_register_callbacks(void)
+{
+ register_hotcpu_notifier(&qdf_cpuhp_notifier_block);
+}
+
+static inline void qdf_cpuhp_unregister_callbacks(void)
+{
+ unregister_hotcpu_notifier(&qdf_cpuhp_notifier_block);
+}
+#else
+static enum cpuhp_state registered_hotplug_state;
+
+static int qdf_cpuhp_up_handler(unsigned int cpu)
+{
+ __qdf_cpuhp_on_up(cpu);
+
+ return 0;
+}
+
+static int qdf_cpuhp_down_handler(unsigned int cpu)
+{
+ __qdf_cpuhp_on_down(cpu);
+
+ return 0;
+}
+
+static inline void qdf_cpuhp_register_callbacks(void)
+{
+ registered_hotplug_state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+ "wlan/qca-qdf:online",
+ qdf_cpuhp_up_handler,
+ qdf_cpuhp_down_handler);
+}
+
+static inline void qdf_cpuhp_unregister_callbacks(void)
+{
+ QDF_BUG(registered_hotplug_state);
+ if (registered_hotplug_state)
+ cpuhp_remove_state(registered_hotplug_state);
+}
+#endif /* KERNEL_VERSION(4, 6, 0) */
+
+void __qdf_cpuhp_os_init(__qdf_cpuhp_emit on_up, __qdf_cpuhp_emit on_down)
+{
+ __qdf_cpuhp_on_up = on_up;
+ __qdf_cpuhp_on_down = on_down;
+
+ qdf_cpuhp_register_callbacks();
+}
+
+void __qdf_cpuhp_os_deinit(void)
+{
+ qdf_cpuhp_unregister_callbacks();
+}
+