/* * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. 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: target_if_ext_twt_evt.c * This file contains twt component's target related function definitions */ #include #include #include #include #include #include #include "twt/core/src/wlan_twt_main.h" static int target_if_twt_setup_complete_event_handler(ol_scn_t scn, uint8_t *event, uint32_t len) { QDF_STATUS qdf_status; struct wmi_unified *wmi_handle; struct wlan_objmgr_psoc *psoc; struct twt_add_dialog_complete_event *data; struct wlan_lmac_if_twt_rx_ops *twt_rx_ops; TARGET_IF_ENTER(); psoc = target_if_get_psoc_from_scn_hdl(scn); if (!psoc) { target_if_err("psoc is null"); return -EINVAL; } wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); if (!wmi_handle) { target_if_err("wmi_handle is null"); return -EINVAL; } twt_rx_ops = wlan_twt_get_rx_ops(psoc); if (!twt_rx_ops || !twt_rx_ops->twt_setup_comp_cb) { target_if_err("No valid twt setup complete rx ops"); return -EINVAL; } data = qdf_mem_malloc(sizeof(*data)); if (!data) return -ENOMEM; qdf_status = wmi_extract_twt_add_dialog_comp_event(wmi_handle, event, &data->params); if (QDF_IS_STATUS_ERROR(qdf_status)) { target_if_err("extract twt add dialog event failed (status=%d)", qdf_status); goto done; } if (data->params.num_additional_twt_params) { qdf_status = wmi_extract_twt_add_dialog_comp_additional_params( wmi_handle, event, len, 0, &data->additional_params); if (QDF_IS_STATUS_ERROR(qdf_status)) goto done; } qdf_status = twt_rx_ops->twt_setup_comp_cb(psoc, data); done: qdf_mem_free(data); return qdf_status_to_os_return(qdf_status); } static int target_if_twt_teardown_complete_event_handler(ol_scn_t scn, uint8_t *event, uint32_t len) { QDF_STATUS qdf_status; struct wmi_unified *wmi_handle; struct wlan_objmgr_psoc *psoc; struct twt_del_dialog_complete_event_param *data; struct wlan_lmac_if_twt_rx_ops *twt_rx_ops; TARGET_IF_ENTER(); psoc = target_if_get_psoc_from_scn_hdl(scn); if (!psoc) { target_if_err("psoc is null"); return -EINVAL; } wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); if (!wmi_handle) { target_if_err("wmi_handle is null"); return -EINVAL; } twt_rx_ops = wlan_twt_get_rx_ops(psoc); if (!twt_rx_ops || !twt_rx_ops->twt_teardown_comp_cb) { target_if_err("No valid twt teardown complete rx ops"); return -EINVAL; } data = qdf_mem_malloc(sizeof(*data)); if (!data) return -ENOMEM; qdf_status = wmi_extract_twt_del_dialog_comp_event(wmi_handle, event, data); if (QDF_IS_STATUS_ERROR(qdf_status)) { target_if_err("extract twt del dialog event failed (status=%d)", qdf_status); goto done; } qdf_status = twt_rx_ops->twt_teardown_comp_cb(psoc, data); done: qdf_mem_free(data); return qdf_status_to_os_return(qdf_status); } /** * target_if_twt_pause_complete_event_handler - TWT pause complete handler * @scn: scn * @event: buffer with event * @len: buffer length * * Return: 0 on success, negative value on failure */ static int target_if_twt_pause_complete_event_handler(ol_scn_t scn, uint8_t *event, uint32_t len) { QDF_STATUS qdf_status; struct wmi_unified *wmi_handle; struct wlan_objmgr_psoc *psoc; struct twt_pause_dialog_complete_event_param *param; struct wlan_lmac_if_twt_rx_ops *twt_rx_ops; TARGET_IF_ENTER(); psoc = target_if_get_psoc_from_scn_hdl(scn); if (!psoc) { target_if_err("psoc is null"); return -EINVAL; } wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); if (!wmi_handle) { target_if_err("wmi_handle is null"); return -EINVAL; } twt_rx_ops = wlan_twt_get_rx_ops(psoc); if (!twt_rx_ops || !twt_rx_ops->twt_pause_comp_cb) { target_if_err("No valid twt pause complete rx ops"); return -EINVAL; } param = qdf_mem_malloc(sizeof(*param)); if (!param) return -ENOMEM; qdf_status = wmi_extract_twt_pause_dialog_comp_event(wmi_handle, event, param); if (QDF_IS_STATUS_ERROR(qdf_status)) { target_if_err("extract twt pause dialog event failed (status=%d)", qdf_status); goto done; } qdf_status = twt_rx_ops->twt_pause_comp_cb(psoc, param); done: qdf_mem_free(param); return qdf_status_to_os_return(qdf_status); } /** * target_if_twt_resume_complete_event_handler - TWT resume complete evt handler * @scn: scn * @event: buffer with event * @len: buffer length * * Return: 0 on success, negative value on failure */ static int target_if_twt_resume_complete_event_handler(ol_scn_t scn, uint8_t *event, uint32_t len) { QDF_STATUS qdf_status; struct wmi_unified *wmi_handle; struct wlan_objmgr_psoc *psoc; struct twt_resume_dialog_complete_event_param *param; struct wlan_lmac_if_twt_rx_ops *twt_rx_ops; TARGET_IF_ENTER(); psoc = target_if_get_psoc_from_scn_hdl(scn); if (!psoc) { target_if_err("psoc is null"); return -EINVAL; } wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); if (!wmi_handle) { target_if_err("wmi_handle is null"); return -EINVAL; } twt_rx_ops = wlan_twt_get_rx_ops(psoc); if (!twt_rx_ops || !twt_rx_ops->twt_resume_comp_cb) { target_if_err("No valid twt resume complete rx ops"); return -EINVAL; } param = qdf_mem_malloc(sizeof(*param)); if (!param) return -ENOMEM; qdf_status = wmi_extract_twt_resume_dialog_comp_event(wmi_handle, event, param); if (QDF_IS_STATUS_ERROR(qdf_status)) { target_if_err("extract twt resume event failed (status=%d)", qdf_status); goto done; } qdf_status = twt_rx_ops->twt_resume_comp_cb(psoc, param); done: qdf_mem_free(param); return qdf_status_to_os_return(qdf_status); } /** * target_if_twt_nudge_complete_event_handler - TWT nudge complete evt handler * @scn: scn * @event: buffer with event * @len: buffer length * * Return: 0 on success, negative value on failure */ static int target_if_twt_nudge_complete_event_handler(ol_scn_t scn, uint8_t *event, uint32_t len) { QDF_STATUS qdf_status; struct wmi_unified *wmi_handle; struct wlan_objmgr_psoc *psoc; struct twt_nudge_dialog_complete_event_param *param; struct wlan_lmac_if_twt_rx_ops *twt_rx_ops; TARGET_IF_ENTER(); psoc = target_if_get_psoc_from_scn_hdl(scn); if (!psoc) { target_if_err("psoc is null"); return -EINVAL; } wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); if (!wmi_handle) { target_if_err("wmi_handle is null"); return -EINVAL; } twt_rx_ops = wlan_twt_get_rx_ops(psoc); if (!twt_rx_ops || !twt_rx_ops->twt_nudge_comp_cb) { target_if_err("No valid twt nudge complete rx ops"); return -EINVAL; } param = qdf_mem_malloc(sizeof(*param)); if (!param) return -ENOMEM; qdf_status = wmi_extract_twt_nudge_dialog_comp_event(wmi_handle, event, param); if (QDF_IS_STATUS_ERROR(qdf_status)) { target_if_err("extract twt nudge event failed (status=%d)", qdf_status); goto done; } qdf_status = twt_rx_ops->twt_nudge_comp_cb(psoc, param); done: qdf_mem_free(param); return qdf_status_to_os_return(qdf_status); } static int target_if_twt_notify_event_handler(ol_scn_t scn, uint8_t *event, uint32_t len) { QDF_STATUS qdf_status; struct wmi_unified *wmi_handle; struct wlan_objmgr_psoc *psoc; struct twt_notify_event_param *data; struct wlan_lmac_if_twt_rx_ops *twt_rx_ops; TARGET_IF_ENTER(); psoc = target_if_get_psoc_from_scn_hdl(scn); if (!psoc) { target_if_err("psoc is null"); return -EINVAL; } wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); if (!wmi_handle) { target_if_err("wmi_handle is null"); return -EINVAL; } twt_rx_ops = wlan_twt_get_rx_ops(psoc); if (!twt_rx_ops || !twt_rx_ops->twt_notify_comp_cb) { target_if_err("No valid twt notify rx ops"); return -EINVAL; } data = qdf_mem_malloc(sizeof(*data)); if (!data) return -ENOMEM; qdf_status = wmi_extract_twt_notify_event(wmi_handle, event, data); if (QDF_IS_STATUS_ERROR(qdf_status)) { target_if_err("extract twt notify event failed (status=%d)", qdf_status); goto done; } qdf_status = twt_rx_ops->twt_notify_comp_cb(psoc, data); done: qdf_mem_free(data); return qdf_status_to_os_return(qdf_status); } static int target_if_twt_ack_complete_event_handler(ol_scn_t scn, uint8_t *event, uint32_t len) { QDF_STATUS qdf_status; struct wmi_unified *wmi_handle; struct wlan_objmgr_psoc *psoc; struct twt_ack_complete_event_param *data; struct wlan_lmac_if_twt_rx_ops *twt_rx_ops; TARGET_IF_ENTER(); psoc = target_if_get_psoc_from_scn_hdl(scn); if (!psoc) { target_if_err("psoc is null"); return -EINVAL; } wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); if (!wmi_handle) { target_if_err("wmi_handle is null"); return -EINVAL; } twt_rx_ops = wlan_twt_get_rx_ops(psoc); if (!twt_rx_ops || !twt_rx_ops->twt_ack_comp_cb) { target_if_err("No valid twt ack rx ops"); return -EINVAL; } data = qdf_mem_malloc(sizeof(*data)); if (!data) return -ENOMEM; qdf_status = wmi_extract_twt_ack_comp_event(wmi_handle, event, data); if (QDF_IS_STATUS_ERROR(qdf_status)) { target_if_err("extract twt ack event failed (status=%d)", qdf_status); goto done; } qdf_status = twt_rx_ops->twt_ack_comp_cb(psoc, data); done: qdf_mem_free(data); return qdf_status_to_os_return(qdf_status); } QDF_STATUS target_if_twt_register_ext_events(struct wlan_objmgr_psoc *psoc) { QDF_STATUS status; struct wmi_unified *wmi_handle; wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); if (!wmi_handle) { target_if_err("wmi_handle is null!"); return QDF_STATUS_E_INVAL; } status = wmi_unified_register_event_handler (wmi_handle, wmi_twt_add_dialog_complete_event_id, target_if_twt_setup_complete_event_handler, WMI_RX_WORK_CTX); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to register twt add dialog event cb"); return status; } status = wmi_unified_register_event_handler (wmi_handle, wmi_twt_del_dialog_complete_event_id, target_if_twt_teardown_complete_event_handler, WMI_RX_WORK_CTX); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to register twt del dialog event cb"); return status; } status = wmi_unified_register_event_handler (wmi_handle, wmi_twt_pause_dialog_complete_event_id, target_if_twt_pause_complete_event_handler, WMI_RX_WORK_CTX); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to register twt pause dialog event cb"); return status; } status = wmi_unified_register_event_handler (wmi_handle, wmi_twt_resume_dialog_complete_event_id, target_if_twt_resume_complete_event_handler, WMI_RX_WORK_CTX); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to register twt resume dialog event cb"); return status; } status = wmi_unified_register_event_handler (wmi_handle, wmi_twt_nudge_dialog_complete_event_id, target_if_twt_nudge_complete_event_handler, WMI_RX_WORK_CTX); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to register twt nudge dialog event cb"); return status; } status = wmi_unified_register_event_handler (wmi_handle, wmi_twt_notify_event_id, target_if_twt_notify_event_handler, WMI_RX_WORK_CTX); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to register twt notify event cb"); return status; } status = wmi_unified_register_event_handler (wmi_handle, wmi_twt_ack_complete_event_id, target_if_twt_ack_complete_event_handler, WMI_RX_WORK_CTX); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to register twt ack event cb"); return status; } return status; } QDF_STATUS target_if_twt_deregister_ext_events(struct wlan_objmgr_psoc *psoc) { QDF_STATUS status; struct wmi_unified *wmi_handle; wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); if (!wmi_handle) { target_if_err("wmi_handle is null"); return QDF_STATUS_E_NULL_VALUE; } status = wmi_unified_unregister_event_handler(wmi_handle, wmi_twt_add_dialog_complete_event_id); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to deregister twt add dialog event cb"); return status; } status = wmi_unified_unregister_event_handler(wmi_handle, wmi_twt_del_dialog_complete_event_id); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to deregister twt del dialog event cb"); return status; } status = wmi_unified_unregister_event_handler(wmi_handle, wmi_twt_pause_dialog_complete_event_id); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to deregister twt pause dialog event cb"); return status; } status = wmi_unified_unregister_event_handler(wmi_handle, wmi_twt_resume_dialog_complete_event_id); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to deregister twt resume dialog event"); return status; } status = wmi_unified_unregister_event_handler(wmi_handle, wmi_twt_nudge_dialog_complete_event_id); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to deregister twt nudge dialog event cb"); return status; } status = wmi_unified_unregister_event_handler(wmi_handle, wmi_twt_notify_event_id); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to deregister twt notify event cb"); return status; } status = wmi_unified_unregister_event_handler(wmi_handle, wmi_twt_ack_complete_event_id); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("Failed to deregister twt ack complete event cb"); return status; } return status; }