1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
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: HDD object manager API source file to create/destroy PSOC,
22  *  PDEV, VDEV and PEER objects.
23  */
24 
25 #include <wlan_hdd_object_manager.h>
26 #include <wlan_osif_priv.h>
27 #include <wlan_reg_ucfg_api.h>
28 #include <target_if.h>
29 #include <os_if_spectral_netlink.h>
30 
hdd_init_pdev_os_priv(struct hdd_context * hdd_ctx,struct pdev_osif_priv * os_priv)31 static void hdd_init_pdev_os_priv(struct hdd_context *hdd_ctx,
32 	struct pdev_osif_priv *os_priv)
33 {
34 	/* Initialize the OS private structure*/
35 	os_priv->wiphy = hdd_ctx->wiphy;
36 	os_priv->legacy_osif_priv = hdd_ctx;
37 	wlan_cfg80211_scan_priv_init(hdd_ctx->pdev);
38 	os_if_spectral_netlink_init(hdd_ctx->pdev);
39 }
40 
hdd_deinit_pdev_os_priv(struct wlan_objmgr_pdev * pdev)41 static void hdd_deinit_pdev_os_priv(struct wlan_objmgr_pdev *pdev)
42 {
43 	os_if_spectral_netlink_deinit(pdev);
44 	wlan_cfg80211_scan_priv_deinit(pdev);
45 }
hdd_init_psoc_qdf_ctx(struct wlan_objmgr_psoc * psoc)46 static void hdd_init_psoc_qdf_ctx(struct wlan_objmgr_psoc *psoc)
47 {
48 	qdf_device_t qdf_ctx;
49 
50 	qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
51 	if (!qdf_ctx)
52 		return;
53 
54 	wlan_psoc_set_qdf_dev(psoc, qdf_ctx);
55 }
56 
hdd_objmgr_create_and_store_psoc(struct hdd_context * hdd_ctx,uint8_t psoc_id)57 int hdd_objmgr_create_and_store_psoc(struct hdd_context *hdd_ctx,
58 				     uint8_t psoc_id)
59 {
60 	QDF_STATUS status;
61 	struct wlan_objmgr_psoc *psoc;
62 
63 	psoc = wlan_objmgr_psoc_obj_create(psoc_id, WLAN_DEV_OL);
64 	if (!psoc)
65 		return -ENOMEM;
66 
67 	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_HDD_ID_OBJ_MGR);
68 	if (QDF_IS_STATUS_ERROR(status)) {
69 		hdd_err("Failed to acquire psoc ref; status:%d", status);
70 		QDF_BUG(false);
71 		goto psoc_destroy;
72 	}
73 
74 	hdd_init_psoc_qdf_ctx(psoc);
75 	hdd_ctx->psoc = psoc;
76 
77 	return 0;
78 
79 psoc_destroy:
80 	wlan_objmgr_psoc_obj_delete(psoc);
81 
82 	return qdf_status_to_os_return(status);
83 }
84 
hdd_objmgr_release_and_destroy_psoc(struct hdd_context * hdd_ctx)85 int hdd_objmgr_release_and_destroy_psoc(struct hdd_context *hdd_ctx)
86 {
87 	QDF_STATUS status;
88 	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
89 
90 	hdd_ctx->psoc = NULL;
91 
92 	QDF_BUG(psoc);
93 	if (!psoc)
94 		return -EINVAL;
95 
96 	wlan_objmgr_print_ref_all_objects_per_psoc(psoc);
97 
98 	status = wlan_objmgr_psoc_obj_delete(psoc);
99 	wlan_objmgr_psoc_release_ref(psoc, WLAN_HDD_ID_OBJ_MGR);
100 
101 	return qdf_status_to_os_return(status);
102 }
103 
hdd_objmgr_update_tgt_max_vdev_psoc(struct hdd_context * hdd_ctx,uint8_t max_vdev)104 void hdd_objmgr_update_tgt_max_vdev_psoc(struct hdd_context *hdd_ctx,
105 					 uint8_t max_vdev)
106 {
107 	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
108 
109 	if (!psoc) {
110 		hdd_err("Psoc NULL");
111 		return;
112 	}
113 
114 	wlan_psoc_set_max_vdev_count(psoc, max_vdev);
115 }
116 
hdd_check_internal_netdev_state(struct net_device * netdev)117 static int hdd_check_internal_netdev_state(struct net_device *netdev)
118 {
119 	struct hdd_adapter *adapter;
120 
121 	if (!netdev)
122 		return false;
123 
124 	adapter = netdev_priv(netdev);
125 	if (!adapter)
126 		return false;
127 
128 	hdd_debug("netdev name %s, netdev flags 0x%x, event_flags %lu",
129 		  netdev->name, netdev->flags, adapter->event_flags);
130 	if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags) &&
131 	    (netdev->flags & IFF_UP))
132 		return true;
133 	else
134 		return false;
135 }
136 
hdd_objmgr_create_and_store_pdev(struct hdd_context * hdd_ctx)137 int hdd_objmgr_create_and_store_pdev(struct hdd_context *hdd_ctx)
138 {
139 	QDF_STATUS status;
140 	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
141 	struct wlan_objmgr_pdev *pdev;
142 	struct pdev_osif_priv *priv;
143 	struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap_ptr;
144 	uint32_t low_2ghz_chan = 0;
145 	uint32_t high_2ghz_chan = 0;
146 	uint32_t low_5ghz_chan = 0;
147 	uint32_t high_5ghz_chan = 0;
148 
149 	if (!psoc) {
150 		hdd_err("Psoc NULL");
151 		return -EINVAL;
152 	}
153 
154 	priv = qdf_mem_malloc(sizeof(*priv));
155 	if (!priv)
156 		return -ENOMEM;
157 
158 	reg_cap_ptr = ucfg_reg_get_hal_reg_cap(psoc);
159 	if (!reg_cap_ptr) {
160 		hdd_err("Failed to get reg capability");
161 		status = QDF_STATUS_E_INVAL;
162 		goto free_priv;
163 	}
164 	ucfg_mlme_get_phy_max_freq_range(psoc, &low_2ghz_chan,
165 					 &high_2ghz_chan, &low_5ghz_chan,
166 					 &high_5ghz_chan);
167 	reg_cap_ptr->phy_id = 0;
168 	reg_cap_ptr->low_2ghz_chan = low_2ghz_chan;
169 	reg_cap_ptr->high_2ghz_chan = high_2ghz_chan;
170 	reg_cap_ptr->low_5ghz_chan = low_5ghz_chan;
171 	reg_cap_ptr->high_5ghz_chan = high_5ghz_chan;
172 	hdd_debug("pdev freq range %d %d %d %d", reg_cap_ptr->low_2ghz_chan,
173 		  reg_cap_ptr->high_2ghz_chan, reg_cap_ptr->low_5ghz_chan,
174 		  reg_cap_ptr->high_5ghz_chan);
175 	priv->osif_check_netdev_state = hdd_check_internal_netdev_state;
176 	pdev = wlan_objmgr_pdev_obj_create(psoc, priv);
177 	if (!pdev) {
178 		hdd_err("pdev obj create failed");
179 		status = QDF_STATUS_E_NOMEM;
180 		goto free_priv;
181 	}
182 
183 
184 	status = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_HDD_ID_OBJ_MGR);
185 	if (QDF_IS_STATUS_ERROR(status)) {
186 		hdd_err("Failed to acquire pdev ref; status:%d", status);
187 		QDF_BUG(false);
188 		goto pdev_destroy;
189 	}
190 
191 	status = target_if_alloc_pdev_tgt_info(pdev);
192 	if (status != QDF_STATUS_SUCCESS) {
193 		hdd_err("pdev tgt info alloc failed");
194 		goto pdev_destroy;
195 	}
196 
197 	hdd_ctx->pdev = pdev;
198 	sme_store_pdev(hdd_ctx->mac_handle, hdd_ctx->pdev);
199 	hdd_init_pdev_os_priv(hdd_ctx, priv);
200 	return 0;
201 
202 pdev_destroy:
203 	wlan_objmgr_pdev_obj_delete(pdev);
204 free_priv:
205 	qdf_mem_free(priv);
206 
207 	return qdf_status_to_os_return(status);
208 }
209 
hdd_objmgr_release_and_destroy_pdev(struct hdd_context * hdd_ctx)210 int hdd_objmgr_release_and_destroy_pdev(struct hdd_context *hdd_ctx)
211 {
212 	QDF_STATUS status;
213 	struct wlan_objmgr_pdev *pdev = hdd_ctx->pdev;
214 	struct pdev_osif_priv *osif_priv;
215 
216 	hdd_ctx->pdev = NULL;
217 
218 	QDF_BUG(pdev);
219 	if (!pdev)
220 		return -EINVAL;
221 
222 	target_if_free_pdev_tgt_info(pdev);
223 
224 	hdd_deinit_pdev_os_priv(pdev);
225 	osif_priv = wlan_pdev_get_ospriv(pdev);
226 	wlan_pdev_reset_ospriv(pdev);
227 	qdf_mem_free(osif_priv);
228 
229 	status = wlan_objmgr_pdev_obj_delete(pdev);
230 	wlan_objmgr_pdev_release_ref(pdev, WLAN_HDD_ID_OBJ_MGR);
231 
232 	return qdf_status_to_os_return(status);
233 }
234 
hdd_objmgr_set_peer_mlme_auth_state(struct wlan_objmgr_vdev * vdev,bool is_authenticated)235 int hdd_objmgr_set_peer_mlme_auth_state(struct wlan_objmgr_vdev *vdev,
236 					bool is_authenticated)
237 {
238 	struct wlan_objmgr_peer *peer;
239 
240 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_OSIF_ID);
241 	if (!peer) {
242 		hdd_err("peer is null");
243 		return -EINVAL;
244 	}
245 
246 	wlan_peer_obj_lock(peer);
247 	wlan_peer_mlme_set_auth_state(peer, is_authenticated);
248 	wlan_peer_obj_unlock(peer);
249 
250 	wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
251 	return 0;
252 }
253 
hdd_objmgr_set_peer_mlme_state(struct wlan_objmgr_vdev * vdev,enum wlan_peer_state peer_state)254 int hdd_objmgr_set_peer_mlme_state(struct wlan_objmgr_vdev *vdev,
255 	enum wlan_peer_state peer_state)
256 {
257 	struct wlan_objmgr_peer *peer;
258 
259 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_OSIF_ID);
260 	if (!peer) {
261 		hdd_err("peer is null");
262 		return -EINVAL;
263 	}
264 
265 	wlan_peer_obj_lock(peer);
266 	wlan_peer_mlme_set_state(peer, WLAN_ASSOC_STATE);
267 	wlan_peer_obj_unlock(peer);
268 
269 	wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
270 	return 0;
271 }
272 
273 #ifdef WLAN_OBJMGR_REF_ID_TRACE
274 struct wlan_objmgr_vdev *
__hdd_objmgr_get_vdev_by_user(struct wlan_hdd_link_info * link_info,wlan_objmgr_ref_dbgid id,const char * func,int line)275 __hdd_objmgr_get_vdev_by_user(struct wlan_hdd_link_info *link_info,
276 			      wlan_objmgr_ref_dbgid id,
277 			      const char *func, int line)
278 {
279 	struct wlan_objmgr_vdev *vdev;
280 	QDF_STATUS status;
281 
282 	qdf_spin_lock_bh(&link_info->vdev_lock);
283 	vdev = link_info->vdev;
284 	if (vdev) {
285 		status = wlan_objmgr_vdev_try_get_ref_debug(vdev, id, func,
286 							    line);
287 		if (QDF_IS_STATUS_ERROR(status))
288 			vdev = NULL;
289 	}
290 	qdf_spin_unlock_bh(&link_info->vdev_lock);
291 
292 	if (!vdev)
293 		hdd_debug("VDEV is NULL (via %s, id %d)", func, id);
294 
295 	return vdev;
296 }
297 #else
298 struct wlan_objmgr_vdev *
__hdd_objmgr_get_vdev_by_user(struct wlan_hdd_link_info * link_info,wlan_objmgr_ref_dbgid id,const char * func)299 __hdd_objmgr_get_vdev_by_user(struct wlan_hdd_link_info *link_info,
300 			      wlan_objmgr_ref_dbgid id,
301 			      const char *func)
302 {
303 	struct wlan_objmgr_vdev *vdev;
304 	QDF_STATUS status;
305 
306 	qdf_spin_lock_bh(&link_info->vdev_lock);
307 	vdev = link_info->vdev;
308 	if (vdev) {
309 		status = wlan_objmgr_vdev_try_get_ref(vdev, id);
310 		if (QDF_IS_STATUS_ERROR(status))
311 			vdev = NULL;
312 	}
313 	qdf_spin_unlock_bh(&link_info->vdev_lock);
314 
315 	if (!vdev)
316 		hdd_debug("VDEV is NULL (via %s, id %d)", func, id);
317 
318 	return vdev;
319 }
320 #endif
321 
322 #ifdef WLAN_OBJMGR_REF_ID_TRACE
323 void
__hdd_objmgr_put_vdev_by_user(struct wlan_objmgr_vdev * vdev,wlan_objmgr_ref_dbgid id,const char * func,int line)324 __hdd_objmgr_put_vdev_by_user(struct wlan_objmgr_vdev *vdev,
325 			      wlan_objmgr_ref_dbgid id, const char *func,
326 			      int line)
327 {
328 	if (!vdev) {
329 		hdd_err("VDEV is NULL (via %s, id %d)", func, id);
330 		return;
331 	}
332 
333 	wlan_objmgr_vdev_release_ref_debug(vdev, id, func, line);
334 }
335 #else
336 void
__hdd_objmgr_put_vdev_by_user(struct wlan_objmgr_vdev * vdev,wlan_objmgr_ref_dbgid id,const char * func)337 __hdd_objmgr_put_vdev_by_user(struct wlan_objmgr_vdev *vdev,
338 			      wlan_objmgr_ref_dbgid id, const char *func)
339 {
340 	if (!vdev) {
341 		hdd_err("VDEV is NULL (via %s, id %d)", func, id);
342 		return;
343 	}
344 
345 	wlan_objmgr_vdev_release_ref(vdev, id);
346 }
347 #endif
348