1 /*
2  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 /**
19  * DOC: wlan_twt_objmgr.c
20  * This file defines the APIs of TWT component.
21  */
22 #include "wlan_twt_common.h"
23 #include "wlan_twt_priv.h"
24 #include "wlan_twt_objmgr_handler.h"
25 #include "wlan_objmgr_peer_obj.h"
26 #include "include/wlan_mlme_cmn.h"
27 
28 QDF_STATUS
wlan_twt_psoc_obj_create_handler(struct wlan_objmgr_psoc * psoc,void * arg)29 wlan_twt_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, void *arg)
30 {
31 	QDF_STATUS status;
32 	struct twt_psoc_priv_obj *twt_psoc_obj;
33 
34 	twt_psoc_obj = qdf_mem_malloc(sizeof(*twt_psoc_obj));
35 	if (!twt_psoc_obj)
36 		return QDF_STATUS_E_NOMEM;
37 
38 	twt_psoc_obj->enable_context.context = NULL;
39 	twt_psoc_obj->disable_context.context = NULL;
40 	twt_psoc_obj->twt_pmo_disabled = 0;
41 
42 	status = wlan_objmgr_psoc_component_obj_attach(psoc,
43 						       WLAN_UMAC_COMP_TWT,
44 						       (void *)twt_psoc_obj,
45 						       QDF_STATUS_SUCCESS);
46 
47 	if (QDF_IS_STATUS_ERROR(status)) {
48 		qdf_mem_free(twt_psoc_obj);
49 		twt_err("Failed to attach twt psoc priv object");
50 		return status;
51 	}
52 
53 	twt_debug("twt psoc priv obj attach successful");
54 	return status;
55 }
56 
57 QDF_STATUS
wlan_twt_psoc_obj_destroy_handler(struct wlan_objmgr_psoc * psoc,void * arg)58 wlan_twt_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc, void *arg)
59 {
60 	QDF_STATUS status;
61 	struct twt_psoc_priv_obj *twt_psoc_obj;
62 
63 	twt_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
64 						WLAN_UMAC_COMP_TWT);
65 	if (!twt_psoc_obj) {
66 		twt_err("Failed to get twt obj in psoc");
67 		return QDF_STATUS_E_FAILURE;
68 	}
69 
70 	status = wlan_objmgr_psoc_component_obj_detach(psoc,
71 						       WLAN_UMAC_COMP_TWT,
72 						       twt_psoc_obj);
73 
74 	if (QDF_IS_STATUS_ERROR(status))
75 		twt_err("Failed to detach twt psoc priv object");
76 
77 	qdf_mem_free(twt_psoc_obj);
78 
79 	return status;
80 }
81 
82 QDF_STATUS
wlan_twt_vdev_obj_create_handler(struct wlan_objmgr_vdev * vdev,void * arg)83 wlan_twt_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev, void *arg)
84 {
85 	QDF_STATUS status;
86 	struct twt_vdev_priv_obj *twt_vdev_obj;
87 
88 	twt_vdev_obj = qdf_mem_malloc(sizeof(*twt_vdev_obj));
89 	if (!twt_vdev_obj)
90 		return QDF_STATUS_E_NOMEM;
91 
92 	twt_vdev_obj->twt_wait_for_notify = false;
93 
94 	status = wlan_objmgr_vdev_component_obj_attach(vdev,
95 						       WLAN_UMAC_COMP_TWT,
96 						       twt_vdev_obj,
97 						       QDF_STATUS_SUCCESS);
98 
99 	if (QDF_IS_STATUS_ERROR(status)) {
100 		qdf_mem_free(twt_vdev_obj);
101 		twt_err("Failed to attach twt vdev priv object");
102 		return status;
103 	}
104 
105 	twt_debug("twt vdev priv obj attach successful");
106 
107 	status = mlme_twt_vdev_create_notification(vdev);
108 
109 	if (QDF_IS_STATUS_ERROR(status)) {
110 		twt_err("vdev create notification failed");
111 		return status;
112 	}
113 
114 	return status;
115 }
116 
117 QDF_STATUS
wlan_twt_vdev_obj_destroy_handler(struct wlan_objmgr_vdev * vdev,void * arg)118 wlan_twt_vdev_obj_destroy_handler(struct wlan_objmgr_vdev *vdev, void *arg)
119 {
120 	QDF_STATUS status;
121 	struct twt_vdev_priv_obj *twt_vdev_obj;
122 
123 	status = mlme_twt_vdev_destroy_notification(vdev);
124 	if (QDF_IS_STATUS_ERROR(status)) {
125 		twt_err("vdev destroy notification failed");
126 		return status;
127 	}
128 
129 	twt_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
130 							    WLAN_UMAC_COMP_TWT);
131 	if (!twt_vdev_obj) {
132 		twt_err("Failed to get twt obj in vdev");
133 		return QDF_STATUS_E_FAILURE;
134 	}
135 
136 	status = wlan_objmgr_vdev_component_obj_detach(vdev,
137 						       WLAN_UMAC_COMP_TWT,
138 						       twt_vdev_obj);
139 
140 	if (QDF_IS_STATUS_ERROR(status))
141 		twt_err("Failed to detach twt vdev priv object");
142 
143 	qdf_mem_free(twt_vdev_obj);
144 
145 	return status;
146 }
147 
148 QDF_STATUS
wlan_twt_peer_obj_create_handler(struct wlan_objmgr_peer * peer,void * arg)149 wlan_twt_peer_obj_create_handler(struct wlan_objmgr_peer *peer, void *arg)
150 {
151 	struct twt_peer_priv_obj *twt_peer_obj = NULL;
152 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
153 
154 	if (!peer) {
155 		twt_err("peer is NULL");
156 		return QDF_STATUS_E_FAILURE;
157 	}
158 
159 	twt_peer_obj = qdf_mem_malloc(sizeof(*twt_peer_obj));
160 	if (!twt_peer_obj)
161 		return QDF_STATUS_E_NOMEM;
162 
163 	twt_lock_create(&twt_peer_obj->twt_peer_lock);
164 
165 	status = wlan_objmgr_peer_component_obj_attach(peer,
166 						       WLAN_UMAC_COMP_TWT,
167 						       twt_peer_obj,
168 						       QDF_STATUS_SUCCESS);
169 
170 	if (QDF_IS_STATUS_ERROR(status)) {
171 		twt_lock_destroy(&twt_peer_obj->twt_peer_lock);
172 		qdf_mem_free(twt_peer_obj);
173 		twt_err("peer twt object attach failed");
174 		return QDF_STATUS_E_FAILURE;
175 	}
176 
177 	twt_debug("twt peer priv obj attach successful");
178 	return status;
179 }
180 
181 QDF_STATUS
wlan_twt_peer_obj_destroy_handler(struct wlan_objmgr_peer * peer,void * arg)182 wlan_twt_peer_obj_destroy_handler(struct wlan_objmgr_peer *peer, void *arg)
183 {
184 	struct twt_peer_priv_obj *twt_peer_obj;
185 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
186 
187 	if (!peer) {
188 		twt_err("peer is NULL");
189 		return QDF_STATUS_E_INVAL;
190 	}
191 
192 	twt_peer_obj = wlan_objmgr_peer_get_comp_private_obj(peer,
193 						WLAN_UMAC_COMP_TWT);
194 	if (!twt_peer_obj) {
195 		twt_err("twt_peer_obj is NULL");
196 		return QDF_STATUS_E_INVAL;
197 	}
198 
199 	twt_lock_destroy(&twt_peer_obj->twt_peer_lock);
200 
201 	status = wlan_objmgr_peer_component_obj_detach(peer, WLAN_UMAC_COMP_TWT,
202 						       twt_peer_obj);
203 	if (QDF_IS_STATUS_ERROR(status))
204 		twt_warn("Failed to detach twt peer priv object");
205 
206 	qdf_mem_free(twt_peer_obj);
207 	twt_debug("peer twt object detached");
208 	return QDF_STATUS_SUCCESS;
209 }
210 
211 QDF_STATUS
wlan_twt_psoc_set_pmo_disable(struct wlan_objmgr_psoc * psoc,enum twt_disable_reason reason)212 wlan_twt_psoc_set_pmo_disable(struct wlan_objmgr_psoc *psoc,
213 			      enum twt_disable_reason reason)
214 {
215 	struct twt_psoc_priv_obj *twt_psoc_obj;
216 
217 	twt_psoc_obj = wlan_twt_psoc_get_comp_private_obj(psoc);
218 	if (!twt_psoc_obj) {
219 		twt_err("twt_psoc_obj is NULL");
220 		return QDF_STATUS_E_INVAL;
221 	}
222 	twt_psoc_obj->twt_pmo_disabled |= reason;
223 	twt_debug("Psoc twt_disabled %x", twt_psoc_obj->twt_pmo_disabled);
224 
225 	return QDF_STATUS_SUCCESS;
226 }
227 
228 QDF_STATUS
wlan_twt_psoc_set_pmo_enable(struct wlan_objmgr_psoc * psoc,enum twt_disable_reason reason)229 wlan_twt_psoc_set_pmo_enable(struct wlan_objmgr_psoc *psoc,
230 			     enum twt_disable_reason reason)
231 {
232 	struct twt_psoc_priv_obj *twt_psoc_obj;
233 
234 	twt_psoc_obj = wlan_twt_psoc_get_comp_private_obj(psoc);
235 	if (!twt_psoc_obj) {
236 		twt_err("twt_psoc_obj is NULL");
237 		return QDF_STATUS_E_INVAL;
238 	}
239 	twt_psoc_obj->twt_pmo_disabled &= ~reason;
240 	twt_debug("Psoc twt_disabled %x", twt_psoc_obj->twt_pmo_disabled);
241 
242 	return QDF_STATUS_SUCCESS;
243 }
244 
245