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_6018.h" 32 #include "init_deinit_lmac.h" 33 #include "cfg_ucfg_api.h" 34 #include "cfr_cfg.h" 35 36 static wdi_event_subscribe g_cfr_subscribe; 37 38 static void target_cfr_callback(void *pdev_obj, enum WDI_EVENT event, 39 void *data, u_int16_t peer_id, 40 uint32_t status) 41 { 42 struct wlan_objmgr_pdev *pdev; 43 qdf_nbuf_t nbuf = (qdf_nbuf_t)data; 44 qdf_nbuf_t data_clone; 45 46 pdev = (struct wlan_objmgr_pdev *)pdev_obj; 47 if (qdf_unlikely((!pdev || !data))) { 48 cfr_err("Invalid pdev %pK or data %pK for event %d", 49 pdev, data, event); 50 qdf_nbuf_free(nbuf); 51 return; 52 } 53 54 if (event != WDI_EVENT_RX_PPDU_DESC) { 55 cfr_debug("event is %d", event); 56 qdf_nbuf_free(nbuf); 57 return; 58 } 59 60 data_clone = qdf_nbuf_clone(nbuf); 61 if (data_clone) 62 wlan_cfr_rx_tlv_process(pdev, (void *)data_clone); 63 64 qdf_nbuf_free(nbuf); 65 } 66 67 QDF_STATUS 68 target_if_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev, 69 bool is_subscribe) 70 { 71 ol_txrx_soc_handle soc; 72 struct wlan_objmgr_psoc *psoc; 73 struct pdev_cfr *pcfr; 74 75 if (!pdev) { 76 cfr_err("Null pdev"); 77 return QDF_STATUS_E_INVAL; 78 } 79 80 pcfr = wlan_objmgr_pdev_get_comp_private_obj( 81 pdev, WLAN_UMAC_COMP_CFR); 82 if (!pcfr) { 83 cfr_err("pcfr is NULL"); 84 return QDF_STATUS_E_INVAL; 85 } 86 87 psoc = wlan_pdev_get_psoc(pdev); 88 if (!psoc) { 89 cfr_err("Null psoc"); 90 return QDF_STATUS_E_INVAL; 91 } 92 93 soc = wlan_psoc_get_dp_handle(psoc); 94 if (!soc) { 95 cfr_err("Null soc"); 96 return QDF_STATUS_E_INVAL; 97 } 98 99 g_cfr_subscribe.callback = target_cfr_callback; 100 g_cfr_subscribe.context = pdev; 101 cdp_set_cfr_rcc(soc, 0, is_subscribe); 102 cdp_enable_mon_reap_timer(soc, 0, is_subscribe); 103 if (is_subscribe) { 104 if (cdp_wdi_event_sub(soc, 0, &g_cfr_subscribe, 105 WDI_EVENT_RX_PPDU_DESC)) { 106 cfr_err("wdi event sub fail"); 107 return QDF_STATUS_E_FAILURE; 108 } 109 } else { 110 if (cdp_wdi_event_unsub(soc, 0, &g_cfr_subscribe, 111 WDI_EVENT_RX_PPDU_DESC)) { 112 cfr_err("wdi event unsub fail"); 113 return QDF_STATUS_E_FAILURE; 114 } 115 } 116 117 return QDF_STATUS_SUCCESS; 118 } 119 120 QDF_STATUS cfr_6490_init_pdev(struct wlan_objmgr_psoc *psoc, 121 struct wlan_objmgr_pdev *pdev) 122 { 123 struct pdev_cfr *cfr_pdev; 124 struct psoc_cfr *cfr_psoc; 125 struct wmi_unified *wmi_handle = NULL; 126 bool cfr_capable; 127 QDF_STATUS status; 128 129 if (!psoc || !pdev) { 130 cfr_err("null pdev or psoc"); 131 return QDF_STATUS_E_FAILURE; 132 } 133 134 cfr_pdev = wlan_objmgr_pdev_get_comp_private_obj( 135 pdev, WLAN_UMAC_COMP_CFR); 136 if (!cfr_pdev) { 137 cfr_err("null pdev cfr"); 138 return QDF_STATUS_E_FAILURE; 139 } 140 141 cfr_psoc = wlan_objmgr_psoc_get_comp_private_obj( 142 psoc, WLAN_UMAC_COMP_CFR); 143 144 if (!cfr_psoc) { 145 cfr_err("null psoc cfr"); 146 return QDF_STATUS_E_FAILURE; 147 } 148 149 wmi_handle = lmac_get_pdev_wmi_handle(pdev); 150 if (!wmi_handle) { 151 cfr_err("null wmi handle"); 152 return QDF_STATUS_E_FAILURE; 153 } 154 155 if (wlan_cfr_is_feature_disabled(pdev)) { 156 cfr_pdev->is_cfr_capable = 0; 157 cfr_psoc->is_cfr_capable = 0; 158 cfr_info("cfr disabled"); 159 return QDF_STATUS_SUCCESS; 160 } 161 162 cfr_capable = wmi_service_enabled(wmi_handle, 163 wmi_service_cfr_capture_support); 164 cfr_pdev->is_cfr_capable = cfr_capable; 165 cfr_psoc->is_cfr_capable = cfr_capable; 166 if (!cfr_capable) { 167 cfr_err("FW doesn't support CFR"); 168 return QDF_STATUS_SUCCESS; 169 } 170 171 status = cfr_6018_init_pdev(psoc, pdev); 172 cfr_pdev->chip_type = CFR_CAPTURE_RADIO_HSP; 173 174 return status; 175 } 176 177 QDF_STATUS cfr_6490_deinit_pdev(struct wlan_objmgr_psoc *psoc, 178 struct wlan_objmgr_pdev *pdev) 179 { 180 struct pdev_cfr *pcfr; 181 182 if (!psoc || !pdev) { 183 cfr_err("null pdev or psoc"); 184 return QDF_STATUS_E_FAILURE; 185 } 186 187 pcfr = wlan_objmgr_pdev_get_comp_private_obj( 188 pdev, WLAN_UMAC_COMP_CFR); 189 if (!pcfr) { 190 cfr_err("null pdev cfr"); 191 return QDF_STATUS_E_FAILURE; 192 } 193 194 if (!pcfr->is_cfr_capable) { 195 cfr_info("cfr disabled or FW not support"); 196 return QDF_STATUS_SUCCESS; 197 } 198 199 return cfr_6018_deinit_pdev(psoc, pdev); 200 } 201