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 47 psoc = target_if_get_psoc_from_scn_hdl(sc); 48 if (!psoc) { 49 ftm_err("null psoc"); 50 return QDF_STATUS_E_INVAL; 51 } 52 53 status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_FTM_ID); 54 if (QDF_IS_STATUS_ERROR(status)) { 55 ftm_err("unable to get psoc reference"); 56 return QDF_STATUS_E_INVAL; 57 } 58 59 event.datalen = len; 60 if (wmi_extract_pdev_utf_event(GET_WMI_HDL_FROM_PSOC(psoc), 61 event_buf, &event) != QDF_STATUS_SUCCESS) { 62 ftm_err("Extracting utf event failed"); 63 wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID); 64 return QDF_STATUS_E_INVAL; 65 } 66 67 pdev = wlan_objmgr_get_pdev_by_id(psoc, event.pdev_id, WLAN_FTM_ID); 68 if (!pdev) { 69 ftm_err("null pdev"); 70 wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID); 71 return QDF_STATUS_E_INVAL; 72 } 73 74 ftm_rx_ops = target_if_ftm_get_rx_ops(psoc); 75 76 if (ftm_rx_ops->ftm_ev_handler) { 77 status = ftm_rx_ops->ftm_ev_handler(pdev, 78 event.data, event.datalen); 79 if (QDF_IS_STATUS_ERROR(status)) 80 status = QDF_STATUS_E_INVAL; 81 } else { 82 status = QDF_STATUS_E_INVAL; 83 } 84 85 wlan_objmgr_pdev_release_ref(pdev, WLAN_FTM_ID); 86 wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID); 87 88 return status; 89 } 90 91 QDF_STATUS target_if_ftm_cmd_send(struct wlan_objmgr_pdev *pdev, 92 uint8_t *buf, uint32_t len, 93 uint8_t pdev_id) 94 { 95 QDF_STATUS ret; 96 wmi_unified_t handle; 97 struct pdev_utf_params param; 98 99 if (!pdev) { 100 target_if_err("null pdev"); 101 return QDF_STATUS_E_FAILURE; 102 } 103 104 handle = get_wmi_unified_hdl_from_pdev(pdev); 105 if (!handle) { 106 target_if_err("null handle"); 107 return QDF_STATUS_E_FAILURE; 108 } 109 param.utf_payload = buf; 110 param.len = len; 111 112 ret = wmi_unified_pdev_utf_cmd_send(handle, ¶m, pdev_id); 113 if (QDF_IS_STATUS_ERROR(ret)) 114 ftm_err("wmi utf cmd send failed, ret: %d", ret); 115 116 return ret; 117 } 118 119 QDF_STATUS target_if_ftm_attach(struct wlan_objmgr_psoc *psoc) 120 { 121 int ret; 122 wmi_unified_t handle; 123 124 if (!psoc) { 125 target_if_err("null psoc"); 126 return QDF_STATUS_E_FAILURE; 127 } 128 129 handle = get_wmi_unified_hdl_from_psoc(psoc); 130 if (!handle) { 131 target_if_err("null handle"); 132 return QDF_STATUS_E_FAILURE; 133 } 134 ret = wmi_unified_register_event_handler(handle, 135 wmi_pdev_utf_event_id, 136 target_if_ftm_process_utf_event, 137 WMI_RX_UMAC_CTX); 138 if (ret) { 139 ftm_err("wmi event registration failed, ret: %d", ret); 140 return QDF_STATUS_E_FAILURE; 141 } 142 143 return QDF_STATUS_SUCCESS; 144 } 145 146 QDF_STATUS target_if_ftm_detach(struct wlan_objmgr_psoc *psoc) 147 148 { 149 int ret; 150 wmi_unified_t handle; 151 152 if (!psoc) { 153 target_if_err("null psoc"); 154 return QDF_STATUS_E_FAILURE; 155 } 156 157 handle = get_wmi_unified_hdl_from_psoc(psoc); 158 if (!handle) { 159 target_if_err("null handle"); 160 return QDF_STATUS_E_FAILURE; 161 } 162 ret = wmi_unified_unregister_event_handler(handle, 163 wmi_pdev_utf_event_id); 164 165 if (ret) { 166 ftm_err("wmi event deregistration failed, ret: %d", ret); 167 return QDF_STATUS_E_FAILURE; 168 } 169 170 return QDF_STATUS_SUCCESS; 171 } 172 173 QDF_STATUS target_if_ftm_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 174 { 175 struct wlan_lmac_if_ftm_tx_ops *ftm_tx_ops; 176 177 if (!tx_ops) { 178 ftm_err("invalid tx_ops"); 179 return QDF_STATUS_E_FAILURE; 180 } 181 182 ftm_tx_ops = &tx_ops->ftm_tx_ops; 183 ftm_tx_ops->ftm_attach = target_if_ftm_attach; 184 ftm_tx_ops->ftm_detach = target_if_ftm_detach; 185 ftm_tx_ops->ftm_cmd_send = target_if_ftm_cmd_send; 186 187 return QDF_STATUS_SUCCESS; 188 } 189