1 /* 2 * Copyright (c) 2018 The Linux Foundation. All rights reserved. 3 * 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: offload lmac interface APIs definitions for FTM 22 */ 23 24 #include <qdf_status.h> 25 #include <target_if_ftm.h> 26 #include <wmi_unified_priv.h> 27 #include <wlan_objmgr_psoc_obj.h> 28 #include <target_if.h> 29 #include <wlan_lmac_if_def.h> 30 #include <wlan_ftm_ucfg_api.h> 31 32 static inline struct wlan_lmac_if_ftm_rx_ops * 33 target_if_ftm_get_rx_ops(struct wlan_objmgr_psoc *psoc) 34 { 35 return &psoc->soc_cb.rx_ops.ftm_rx_ops; 36 } 37 38 static int 39 target_if_ftm_process_utf_event(ol_scn_t sc, uint8_t *event_buf, uint32_t len) 40 { 41 struct wlan_objmgr_psoc *psoc; 42 struct wlan_objmgr_pdev *pdev; 43 struct wmi_host_pdev_utf_event event; 44 struct wlan_lmac_if_ftm_rx_ops *ftm_rx_ops; 45 QDF_STATUS status = QDF_STATUS_E_FAILURE; 46 uint32_t pdev_id; 47 48 psoc = target_if_get_psoc_from_scn_hdl(sc); 49 if (!psoc) { 50 ftm_err("null psoc"); 51 return QDF_STATUS_E_INVAL; 52 } 53 54 status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_FTM_ID); 55 if (QDF_IS_STATUS_ERROR(status)) { 56 ftm_err("unable to get psoc reference"); 57 return QDF_STATUS_E_INVAL; 58 } 59 60 event.datalen = len; 61 if (wmi_extract_pdev_utf_event(GET_WMI_HDL_FROM_PSOC(psoc), 62 event_buf, &event) != QDF_STATUS_SUCCESS) { 63 ftm_err("Extracting utf event failed"); 64 wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID); 65 return QDF_STATUS_E_INVAL; 66 } 67 68 pdev_id = event.pdev_id; 69 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_FTM_ID); 70 if (!pdev) { 71 pdev_id = TGT_WMI_PDEV_ID_SOC; 72 ftm_debug("Can't find pdev by pdev_id %d, try soc_id", 73 event.pdev_id); 74 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_FTM_ID); 75 if (!pdev) { 76 ftm_err("null pdev"); 77 wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID); 78 return QDF_STATUS_E_INVAL; 79 } 80 } 81 82 ftm_rx_ops = target_if_ftm_get_rx_ops(psoc); 83 84 if (ftm_rx_ops->ftm_ev_handler) { 85 status = ftm_rx_ops->ftm_ev_handler(pdev, 86 event.data, event.datalen); 87 if (QDF_IS_STATUS_ERROR(status)) 88 status = QDF_STATUS_E_INVAL; 89 } else { 90 status = QDF_STATUS_E_INVAL; 91 } 92 93 wlan_objmgr_pdev_release_ref(pdev, WLAN_FTM_ID); 94 wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID); 95 96 return status; 97 } 98 99 QDF_STATUS target_if_ftm_cmd_send(struct wlan_objmgr_pdev *pdev, 100 uint8_t *buf, uint32_t len, 101 uint8_t pdev_id) 102 { 103 QDF_STATUS ret; 104 wmi_unified_t handle; 105 struct pdev_utf_params param; 106 107 if (!pdev) { 108 target_if_err("null pdev"); 109 return QDF_STATUS_E_FAILURE; 110 } 111 112 handle = get_wmi_unified_hdl_from_pdev(pdev); 113 if (!handle) { 114 target_if_err("null handle"); 115 return QDF_STATUS_E_FAILURE; 116 } 117 param.utf_payload = buf; 118 param.len = len; 119 120 ret = wmi_unified_pdev_utf_cmd_send(handle, ¶m, pdev_id); 121 if (QDF_IS_STATUS_ERROR(ret)) 122 ftm_err("wmi utf cmd send failed, ret: %d", ret); 123 124 return ret; 125 } 126 127 QDF_STATUS target_if_ftm_attach(struct wlan_objmgr_psoc *psoc) 128 { 129 int ret; 130 wmi_unified_t handle; 131 132 if (!psoc) { 133 target_if_err("null psoc"); 134 return QDF_STATUS_E_FAILURE; 135 } 136 137 handle = get_wmi_unified_hdl_from_psoc(psoc); 138 if (!handle) { 139 target_if_err("null handle"); 140 return QDF_STATUS_E_FAILURE; 141 } 142 ret = wmi_unified_register_event_handler(handle, 143 wmi_pdev_utf_event_id, 144 target_if_ftm_process_utf_event, 145 WMI_RX_UMAC_CTX); 146 if (ret) { 147 ftm_err("wmi event registration failed, ret: %d", ret); 148 return QDF_STATUS_E_FAILURE; 149 } 150 151 return QDF_STATUS_SUCCESS; 152 } 153 154 QDF_STATUS target_if_ftm_detach(struct wlan_objmgr_psoc *psoc) 155 156 { 157 int ret; 158 wmi_unified_t handle; 159 160 if (!psoc) { 161 target_if_err("null psoc"); 162 return QDF_STATUS_E_FAILURE; 163 } 164 165 handle = get_wmi_unified_hdl_from_psoc(psoc); 166 if (!handle) { 167 target_if_err("null handle"); 168 return QDF_STATUS_E_FAILURE; 169 } 170 ret = wmi_unified_unregister_event_handler(handle, 171 wmi_pdev_utf_event_id); 172 173 if (ret) { 174 ftm_err("wmi event deregistration failed, ret: %d", ret); 175 return QDF_STATUS_E_FAILURE; 176 } 177 178 return QDF_STATUS_SUCCESS; 179 } 180 181 QDF_STATUS target_if_ftm_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 182 { 183 struct wlan_lmac_if_ftm_tx_ops *ftm_tx_ops; 184 185 if (!tx_ops) { 186 ftm_err("invalid tx_ops"); 187 return QDF_STATUS_E_FAILURE; 188 } 189 190 ftm_tx_ops = &tx_ops->ftm_tx_ops; 191 ftm_tx_ops->ftm_attach = target_if_ftm_attach; 192 ftm_tx_ops->ftm_detach = target_if_ftm_detach; 193 ftm_tx_ops->ftm_cmd_send = target_if_ftm_cmd_send; 194 195 return QDF_STATUS_SUCCESS; 196 } 197