1 /*
2 * Copyright (c) 2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /**
19 * DOC: wlan_cm_host_util.c
20 *
21 * Implements Host roam (LFR2) reassoc specific legacy code for
22 * connection manager
23 */
24
25 #include "wlan_cm_vdev_api.h"
26 #include "wlan_scan_api.h"
27 #include "wlan_scan_utils_api.h"
28 #include "wlan_policy_mgr_api.h"
29 #include "wlan_roam_debug.h"
30 #include "wni_api.h"
31 #include "wlan_logging_sock_svc.h"
32 #include "connection_mgr/core/src/wlan_cm_roam.h"
33
34 /*
35 * cm_copy_ssids_from_rso_config_params() - copy SSID from rso_config_params
36 * to scan filter
37 * @rso_usr_cfg: rso user config
38 * @filter: scan filter
39 *
40 * Return void
41 */
42 static void
cm_copy_ssids_from_rso_config_params(struct rso_user_config * rso_usr_cfg,struct scan_filter * filter)43 cm_copy_ssids_from_rso_config_params(struct rso_user_config *rso_usr_cfg,
44 struct scan_filter *filter)
45 {
46 uint8_t i;
47 uint8_t max_ssid;
48
49 if (!rso_usr_cfg->num_ssid_allowed_list)
50 return;
51 max_ssid = QDF_MIN(WLAN_SCAN_FILTER_NUM_SSID, MAX_SSID_ALLOWED_LIST);
52
53 filter->num_of_ssid = rso_usr_cfg->num_ssid_allowed_list;
54 if (filter->num_of_ssid > max_ssid)
55 filter->num_of_ssid = max_ssid;
56 for (i = 0; i < filter->num_of_ssid; i++)
57 qdf_mem_copy(&filter->ssid_list[i],
58 &rso_usr_cfg->ssid_allowed_list[i],
59 sizeof(struct wlan_ssid));
60 }
61
cm_update_advance_roam_scan_filter(struct wlan_objmgr_vdev * vdev,struct scan_filter * filter)62 QDF_STATUS cm_update_advance_roam_scan_filter(
63 struct wlan_objmgr_vdev *vdev, struct scan_filter *filter)
64 {
65 uint8_t num_ch = 0;
66 struct wlan_objmgr_psoc *psoc;
67 struct rso_config *rso_cfg;
68 struct rso_chan_info *chan_lst;
69 struct wlan_mlme_psoc_ext_obj *mlme_obj;
70 struct rso_user_config *rso_usr_cfg;
71
72 psoc = wlan_vdev_get_psoc(vdev);
73 if (!psoc) {
74 mlme_debug("psoc is NULL");
75 return QDF_STATUS_E_INVAL;
76 }
77
78 mlme_obj = mlme_get_psoc_ext_obj(psoc);
79 if (!mlme_obj)
80 return QDF_STATUS_E_FAILURE;
81
82 rso_usr_cfg = wlan_cm_get_rso_user_config(vdev);
83 if (!rso_usr_cfg)
84 return QDF_STATUS_E_INVAL;
85
86 mlme_debug("No of Allowed SSID List:%d",
87 rso_usr_cfg->num_ssid_allowed_list);
88
89 if (rso_usr_cfg->num_ssid_allowed_list) {
90 cm_copy_ssids_from_rso_config_params(rso_usr_cfg, filter);
91 } else {
92 filter->num_of_ssid = 1;
93 wlan_vdev_mlme_get_ssid(vdev, filter->ssid_list[0].ssid,
94 &filter->ssid_list[0].length);
95
96 mlme_debug("Filtering for SSID " QDF_SSID_FMT ",length of SSID = %u",
97 QDF_SSID_REF(filter->ssid_list[0].length,
98 filter->ssid_list[0].ssid),
99 filter->ssid_list[0].length);
100 }
101
102 rso_cfg = wlan_cm_get_rso_config(vdev);
103 if (!rso_cfg)
104 return QDF_STATUS_E_FAILURE;
105
106 chan_lst = &rso_cfg->roam_scan_freq_lst;
107 num_ch = chan_lst->num_chan;
108 if (num_ch) {
109 filter->num_of_channels = num_ch;
110 if (filter->num_of_channels > NUM_CHANNELS)
111 filter->num_of_channels = NUM_CHANNELS;
112 qdf_mem_copy(filter->chan_freq_list, chan_lst->freq_list,
113 filter->num_of_channels *
114 sizeof(filter->chan_freq_list[0]));
115 }
116
117 if (rso_cfg->is_11r_assoc)
118 /*
119 * MDIE should be added as a part of profile. This should be
120 * added as a part of filter as well
121 */
122 filter->mobility_domain = rso_cfg->mdid.mobility_domain;
123 filter->enable_adaptive_11r =
124 wlan_mlme_adaptive_11r_enabled(psoc);
125
126 if (rso_cfg->orig_sec_info.rsn_caps &
127 WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)
128 filter->pmf_cap = WLAN_PMF_REQUIRED;
129 else if (rso_cfg->orig_sec_info.rsn_caps &
130 WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)
131 filter->pmf_cap = WLAN_PMF_CAPABLE;
132
133 return QDF_STATUS_SUCCESS;
134 }
135
136 QDF_STATUS
cm_handle_reassoc_req(struct wlan_objmgr_vdev * vdev,struct wlan_cm_vdev_reassoc_req * req)137 cm_handle_reassoc_req(struct wlan_objmgr_vdev *vdev,
138 struct wlan_cm_vdev_reassoc_req *req)
139 {
140 struct cm_vdev_join_req *join_req;
141 struct scheduler_msg msg;
142 QDF_STATUS status;
143 struct wlan_objmgr_pdev *pdev;
144 struct wlan_objmgr_psoc *psoc;
145 struct rso_config *rso_cfg;
146
147 if (!vdev || !req)
148 return QDF_STATUS_E_FAILURE;
149
150 pdev = wlan_vdev_get_pdev(vdev);
151 if (!pdev) {
152 mlme_err(CM_PREFIX_FMT "pdev not found",
153 CM_PREFIX_REF(req->vdev_id, req->cm_id));
154 return QDF_STATUS_E_INVAL;
155 }
156 psoc = wlan_pdev_get_psoc(pdev);
157 if (!psoc) {
158 mlme_err(CM_PREFIX_FMT "psoc not found",
159 CM_PREFIX_REF(req->vdev_id, req->cm_id));
160 return QDF_STATUS_E_INVAL;
161 }
162
163 rso_cfg = wlan_cm_get_rso_config(vdev);
164 if (!rso_cfg)
165 return QDF_STATUS_E_NOSUPPORT;
166
167 qdf_mem_zero(&msg, sizeof(msg));
168 join_req = qdf_mem_malloc(sizeof(*join_req));
169 if (!join_req)
170 return QDF_STATUS_E_NOMEM;
171
172 wlan_cm_set_disable_hi_rssi(pdev, req->vdev_id, true);
173 mlme_debug(CM_PREFIX_FMT "Disabling HI_RSSI, AP freq=%d, rssi=%d",
174 CM_PREFIX_REF(req->vdev_id, req->cm_id),
175 req->bss->entry->channel.chan_freq,
176 req->bss->entry->rssi_raw);
177
178 if (rso_cfg->assoc_ie.ptr) {
179 join_req->assoc_ie.ptr = qdf_mem_malloc(rso_cfg->assoc_ie.len);
180 if (!join_req->assoc_ie.ptr)
181 return QDF_STATUS_E_NOMEM;
182 qdf_mem_copy(join_req->assoc_ie.ptr, rso_cfg->assoc_ie.ptr,
183 rso_cfg->assoc_ie.len);
184 join_req->assoc_ie.len = rso_cfg->assoc_ie.len;
185 }
186
187 join_req->entry = util_scan_copy_cache_entry(req->bss->entry);
188 if (!join_req->entry) {
189 mlme_err(CM_PREFIX_FMT "Failed to copy scan entry",
190 CM_PREFIX_REF(req->vdev_id, req->cm_id));
191 cm_free_join_req(join_req);
192 return QDF_STATUS_E_NOMEM;
193 }
194 join_req->vdev_id = req->vdev_id;
195 join_req->cm_id = req->cm_id;
196
197 status = cm_csr_handle_join_req(vdev, NULL, join_req, true);
198 if (QDF_IS_STATUS_ERROR(status)) {
199 mlme_err(CM_PREFIX_FMT "fail to fill params from legacy",
200 CM_PREFIX_REF(req->vdev_id, req->cm_id));
201 cm_free_join_req(join_req);
202 return QDF_STATUS_E_FAILURE;
203 }
204
205 wlan_rec_conn_info(req->vdev_id, DEBUG_CONN_CONNECTING,
206 req->bss->entry->bssid.bytes,
207 req->bss->entry->neg_sec_info.key_mgmt,
208 req->bss->entry->channel.chan_freq);
209
210 msg.bodyptr = join_req;
211 msg.type = CM_REASSOC_REQ;
212 msg.flush_callback = cm_flush_join_req;
213
214 status = scheduler_post_message(QDF_MODULE_ID_MLME,
215 QDF_MODULE_ID_PE,
216 QDF_MODULE_ID_PE, &msg);
217 if (QDF_IS_STATUS_ERROR(status)) {
218 mlme_err(CM_PREFIX_FMT "msg post fail",
219 CM_PREFIX_REF(req->vdev_id, req->cm_id));
220 cm_free_join_req(join_req);
221 }
222
223 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
224 wlan_register_txrx_packetdump(OL_TXRX_PDEV_ID);
225
226 return status;
227 }
228
cm_handle_roam_start(struct wlan_objmgr_vdev * vdev,struct wlan_cm_roam_req * req)229 QDF_STATUS cm_handle_roam_start(struct wlan_objmgr_vdev *vdev,
230 struct wlan_cm_roam_req *req)
231 {
232 if (!vdev || !req) {
233 mlme_err("vdev or req is NULL");
234 return QDF_STATUS_E_INVAL;
235 }
236
237 if (req->source == CM_ROAMING_HOST)
238 cm_roam_state_change(wlan_vdev_get_pdev(vdev),
239 wlan_vdev_get_id(vdev),
240 WLAN_ROAM_RSO_STOPPED,
241 REASON_OS_REQUESTED_ROAMING_NOW,
242 NULL, false);
243 return QDF_STATUS_SUCCESS;
244 }
245
246