1 /*
2 * Copyright (c) 2018-2020 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: This implementation of init/deint functions for FTM services.
22 */
23
24 #include "wlan_ftm_svc_i.h"
25 #include <wlan_lmac_if_def.h>
26 #include <wlan_ftm_ucfg_api.h>
27 #include "target_if.h"
28
29 static inline struct wlan_lmac_if_ftm_tx_ops *
wlan_psoc_get_ftm_txops(struct wlan_objmgr_psoc * psoc)30 wlan_psoc_get_ftm_txops(struct wlan_objmgr_psoc *psoc)
31 {
32 struct wlan_lmac_if_tx_ops *tx_ops;
33
34 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
35 if (!tx_ops) {
36 ftm_err("tx_ops is NULL");
37 return NULL;
38 }
39
40 return &tx_ops->ftm_tx_ops;
41 }
42
43 static QDF_STATUS
ftm_pdev_obj_init(struct wifi_ftm_pdev_priv_obj * ftm_pdev_obj)44 ftm_pdev_obj_init(struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj)
45 {
46 ftm_pdev_obj->data = qdf_mem_malloc(FTM_CMD_MAX_BUF_LENGTH);
47 if (!ftm_pdev_obj->data)
48 return QDF_STATUS_E_NOMEM;
49
50 ftm_pdev_obj->length = 0;
51
52 ftm_pdev_obj->cmd_type = WIFI_FTM_CMD_UNKNOWN;
53 return QDF_STATUS_SUCCESS;
54 }
55
56 QDF_STATUS
wlan_ftm_pdev_obj_create_notification(struct wlan_objmgr_pdev * pdev,void * arg_list)57 wlan_ftm_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev,
58 void *arg_list)
59 {
60 QDF_STATUS status;
61 struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj;
62 uint32_t device_mode;
63 struct wlan_objmgr_psoc *psoc;
64 struct target_psoc_info *target_psoc_info;
65
66 psoc = wlan_pdev_get_psoc(pdev);
67 if (!psoc)
68 return QDF_STATUS_E_FAULT;
69
70 target_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
71 if (!target_psoc_info)
72 return QDF_STATUS_E_FAULT;
73
74 device_mode = target_psoc_get_device_mode(target_psoc_info);
75
76 if (device_mode != QDF_GLOBAL_FTM_MODE)
77 return QDF_STATUS_SUCCESS;
78
79 ftm_pdev_obj = qdf_mem_malloc(sizeof(*ftm_pdev_obj));
80
81 if (!ftm_pdev_obj)
82 return QDF_STATUS_E_NOMEM;
83
84 ftm_pdev_obj->pdev = pdev;
85 status = ftm_pdev_obj_init(ftm_pdev_obj);
86
87 if (QDF_IS_STATUS_ERROR(status)) {
88 ftm_err("ftm pdev obj init failed");
89 qdf_mem_free(ftm_pdev_obj);
90 return status;
91 }
92
93 status = wlan_objmgr_pdev_component_obj_attach(pdev,
94 WLAN_UMAC_COMP_FTM,
95 ftm_pdev_obj,
96 QDF_STATUS_SUCCESS);
97
98 if (QDF_IS_STATUS_ERROR(status)) {
99 ftm_err("ftm pdev obj attach failed");
100 qdf_mem_free(ftm_pdev_obj);
101 return status;
102 }
103
104 return status;
105 }
106
107 static QDF_STATUS
ftm_pdev_obj_deinit(struct wifi_ftm_pdev_priv_obj * ftm_pdev_obj)108 ftm_pdev_obj_deinit(struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj)
109 {
110 if (ftm_pdev_obj->data) {
111 qdf_mem_free(ftm_pdev_obj->data);
112
113 ftm_pdev_obj->data = NULL;
114 ftm_pdev_obj->length = 0;
115 }
116
117 return QDF_STATUS_SUCCESS;
118 }
119
120 QDF_STATUS
wlan_ftm_pdev_obj_destroy_notification(struct wlan_objmgr_pdev * pdev,void * arg_list)121 wlan_ftm_pdev_obj_destroy_notification(struct wlan_objmgr_pdev *pdev,
122 void *arg_list)
123 {
124 QDF_STATUS status;
125 struct wifi_ftm_pdev_priv_obj *ftm_pdev_obj;
126 struct wlan_objmgr_psoc *psoc;
127 struct target_psoc_info *target_psoc_info;
128 uint32_t device_mode;
129
130 psoc = wlan_pdev_get_psoc(pdev);
131 if (!psoc)
132 return QDF_STATUS_E_FAULT;
133
134 target_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
135 if (!target_psoc_info)
136 return QDF_STATUS_E_FAULT;
137
138 device_mode = target_psoc_get_device_mode(target_psoc_info);
139 if (device_mode != QDF_GLOBAL_FTM_MODE)
140 return QDF_STATUS_SUCCESS;
141
142 ftm_pdev_obj =
143 wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_FTM);
144
145 if (!ftm_pdev_obj) {
146 ftm_err("invalid wifi ftm obj");
147 return QDF_STATUS_E_FAULT;
148 }
149
150 status = wlan_objmgr_pdev_component_obj_detach(pdev, WLAN_UMAC_COMP_FTM,
151 ftm_pdev_obj);
152
153 status = ftm_pdev_obj_deinit(ftm_pdev_obj);
154 ftm_pdev_obj->pdev = NULL;
155
156 qdf_mem_free(ftm_pdev_obj);
157
158 return status;
159 }
160
161 QDF_STATUS
wlan_ftm_testmode_attach(struct wlan_objmgr_psoc * psoc)162 wlan_ftm_testmode_attach(struct wlan_objmgr_psoc *psoc)
163 {
164 struct wlan_lmac_if_ftm_tx_ops *ftm_tx_ops;
165
166 ftm_tx_ops = wlan_psoc_get_ftm_txops(psoc);
167 if (!ftm_tx_ops) {
168 ftm_err("ftm_tx_ops is NULL");
169 return QDF_STATUS_E_FAULT;
170 }
171
172 if (ftm_tx_ops->ftm_attach)
173 return ftm_tx_ops->ftm_attach(psoc);
174 else
175 return QDF_STATUS_SUCCESS;
176 }
177
178 QDF_STATUS
wlan_ftm_testmode_detach(struct wlan_objmgr_psoc * psoc)179 wlan_ftm_testmode_detach(struct wlan_objmgr_psoc *psoc)
180 {
181 struct wlan_lmac_if_ftm_tx_ops *ftm_tx_ops;
182
183 ftm_tx_ops = wlan_psoc_get_ftm_txops(psoc);
184 if (!ftm_tx_ops) {
185 ftm_err("ftm_tx_ops is NULL");
186 return QDF_STATUS_E_FAULT;
187 }
188
189 if (ftm_tx_ops->ftm_detach)
190 return ftm_tx_ops->ftm_detach(psoc);
191 else
192 return QDF_STATUS_SUCCESS;
193 }
194
195 QDF_STATUS
wlan_ftm_cmd_send(struct wlan_objmgr_pdev * pdev,uint8_t * buf,uint32_t len,uint8_t pdev_id)196 wlan_ftm_cmd_send(struct wlan_objmgr_pdev *pdev, uint8_t *buf,
197 uint32_t len, uint8_t pdev_id)
198 {
199 struct wlan_lmac_if_ftm_tx_ops *ftm_tx_ops;
200 struct wlan_objmgr_psoc *psoc;
201
202 psoc = wlan_pdev_get_psoc(pdev);
203 if (!psoc)
204 return QDF_STATUS_E_NOENT;
205
206 ftm_tx_ops = wlan_psoc_get_ftm_txops(psoc);
207 if (!ftm_tx_ops) {
208 ftm_err("ftm_tx_ops is NULL");
209 return QDF_STATUS_E_FAULT;
210 }
211
212 if (ftm_tx_ops->ftm_cmd_send)
213 return ftm_tx_ops->ftm_cmd_send(pdev, buf, len, pdev_id);
214
215 return QDF_STATUS_SUCCESS;
216 }
217