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