1 /* 2 * Copyright (c) 2020, 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 dcs_stats_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 (wmi_extract_dcs_im_tgt_stats(wmi_handle, data, &ev.wlan_stat) != 79 QDF_STATUS_SUCCESS) { 80 target_if_err("Unable to extract WLAN IM stats"); 81 return -EINVAL; 82 } 83 84 status = rx_ops->process_dcs_event(psoc, &ev); 85 86 return qdf_status_to_os_return(status); 87 } 88 89 static QDF_STATUS 90 target_if_dcs_register_event_handler(struct wlan_objmgr_psoc *psoc) 91 { 92 QDF_STATUS ret_val; 93 struct wmi_unified *wmi_handle; 94 95 if (!psoc) { 96 target_if_err("PSOC is NULL!"); 97 return QDF_STATUS_E_NULL_VALUE; 98 } 99 100 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 101 if (!wmi_handle) { 102 target_if_err("wmi_handle is null"); 103 return QDF_STATUS_E_INVAL; 104 } 105 106 ret_val = wmi_unified_register_event_handler( 107 wmi_handle, 108 wmi_dcs_interference_event_id, 109 target_if_dcs_interference_event_handler, 110 WMI_RX_WORK_CTX); 111 if (QDF_IS_STATUS_ERROR(ret_val)) 112 target_if_err("Failed to register dcs interference event cb"); 113 114 return ret_val; 115 } 116 117 static QDF_STATUS 118 target_if_dcs_unregister_event_handler(struct wlan_objmgr_psoc *psoc) 119 { 120 struct wmi_unified *wmi_handle; 121 122 if (!psoc) { 123 target_if_err("PSOC is NULL!"); 124 return QDF_STATUS_E_INVAL; 125 } 126 127 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 128 if (!wmi_handle) { 129 target_if_err("wmi_handle is null"); 130 return QDF_STATUS_E_INVAL; 131 } 132 wmi_unified_unregister_event_handler(wmi_handle, 133 wmi_dcs_interference_event_id); 134 135 return QDF_STATUS_SUCCESS; 136 } 137 138 /** 139 * target_if_dcs_cmd_send() - Send WMI command for dcs requests 140 * @psoc: psoc pointer 141 * @pdev_id: pdev_id 142 * @is_host_pdev_id: pdev_id is host pdev_id or not 143 * @dcs_enable: dcs enable or not 144 * 145 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error 146 */ 147 static QDF_STATUS 148 target_if_dcs_cmd_send(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id, 149 bool is_host_pdev_id, uint32_t dcs_enable) 150 { 151 QDF_STATUS ret; 152 struct wmi_unified *wmi_handle; 153 154 if (!psoc) { 155 target_if_err("null psoc"); 156 return QDF_STATUS_E_FAILURE; 157 } 158 159 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 160 if (!wmi_handle) { 161 target_if_err("null handle"); 162 return QDF_STATUS_E_FAILURE; 163 } 164 165 ret = wmi_send_dcs_pdev_param(wmi_handle, pdev_id, 166 is_host_pdev_id, dcs_enable); 167 if (QDF_IS_STATUS_ERROR(ret)) 168 target_if_err("wmi dcs cmd send failed, ret: %d", ret); 169 170 return ret; 171 } 172 173 QDF_STATUS 174 target_if_dcs_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 175 { 176 struct wlan_target_if_dcs_tx_ops *dcs_tx_ops; 177 178 if (!tx_ops) { 179 target_if_err("lmac tx ops is NULL!"); 180 return QDF_STATUS_E_INVAL; 181 } 182 183 dcs_tx_ops = &tx_ops->dcs_tx_ops; 184 if (!dcs_tx_ops) { 185 target_if_err("lmac tx ops is NULL!"); 186 return QDF_STATUS_E_FAILURE; 187 } 188 189 dcs_tx_ops->dcs_attach = 190 target_if_dcs_register_event_handler; 191 dcs_tx_ops->dcs_detach = 192 target_if_dcs_unregister_event_handler; 193 dcs_tx_ops->dcs_cmd_send = target_if_dcs_cmd_send; 194 195 return QDF_STATUS_SUCCESS; 196 } 197 198