1 /* 2 * Copyright (c) 2020 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC : target_if_cfr_6490.c 21 * 22 * Target interface of CFR for QCA6490 implementation 23 * 24 */ 25 26 #include <cdp_txrx_ctrl.h> 27 #include "target_if_cfr.h" 28 #include <qdf_nbuf.h> 29 #include "wlan_cfr_utils_api.h" 30 #include "target_if_cfr_6490.h" 31 #include "target_if_cfr_enh.h" 32 #include "init_deinit_lmac.h" 33 #include "cfg_ucfg_api.h" 34 #include "cfr_cfg.h" 35 36 #ifdef WLAN_ENH_CFR_ENABLE 37 #ifdef CFR_USE_FIXED_FOLDER 38 static wdi_event_subscribe g_cfr_subscribe; 39 40 static void target_cfr_callback(void *pdev_obj, enum WDI_EVENT event, 41 void *data, u_int16_t peer_id, 42 uint32_t status) 43 { 44 struct wlan_objmgr_pdev *pdev; 45 qdf_nbuf_t nbuf = (qdf_nbuf_t)data; 46 qdf_nbuf_t data_clone; 47 48 pdev = (struct wlan_objmgr_pdev *)pdev_obj; 49 if (qdf_unlikely((!pdev || !data))) { 50 cfr_err("Invalid pdev %pK or data %pK for event %d", 51 pdev, data, event); 52 qdf_nbuf_free(nbuf); 53 return; 54 } 55 56 if (event != WDI_EVENT_RX_PPDU_DESC) { 57 cfr_debug("event is %d", event); 58 qdf_nbuf_free(nbuf); 59 return; 60 } 61 62 data_clone = qdf_nbuf_clone(nbuf); 63 if (data_clone) 64 wlan_cfr_rx_tlv_process(pdev, (void *)data_clone); 65 66 qdf_nbuf_free(nbuf); 67 } 68 69 QDF_STATUS 70 target_if_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev, 71 bool is_subscribe) 72 { 73 ol_txrx_soc_handle soc; 74 struct wlan_objmgr_psoc *psoc; 75 struct pdev_cfr *pcfr; 76 77 if (!pdev) { 78 cfr_err("Null pdev"); 79 return QDF_STATUS_E_INVAL; 80 } 81 82 pcfr = wlan_objmgr_pdev_get_comp_private_obj( 83 pdev, WLAN_UMAC_COMP_CFR); 84 if (!pcfr) { 85 cfr_err("pcfr is NULL"); 86 return QDF_STATUS_E_INVAL; 87 } 88 89 psoc = wlan_pdev_get_psoc(pdev); 90 if (!psoc) { 91 cfr_err("Null psoc"); 92 return QDF_STATUS_E_INVAL; 93 } 94 95 soc = wlan_psoc_get_dp_handle(psoc); 96 if (!soc) { 97 cfr_err("Null soc"); 98 return QDF_STATUS_E_INVAL; 99 } 100 101 g_cfr_subscribe.callback = target_cfr_callback; 102 g_cfr_subscribe.context = pdev; 103 cdp_set_cfr_rcc(soc, 0, is_subscribe); 104 cdp_enable_mon_reap_timer(soc, 0, is_subscribe); 105 if (is_subscribe) { 106 if (cdp_wdi_event_sub(soc, 0, &g_cfr_subscribe, 107 WDI_EVENT_RX_PPDU_DESC)) { 108 cfr_err("wdi event sub fail"); 109 return QDF_STATUS_E_FAILURE; 110 } 111 } else { 112 if (cdp_wdi_event_unsub(soc, 0, &g_cfr_subscribe, 113 WDI_EVENT_RX_PPDU_DESC)) { 114 cfr_err("wdi event unsub fail"); 115 return QDF_STATUS_E_FAILURE; 116 } 117 } 118 119 return QDF_STATUS_SUCCESS; 120 } 121 #endif 122 #endif 123 124 QDF_STATUS cfr_6490_init_pdev(struct wlan_objmgr_psoc *psoc, 125 struct wlan_objmgr_pdev *pdev) 126 { 127 struct pdev_cfr *cfr_pdev; 128 struct psoc_cfr *cfr_psoc; 129 struct wmi_unified *wmi_handle = NULL; 130 bool cfr_capable; 131 QDF_STATUS status; 132 133 if (!psoc || !pdev) { 134 cfr_err("null pdev or psoc"); 135 return QDF_STATUS_E_FAILURE; 136 } 137 138 cfr_pdev = wlan_objmgr_pdev_get_comp_private_obj( 139 pdev, WLAN_UMAC_COMP_CFR); 140 if (!cfr_pdev) { 141 cfr_err("null pdev cfr"); 142 return QDF_STATUS_E_FAILURE; 143 } 144 145 cfr_psoc = wlan_objmgr_psoc_get_comp_private_obj( 146 psoc, WLAN_UMAC_COMP_CFR); 147 148 if (!cfr_psoc) { 149 cfr_err("null psoc cfr"); 150 return QDF_STATUS_E_FAILURE; 151 } 152 153 wmi_handle = lmac_get_pdev_wmi_handle(pdev); 154 if (!wmi_handle) { 155 cfr_err("null wmi handle"); 156 return QDF_STATUS_E_FAILURE; 157 } 158 159 if (wlan_cfr_is_feature_disabled(pdev)) { 160 cfr_pdev->is_cfr_capable = 0; 161 cfr_psoc->is_cfr_capable = 0; 162 cfr_info("cfr disabled"); 163 return QDF_STATUS_SUCCESS; 164 } 165 166 cfr_capable = wmi_service_enabled(wmi_handle, 167 wmi_service_cfr_capture_support); 168 cfr_pdev->is_cfr_capable = cfr_capable; 169 cfr_psoc->is_cfr_capable = cfr_capable; 170 if (!cfr_capable) { 171 cfr_err("FW doesn't support CFR"); 172 return QDF_STATUS_SUCCESS; 173 } 174 175 status = cfr_enh_init_pdev(psoc, pdev); 176 cfr_pdev->chip_type = CFR_CAPTURE_RADIO_HSP; 177 178 return status; 179 } 180 181 QDF_STATUS cfr_6490_deinit_pdev(struct wlan_objmgr_psoc *psoc, 182 struct wlan_objmgr_pdev *pdev) 183 { 184 struct pdev_cfr *pcfr; 185 186 if (!psoc || !pdev) { 187 cfr_err("null pdev or psoc"); 188 return QDF_STATUS_E_FAILURE; 189 } 190 191 pcfr = wlan_objmgr_pdev_get_comp_private_obj( 192 pdev, WLAN_UMAC_COMP_CFR); 193 if (!pcfr) { 194 cfr_err("null pdev cfr"); 195 return QDF_STATUS_E_FAILURE; 196 } 197 198 if (!pcfr->is_cfr_capable) { 199 cfr_info("cfr disabled or FW not support"); 200 return QDF_STATUS_SUCCESS; 201 } 202 203 return cfr_enh_deinit_pdev(psoc, pdev); 204 } 205