1 /* 2 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /** 18 * DOC: target_if_dcs.c 19 * 20 * This file provide definition for APIs registered through lmac Tx Ops 21 */ 22 23 #include <wmi_unified_api.h> 24 #include <wmi_unified_priv.h> 25 #include <wmi_unified_dcs_api.h> 26 #include <init_deinit_lmac.h> 27 #include "wlan_dcs_tgt_api.h" 28 #include "target_if_dcs.h" 29 30 /** 31 * target_if_dcs_interference_event_handler() - function to handle dcs event 32 * from firmware. 33 * @scn: scn handle 34 * @data: data buffer for event 35 * @datalen: data length 36 * 37 * Return: status of operation. 38 */ 39 static int target_if_dcs_interference_event_handler(ol_scn_t scn, 40 uint8_t *data, 41 uint32_t datalen) 42 { 43 QDF_STATUS status; 44 struct wlan_host_dcs_event ev; 45 struct wlan_objmgr_psoc *psoc; 46 struct wmi_unified *wmi_handle; 47 struct wlan_target_if_dcs_rx_ops *rx_ops; 48 49 if (!scn || !data) { 50 target_if_err("scn: 0x%pK, data: 0x%pK", scn, data); 51 return -EINVAL; 52 } 53 psoc = target_if_get_psoc_from_scn_hdl(scn); 54 if (!psoc) { 55 target_if_err("null psoc"); 56 return -EINVAL; 57 } 58 59 rx_ops = target_if_dcs_get_rx_ops(psoc); 60 if (!rx_ops || !rx_ops->process_dcs_event) { 61 target_if_err("callback not registered"); 62 return -EINVAL; 63 } 64 65 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 66 if (!wmi_handle) { 67 target_if_err("wmi_handle is null"); 68 return -EINVAL; 69 } 70 71 if (wmi_extract_dcs_interference_type(wmi_handle, data, 72 &ev.dcs_param) != 73 QDF_STATUS_SUCCESS) { 74 target_if_err("Unable to extract dcs interference type"); 75 return -EINVAL; 76 } 77 78 if (ev.dcs_param.interference_type == WLAN_HOST_DCS_WLANIM && 79 wmi_extract_dcs_im_tgt_stats(wmi_handle, data, &ev.wlan_stat) != 80 QDF_STATUS_SUCCESS) { 81 target_if_err("Unable to extract WLAN IM stats"); 82 return -EINVAL; 83 } 84 85 if (ev.dcs_param.interference_type == WLAN_HOST_DCS_AWGNIM && 86 wmi_extract_dcs_awgn_info(wmi_handle, data, &ev.awgn_info) != 87 QDF_STATUS_SUCCESS) { 88 target_if_err("Unable to extract AWGN info"); 89 return -EINVAL; 90 } 91 92 status = rx_ops->process_dcs_event(psoc, &ev); 93 94 return qdf_status_to_os_return(status); 95 } 96 97 static QDF_STATUS 98 target_if_dcs_register_event_handler(struct wlan_objmgr_psoc *psoc) 99 { 100 QDF_STATUS ret_val; 101 struct wmi_unified *wmi_handle; 102 103 if (!psoc) { 104 target_if_err("PSOC is NULL!"); 105 return QDF_STATUS_E_NULL_VALUE; 106 } 107 108 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 109 if (!wmi_handle) { 110 target_if_err("wmi_handle is null"); 111 return QDF_STATUS_E_INVAL; 112 } 113 114 ret_val = wmi_unified_register_event_handler( 115 wmi_handle, 116 wmi_dcs_interference_event_id, 117 target_if_dcs_interference_event_handler, 118 WMI_RX_WORK_CTX); 119 if (QDF_IS_STATUS_ERROR(ret_val)) 120 target_if_err("Failed to register dcs interference event cb"); 121 122 return ret_val; 123 } 124 125 static QDF_STATUS 126 target_if_dcs_unregister_event_handler(struct wlan_objmgr_psoc *psoc) 127 { 128 struct wmi_unified *wmi_handle; 129 130 if (!psoc) { 131 target_if_err("PSOC is NULL!"); 132 return QDF_STATUS_E_INVAL; 133 } 134 135 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 136 if (!wmi_handle) { 137 target_if_err("wmi_handle is null"); 138 return QDF_STATUS_E_INVAL; 139 } 140 wmi_unified_unregister_event_handler(wmi_handle, 141 wmi_dcs_interference_event_id); 142 143 return QDF_STATUS_SUCCESS; 144 } 145 146 /** 147 * target_if_dcs_cmd_send() - Send WMI command for dcs requests 148 * @psoc: psoc pointer 149 * @pdev_id: pdev_id 150 * @is_host_pdev_id: pdev_id is host pdev_id or not 151 * @dcs_enable: dcs enable or not 152 * 153 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error 154 */ 155 static QDF_STATUS 156 target_if_dcs_cmd_send(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id, 157 bool is_host_pdev_id, uint32_t dcs_enable) 158 { 159 QDF_STATUS ret; 160 struct wmi_unified *wmi_handle; 161 162 if (!psoc) { 163 target_if_err("null psoc"); 164 return QDF_STATUS_E_FAILURE; 165 } 166 167 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 168 if (!wmi_handle) { 169 target_if_err("null handle"); 170 return QDF_STATUS_E_FAILURE; 171 } 172 173 ret = wmi_send_dcs_pdev_param(wmi_handle, pdev_id, 174 is_host_pdev_id, dcs_enable); 175 if (QDF_IS_STATUS_ERROR(ret)) 176 target_if_err("wmi dcs cmd send failed, ret: %d", ret); 177 178 return ret; 179 } 180 181 QDF_STATUS 182 target_if_dcs_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 183 { 184 struct wlan_target_if_dcs_tx_ops *dcs_tx_ops; 185 186 if (!tx_ops) { 187 target_if_err("lmac tx ops is NULL!"); 188 return QDF_STATUS_E_INVAL; 189 } 190 191 dcs_tx_ops = &tx_ops->dcs_tx_ops; 192 if (!dcs_tx_ops) { 193 target_if_err("lmac tx ops is NULL!"); 194 return QDF_STATUS_E_FAILURE; 195 } 196 197 dcs_tx_ops->dcs_attach = 198 target_if_dcs_register_event_handler; 199 dcs_tx_ops->dcs_detach = 200 target_if_dcs_unregister_event_handler; 201 dcs_tx_ops->dcs_cmd_send = target_if_dcs_cmd_send; 202 203 return QDF_STATUS_SUCCESS; 204 } 205 206