xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c (revision 45a38684b07295822dc8eba39e293408f203eec8)
1 /*
2  * Copyright (c) 2012-2015, 2020, The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  * DOC: Implements disconnect specific apis of connection manager
19  */
20 #include "wlan_cm_main_api.h"
21 #include "wlan_cm_sm.h"
22 #include <wlan_serialization_api.h>
23 
24 static QDF_STATUS
25 cm_ser_disconnect_cb(struct wlan_serialization_command *cmd,
26 		     enum wlan_serialization_cb_reason reason)
27 {
28 	QDF_STATUS status = QDF_STATUS_SUCCESS;
29 	struct wlan_objmgr_vdev *vdev;
30 
31 	if (!cmd) {
32 		mlme_err("cmd is NULL, reason: %d", reason);
33 		QDF_ASSERT(0);
34 		return QDF_STATUS_E_NULL_VALUE;
35 	}
36 
37 	vdev = cmd->vdev;
38 
39 	switch (reason) {
40 	case WLAN_SER_CB_ACTIVATE_CMD:
41 		/* Post event disconnect active to CM SM */
42 		break;
43 
44 	case WLAN_SER_CB_CANCEL_CMD:
45 		/* command removed from pending list. */
46 		break;
47 
48 	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
49 		mlme_err("Active command timeout cm_id %d", cmd->cmd_id);
50 		QDF_ASSERT(0);
51 		break;
52 
53 	case WLAN_SER_CB_RELEASE_MEM_CMD:
54 		/* command completed. Release reference of vdev */
55 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
56 		break;
57 
58 	default:
59 		QDF_ASSERT(0);
60 		status = QDF_STATUS_E_INVAL;
61 		break;
62 	}
63 
64 	return status;
65 }
66 
67 #define DISCONNECT_TIMEOUT   STOP_RESPONSE_TIMER + DELETE_RESPONSE_TIMER + 1000
68 
69 static QDF_STATUS cm_ser_disconnect_req(struct wlan_objmgr_pdev *pdev,
70 					struct cnx_mgr *cm_ctx,
71 					struct cm_disconnect_req *req)
72 {
73 	struct wlan_serialization_command cmd = {0, };
74 	enum wlan_serialization_status ser_cmd_status;
75 	QDF_STATUS status;
76 
77 	status = wlan_objmgr_vdev_try_get_ref(cm_ctx->vdev, WLAN_MLME_CM_ID);
78 	if (QDF_IS_STATUS_ERROR(status)) {
79 		mlme_err("unable to get reference");
80 		return status;
81 	}
82 
83 	cmd.cmd_type = WLAN_SER_CMD_VDEV_CONNECT;
84 	cmd.cmd_id = req->cm_id;
85 	cmd.cmd_cb = cm_ser_disconnect_cb;
86 	cmd.source = WLAN_UMAC_COMP_MLME;
87 	cmd.is_high_priority = false;
88 	cmd.cmd_timeout_duration = DISCONNECT_TIMEOUT;
89 	cmd.vdev = cm_ctx->vdev;
90 
91 	ser_cmd_status = wlan_serialization_request(&cmd);
92 	switch (ser_cmd_status) {
93 	case WLAN_SER_CMD_PENDING:
94 		/* command moved to pending list.Do nothing */
95 		break;
96 	case WLAN_SER_CMD_ACTIVE:
97 		/* command moved to active list. Do nothing */
98 		break;
99 	default:
100 		mlme_err("ser cmd status %d", ser_cmd_status);
101 		wlan_objmgr_vdev_release_ref(cm_ctx->vdev, WLAN_MLME_CM_ID);
102 
103 		return QDF_STATUS_E_FAILURE;
104 	}
105 
106 	return QDF_STATUS_SUCCESS;
107 }
108 
109 QDF_STATUS cm_disconnect_start(struct cnx_mgr *cm_ctx,
110 			       struct cm_disconnect_req *req)
111 {
112 	struct wlan_objmgr_pdev *pdev;
113 
114 	/* Interface event */
115 	pdev = wlan_vdev_get_pdev(cm_ctx->vdev);
116 	if (!pdev)
117 		return QDF_STATUS_E_INVAL;
118 
119 	/*
120 	 * Interface event, stop scan, disconnect TDLS, P2P roc cleanup
121 	 */
122 
123 	/* Serialize disconnect req, Handle failure status */
124 	cm_ser_disconnect_req(pdev, cm_ctx, req);
125 
126 	return QDF_STATUS_SUCCESS;
127 }
128 
129 QDF_STATUS cm_disconnect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
130 {
131 	/*
132 	 * call vdev sm to start disconnect.
133 	 */
134 	return QDF_STATUS_SUCCESS;
135 }
136 
137 QDF_STATUS cm_disconnect_complete(struct cnx_mgr *cm_ctx,
138 				  struct wlan_cm_discon_rsp *resp)
139 {
140 	/*
141 	 * inform osif, inform interface manager
142 	 * update fils/wep key and inform legacy, update bcn filter and scan
143 	 * entry mlme info, blm action and remove from serialization at the end.
144 	 */
145 	return QDF_STATUS_SUCCESS;
146 }
147 
148 QDF_STATUS cm_disconnect_start_req(struct wlan_objmgr_vdev *vdev,
149 				   struct wlan_cm_disconnect_req *req)
150 {
151 	struct cnx_mgr *cm_ctx = NULL;
152 	struct cm_disconnect_req *cm_req = NULL;
153 
154 	/*
155 	 * Prepare cm_disconnect_req cm_req, get cm id and inform it to
156 	 * OSIF. store disconnect req to the cm ctx req_list
157 	 */
158 
159 	return cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_DISCONNECT_REQ,
160 				   sizeof(*cm_req), cm_req);
161 }
162