1 /* 2 * Copyright (c) 2020, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: contains coex target if functions 20 */ 21 #include <wlan_coex_main.h> 22 #include <target_if_coex.h> 23 #include "wlan_coex_public_structs.h" 24 25 /** 26 * target_if_coex_config_send() - Function to send coex config command 27 * @pdev: PDEV object 28 * @param: Pointer to coex config parameters 29 * 30 * Return: QDF STATUS 31 */ 32 static QDF_STATUS 33 target_if_coex_config_send(struct wlan_objmgr_pdev *pdev, 34 struct coex_config_params *param) 35 { 36 wmi_unified_t pdev_wmi_handle; 37 38 pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev); 39 if (!pdev_wmi_handle) { 40 coex_err("Invalid PDEV WMI handle"); 41 return QDF_STATUS_E_FAILURE; 42 } 43 44 return wmi_unified_send_coex_config_cmd(pdev_wmi_handle, param); 45 } 46 47 /** 48 * target_if_coex_multi_config_send() - Function to send coex multiple config 49 * command 50 * @pdev: PDEV object 51 * @param: Pointer to coex multiple config parameters 52 * 53 * Return: QDF STATUS 54 */ 55 static QDF_STATUS 56 target_if_coex_multi_config_send(struct wlan_objmgr_pdev *pdev, 57 struct coex_multi_config *param) 58 { 59 wmi_unified_t pdev_wmi_handle; 60 61 pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev); 62 if (!pdev_wmi_handle) { 63 coex_err("Invalid PDEV WMI handle"); 64 return QDF_STATUS_E_FAILURE; 65 } 66 67 return wmi_unified_send_coex_multi_config_cmd(pdev_wmi_handle, param); 68 } 69 70 /** 71 * target_if_coex_get_multi_config_support() - Function to get coex multiple 72 * config command support 73 * @psoc: PSOC object 74 * 75 * Return: true if target support coex multiple config command 76 */ 77 static bool 78 target_if_coex_get_multi_config_support(struct wlan_objmgr_psoc *psoc) 79 { 80 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 81 82 if (!wmi_handle) { 83 target_if_err("Invalid wmi handle"); 84 return false; 85 } 86 87 return wmi_service_enabled(wmi_handle, 88 wmi_service_multiple_coex_config_support); 89 } 90 91 QDF_STATUS 92 target_if_coex_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 93 { 94 struct wlan_lmac_if_coex_tx_ops *coex_ops; 95 96 if (!tx_ops) { 97 coex_err("target if tx ops is NULL!"); 98 return QDF_STATUS_E_INVAL; 99 } 100 101 coex_ops = &tx_ops->coex_ops; 102 coex_ops->coex_config_send = target_if_coex_config_send; 103 coex_ops->coex_multi_config_send = target_if_coex_multi_config_send; 104 coex_ops->coex_get_multi_config_support = 105 target_if_coex_get_multi_config_support; 106 107 return QDF_STATUS_SUCCESS; 108 } 109 110 #ifdef WLAN_FEATURE_DBAM_CONFIG 111 QDF_STATUS 112 target_if_dbam_process_event(struct wlan_objmgr_psoc *psoc, 113 enum coex_dbam_comp_status resp) 114 { 115 struct coex_psoc_obj *coex_obj; 116 struct wlan_coex_callback *cb; 117 118 if (!psoc) { 119 coex_err("psoc is null"); 120 return QDF_STATUS_E_INVAL; 121 } 122 123 coex_obj = wlan_psoc_get_coex_obj(psoc); 124 if (!coex_obj) { 125 coex_err("failed to get coex_obj"); 126 return QDF_STATUS_E_INVAL; 127 } 128 129 cb = &coex_obj->cb; 130 if (cb->set_dbam_config_cb) 131 cb->set_dbam_config_cb(cb->set_dbam_config_ctx, &resp); 132 133 return QDF_STATUS_SUCCESS; 134 } 135 136 /** 137 * target_if_dbam_response_event_handler() - function to handle dbam response 138 * event from firmware. 139 * @scn: scn handle 140 * @data: data buffer foe the event 141 * @len: data length 142 * 143 * Return: 0 on success, and error code on failure 144 */ 145 static int target_if_dbam_response_event_handler(ol_scn_t scn, 146 uint8_t *data, 147 uint32_t len) 148 { 149 QDF_STATUS status; 150 struct wlan_objmgr_psoc *psoc; 151 wmi_unified_t wmi_handle; 152 struct wlan_lmac_if_dbam_rx_ops *rx_ops; 153 struct coex_dbam_config_resp resp = {0}; 154 155 target_if_debug("scn:%pK, data:%pK, datalen:%d", scn, data, len); 156 if (!scn || !data) { 157 target_if_err("scn: 0x%pK, data: 0x%pK", scn, data); 158 return -EINVAL; 159 } 160 161 psoc = target_if_get_psoc_from_scn_hdl(scn); 162 if (!psoc) { 163 target_if_err("psoc is Null"); 164 return -EINVAL; 165 } 166 167 rx_ops = wlan_psoc_get_dbam_rx_ops(psoc); 168 if (!rx_ops || !rx_ops->dbam_resp_event) { 169 target_if_err("callback not registered"); 170 return -EINVAL; 171 } 172 173 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 174 if (!wmi_handle) { 175 target_if_err("wmi_handle is null"); 176 return -EINVAL; 177 } 178 179 status = wmi_extract_dbam_config_response(wmi_handle, data, &resp); 180 if (QDF_IS_STATUS_ERROR(status)) { 181 target_if_err("Failed to extract dbam config response"); 182 return -EINVAL; 183 } 184 185 status = rx_ops->dbam_resp_event(psoc, resp.dbam_resp); 186 if (QDF_IS_STATUS_ERROR(status)) { 187 target_if_err("process dbam response event failed"); 188 return -EINVAL; 189 } 190 191 return 0; 192 } 193 194 /** 195 * target_if_dbam_config_send() - Send WMI command for DBAM configuration 196 * @psoc: psoc pointer 197 * @param: dbam config parameters 198 * 199 * Return: QDF_STATUS 200 */ 201 static QDF_STATUS 202 target_if_dbam_config_send(struct wlan_objmgr_psoc *psoc, 203 struct coex_dbam_config_params *param) 204 { 205 QDF_STATUS status; 206 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 207 208 if (!wmi_handle) { 209 target_if_err("Invalid WMI handle"); 210 return QDF_STATUS_E_FAILURE; 211 } 212 213 status = wmi_unified_send_dbam_config_cmd(wmi_handle, param); 214 if (QDF_IS_STATUS_ERROR(status)) 215 target_if_err("Failed to send DBAM config %d", status); 216 217 return status; 218 } 219 220 static QDF_STATUS 221 target_if_dbam_register_event_handler(struct wlan_objmgr_psoc *psoc) 222 { 223 QDF_STATUS status; 224 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 225 226 if (!wmi_handle) { 227 target_if_err("Invalid WMI handle"); 228 return QDF_STATUS_E_INVAL; 229 } 230 231 status = wmi_unified_register_event_handler(wmi_handle, 232 wmi_coex_dbam_complete_event_id, 233 target_if_dbam_response_event_handler, 234 WMI_RX_WORK_CTX); 235 236 if (QDF_IS_STATUS_ERROR(status)) 237 target_if_err("Failed to register dbam complete event cb"); 238 239 return status; 240 } 241 242 static QDF_STATUS 243 target_if_dbam_unregister_event_handler(struct wlan_objmgr_psoc *psoc) 244 { 245 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 246 247 if (!wmi_handle) { 248 target_if_err("Invalid WMI handle"); 249 return QDF_STATUS_E_INVAL; 250 } 251 252 wmi_unified_unregister_event_handler(wmi_handle, 253 wmi_coex_dbam_complete_event_id); 254 255 return QDF_STATUS_SUCCESS; 256 } 257 258 QDF_STATUS 259 target_if_dbam_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 260 { 261 struct wlan_lmac_if_dbam_tx_ops *dbam_tx_ops; 262 263 if (!tx_ops) { 264 target_if_err("target if tx ops is NULL!"); 265 return QDF_STATUS_E_INVAL; 266 } 267 268 dbam_tx_ops = &tx_ops->dbam_tx_ops; 269 if (!dbam_tx_ops) { 270 target_if_err("target if dbam ops is NULL!"); 271 return QDF_STATUS_E_FAILURE; 272 } 273 274 dbam_tx_ops->set_dbam_config = target_if_dbam_config_send; 275 dbam_tx_ops->dbam_event_attach = target_if_dbam_register_event_handler; 276 dbam_tx_ops->dbam_event_detach = 277 target_if_dbam_unregister_event_handler; 278 279 return QDF_STATUS_SUCCESS; 280 } 281 #endif 282