/* * Copyright (c) 2017 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(); }