1  /*
2   * Copyright (c) 2012-2015, 2020-2021 The Linux Foundation. All rights reserved.
3   * Copyright (c) 2022-2024 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: osif_cm_util.c
20   *
21   * This file maintains definitaions of connect, disconnect, roam
22   * common apis.
23   */
24  #include <include/wlan_mlme_cmn.h>
25  #include "osif_cm_util.h"
26  #include "wlan_osif_priv.h"
27  #include "wlan_cfg80211.h"
28  #include "osif_cm_rsp.h"
29  #include "wlan_cfg80211_scan.h"
30  #include "wlan_mlo_mgr_sta.h"
31  
32  enum qca_sta_connect_fail_reason_codes
osif_cm_mac_to_qca_connect_fail_reason(enum wlan_status_code internal_reason)33  osif_cm_mac_to_qca_connect_fail_reason(enum wlan_status_code internal_reason)
34  {
35  	enum qca_sta_connect_fail_reason_codes reason = 0;
36  
37  	if (internal_reason < STATUS_PROP_START)
38  		return reason;
39  
40  	switch (internal_reason) {
41  	case STATUS_NO_NETWORK_FOUND:
42  		reason = QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND;
43  		break;
44  	case STATUS_AUTH_TX_FAIL:
45  		reason = QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL;
46  		break;
47  	case STATUS_AUTH_NO_ACK_RECEIVED:
48  		reason = QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED;
49  		break;
50  	case STATUS_AUTH_NO_RESP_RECEIVED:
51  		reason = QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED;
52  		break;
53  	case STATUS_ASSOC_TX_FAIL:
54  		reason = QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL;
55  		break;
56  	case STATUS_ASSOC_NO_ACK_RECEIVED:
57  		reason = QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED;
58  		break;
59  	case STATUS_ASSOC_NO_RESP_RECEIVED:
60  		reason = QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED;
61  		break;
62  	default:
63  		osif_debug("QCA code not present for internal status code %d",
64  			   internal_reason);
65  	}
66  
67  	return reason;
68  }
69  
70  const char *
osif_cm_qca_reason_to_str(enum qca_disconnect_reason_codes reason)71  osif_cm_qca_reason_to_str(enum qca_disconnect_reason_codes reason)
72  {
73  	switch (reason) {
74  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_INTERNAL_ROAM_FAILURE);
75  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_EXTERNAL_ROAM_FAILURE);
76  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_GATEWAY_REACHABILITY_FAILURE);
77  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_UNSUPPORTED_CHANNEL_CSA);
78  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_OPER_CHANNEL_DISABLED_INDOOR);
79  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_OPER_CHANNEL_USER_DISABLED);
80  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_DEVICE_RECOVERY);
81  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_KEY_TIMEOUT);
82  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_OPER_CHANNEL_BAND_CHANGE);
83  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_IFACE_DOWN);
84  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_PEER_XRETRY_FAIL);
85  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_PEER_INACTIVITY);
86  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_SA_QUERY_TIMEOUT);
87  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_BEACON_MISS_FAILURE);
88  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_CHANNEL_SWITCH_FAILURE);
89  	CASE_RETURN_STRING(QCA_DISCONNECT_REASON_USER_TRIGGERED);
90  	case QCA_DISCONNECT_REASON_UNSPECIFIED:
91  		return "";
92  	default:
93  		return "Unknown";
94  	}
95  }
96  
97  enum qca_disconnect_reason_codes
osif_cm_mac_to_qca_reason(enum wlan_reason_code internal_reason)98  osif_cm_mac_to_qca_reason(enum wlan_reason_code internal_reason)
99  {
100  	enum qca_disconnect_reason_codes reason =
101  					QCA_DISCONNECT_REASON_UNSPECIFIED;
102  
103  	if (internal_reason < REASON_PROP_START)
104  		return reason;
105  
106  	switch (internal_reason) {
107  	case REASON_HOST_TRIGGERED_ROAM_FAILURE:
108  	case REASON_FW_TRIGGERED_ROAM_FAILURE:
109  		reason = QCA_DISCONNECT_REASON_INTERNAL_ROAM_FAILURE;
110  		break;
111  	case REASON_USER_TRIGGERED_ROAM_FAILURE:
112  		reason = QCA_DISCONNECT_REASON_EXTERNAL_ROAM_FAILURE;
113  		break;
114  	case REASON_GATEWAY_REACHABILITY_FAILURE:
115  		reason =
116  		QCA_DISCONNECT_REASON_GATEWAY_REACHABILITY_FAILURE;
117  		break;
118  	case REASON_UNSUPPORTED_CHANNEL_CSA:
119  		reason = QCA_DISCONNECT_REASON_UNSUPPORTED_CHANNEL_CSA;
120  		break;
121  	case REASON_OPER_CHANNEL_DISABLED_INDOOR:
122  		reason =
123  		QCA_DISCONNECT_REASON_OPER_CHANNEL_DISABLED_INDOOR;
124  		break;
125  	case REASON_OPER_CHANNEL_USER_DISABLED:
126  		reason =
127  		QCA_DISCONNECT_REASON_OPER_CHANNEL_USER_DISABLED;
128  		break;
129  	case REASON_DEVICE_RECOVERY:
130  		reason = QCA_DISCONNECT_REASON_DEVICE_RECOVERY;
131  		break;
132  	case REASON_KEY_TIMEOUT:
133  		reason = QCA_DISCONNECT_REASON_KEY_TIMEOUT;
134  		break;
135  	case REASON_OPER_CHANNEL_BAND_CHANGE:
136  		reason = QCA_DISCONNECT_REASON_OPER_CHANNEL_BAND_CHANGE;
137  		break;
138  	case REASON_IFACE_DOWN:
139  		reason = QCA_DISCONNECT_REASON_IFACE_DOWN;
140  		break;
141  	case REASON_PEER_XRETRY_FAIL:
142  		reason = QCA_DISCONNECT_REASON_PEER_XRETRY_FAIL;
143  		break;
144  	case REASON_PEER_INACTIVITY:
145  		reason = QCA_DISCONNECT_REASON_PEER_INACTIVITY;
146  		break;
147  	case REASON_SA_QUERY_TIMEOUT:
148  		reason = QCA_DISCONNECT_REASON_SA_QUERY_TIMEOUT;
149  		break;
150  	case REASON_CHANNEL_SWITCH_FAILED:
151  		reason = QCA_DISCONNECT_REASON_CHANNEL_SWITCH_FAILURE;
152  		break;
153  	case REASON_BEACON_MISSED:
154  		reason = QCA_DISCONNECT_REASON_BEACON_MISS_FAILURE;
155  		break;
156  	default:
157  		osif_debug("No QCA reason code for mac reason: %u",
158  			   internal_reason);
159  		/* Unspecified reason by default */
160  	}
161  
162  	return reason;
163  }
164  
165  static struct osif_cm_ops *osif_cm_legacy_ops;
166  
osif_cm_reset_id_and_src_no_lock(struct vdev_osif_priv * osif_priv)167  void osif_cm_reset_id_and_src_no_lock(struct vdev_osif_priv *osif_priv)
168  {
169  	osif_priv->cm_info.last_id = CM_ID_INVALID;
170  	osif_priv->cm_info.last_source = CM_SOURCE_INVALID;
171  }
172  
osif_cm_reset_id_and_src(struct wlan_objmgr_vdev * vdev)173  QDF_STATUS osif_cm_reset_id_and_src(struct wlan_objmgr_vdev *vdev)
174  {
175  	struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev);
176  
177  	if (!osif_priv) {
178  		osif_err("Invalid vdev osif priv");
179  		return QDF_STATUS_E_INVAL;
180  	}
181  	qdf_spinlock_acquire(&osif_priv->cm_info.cmd_id_lock);
182  	osif_cm_reset_id_and_src_no_lock(osif_priv);
183  	qdf_spinlock_release(&osif_priv->cm_info.cmd_id_lock);
184  
185  	return QDF_STATUS_SUCCESS;
186  }
187  
188  /**
189   * osif_cm_connect_complete_cb() - Connect complete callback
190   * @vdev: vdev pointer
191   * @rsp: connect response
192   *
193   * Return: QDF_STATUS
194   */
195  static QDF_STATUS
osif_cm_connect_complete_cb(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp)196  osif_cm_connect_complete_cb(struct wlan_objmgr_vdev *vdev,
197  			    struct wlan_cm_connect_resp *rsp)
198  {
199  	return osif_connect_handler(vdev, rsp);
200  }
201  
202  /**
203   * osif_cm_failed_candidate_cb() - Callback to indicate failed candidate
204   * @vdev: vdev pointer
205   * @rsp: connect response
206   *
207   * Return: QDF_STATUS
208   */
209  static QDF_STATUS
osif_cm_failed_candidate_cb(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp)210  osif_cm_failed_candidate_cb(struct wlan_objmgr_vdev *vdev,
211  			    struct wlan_cm_connect_resp *rsp)
212  {
213  	return osif_failed_candidate_handler(vdev, rsp);
214  }
215  
216  /**
217   * osif_cm_update_id_and_src_cb() - Callback to update id and
218   * source of the connect/disconnect request
219   * @vdev: vdev pointer
220   * @source: Source of the connect req
221   * @cm_id: Connect/disconnect id
222   *
223   * Context: Any context. Takes and releases cmd id spinlock
224   * Return: QDF_STATUS
225   */
226  static QDF_STATUS
osif_cm_update_id_and_src_cb(struct wlan_objmgr_vdev * vdev,enum wlan_cm_source source,wlan_cm_id cm_id)227  osif_cm_update_id_and_src_cb(struct wlan_objmgr_vdev *vdev,
228  			     enum wlan_cm_source source, wlan_cm_id cm_id)
229  {
230  	struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev);
231  
232  	if (!osif_priv) {
233  		osif_err("Invalid vdev osif priv");
234  		return QDF_STATUS_E_INVAL;
235  	}
236  
237  	qdf_spinlock_acquire(&osif_priv->cm_info.cmd_id_lock);
238  	osif_priv->cm_info.last_id = cm_id;
239  	osif_priv->cm_info.last_source = source;
240  	qdf_spinlock_release(&osif_priv->cm_info.cmd_id_lock);
241  
242  	return QDF_STATUS_SUCCESS;
243  }
244  
245  /**
246   * osif_cm_disconnect_complete_cb() - Disconnect done callback
247   * @vdev: vdev pointer
248   * @rsp: Disconnect response
249   *
250   * Context: Any context
251   * Return: QDF_STATUS
252   */
253  
254  static QDF_STATUS
osif_cm_disconnect_complete_cb(struct wlan_objmgr_vdev * vdev,struct wlan_cm_discon_rsp * rsp)255  osif_cm_disconnect_complete_cb(struct wlan_objmgr_vdev *vdev,
256  			       struct wlan_cm_discon_rsp *rsp)
257  {
258  	return osif_disconnect_handler(vdev, rsp);
259  }
260  
261  #ifdef CONN_MGR_ADV_FEATURE
osif_cm_unlink_bss(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * bssid)262  void osif_cm_unlink_bss(struct wlan_objmgr_vdev *vdev,
263  			struct qdf_mac_addr *bssid)
264  {
265  	struct scan_filter *filter;
266  
267  	filter = qdf_mem_malloc(sizeof(*filter));
268  	if (!filter)
269  		return;
270  
271  	filter->num_of_bssid = 1;
272  	qdf_copy_macaddr(&filter->bssid_list[0], bssid);
273  	ucfg_scan_flush_results(wlan_vdev_get_pdev(vdev), filter);
274  	qdf_mem_free(filter);
275  }
276  
277  static QDF_STATUS
osif_cm_disable_netif_queue(struct wlan_objmgr_vdev * vdev)278  osif_cm_disable_netif_queue(struct wlan_objmgr_vdev *vdev)
279  {
280  	return osif_cm_netif_queue_ind(vdev,
281  				       WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
282  				       WLAN_CONTROL_PATH);
283  }
284  
285  /**
286   * osif_cm_roam_sync_cb() - Roam sync callback
287   * @vdev: vdev pointer
288   *
289   * This callback indicates os_if that roam sync ind received
290   * so that os_if can stop all the activity on this connection
291   *
292   * Return: QDF_STATUS
293   */
294  static QDF_STATUS
osif_cm_roam_sync_cb(struct wlan_objmgr_vdev * vdev)295  osif_cm_roam_sync_cb(struct wlan_objmgr_vdev *vdev)
296  {
297  	osif_cm_napi_serialize(true);
298  	return osif_cm_netif_queue_ind(vdev,
299  				       WLAN_STOP_ALL_NETIF_QUEUE,
300  				       WLAN_CONTROL_PATH);
301  }
302  
303  /**
304   * osif_pmksa_candidate_notify_cb() - Roam pmksa candidate notify callback
305   * @vdev: vdev pointer
306   * @bssid: bssid
307   * @index: index
308   * @preauth: preauth flag
309   *
310   * Return: QDF_STATUS
311   */
312  static QDF_STATUS
osif_pmksa_candidate_notify_cb(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * bssid,int index,bool preauth)313  osif_pmksa_candidate_notify_cb(struct wlan_objmgr_vdev *vdev,
314  			       struct qdf_mac_addr *bssid,
315  			       int index, bool preauth)
316  {
317  	return osif_pmksa_candidate_notify(vdev, bssid, index, preauth);
318  }
319  
320  /**
321   * osif_cm_send_keys_cb() - Send keys callback
322   * @vdev: vdev pointer
323   * @key_index: key index
324   * @pairwise: true if pairwise
325   * @cipher_type: cipher type
326   *
327   * This callback indicates os_if that
328   * so that os_if can stop all the activity on this connection
329   *
330   * Return: QDF_STATUS
331   */
332  static QDF_STATUS
osif_cm_send_keys_cb(struct wlan_objmgr_vdev * vdev,uint8_t key_index,bool pairwise,enum wlan_crypto_cipher_type cipher_type)333  osif_cm_send_keys_cb(struct wlan_objmgr_vdev *vdev, uint8_t key_index,
334  		     bool pairwise, enum wlan_crypto_cipher_type cipher_type)
335  {
336  	return osif_cm_send_vdev_keys(vdev,
337  				       key_index,
338  				       pairwise,
339  				       cipher_type);
340  }
341  #else
342  static inline QDF_STATUS
osif_cm_disable_netif_queue(struct wlan_objmgr_vdev * vdev)343  osif_cm_disable_netif_queue(struct wlan_objmgr_vdev *vdev)
344  {
345  	return QDF_STATUS_SUCCESS;
346  }
347  #endif
348  
349  #if defined(CONN_MGR_ADV_FEATURE) && defined(WLAN_FEATURE_11BE_MLO)
350  /**
351   * osif_link_reconfig_notify_cb() - Link reconfig notify callback
352   * @vdev: vdev pointer
353   *
354   * Return: QDF_STATUS
355   */
356  static QDF_STATUS
osif_link_reconfig_notify_cb(struct wlan_objmgr_vdev * vdev)357  osif_link_reconfig_notify_cb(struct wlan_objmgr_vdev *vdev)
358  {
359  	struct vdev_osif_priv *osif_priv;
360  	struct wlan_objmgr_vdev *assoc_vdev;
361  	struct wireless_dev *wdev;
362  	uint8_t link_id;
363  	uint16_t link_mask;
364  	struct pdev_osif_priv *pdev_osif_priv;
365  	struct wlan_objmgr_pdev *pdev;
366  	uint32_t data_len;
367  	struct sk_buff *vendor_event;
368  	struct qdf_mac_addr ap_mld_mac;
369  	QDF_STATUS status;
370  
371  	assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev);
372  	if (!assoc_vdev) {
373  		osif_err("Failed to get assoc vdev");
374  		return QDF_STATUS_E_INVAL;
375  	}
376  
377  	osif_priv = wlan_vdev_get_ospriv(assoc_vdev);
378  	if (!osif_priv) {
379  		osif_err("Invalid vdev osif priv");
380  		return QDF_STATUS_E_INVAL;
381  	}
382  
383  	wdev = osif_priv->wdev;
384  	if (!wdev) {
385  		osif_err("wdev is null");
386  		return QDF_STATUS_E_INVAL;
387  	}
388  	pdev = wlan_vdev_get_pdev(assoc_vdev);
389  	if (!pdev) {
390  		osif_debug("null pdev");
391  		return QDF_STATUS_E_INVAL;
392  	}
393  	pdev_osif_priv = wlan_pdev_get_ospriv(pdev);
394  	if (!pdev_osif_priv || !pdev_osif_priv->wiphy) {
395  		osif_debug("null wiphy");
396  		return QDF_STATUS_E_INVAL;
397  	}
398  
399  	link_id = wlan_vdev_get_link_id(vdev);
400  	link_mask = 1 << link_id;
401  	osif_debug("link reconfig on vdev %d with link id %d mask 0x%x",
402  		   wlan_vdev_get_id(vdev), link_id, link_mask);
403  
404  	status = wlan_vdev_get_bss_peer_mld_mac(vdev, &ap_mld_mac);
405  	if (QDF_IS_STATUS_ERROR(status)) {
406  		osif_debug("get peer mld failed, vdev %d",
407  			   wlan_vdev_get_id(vdev));
408  		return status;
409  	}
410  	osif_debug("ap mld addr: "QDF_MAC_ADDR_FMT,
411  		   QDF_MAC_ADDR_REF(ap_mld_mac.bytes));
412  
413  	data_len = nla_total_size(QDF_MAC_ADDR_SIZE) +
414  		   nla_total_size(sizeof(uint16_t)) +
415  		   NLMSG_HDRLEN;
416  
417  	vendor_event =
418  	wlan_cfg80211_vendor_event_alloc(pdev_osif_priv->wiphy,
419  					 wdev, data_len,
420  					 QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG_INDEX,
421  					 GFP_KERNEL);
422  	if (!vendor_event) {
423  		osif_debug("wlan_cfg80211_vendor_event_alloc failed");
424  		return QDF_STATUS_E_NOMEM;
425  	}
426  
427  	if (nla_put(vendor_event,
428  		    QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_AP_MLD_ADDR,
429  		    QDF_MAC_ADDR_SIZE, &ap_mld_mac.bytes[0]) ||
430  	    nla_put_u16(vendor_event,
431  			QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_REMOVED_LINKS,
432  			link_mask)) {
433  		osif_debug("QCA_WLAN_VENDOR_ATTR put fail");
434  		wlan_cfg80211_vendor_free_skb(vendor_event);
435  		return QDF_STATUS_E_INVAL;
436  	}
437  
438  	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
439  
440  	return QDF_STATUS_SUCCESS;
441  }
442  #else
443  static inline QDF_STATUS
osif_link_reconfig_notify_cb(struct wlan_objmgr_vdev * vdev)444  osif_link_reconfig_notify_cb(struct wlan_objmgr_vdev *vdev)
445  {
446  	return QDF_STATUS_SUCCESS;
447  }
448  #endif
449  
450  /**
451   * osif_cm_disconnect_start_cb() - Disconnect start callback
452   * @vdev: vdev pointer
453   * @source: Disconnect source
454   *
455   * This callback indicates os_if that disconnection is started
456   * so that os_if can stop all the activity on this connection
457   *
458   * Return: QDF_STATUS
459   */
osif_cm_disconnect_start_cb(struct wlan_objmgr_vdev * vdev,enum wlan_cm_source source)460  static QDF_STATUS osif_cm_disconnect_start_cb(struct wlan_objmgr_vdev *vdev,
461  					      enum wlan_cm_source source)
462  {
463  	/* Don't stop netif queues for link switch disconnect */
464  	if (source == CM_MLO_LINK_SWITCH_DISCONNECT ||
465  	    source == CM_MLO_ROAM_INTERNAL_DISCONNECT)
466  		return QDF_STATUS_SUCCESS;
467  
468  	/* Disable netif queue on disconnect start */
469  	return osif_cm_disable_netif_queue(vdev);
470  }
471  
472  #ifdef WLAN_FEATURE_ROAM_OFFLOAD
473  /**
474   * osif_cm_roam_start_cb() - Roam start callback
475   * @vdev: vdev pointer
476   *
477   * This callback indicates os_if that roaming has started
478   * so that os_if can stop all the activity on this connection
479   *
480   * Return: QDF_STATUS
481   */
482  static QDF_STATUS
osif_cm_roam_start_cb(struct wlan_objmgr_vdev * vdev)483  osif_cm_roam_start_cb(struct wlan_objmgr_vdev *vdev)
484  {
485  	osif_cm_perfd_set_cpufreq(true);
486  	return osif_cm_netif_queue_ind(vdev,
487  				       WLAN_STOP_ALL_NETIF_QUEUE,
488  				       WLAN_CONTROL_PATH);
489  }
490  
491  /**
492   * osif_cm_roam_abort_cb() - Roam abort callback
493   * @vdev: vdev pointer
494   *
495   * This callback indicates os_if that roaming has been aborted
496   * so that os_if can resume all the activity on this connection
497   *
498   * Return: QDF_STATUS
499   */
500  static QDF_STATUS
osif_cm_roam_abort_cb(struct wlan_objmgr_vdev * vdev)501  osif_cm_roam_abort_cb(struct wlan_objmgr_vdev *vdev)
502  {
503  	osif_cm_perfd_set_cpufreq(false);
504  	osif_cm_napi_serialize(false);
505  	return osif_cm_netif_queue_ind(vdev,
506  				       WLAN_WAKE_ALL_NETIF_QUEUE,
507  				       WLAN_CONTROL_PATH);
508  }
509  
510  /**
511   * osif_cm_roam_cmpl_cb() - Roam sync complete callback
512   * @vdev: vdev pointer
513   *
514   * This callback indicates os_if that roam sync is complete
515   * so that os_if can stop all the activity on this connection
516   *
517   * Return: QDF_STATUS
518   */
519  
520  static QDF_STATUS
osif_cm_roam_cmpl_cb(struct wlan_objmgr_vdev * vdev)521  osif_cm_roam_cmpl_cb(struct wlan_objmgr_vdev *vdev)
522  {
523  	osif_cm_perfd_set_cpufreq(false);
524  	return osif_cm_napi_serialize(false);
525  }
526  
527  /**
528   * osif_cm_get_scan_ie_params() - Function to get scan ie params
529   * @vdev: vdev pointer
530   * @scan_ie: Pointer to scan_ie
531   * @dot11mode_filter: Pointer to dot11mode_filter
532   *
533   * Get scan IE params from adapter corresponds to given vdev
534   *
535   * Return: QDF_STATUS
536   */
537  static QDF_STATUS
osif_cm_get_scan_ie_params(struct wlan_objmgr_vdev * vdev,struct element_info * scan_ie,enum dot11_mode_filter * dot11mode_filter)538  osif_cm_get_scan_ie_params(struct wlan_objmgr_vdev *vdev,
539  			   struct element_info *scan_ie,
540  			   enum dot11_mode_filter *dot11mode_filter)
541  {
542  	osif_cm_get_scan_ie_params_cb cb = NULL;
543  
544  	if (osif_cm_legacy_ops)
545  		cb = osif_cm_legacy_ops->get_scan_ie_params_cb;
546  	if (cb)
547  		return cb(vdev, scan_ie, dot11mode_filter);
548  
549  	return QDF_STATUS_E_FAILURE;
550  }
551  
552  /**
553   * osif_cm_get_scan_ie_info_cb() - Roam get scan ie params callback
554   * @vdev: vdev pointer
555   * @scan_ie: pointer to scan ie
556   * @dot11mode_filter: pointer to dot11 mode filter
557   *
558   * This callback gets scan ie params from os_if
559   *
560   * Return: QDF_STATUS
561   */
562  
563  static QDF_STATUS
osif_cm_get_scan_ie_info_cb(struct wlan_objmgr_vdev * vdev,struct element_info * scan_ie,enum dot11_mode_filter * dot11mode_filter)564  osif_cm_get_scan_ie_info_cb(struct wlan_objmgr_vdev *vdev,
565  			    struct element_info *scan_ie,
566  			    enum dot11_mode_filter *dot11mode_filter)
567  {
568  	return osif_cm_get_scan_ie_params(vdev, scan_ie, dot11mode_filter);
569  }
570  
571  /**
572   * osif_cm_roam_rt_stats_evt_cb() - Roam stats callback
573   * @roam_stats: roam_stats_event pointer
574   * @idx: TLV idx for roam_stats_event
575   *
576   * This callback indicates os_if that roam stats event is received
577   * so that os_if can send the event
578   *
579   * Return: void
580   */
581  
582  static void
osif_cm_roam_rt_stats_evt_cb(struct roam_stats_event * roam_stats,uint8_t idx)583  osif_cm_roam_rt_stats_evt_cb(struct roam_stats_event *roam_stats,
584  		      uint8_t idx)
585  {
586  	if (osif_cm_legacy_ops &&
587  	    osif_cm_legacy_ops->roam_rt_stats_event_cb)
588  		osif_cm_legacy_ops->roam_rt_stats_event_cb(roam_stats, idx);
589  }
590  
591  #endif
592  
593  #ifdef WLAN_FEATURE_PREAUTH_ENABLE
594  /**
595   * osif_cm_ft_preauth_cmpl_cb() - Roam ft preauth complete callback
596   * @vdev: vdev pointer
597   * @rsp: preauth response
598   *
599   * This callback indicates os_if that roam ft preauth is complete
600   * so that os_if can send fast transition event
601   *
602   * Return: QDF_STATUS
603   */
604  
605  static QDF_STATUS
osif_cm_ft_preauth_cmpl_cb(struct wlan_objmgr_vdev * vdev,struct wlan_preauth_rsp * rsp)606  osif_cm_ft_preauth_cmpl_cb(struct wlan_objmgr_vdev *vdev,
607  			   struct wlan_preauth_rsp *rsp)
608  {
609  	osif_cm_ft_preauth_complete_cb cb = NULL;
610  	QDF_STATUS ret = QDF_STATUS_SUCCESS;
611  
612  	if (osif_cm_legacy_ops)
613  		cb = osif_cm_legacy_ops->ft_preauth_complete_cb;
614  	if (cb)
615  		ret = cb(vdev, rsp);
616  
617  	return ret;
618  }
619  
620  #ifdef FEATURE_WLAN_ESE
621  /**
622   * osif_cm_cckm_preauth_cmpl_cb() - Roam cckm preauth complete callback
623   * @vdev: vdev pointer
624   * @rsp: preauth response
625   *
626   * This callback indicates os_if that roam cckm preauth is complete
627   * so that os_if can send cckm preauth indication to the supplicant
628   * via wireless custom event.
629   *
630   * Return: QDF_STATUS
631   */
632  
633  static QDF_STATUS
osif_cm_cckm_preauth_cmpl_cb(struct wlan_objmgr_vdev * vdev,struct wlan_preauth_rsp * rsp)634  osif_cm_cckm_preauth_cmpl_cb(struct wlan_objmgr_vdev *vdev,
635  			     struct wlan_preauth_rsp *rsp)
636  {
637  	osif_cm_cckm_preauth_complete_cb cb = NULL;
638  	QDF_STATUS ret = QDF_STATUS_SUCCESS;
639  
640  	if (osif_cm_legacy_ops)
641  		cb = osif_cm_legacy_ops->cckm_preauth_complete_cb;
642  	if (cb)
643  		ret = cb(vdev, rsp);
644  
645  	return ret;
646  }
647  #endif
648  #endif
649  
650  #ifdef WLAN_BOOST_CPU_FREQ_IN_ROAM
651  /**
652   * osif_cm_perfd_reset_cpufreq_ctrl_cb() - Callback to reset CPU freq
653   *
654   * This callback indicates os_if to reset the request to boost CPU freq
655   *
656   * Return: None
657   */
osif_cm_perfd_reset_cpufreq_ctrl_cb(void)658  static void osif_cm_perfd_reset_cpufreq_ctrl_cb(void)
659  {
660  	osif_cm_perfd_set_cpufreq(false);
661  }
662  #endif
663  
664  static struct mlme_cm_ops cm_ops = {
665  #ifdef CONN_MGR_ADV_FEATURE
666  	.mlme_cm_connect_active_notify_cb = osif_cm_connect_active_notify,
667  #endif
668  	.mlme_cm_connect_complete_cb = osif_cm_connect_complete_cb,
669  	.mlme_cm_failed_candidate_cb = osif_cm_failed_candidate_cb,
670  	.mlme_cm_update_id_and_src_cb = osif_cm_update_id_and_src_cb,
671  	.mlme_cm_disconnect_complete_cb = osif_cm_disconnect_complete_cb,
672  	.mlme_cm_disconnect_start_cb = osif_cm_disconnect_start_cb,
673  #ifdef CONN_MGR_ADV_FEATURE
674  	.mlme_cm_roam_sync_cb = osif_cm_roam_sync_cb,
675  	.mlme_cm_pmksa_candidate_notify_cb = osif_pmksa_candidate_notify_cb,
676  	.mlme_cm_send_keys_cb = osif_cm_send_keys_cb,
677  	.mlme_cm_link_reconfig_notify_cb = osif_link_reconfig_notify_cb,
678  #endif
679  #ifdef WLAN_FEATURE_ROAM_OFFLOAD
680  	.mlme_cm_roam_start_cb = osif_cm_roam_start_cb,
681  	.mlme_cm_roam_abort_cb = osif_cm_roam_abort_cb,
682  	.mlme_cm_roam_cmpl_cb = osif_cm_roam_cmpl_cb,
683  	.mlme_cm_roam_get_scan_ie_cb = osif_cm_get_scan_ie_info_cb,
684  	.mlme_cm_roam_rt_stats_cb = osif_cm_roam_rt_stats_evt_cb,
685  #endif
686  #ifdef WLAN_FEATURE_PREAUTH_ENABLE
687  	.mlme_cm_ft_preauth_cmpl_cb = osif_cm_ft_preauth_cmpl_cb,
688  #ifdef FEATURE_WLAN_ESE
689  	.mlme_cm_cckm_preauth_cmpl_cb = osif_cm_cckm_preauth_cmpl_cb,
690  #endif
691  #endif
692  #ifdef WLAN_VENDOR_HANDOFF_CONTROL
693  	.mlme_cm_get_vendor_handoff_params_cb =
694  					osif_cm_vendor_handoff_params_cb,
695  #endif
696  #ifdef WLAN_BOOST_CPU_FREQ_IN_ROAM
697  	.mlme_cm_perfd_reset_cpufreq_ctrl_cb =
698  				osif_cm_perfd_reset_cpufreq_ctrl_cb,
699  #endif
700  };
701  
702  /**
703   * osif_cm_get_global_ops() - Get connection manager global ops
704   *
705   * Return: Connection manager global ops
706   */
osif_cm_get_global_ops(void)707  static struct mlme_cm_ops *osif_cm_get_global_ops(void)
708  {
709  	return &cm_ops;
710  }
711  
osif_cm_register_cb(void)712  QDF_STATUS osif_cm_register_cb(void)
713  {
714  	mlme_set_osif_cm_cb(osif_cm_get_global_ops);
715  
716  	return QDF_STATUS_SUCCESS;
717  }
718  
osif_cm_osif_priv_init(struct wlan_objmgr_vdev * vdev)719  QDF_STATUS osif_cm_osif_priv_init(struct wlan_objmgr_vdev *vdev)
720  {
721  	struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev);
722  	enum QDF_OPMODE mode = wlan_vdev_mlme_get_opmode(vdev);
723  
724  	if (mode != QDF_STA_MODE && mode != QDF_P2P_CLIENT_MODE)
725  		return QDF_STATUS_SUCCESS;
726  
727  	if (!osif_priv) {
728  		osif_err("Invalid vdev osif priv");
729  		return QDF_STATUS_E_INVAL;
730  	}
731  
732  	qdf_spinlock_create(&osif_priv->cm_info.cmd_id_lock);
733  
734  	return QDF_STATUS_SUCCESS;
735  }
736  
osif_cm_osif_priv_deinit(struct wlan_objmgr_vdev * vdev)737  QDF_STATUS osif_cm_osif_priv_deinit(struct wlan_objmgr_vdev *vdev)
738  {
739  	struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev);
740  	enum QDF_OPMODE mode = wlan_vdev_mlme_get_opmode(vdev);
741  
742  	if (mode != QDF_STA_MODE && mode != QDF_P2P_CLIENT_MODE)
743  		return QDF_STATUS_SUCCESS;
744  
745  	if (!osif_priv) {
746  		osif_err("Invalid vdev osif priv");
747  		return QDF_STATUS_E_INVAL;
748  	}
749  	qdf_spinlock_destroy(&osif_priv->cm_info.cmd_id_lock);
750  
751  	return QDF_STATUS_SUCCESS;
752  }
753  
754  #ifdef CONN_MGR_ADV_FEATURE
osif_cm_connect_active_notify(uint8_t vdev_id)755  void osif_cm_connect_active_notify(uint8_t vdev_id)
756  {
757  	if (osif_cm_legacy_ops && osif_cm_legacy_ops->connect_active_notify_cb)
758  		osif_cm_legacy_ops->connect_active_notify_cb(vdev_id);
759  }
760  #endif
761  
osif_cm_connect_comp_ind(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp,enum osif_cb_type type)762  QDF_STATUS osif_cm_connect_comp_ind(struct wlan_objmgr_vdev *vdev,
763  				    struct wlan_cm_connect_resp *rsp,
764  				    enum osif_cb_type type)
765  {
766  	osif_cm_connect_comp_cb cb = NULL;
767  	QDF_STATUS ret = QDF_STATUS_SUCCESS;
768  
769  	if (osif_cm_legacy_ops)
770  		cb = osif_cm_legacy_ops->connect_complete_cb;
771  	if (cb)
772  		ret = cb(vdev, rsp, type);
773  
774  	return ret;
775  }
776  
777  #ifdef WLAN_VENDOR_HANDOFF_CONTROL
osif_cm_vendor_handoff_params_cb(struct wlan_objmgr_psoc * psoc,void * vendor_handoff_context)778  QDF_STATUS osif_cm_vendor_handoff_params_cb(struct wlan_objmgr_psoc *psoc,
779  					    void *vendor_handoff_context)
780  {
781  	osif_cm_get_vendor_handoff_params_cb cb = NULL;
782  
783  	if (osif_cm_legacy_ops)
784  		cb = osif_cm_legacy_ops->vendor_handoff_params_cb;
785  	if (cb)
786  		return cb(psoc, vendor_handoff_context);
787  
788  	return QDF_STATUS_E_FAILURE;
789  }
790  #endif
791  
osif_cm_disconnect_comp_ind(struct wlan_objmgr_vdev * vdev,struct wlan_cm_discon_rsp * rsp,enum osif_cb_type type)792  QDF_STATUS osif_cm_disconnect_comp_ind(struct wlan_objmgr_vdev *vdev,
793  				       struct wlan_cm_discon_rsp *rsp,
794  				       enum osif_cb_type type)
795  {
796  	osif_cm_disconnect_comp_cb cb = NULL;
797  	QDF_STATUS ret = QDF_STATUS_SUCCESS;
798  
799  	if (osif_cm_legacy_ops)
800  		cb = osif_cm_legacy_ops->disconnect_complete_cb;
801  	if (cb)
802  		ret = cb(vdev, rsp, type);
803  
804  	return ret;
805  }
806  
807  #ifdef CONN_MGR_ADV_FEATURE
osif_cm_netif_queue_ind(struct wlan_objmgr_vdev * vdev,enum netif_action_type action,enum netif_reason_type reason)808  QDF_STATUS osif_cm_netif_queue_ind(struct wlan_objmgr_vdev *vdev,
809  				   enum netif_action_type action,
810  				   enum netif_reason_type reason)
811  {
812  	osif_cm_netif_queue_ctrl_cb cb = NULL;
813  	QDF_STATUS ret = QDF_STATUS_SUCCESS;
814  
815  	if (osif_cm_legacy_ops)
816  		cb = osif_cm_legacy_ops->netif_queue_control_cb;
817  	if (cb)
818  		ret = cb(vdev, action, reason);
819  
820  	return ret;
821  }
822  
osif_cm_napi_serialize(bool action)823  QDF_STATUS osif_cm_napi_serialize(bool action)
824  {
825  	os_if_cm_napi_serialize_ctrl_cb cb = NULL;
826  	QDF_STATUS ret = QDF_STATUS_SUCCESS;
827  
828  	if (osif_cm_legacy_ops)
829  		cb = osif_cm_legacy_ops->napi_serialize_control_cb;
830  	if (cb)
831  		ret = cb(action);
832  
833  	return ret;
834  }
835  
osif_cm_save_gtk(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp)836  QDF_STATUS osif_cm_save_gtk(struct wlan_objmgr_vdev *vdev,
837  			    struct wlan_cm_connect_resp *rsp)
838  {
839  	osif_cm_save_gtk_cb cb = NULL;
840  	QDF_STATUS ret = QDF_STATUS_SUCCESS;
841  
842  	if (osif_cm_legacy_ops)
843  		cb = osif_cm_legacy_ops->save_gtk_cb;
844  	if (cb)
845  		ret = cb(vdev, rsp);
846  
847  	return ret;
848  }
849  
850  QDF_STATUS
osif_cm_send_vdev_keys(struct wlan_objmgr_vdev * vdev,uint8_t key_index,bool pairwise,enum wlan_crypto_cipher_type cipher_type)851  osif_cm_send_vdev_keys(struct wlan_objmgr_vdev *vdev,
852  		       uint8_t key_index,
853  		       bool pairwise,
854  		       enum wlan_crypto_cipher_type cipher_type)
855  {
856  	osif_cm_send_vdev_keys_cb cb = NULL;
857  
858  	if (osif_cm_legacy_ops)
859  		cb = osif_cm_legacy_ops->send_vdev_keys_cb;
860  	if (cb)
861  		return cb(vdev, key_index, pairwise, cipher_type);
862  
863  	return QDF_STATUS_E_FAILURE;
864  }
865  #endif
866  
867  #ifdef WLAN_FEATURE_FILS_SK
osif_cm_set_hlp_data(struct net_device * dev,struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp)868  QDF_STATUS osif_cm_set_hlp_data(struct net_device *dev,
869  				struct wlan_objmgr_vdev *vdev,
870  				struct wlan_cm_connect_resp *rsp)
871  {
872  	osif_cm_set_hlp_data_cb cb = NULL;
873  	QDF_STATUS ret = QDF_STATUS_SUCCESS;
874  
875  	if (osif_cm_legacy_ops)
876  		cb = osif_cm_legacy_ops->set_hlp_data_cb;
877  	if (cb)
878  		ret = cb(dev, vdev, rsp);
879  
880  	return ret;
881  }
882  #endif
883  
osif_cm_set_legacy_cb(struct osif_cm_ops * osif_legacy_ops)884  void osif_cm_set_legacy_cb(struct osif_cm_ops *osif_legacy_ops)
885  {
886  	osif_cm_legacy_ops = osif_legacy_ops;
887  }
888  
osif_cm_reset_legacy_cb(void)889  void osif_cm_reset_legacy_cb(void)
890  {
891  	osif_cm_legacy_ops = NULL;
892  }
893  
894  #ifdef WLAN_BOOST_CPU_FREQ_IN_ROAM
osif_cm_perfd_set_cpufreq(bool action)895  QDF_STATUS osif_cm_perfd_set_cpufreq(bool action)
896  {
897  	os_if_cm_perfd_set_cpufreq_ctrl_cb cb = NULL;
898  	QDF_STATUS ret = QDF_STATUS_SUCCESS;
899  
900  	if (osif_cm_legacy_ops)
901  		cb = osif_cm_legacy_ops->perfd_set_cpufreq_cb;
902  	if (cb)
903  		ret = cb(action);
904  
905  	return ret;
906  }
907  #endif
908