diff --git a/init_deinit/dispatcher/inc/dispatcher_init_deinit.h b/init_deinit/dispatcher/inc/dispatcher_init_deinit.h new file mode 100644 index 000000000000..97bbab7158a1 --- /dev/null +++ b/init_deinit/dispatcher/inc/dispatcher_init_deinit.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2016 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: This file provides various init/deinit trigger point for new + * components. + */ + +#if !defined(__DISPATCHER_INIT_H) +#define __DISPATCHER_INIT_H + +#include + +/** + * dispatcher_init(): API to init all new components + * + * This API calls all new components init APIs. This is invoked + * from HDD/OS_If layer during: + * 1) Driver load sequence + * 2) before probing the attached device. + * 3) FW is not ready + * 4) WMI channel is not established + * + * A component can't communicate with FW during init stage. + * + * Return: none + */ +QDF_STATUS dispatcher_init(void); + +/** + * dispatcher_deinit(): API to de-init all new components + * + * This API calls all new components de-init APIs. This is invoked + * from HDD/OS_If layer during: + * 1) Driver unload sequence + * 2) FW is dead + * 3) WMI channel is destroyed + * 4) all PDEV and PSOC objects are destroyed + * + * A component can't communicate with FW during de-init stage. + * + * Return: none + */ +QDF_STATUS dispatcher_deinit(void); + +/** + * dispatcher_psoc_open(): API to trigger PSOC open for all new components + * + * This API calls all new components PSOC OPEN APIs. This is invoked from + * HDD/OS_If layer during: + * 1) Driver load sequence + * 2) PSOC object is created + * 3) FW is not yet ready + * 4) WMI channel is not yet established with FW + * + * PSOC open happens before FW WMI ready and hence a component can't + * communicate with FW during PSOC open sequence. + * + * Return: none + */ +QDF_STATUS dispatcher_psoc_open(void); + +/** + * dispatcher_psoc_close(): API to trigger PSOC close for all new components + * + * This API calls all new components PSOC CLOSE APIs. This is invoked from + * HDD/OS_If layer during: + * 1) Driver unload sequence + * 2) PSOC object is destroyed + * 3) FW is already dead(PDEV suspended) + * 4) WMI channel is destroyed with FW + * + * A component can't communicate with FW during PSOC close. + * + * Return: none + */ +QDF_STATUS dispatcher_psoc_close(void); + +/** + * dispatcher_psoc_enable(): API to trigger PSOC enable(start) for all new + * components + * + * This API calls all new components PSOC enable(start) APIs. This is invoked + * from HDD/OS_If layer during: + * 1) Driver load sequence + * 2) PSOC object is created + * 3) WMI endpoint and WMI channel is ready with FW + * 4) WMI FW ready event is also received from FW. + * + * FW is already ready and WMI channel is established by this time so a + * component can communicate with FW during PSOC enable sequence. + * + * Return: none + */ +QDF_STATUS dispatcher_psoc_enable(void); + +/** + * dispatcher_psoc_disable(): API to trigger PSOC disable(stop) for all new + * components + * + * This API calls all new components PSOC disable(stop) APIs. This is invoked + * from HDD/OS_If layer during: + * 1) Driver unload sequence + * 2) WMI channel is still available + * 3) FW is still running and up + * 4) PSOC object is not destroyed + * + * A component should abort all its ongign transaction with FW at this stage + * for example scan component needs to abort all its ongoing scan in FW because + * is goign to be stopped very soon. + * + * Return: none + */ +QDF_STATUS dispatcher_psoc_disable(void); + +#endif /* End of !defined(__DISPATCHER_INIT_H) */ diff --git a/init_deinit/dispatcher/src/dispatcher_init_deinit.c b/init_deinit/dispatcher/src/dispatcher_init_deinit.c new file mode 100644 index 000000000000..aaf244f2a28c --- /dev/null +++ b/init_deinit/dispatcher/src/dispatcher_init_deinit.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2016 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. + */ + +#include +#include +#include + +/** + * DOC: This file provides various init/deinit trigger point for new + * components. + */ + +/* All new components needs to replace their dummy init/deinit + * psoc_open, psco_close, psoc_enable and psoc_disable APIs once + * thier actual handlers are ready + */ + +static QDF_STATUS obj_manager_init(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS obj_manager_deinit(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS scm_init(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS scm_deinit(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS p2p_init(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS p2p_deinit(void) +{ + return QDF_STATUS_SUCCESS; +} + + +static QDF_STATUS tdls_init(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS tdls_deinit(void) +{ + return QDF_STATUS_SUCCESS; +} + + +static QDF_STATUS scheduler_init(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS scheduler_deinit(void) +{ + return QDF_STATUS_SUCCESS; +} + + +static QDF_STATUS scm_psoc_open(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS scm_psoc_close(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS p2p_psoc_open(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS p2p_psoc_close(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS tdls_psoc_open(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS tdls_psoc_close(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS scm_psoc_enable(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS scm_psoc_disable(void) +{ + return QDF_STATUS_SUCCESS; +} + + +static QDF_STATUS p2p_psoc_enable(void) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS p2p_psoc_disable(void) +{ + return QDF_STATUS_SUCCESS; +} + + +static QDF_STATUS tdls_psoc_enable(void) +{ + return QDF_STATUS_SUCCESS; +} + + +static QDF_STATUS tdls_psoc_disable(void) +{ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS dispatcher_init(void) +{ + if (QDF_STATUS_SUCCESS != obj_manager_init()) + goto out; + + if (QDF_STATUS_SUCCESS != scm_init()) + goto scm_init_fail; + + if (QDF_STATUS_SUCCESS != p2p_init()) + goto p2p_init_fail; + + if (QDF_STATUS_SUCCESS != tdls_init()) + goto tdls_init_fail; + + if (QDF_STATUS_SUCCESS != scheduler_init()) + goto scheduler_init_fail; + + return QDF_STATUS_SUCCESS; + +scheduler_init_fail: + tdls_deinit(); +tdls_init_fail: + p2p_deinit(); +p2p_init_fail: + scm_deinit(); +scm_init_fail: + obj_manager_deinit(); + +out: + return QDF_STATUS_E_FAILURE; +} + +QDF_STATUS dispatcher_deinit(void) +{ + QDF_BUG(QDF_STATUS_SUCCESS == scheduler_deinit()); + + QDF_BUG(QDF_STATUS_SUCCESS == tdls_deinit()); + + QDF_BUG(QDF_STATUS_SUCCESS == p2p_deinit()); + + QDF_BUG(QDF_STATUS_SUCCESS == scm_deinit()); + + QDF_BUG(QDF_STATUS_SUCCESS == obj_manager_deinit()); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS dispatcher_psoc_open(void) +{ + if (QDF_STATUS_SUCCESS != scm_psoc_open()) + goto out; + + if (QDF_STATUS_SUCCESS != p2p_psoc_open()) + goto p2p_psoc_open_fail; + + if (QDF_STATUS_SUCCESS != tdls_psoc_open()) + goto tdls_psoc_open_fail; + + return QDF_STATUS_SUCCESS; + +tdls_psoc_open_fail: + p2p_psoc_close(); +p2p_psoc_open_fail: + scm_psoc_close(); + +out: + return QDF_STATUS_E_FAILURE; +} + +QDF_STATUS dispatcher_psoc_close(void) +{ + QDF_BUG(QDF_STATUS_SUCCESS == tdls_psoc_close()); + + QDF_BUG(QDF_STATUS_SUCCESS == p2p_psoc_close()); + + QDF_BUG(QDF_STATUS_SUCCESS == scm_psoc_close()); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS dispatcher_psoc_enable(void) +{ + if (QDF_STATUS_SUCCESS != scm_psoc_enable()) + goto out; + + if (QDF_STATUS_SUCCESS != p2p_psoc_enable()) + goto p2p_psoc_enable_fail; + + if (QDF_STATUS_SUCCESS != tdls_psoc_enable()) + goto tdls_psoc_enable_fail; + + return QDF_STATUS_SUCCESS; + +tdls_psoc_enable_fail: + p2p_psoc_disable(); +p2p_psoc_enable_fail: + scm_psoc_disable(); + +out: + return QDF_STATUS_E_FAILURE; +} + +QDF_STATUS dispatcher_psoc_disable(void) +{ + QDF_BUG(QDF_STATUS_SUCCESS == tdls_psoc_disable()); + + QDF_BUG(QDF_STATUS_SUCCESS == p2p_psoc_disable()); + + QDF_BUG(QDF_STATUS_SUCCESS == scm_psoc_disable()); + + return QDF_STATUS_SUCCESS; +}