xref: /wlan-driver/qcacld-3.0/os_if/twt/src/osif_twt_ext_rsp.c (revision 5113495b16420b49004c444715d2daae2066e7dc) !
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
3*5113495bSYour Name  *
4*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for any
5*5113495bSYour Name  * purpose with or without fee is hereby granted, provided that the above
6*5113495bSYour Name  * copyright notice and this permission notice appear in all copies.
7*5113495bSYour Name  *
8*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9*5113495bSYour Name  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10*5113495bSYour Name  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11*5113495bSYour Name  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12*5113495bSYour Name  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13*5113495bSYour Name  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14*5113495bSYour Name  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*5113495bSYour Name  */
16*5113495bSYour Name 
17*5113495bSYour Name /**
18*5113495bSYour Name  * DOC: osif_twt_ext_rsp.c
19*5113495bSYour Name  *
20*5113495bSYour Name  */
21*5113495bSYour Name #include <wlan_cfg80211.h>
22*5113495bSYour Name #include <osif_twt_ext_req.h>
23*5113495bSYour Name #include <osif_twt_rsp.h>
24*5113495bSYour Name #include <osif_twt_ext_rsp.h>
25*5113495bSYour Name #include <wlan_objmgr_psoc_obj.h>
26*5113495bSYour Name #include <wlan_osif_priv.h>
27*5113495bSYour Name #include <wlan_osif_request_manager.h>
28*5113495bSYour Name #include <wlan_cm_api.h>
29*5113495bSYour Name #include <wlan_twt_ucfg_api.h>
30*5113495bSYour Name #include <wlan_cm_ucfg_api.h>
31*5113495bSYour Name #include <wlan_reg_ucfg_api.h>
32*5113495bSYour Name #include <wlan_twt_ucfg_ext_api.h>
33*5113495bSYour Name #include <wlan_twt_ucfg_ext_cfg.h>
34*5113495bSYour Name #include <wlan_cp_stats_ucfg_api.h>
35*5113495bSYour Name 
36*5113495bSYour Name /**
37*5113495bSYour Name  * osif_twt_get_setup_event_len() - Calculates the length of twt
38*5113495bSYour Name  * setup nl response
39*5113495bSYour Name  * @additional_params_present: if true, then length required for
40*5113495bSYour Name  * fixed and additional parameters is returned. if false,
41*5113495bSYour Name  * then length required for fixed parameters is returned.
42*5113495bSYour Name  *
43*5113495bSYour Name  * Return: Length of twt setup nl response
44*5113495bSYour Name  */
45*5113495bSYour Name static
osif_twt_get_setup_event_len(bool additional_params_present)46*5113495bSYour Name uint32_t osif_twt_get_setup_event_len(bool additional_params_present)
47*5113495bSYour Name {
48*5113495bSYour Name 	uint32_t len = 0;
49*5113495bSYour Name 
50*5113495bSYour Name 	len += NLMSG_HDRLEN;
51*5113495bSYour Name 
52*5113495bSYour Name 	/* Length of attribute QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS */
53*5113495bSYour Name 	len += NLA_HDRLEN;
54*5113495bSYour Name 
55*5113495bSYour Name 	/* QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION */
56*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
57*5113495bSYour Name 
58*5113495bSYour Name 	/* QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID */
59*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
60*5113495bSYour Name 	/* QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS */
61*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
62*5113495bSYour Name 
63*5113495bSYour Name 	if (!additional_params_present)
64*5113495bSYour Name 		return len;
65*5113495bSYour Name 
66*5113495bSYour Name 	/* QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE */
67*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
68*5113495bSYour Name 	/*QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE*/
69*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
70*5113495bSYour Name 	/*QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION*/
71*5113495bSYour Name 	len += nla_total_size(sizeof(u32));
72*5113495bSYour Name 	/*QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA*/
73*5113495bSYour Name 	len += nla_total_size(sizeof(u32));
74*5113495bSYour Name 	/*QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP*/
75*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
76*5113495bSYour Name 	/*QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF*/
77*5113495bSYour Name 	len += nla_total_size(sizeof(u64));
78*5113495bSYour Name 	/*QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME*/
79*5113495bSYour Name 	len += nla_total_size(sizeof(u32));
80*5113495bSYour Name 	/*QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER*/
81*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
82*5113495bSYour Name 	/*QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION*/
83*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
84*5113495bSYour Name 	/*QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST*/
85*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
86*5113495bSYour Name 	/*QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED*/
87*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
88*5113495bSYour Name 	/*QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR*/
89*5113495bSYour Name 	len += nla_total_size(QDF_MAC_ADDR_SIZE);
90*5113495bSYour Name 
91*5113495bSYour Name 	return len;
92*5113495bSYour Name }
93*5113495bSYour Name 
94*5113495bSYour Name /**
95*5113495bSYour Name  * osif_twt_get_event_len() - calculate length of skb
96*5113495bSYour Name  * required for sending twt terminate, pause and resume
97*5113495bSYour Name  * command responses.
98*5113495bSYour Name  *
99*5113495bSYour Name  * Return: length of skb
100*5113495bSYour Name  */
osif_twt_get_event_len(void)101*5113495bSYour Name static uint32_t osif_twt_get_event_len(void)
102*5113495bSYour Name {
103*5113495bSYour Name 	uint32_t len = 0;
104*5113495bSYour Name 
105*5113495bSYour Name 	len += NLMSG_HDRLEN;
106*5113495bSYour Name 	/* QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID */
107*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
108*5113495bSYour Name 	/* QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS */
109*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
110*5113495bSYour Name 	/* QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR*/
111*5113495bSYour Name 	len += nla_total_size(QDF_MAC_ADDR_SIZE);
112*5113495bSYour Name 
113*5113495bSYour Name 	return len;
114*5113495bSYour Name }
115*5113495bSYour Name 
116*5113495bSYour Name /**
117*5113495bSYour Name  * twt_add_status_to_vendor_twt_status() - convert from
118*5113495bSYour Name  * HOST_ADD_TWT_STATUS to qca_wlan_vendor_twt_status
119*5113495bSYour Name  * @status: HOST_ADD_TWT_STATUS value from firmware
120*5113495bSYour Name  *
121*5113495bSYour Name  * Return: qca_wlan_vendor_twt_status values corresponding
122*5113495bSYour Name  * to HOST_ADD_TWT_STATUS.
123*5113495bSYour Name  */
124*5113495bSYour Name static enum qca_wlan_vendor_twt_status
twt_add_status_to_vendor_twt_status(enum HOST_ADD_TWT_STATUS status)125*5113495bSYour Name twt_add_status_to_vendor_twt_status(enum HOST_ADD_TWT_STATUS status)
126*5113495bSYour Name {
127*5113495bSYour Name 	switch (status) {
128*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_OK:
129*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_OK;
130*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_TWT_NOT_ENABLED:
131*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_ENABLED;
132*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_USED_DIALOG_ID:
133*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_USED_DIALOG_ID;
134*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_INVALID_PARAM:
135*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM;
136*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_NOT_READY:
137*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_NOT_READY;
138*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_NO_RESOURCE:
139*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE;
140*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_NO_ACK:
141*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK;
142*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_NO_RESPONSE:
143*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_NO_RESPONSE;
144*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_DENIED:
145*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_DENIED;
146*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_UNKNOWN_ERROR:
147*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR;
148*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_AP_PARAMS_NOT_IN_RANGE:
149*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE;
150*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_AP_IE_VALIDATION_FAILED:
151*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID;
152*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_ROAM_IN_PROGRESS:
153*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS;
154*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_CHAN_SW_IN_PROGRESS:
155*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS;
156*5113495bSYour Name 	case HOST_ADD_TWT_STATUS_SCAN_IN_PROGRESS:
157*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS;
158*5113495bSYour Name 	default:
159*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR;
160*5113495bSYour Name 	}
161*5113495bSYour Name }
162*5113495bSYour Name 
163*5113495bSYour Name /**
164*5113495bSYour Name  * twt_del_status_to_vendor_twt_status() - convert from
165*5113495bSYour Name  * HOST_DEL_TWT_STATUS to qca_wlan_vendor_twt_status
166*5113495bSYour Name  * @status: HOST_DEL_TWT_STATUS value from firmware
167*5113495bSYour Name  *
168*5113495bSYour Name  * Return: qca_wlan_vendor_twt_status values corresponding
169*5113495bSYour Name  * to HOST_DEL_TWT_STATUS.
170*5113495bSYour Name  */
171*5113495bSYour Name static enum qca_wlan_vendor_twt_status
twt_del_status_to_vendor_twt_status(enum HOST_TWT_DEL_STATUS status)172*5113495bSYour Name twt_del_status_to_vendor_twt_status(enum HOST_TWT_DEL_STATUS status)
173*5113495bSYour Name {
174*5113495bSYour Name 	switch (status) {
175*5113495bSYour Name 	case HOST_TWT_DEL_STATUS_OK:
176*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_OK;
177*5113495bSYour Name 	case HOST_TWT_DEL_STATUS_DIALOG_ID_NOT_EXIST:
178*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST;
179*5113495bSYour Name 	case HOST_TWT_DEL_STATUS_INVALID_PARAM:
180*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM;
181*5113495bSYour Name 	case HOST_TWT_DEL_STATUS_DIALOG_ID_BUSY:
182*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_SESSION_BUSY;
183*5113495bSYour Name 	case HOST_TWT_DEL_STATUS_NO_RESOURCE:
184*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE;
185*5113495bSYour Name 	case HOST_TWT_DEL_STATUS_NO_ACK:
186*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK;
187*5113495bSYour Name 	case HOST_TWT_DEL_STATUS_UNKNOWN_ERROR:
188*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR;
189*5113495bSYour Name 	case HOST_TWT_DEL_STATUS_PEER_INIT_TEARDOWN:
190*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE;
191*5113495bSYour Name 	case HOST_TWT_DEL_STATUS_ROAMING:
192*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE;
193*5113495bSYour Name 	case HOST_TWT_DEL_STATUS_CONCURRENCY:
194*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE;
195*5113495bSYour Name 	case HOST_TWT_DEL_STATUS_CHAN_SW_IN_PROGRESS:
196*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS;
197*5113495bSYour Name 	case HOST_TWT_DEL_STATUS_SCAN_IN_PROGRESS:
198*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS;
199*5113495bSYour Name 	case HOST_TWT_DEL_STATUS_PS_DISABLE_TEARDOWN:
200*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE;
201*5113495bSYour Name 	default:
202*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR;
203*5113495bSYour Name 	}
204*5113495bSYour Name }
205*5113495bSYour Name 
206*5113495bSYour Name /**
207*5113495bSYour Name  * twt_resume_status_to_vendor_twt_status() - convert from
208*5113495bSYour Name  * HOST_TWT_RESUME_STATUS to qca_wlan_vendor_twt_status
209*5113495bSYour Name  * @status: HOST_TWT_RESUME_STATUS value from firmware
210*5113495bSYour Name  *
211*5113495bSYour Name  * Return: qca_wlan_vendor_twt_status values corresponding
212*5113495bSYour Name  * to the firmware failure status
213*5113495bSYour Name  */
214*5113495bSYour Name static int
twt_resume_status_to_vendor_twt_status(enum HOST_TWT_RESUME_STATUS status)215*5113495bSYour Name twt_resume_status_to_vendor_twt_status(enum HOST_TWT_RESUME_STATUS status)
216*5113495bSYour Name {
217*5113495bSYour Name 	switch (status) {
218*5113495bSYour Name 	case HOST_TWT_RESUME_STATUS_OK:
219*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_OK;
220*5113495bSYour Name 	case HOST_TWT_RESUME_STATUS_DIALOG_ID_NOT_EXIST:
221*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST;
222*5113495bSYour Name 	case HOST_TWT_RESUME_STATUS_INVALID_PARAM:
223*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM;
224*5113495bSYour Name 	case HOST_TWT_RESUME_STATUS_DIALOG_ID_BUSY:
225*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_SESSION_BUSY;
226*5113495bSYour Name 	case HOST_TWT_RESUME_STATUS_NOT_PAUSED:
227*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_NOT_SUSPENDED;
228*5113495bSYour Name 	case HOST_TWT_RESUME_STATUS_NO_RESOURCE:
229*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE;
230*5113495bSYour Name 	case HOST_TWT_RESUME_STATUS_NO_ACK:
231*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK;
232*5113495bSYour Name 	case HOST_TWT_RESUME_STATUS_UNKNOWN_ERROR:
233*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR;
234*5113495bSYour Name 	case HOST_TWT_RESUME_STATUS_CHAN_SW_IN_PROGRESS:
235*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS;
236*5113495bSYour Name 	case HOST_TWT_RESUME_STATUS_ROAM_IN_PROGRESS:
237*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS;
238*5113495bSYour Name 	case HOST_TWT_RESUME_STATUS_SCAN_IN_PROGRESS:
239*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS;
240*5113495bSYour Name 	default:
241*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR;
242*5113495bSYour Name 	}
243*5113495bSYour Name }
244*5113495bSYour Name 
245*5113495bSYour Name /**
246*5113495bSYour Name  * twt_nudge_status_to_vendor_twt_status() - convert from
247*5113495bSYour Name  * HOST_TWT_NUDGE_STATUS to qca_wlan_vendor_twt_status
248*5113495bSYour Name  * @status: HOST_TWT_NUDGE_STATUS value from firmware
249*5113495bSYour Name  *
250*5113495bSYour Name  * Return: qca_wlan_vendor_twt_status values corresponding
251*5113495bSYour Name  * to the firmware failure status
252*5113495bSYour Name  */
253*5113495bSYour Name static int
twt_nudge_status_to_vendor_twt_status(enum HOST_TWT_NUDGE_STATUS status)254*5113495bSYour Name twt_nudge_status_to_vendor_twt_status(enum HOST_TWT_NUDGE_STATUS status)
255*5113495bSYour Name {
256*5113495bSYour Name 	switch (status) {
257*5113495bSYour Name 	case HOST_TWT_NUDGE_STATUS_OK:
258*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_OK;
259*5113495bSYour Name 	case HOST_TWT_NUDGE_STATUS_DIALOG_ID_NOT_EXIST:
260*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST;
261*5113495bSYour Name 	case HOST_TWT_NUDGE_STATUS_INVALID_PARAM:
262*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM;
263*5113495bSYour Name 	case HOST_TWT_NUDGE_STATUS_DIALOG_ID_BUSY:
264*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_SESSION_BUSY;
265*5113495bSYour Name 	case HOST_TWT_NUDGE_STATUS_NO_RESOURCE:
266*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE;
267*5113495bSYour Name 	case HOST_TWT_NUDGE_STATUS_NO_ACK:
268*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK;
269*5113495bSYour Name 	case HOST_TWT_NUDGE_STATUS_UNKNOWN_ERROR:
270*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR;
271*5113495bSYour Name 	case HOST_TWT_NUDGE_STATUS_ALREADY_PAUSED:
272*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED;
273*5113495bSYour Name 	case HOST_TWT_NUDGE_STATUS_CHAN_SW_IN_PROGRESS:
274*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS;
275*5113495bSYour Name 	default:
276*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR;
277*5113495bSYour Name 	}
278*5113495bSYour Name }
279*5113495bSYour Name 
280*5113495bSYour Name /**
281*5113495bSYour Name  * twt_add_cmd_to_vendor_twt_resp_type() - convert from
282*5113495bSYour Name  * HOST_TWT_COMMAND to qca_wlan_vendor_twt_setup_resp_type
283*5113495bSYour Name  * @type: HOST_TWT_COMMAND value from firmware
284*5113495bSYour Name  *
285*5113495bSYour Name  * Return: qca_wlan_vendor_twt_setup_resp_type values for valid
286*5113495bSYour Name  * HOST_TWT_COMMAND value and -EINVAL for invalid value
287*5113495bSYour Name  */
288*5113495bSYour Name static
twt_add_cmd_to_vendor_twt_resp_type(enum HOST_TWT_COMMAND type)289*5113495bSYour Name int twt_add_cmd_to_vendor_twt_resp_type(enum HOST_TWT_COMMAND type)
290*5113495bSYour Name {
291*5113495bSYour Name 	switch (type) {
292*5113495bSYour Name 	case HOST_TWT_COMMAND_ACCEPT_TWT:
293*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_RESP_ACCEPT;
294*5113495bSYour Name 	case HOST_TWT_COMMAND_ALTERNATE_TWT:
295*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_RESP_ALTERNATE;
296*5113495bSYour Name 	case HOST_TWT_COMMAND_DICTATE_TWT:
297*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_RESP_DICTATE;
298*5113495bSYour Name 	case HOST_TWT_COMMAND_REJECT_TWT:
299*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_RESP_REJECT;
300*5113495bSYour Name 	default:
301*5113495bSYour Name 		return -EINVAL;
302*5113495bSYour Name 	}
303*5113495bSYour Name }
304*5113495bSYour Name 
305*5113495bSYour Name /**
306*5113495bSYour Name  * osif_twt_setup_pack_resp_nlmsg() - pack nlmsg response for setup
307*5113495bSYour Name  * @reply_skb: pointer to the response skb structure
308*5113495bSYour Name  * @event: twt event buffer with firmware response
309*5113495bSYour Name  *
310*5113495bSYour Name  * Pack the nl response with parameters and additional parameters
311*5113495bSYour Name  * received from firmware.
312*5113495bSYour Name  * Firmware sends additional parameters only for 2 conditions
313*5113495bSYour Name  * 1) TWT Negotiation is accepted by AP - Firmware sends
314*5113495bSYour Name  * QCA_WLAN_VENDOR_TWT_STATUS_OK with appropriate response type
315*5113495bSYour Name  * in additional parameters
316*5113495bSYour Name  * 2) AP has proposed Alternate values - In this case firmware sends
317*5113495bSYour Name  * QCA_WLAN_VENDOR_TWT_STATUS_DENIED with appropriate response type
318*5113495bSYour Name  * in additional parameters
319*5113495bSYour Name  *
320*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes
321*5113495bSYour Name  * on failure
322*5113495bSYour Name  */
323*5113495bSYour Name static QDF_STATUS
osif_twt_setup_pack_resp_nlmsg(struct sk_buff * reply_skb,struct twt_add_dialog_complete_event * event)324*5113495bSYour Name osif_twt_setup_pack_resp_nlmsg(struct sk_buff *reply_skb,
325*5113495bSYour Name 			       struct twt_add_dialog_complete_event *event)
326*5113495bSYour Name {
327*5113495bSYour Name 	struct nlattr *config_attr;
328*5113495bSYour Name 	uint64_t sp_offset_tsf;
329*5113495bSYour Name 	enum qca_wlan_vendor_twt_status vendor_status;
330*5113495bSYour Name 	int response_type, attr;
331*5113495bSYour Name 	uint32_t wake_duration;
332*5113495bSYour Name 	uint32_t wake_intvl_mantis_us, wake_intvl_mantis_tu;
333*5113495bSYour Name 
334*5113495bSYour Name 	if (nla_put_u8(reply_skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
335*5113495bSYour Name 		       QCA_WLAN_TWT_SET)) {
336*5113495bSYour Name 		osif_err("Failed to put TWT operation");
337*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
338*5113495bSYour Name 	}
339*5113495bSYour Name 
340*5113495bSYour Name 	config_attr = nla_nest_start(reply_skb,
341*5113495bSYour Name 				     QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
342*5113495bSYour Name 	if (!config_attr) {
343*5113495bSYour Name 		osif_err("nla_nest_start error");
344*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
345*5113495bSYour Name 	}
346*5113495bSYour Name 
347*5113495bSYour Name 	sp_offset_tsf = event->additional_params.sp_tsf_us_hi;
348*5113495bSYour Name 	sp_offset_tsf = (sp_offset_tsf << 32) |
349*5113495bSYour Name 			 event->additional_params.sp_tsf_us_lo;
350*5113495bSYour Name 
351*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID;
352*5113495bSYour Name 	if (nla_put_u8(reply_skb, attr, event->params.dialog_id)) {
353*5113495bSYour Name 		osif_err("Failed to put dialog_id");
354*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
355*5113495bSYour Name 	}
356*5113495bSYour Name 
357*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS;
358*5113495bSYour Name 	vendor_status = twt_add_status_to_vendor_twt_status(
359*5113495bSYour Name 							event->params.status);
360*5113495bSYour Name 	if (nla_put_u8(reply_skb, attr, vendor_status)) {
361*5113495bSYour Name 		osif_err("Failed to put setup status");
362*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
363*5113495bSYour Name 	}
364*5113495bSYour Name 
365*5113495bSYour Name 	if (event->params.num_additional_twt_params == 0) {
366*5113495bSYour Name 		nla_nest_end(reply_skb, config_attr);
367*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
368*5113495bSYour Name 	}
369*5113495bSYour Name 
370*5113495bSYour Name 	response_type = twt_add_cmd_to_vendor_twt_resp_type(
371*5113495bSYour Name 					event->additional_params.twt_cmd);
372*5113495bSYour Name 	if (response_type == -EINVAL) {
373*5113495bSYour Name 		osif_err("Invalid response type from firmware");
374*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
375*5113495bSYour Name 	}
376*5113495bSYour Name 
377*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE;
378*5113495bSYour Name 	if (nla_put_u8(reply_skb, attr, response_type)) {
379*5113495bSYour Name 		osif_err("Failed to put setup response type");
380*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
381*5113495bSYour Name 	}
382*5113495bSYour Name 
383*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE;
384*5113495bSYour Name 	if (nla_put_u8(reply_skb, attr, event->additional_params.announce)) {
385*5113495bSYour Name 		osif_err("Failed to put setup flow type");
386*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
387*5113495bSYour Name 	}
388*5113495bSYour Name 
389*5113495bSYour Name 	osif_debug("wake_dur_us %d", event->additional_params.wake_dur_us);
390*5113495bSYour Name 	wake_duration = (event->additional_params.wake_dur_us /
391*5113495bSYour Name 			 TWT_WAKE_DURATION_MULTIPLICATION_FACTOR);
392*5113495bSYour Name 
393*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION;
394*5113495bSYour Name 	if (nla_put_u32(reply_skb, attr, wake_duration)) {
395*5113495bSYour Name 		osif_err("Failed to put wake duration");
396*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
397*5113495bSYour Name 	}
398*5113495bSYour Name 
399*5113495bSYour Name 	wake_intvl_mantis_us = event->additional_params.wake_intvl_us;
400*5113495bSYour Name 	if (nla_put_u32(reply_skb,
401*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA,
402*5113495bSYour Name 			wake_intvl_mantis_us)) {
403*5113495bSYour Name 		osif_err("Failed to put wake interval mantissa in us");
404*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
405*5113495bSYour Name 	}
406*5113495bSYour Name 
407*5113495bSYour Name 	wake_intvl_mantis_tu = (event->additional_params.wake_intvl_us /
408*5113495bSYour Name 				 TWT_WAKE_INTVL_MULTIPLICATION_FACTOR);
409*5113495bSYour Name 
410*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA;
411*5113495bSYour Name 	if (nla_put_u32(reply_skb, attr, wake_intvl_mantis_tu)) {
412*5113495bSYour Name 		osif_err("Failed to put wake interval mantissa in tu");
413*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
414*5113495bSYour Name 	}
415*5113495bSYour Name 	osif_debug("Send mantissa_us:%d, mantissa_tu:%d to userspace",
416*5113495bSYour Name 		  wake_intvl_mantis_us, wake_intvl_mantis_tu);
417*5113495bSYour Name 
418*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP;
419*5113495bSYour Name 	if (nla_put_u8(reply_skb, attr, 0)) {
420*5113495bSYour Name 		osif_err("Failed to put wake interval exp");
421*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
422*5113495bSYour Name 	}
423*5113495bSYour Name 
424*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF;
425*5113495bSYour Name 	if (wlan_cfg80211_nla_put_u64(reply_skb, attr, sp_offset_tsf)) {
426*5113495bSYour Name 		osif_err("Failed to put sp_offset_tsf");
427*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
428*5113495bSYour Name 	}
429*5113495bSYour Name 
430*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME;
431*5113495bSYour Name 	if (nla_put_u32(reply_skb, attr,
432*5113495bSYour Name 			event->additional_params.sp_offset_us)) {
433*5113495bSYour Name 		osif_err("Failed to put sp_offset_us");
434*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
435*5113495bSYour Name 	}
436*5113495bSYour Name 
437*5113495bSYour Name 	if (event->additional_params.trig_en) {
438*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER;
439*5113495bSYour Name 		if (nla_put_flag(reply_skb, attr)) {
440*5113495bSYour Name 			osif_err("Failed to put trig type");
441*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
442*5113495bSYour Name 		}
443*5113495bSYour Name 	}
444*5113495bSYour Name 
445*5113495bSYour Name 	if (event->additional_params.protection) {
446*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION;
447*5113495bSYour Name 		if (nla_put_flag(reply_skb, attr)) {
448*5113495bSYour Name 			osif_err("Failed to put protection flag");
449*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
450*5113495bSYour Name 		}
451*5113495bSYour Name 	}
452*5113495bSYour Name 
453*5113495bSYour Name 	if (event->additional_params.bcast) {
454*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST;
455*5113495bSYour Name 		if (nla_put_flag(reply_skb, attr)) {
456*5113495bSYour Name 			osif_err("Failed to put bcast flag");
457*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
458*5113495bSYour Name 		}
459*5113495bSYour Name 	}
460*5113495bSYour Name 
461*5113495bSYour Name 	if (!event->additional_params.info_frame_disabled) {
462*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED;
463*5113495bSYour Name 		if (nla_put_flag(reply_skb, attr)) {
464*5113495bSYour Name 			osif_err("Failed to put twt info enable flag");
465*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
466*5113495bSYour Name 		}
467*5113495bSYour Name 	}
468*5113495bSYour Name 
469*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR;
470*5113495bSYour Name 	if (nla_put(reply_skb, attr, QDF_MAC_ADDR_SIZE,
471*5113495bSYour Name 		    event->params.peer_macaddr.bytes)) {
472*5113495bSYour Name 		osif_err("Failed to put mac_addr");
473*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
474*5113495bSYour Name 	}
475*5113495bSYour Name 
476*5113495bSYour Name 	nla_nest_end(reply_skb, config_attr);
477*5113495bSYour Name 
478*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
479*5113495bSYour Name }
480*5113495bSYour Name 
481*5113495bSYour Name /**
482*5113495bSYour Name  * twt_notify_status_to_vendor_twt_status() - convert from
483*5113495bSYour Name  * HOST_NOTIFY_TWT_STATUS to qca_wlan_vendor_twt_notify_status
484*5113495bSYour Name  * @status: HOST_TWT_NOTIFY_STATUS value from firmware
485*5113495bSYour Name  *
486*5113495bSYour Name  * Return: qca_wlan_vendor_twt_status values corresponding
487*5113495bSYour Name  * to the firmware failure status
488*5113495bSYour Name  */
489*5113495bSYour Name static enum qca_wlan_vendor_twt_status
twt_notify_status_to_vendor_twt_status(enum HOST_TWT_NOTIFY_STATUS status)490*5113495bSYour Name twt_notify_status_to_vendor_twt_status(enum HOST_TWT_NOTIFY_STATUS status)
491*5113495bSYour Name {
492*5113495bSYour Name 	switch (status) {
493*5113495bSYour Name 	case HOST_TWT_NOTIFY_EVENT_AP_TWT_REQ_BIT_SET:
494*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_TWT_REQUIRED;
495*5113495bSYour Name 	case HOST_TWT_NOTIFY_EVENT_AP_TWT_REQ_BIT_CLEAR:
496*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_REQUIRED;
497*5113495bSYour Name 	default:
498*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_REQUIRED;
499*5113495bSYour Name 	}
500*5113495bSYour Name }
501*5113495bSYour Name 
502*5113495bSYour Name /**
503*5113495bSYour Name  * osif_twt_notify_pack_nlmsg() - pack nlmsg response for TWT notify
504*5113495bSYour Name  * @reply_skb: pointer to the response skb structure
505*5113495bSYour Name  * @event: twt event buffer with firmware response
506*5113495bSYour Name  *
507*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes
508*5113495bSYour Name  * on failure
509*5113495bSYour Name  */
510*5113495bSYour Name static QDF_STATUS
osif_twt_notify_pack_nlmsg(struct sk_buff * reply_skb,struct twt_notify_event_param * event)511*5113495bSYour Name osif_twt_notify_pack_nlmsg(struct sk_buff *reply_skb,
512*5113495bSYour Name 			   struct twt_notify_event_param *event)
513*5113495bSYour Name {
514*5113495bSYour Name 	int attr;
515*5113495bSYour Name 	enum qca_wlan_vendor_twt_status vendor_status;
516*5113495bSYour Name 	enum qca_wlan_twt_operation twt_op;
517*5113495bSYour Name 
518*5113495bSYour Name 	if (event->status == HOST_TWT_NOTIFY_EVENT_READY)
519*5113495bSYour Name 		twt_op = QCA_WLAN_TWT_SETUP_READY_NOTIFY;
520*5113495bSYour Name 	else
521*5113495bSYour Name 		twt_op = QCA_WLAN_TWT_NOTIFY;
522*5113495bSYour Name 
523*5113495bSYour Name 	if (nla_put_u8(reply_skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
524*5113495bSYour Name 		       twt_op)) {
525*5113495bSYour Name 		osif_err("Failed to put TWT notify operation");
526*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
527*5113495bSYour Name 	}
528*5113495bSYour Name 
529*5113495bSYour Name 	if (event->status != HOST_TWT_NOTIFY_EVENT_READY) {
530*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_NOTIFY_STATUS;
531*5113495bSYour Name 		vendor_status = twt_notify_status_to_vendor_twt_status(
532*5113495bSYour Name 								event->status);
533*5113495bSYour Name 		if (nla_put_u8(reply_skb, attr, vendor_status)) {
534*5113495bSYour Name 			osif_err("Failed to put notify status");
535*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
536*5113495bSYour Name 		}
537*5113495bSYour Name 	}
538*5113495bSYour Name 
539*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
540*5113495bSYour Name }
541*5113495bSYour Name 
542*5113495bSYour Name /**
543*5113495bSYour Name  * osif_twt_teardown_pack_resp_nlmsg() - pack nlmsg response for teardown
544*5113495bSYour Name  * @reply_skb: pointer to the response skb structure
545*5113495bSYour Name  * @event: twt event buffer with firmware response
546*5113495bSYour Name  *
547*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes
548*5113495bSYour Name  * on failure
549*5113495bSYour Name  */
550*5113495bSYour Name static QDF_STATUS
osif_twt_teardown_pack_resp_nlmsg(struct sk_buff * reply_skb,struct twt_del_dialog_complete_event_param * event)551*5113495bSYour Name osif_twt_teardown_pack_resp_nlmsg(struct sk_buff *reply_skb,
552*5113495bSYour Name 			     struct twt_del_dialog_complete_event_param *event)
553*5113495bSYour Name {
554*5113495bSYour Name 	struct nlattr *config_attr;
555*5113495bSYour Name 	enum qca_wlan_vendor_twt_status vendor_status;
556*5113495bSYour Name 	int attr;
557*5113495bSYour Name 
558*5113495bSYour Name 	if (nla_put_u8(reply_skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
559*5113495bSYour Name 		       QCA_WLAN_TWT_TERMINATE)) {
560*5113495bSYour Name 		osif_err("Failed to put TWT operation");
561*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
562*5113495bSYour Name 	}
563*5113495bSYour Name 
564*5113495bSYour Name 	config_attr = nla_nest_start(reply_skb,
565*5113495bSYour Name 				     QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
566*5113495bSYour Name 	if (!config_attr) {
567*5113495bSYour Name 		osif_err("nla_nest_start error");
568*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
569*5113495bSYour Name 	}
570*5113495bSYour Name 
571*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID;
572*5113495bSYour Name 	if (nla_put_u8(reply_skb, attr, event->dialog_id)) {
573*5113495bSYour Name 		osif_debug("Failed to put dialog_id");
574*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
575*5113495bSYour Name 	}
576*5113495bSYour Name 
577*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS;
578*5113495bSYour Name 	vendor_status = twt_del_status_to_vendor_twt_status(event->status);
579*5113495bSYour Name 	if (nla_put_u8(reply_skb, attr, vendor_status)) {
580*5113495bSYour Name 		osif_err("Failed to put QCA_WLAN_TWT_TERMINATE");
581*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
582*5113495bSYour Name 	}
583*5113495bSYour Name 
584*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR;
585*5113495bSYour Name 	if (nla_put(reply_skb, attr, QDF_MAC_ADDR_SIZE,
586*5113495bSYour Name 		    event->peer_macaddr.bytes)) {
587*5113495bSYour Name 		osif_err("Failed to put mac_addr");
588*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
589*5113495bSYour Name 	}
590*5113495bSYour Name 
591*5113495bSYour Name 	nla_nest_end(reply_skb, config_attr);
592*5113495bSYour Name 
593*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
594*5113495bSYour Name }
595*5113495bSYour Name 
596*5113495bSYour Name /**
597*5113495bSYour Name  * osif_twt_resume_pack_resp_nlmsg() - pack the skb with
598*5113495bSYour Name  * firmware response for twt resume command
599*5113495bSYour Name  * @reply_skb: skb to store the response
600*5113495bSYour Name  * @event: Pointer to resume dialog complete event buffer
601*5113495bSYour Name  *
602*5113495bSYour Name  * Return: QDF_STATUS
603*5113495bSYour Name  */
604*5113495bSYour Name static QDF_STATUS
osif_twt_resume_pack_resp_nlmsg(struct sk_buff * reply_skb,struct twt_resume_dialog_complete_event_param * event)605*5113495bSYour Name osif_twt_resume_pack_resp_nlmsg(struct sk_buff *reply_skb,
606*5113495bSYour Name 			   struct twt_resume_dialog_complete_event_param *event)
607*5113495bSYour Name {
608*5113495bSYour Name 	struct nlattr *config_attr;
609*5113495bSYour Name 	int vendor_status, attr;
610*5113495bSYour Name 
611*5113495bSYour Name 	if (nla_put_u8(reply_skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
612*5113495bSYour Name 		       QCA_WLAN_TWT_RESUME)) {
613*5113495bSYour Name 		osif_err("Failed to put TWT operation");
614*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
615*5113495bSYour Name 	}
616*5113495bSYour Name 
617*5113495bSYour Name 	config_attr = nla_nest_start(reply_skb,
618*5113495bSYour Name 				     QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
619*5113495bSYour Name 	if (!config_attr) {
620*5113495bSYour Name 		osif_err("nla_nest_start error");
621*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
622*5113495bSYour Name 	}
623*5113495bSYour Name 
624*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID;
625*5113495bSYour Name 	if (nla_put_u8(reply_skb, attr, event->dialog_id)) {
626*5113495bSYour Name 		osif_debug("Failed to put dialog_id");
627*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
628*5113495bSYour Name 	}
629*5113495bSYour Name 
630*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS;
631*5113495bSYour Name 	vendor_status = twt_resume_status_to_vendor_twt_status(event->status);
632*5113495bSYour Name 	if (nla_put_u8(reply_skb, attr, vendor_status)) {
633*5113495bSYour Name 		osif_err("Failed to put QCA_WLAN_TWT_RESUME status");
634*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
635*5113495bSYour Name 	}
636*5113495bSYour Name 
637*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAC_ADDR;
638*5113495bSYour Name 	if (nla_put(reply_skb, attr, QDF_MAC_ADDR_SIZE,
639*5113495bSYour Name 		    event->peer_macaddr.bytes)) {
640*5113495bSYour Name 		osif_err("Failed to put mac_addr");
641*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
642*5113495bSYour Name 	}
643*5113495bSYour Name 
644*5113495bSYour Name 	nla_nest_end(reply_skb, config_attr);
645*5113495bSYour Name 
646*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
647*5113495bSYour Name }
648*5113495bSYour Name 
649*5113495bSYour Name /**
650*5113495bSYour Name  * osif_twt_nudge_pack_resp_nlmsg() - pack the skb with
651*5113495bSYour Name  * firmware response for twt nudge command
652*5113495bSYour Name  * @reply_skb: skb to store the response
653*5113495bSYour Name  * @event: Pointer to nudge dialog complete event buffer
654*5113495bSYour Name  *
655*5113495bSYour Name  * Return: QDF_STATUS
656*5113495bSYour Name  */
657*5113495bSYour Name static QDF_STATUS
osif_twt_nudge_pack_resp_nlmsg(struct sk_buff * reply_skb,struct twt_nudge_dialog_complete_event_param * event)658*5113495bSYour Name osif_twt_nudge_pack_resp_nlmsg(struct sk_buff *reply_skb,
659*5113495bSYour Name 			      struct twt_nudge_dialog_complete_event_param *event)
660*5113495bSYour Name {
661*5113495bSYour Name 	struct nlattr *config_attr;
662*5113495bSYour Name 	int vendor_status, attr;
663*5113495bSYour Name 	uint64_t tsf_val;
664*5113495bSYour Name 
665*5113495bSYour Name 	if (nla_put_u8(reply_skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
666*5113495bSYour Name 		       QCA_WLAN_TWT_NUDGE)) {
667*5113495bSYour Name 		osif_err("Failed to put TWT operation");
668*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
669*5113495bSYour Name 	}
670*5113495bSYour Name 
671*5113495bSYour Name 	config_attr = nla_nest_start(reply_skb,
672*5113495bSYour Name 				     QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
673*5113495bSYour Name 	if (!config_attr) {
674*5113495bSYour Name 		osif_err("nla_nest_start error");
675*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
676*5113495bSYour Name 	}
677*5113495bSYour Name 
678*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID;
679*5113495bSYour Name 	if (nla_put_u8(reply_skb, attr, event->dialog_id)) {
680*5113495bSYour Name 		osif_debug("Failed to put dialog_id");
681*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
682*5113495bSYour Name 	}
683*5113495bSYour Name 
684*5113495bSYour Name 	tsf_val = event->next_twt_tsf_us_hi;
685*5113495bSYour Name 	tsf_val = (tsf_val << 32) | event->next_twt_tsf_us_lo;
686*5113495bSYour Name 	if (wlan_cfg80211_nla_put_u64(reply_skb,
687*5113495bSYour Name 				 QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME_TSF,
688*5113495bSYour Name 				 tsf_val)) {
689*5113495bSYour Name 		osif_err("get_params failed to put TSF Value");
690*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
691*5113495bSYour Name 	}
692*5113495bSYour Name 
693*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS;
694*5113495bSYour Name 	vendor_status = twt_nudge_status_to_vendor_twt_status(event->status);
695*5113495bSYour Name 	if (nla_put_u8(reply_skb, attr, vendor_status)) {
696*5113495bSYour Name 		osif_err("Failed to put QCA_WLAN_TWT_NUDGE status");
697*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
698*5113495bSYour Name 	}
699*5113495bSYour Name 
700*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR;
701*5113495bSYour Name 	if (nla_put(reply_skb, attr, QDF_MAC_ADDR_SIZE,
702*5113495bSYour Name 		    event->peer_macaddr.bytes)) {
703*5113495bSYour Name 		osif_err("Failed to put mac_addr");
704*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
705*5113495bSYour Name 	}
706*5113495bSYour Name 
707*5113495bSYour Name 	nla_nest_end(reply_skb, config_attr);
708*5113495bSYour Name 
709*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
710*5113495bSYour Name }
711*5113495bSYour Name 
712*5113495bSYour Name QDF_STATUS
osif_twt_send_get_capabilities_response(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev)713*5113495bSYour Name osif_twt_send_get_capabilities_response(struct wlan_objmgr_psoc *psoc,
714*5113495bSYour Name 					struct wlan_objmgr_vdev *vdev)
715*5113495bSYour Name {
716*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
717*5113495bSYour Name 	struct nlattr *config_attr;
718*5113495bSYour Name 	struct sk_buff *reply_skb;
719*5113495bSYour Name 	size_t skb_len = NLMSG_HDRLEN;
720*5113495bSYour Name 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
721*5113495bSYour Name 	enum band_info connected_band;
722*5113495bSYour Name 	uint8_t peer_cap = 0, self_cap = 0;
723*5113495bSYour Name 	bool twt_req = false, twt_bcast_req = false;
724*5113495bSYour Name 	bool is_twt_24ghz_allowed = true, val;
725*5113495bSYour Name 	struct qdf_mac_addr peer_mac;
726*5113495bSYour Name 	int ret;
727*5113495bSYour Name 
728*5113495bSYour Name 	/*
729*5113495bSYour Name 	 * Userspace will query the TWT get capabilities before
730*5113495bSYour Name 	 * issuing a get capabilities request. If the STA is
731*5113495bSYour Name 	 * connected, then check the "enable_twt_24ghz" ini
732*5113495bSYour Name 	 * value to advertise the TWT requestor capability.
733*5113495bSYour Name 	 */
734*5113495bSYour Name 	connected_band = ucfg_cm_get_connected_band(vdev);
735*5113495bSYour Name 	ucfg_twt_cfg_get_24ghz_enabled(psoc, &val);
736*5113495bSYour Name 
737*5113495bSYour Name 	osif_debug("connected_band: %d val: %d", connected_band, val);
738*5113495bSYour Name 	if (connected_band == BAND_2G && !val)
739*5113495bSYour Name 		is_twt_24ghz_allowed = false;
740*5113495bSYour Name 
741*5113495bSYour Name 	/* fill the self_capability bitmap  */
742*5113495bSYour Name 	ucfg_twt_cfg_get_requestor(psoc, &twt_req);
743*5113495bSYour Name 	osif_debug("is_twt_24ghz_allowed: %d twt_req: %d",
744*5113495bSYour Name 		   is_twt_24ghz_allowed, twt_req);
745*5113495bSYour Name 	if (twt_req && is_twt_24ghz_allowed)
746*5113495bSYour Name 		self_cap |= QCA_WLAN_TWT_CAPA_REQUESTOR;
747*5113495bSYour Name 
748*5113495bSYour Name 	ucfg_twt_cfg_get_bcast_requestor(psoc, &twt_bcast_req);
749*5113495bSYour Name 	osif_debug("twt_bcast_req: %d", twt_bcast_req);
750*5113495bSYour Name 	self_cap |= (twt_bcast_req ? QCA_WLAN_TWT_CAPA_BROADCAST : 0);
751*5113495bSYour Name 
752*5113495bSYour Name 	ucfg_twt_cfg_get_flex_sched(psoc, &val);
753*5113495bSYour Name 	osif_debug("flex sched: %d", val);
754*5113495bSYour Name 	if (val)
755*5113495bSYour Name 		self_cap |= QCA_WLAN_TWT_CAPA_FLEXIBLE;
756*5113495bSYour Name 
757*5113495bSYour Name 	ret = osif_fill_peer_macaddr(vdev, peer_mac.bytes);
758*5113495bSYour Name 	if (ret)
759*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
760*5113495bSYour Name 
761*5113495bSYour Name 	qdf_status = ucfg_twt_get_peer_capabilities(psoc, &peer_mac, &peer_cap);
762*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(qdf_status))
763*5113495bSYour Name 		return qdf_status;
764*5113495bSYour Name 
765*5113495bSYour Name 	osif_debug("self_cap: 0x%x peer_cap: 0x%x", self_cap, peer_cap);
766*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
767*5113495bSYour Name 	/*
768*5113495bSYour Name 	 * Length of attribute QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF &
769*5113495bSYour Name 	 * QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER
770*5113495bSYour Name 	 */
771*5113495bSYour Name 	skb_len += 2 * nla_total_size(sizeof(u16)) + NLA_HDRLEN;
772*5113495bSYour Name 
773*5113495bSYour Name 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(
774*5113495bSYour Name 							osif_priv->wdev->wiphy,
775*5113495bSYour Name 							skb_len);
776*5113495bSYour Name 	if (!reply_skb) {
777*5113495bSYour Name 		osif_err("TWT: get_caps alloc reply skb failed");
778*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
779*5113495bSYour Name 	}
780*5113495bSYour Name 
781*5113495bSYour Name 	config_attr = nla_nest_start(reply_skb,
782*5113495bSYour Name 				     QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
783*5113495bSYour Name 	if (!config_attr) {
784*5113495bSYour Name 		osif_err("TWT: nla_nest_start error");
785*5113495bSYour Name 		qdf_status = QDF_STATUS_E_FAILURE;
786*5113495bSYour Name 		goto free_skb;
787*5113495bSYour Name 	}
788*5113495bSYour Name 
789*5113495bSYour Name 	if (nla_put_u16(reply_skb, QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF,
790*5113495bSYour Name 	    self_cap)) {
791*5113495bSYour Name 		osif_err("TWT: Failed to fill capabilities");
792*5113495bSYour Name 		qdf_status = QDF_STATUS_E_FAILURE;
793*5113495bSYour Name 		goto free_skb;
794*5113495bSYour Name 	}
795*5113495bSYour Name 
796*5113495bSYour Name 	if (nla_put_u16(reply_skb, QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER,
797*5113495bSYour Name 	    peer_cap)) {
798*5113495bSYour Name 		osif_err("TWT: Failed to fill capabilities");
799*5113495bSYour Name 		qdf_status = QDF_STATUS_E_FAILURE;
800*5113495bSYour Name 		goto free_skb;
801*5113495bSYour Name 	}
802*5113495bSYour Name 
803*5113495bSYour Name 	nla_nest_end(reply_skb, config_attr);
804*5113495bSYour Name 
805*5113495bSYour Name 	if (wlan_cfg80211_vendor_cmd_reply(reply_skb))
806*5113495bSYour Name 		qdf_status = QDF_STATUS_E_INVAL;
807*5113495bSYour Name 	return qdf_status;
808*5113495bSYour Name 
809*5113495bSYour Name free_skb:
810*5113495bSYour Name 	wlan_cfg80211_vendor_free_skb(reply_skb);
811*5113495bSYour Name 	return qdf_status;
812*5113495bSYour Name }
813*5113495bSYour Name 
814*5113495bSYour Name static void
osif_twt_setup_response(struct wlan_objmgr_psoc * psoc,struct twt_add_dialog_complete_event * event)815*5113495bSYour Name osif_twt_setup_response(struct wlan_objmgr_psoc *psoc,
816*5113495bSYour Name 			struct twt_add_dialog_complete_event *event)
817*5113495bSYour Name {
818*5113495bSYour Name 	struct sk_buff *twt_vendor_event;
819*5113495bSYour Name 	struct wireless_dev *wdev;
820*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
821*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
822*5113495bSYour Name 	size_t data_len;
823*5113495bSYour Name 	QDF_STATUS status;
824*5113495bSYour Name 	bool additional_params_present = false;
825*5113495bSYour Name 
826*5113495bSYour Name 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
827*5113495bSYour Name 						event->params.vdev_id,
828*5113495bSYour Name 						WLAN_TWT_ID);
829*5113495bSYour Name 	if (!vdev) {
830*5113495bSYour Name 		osif_err("vdev is null");
831*5113495bSYour Name 		return;
832*5113495bSYour Name 	}
833*5113495bSYour Name 
834*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
835*5113495bSYour Name 	if (!osif_priv) {
836*5113495bSYour Name 		osif_err("osif_priv is null");
837*5113495bSYour Name 		goto fail;
838*5113495bSYour Name 	}
839*5113495bSYour Name 
840*5113495bSYour Name 	wdev = osif_priv->wdev;
841*5113495bSYour Name 	if (!wdev) {
842*5113495bSYour Name 		osif_err("wireless dev is null");
843*5113495bSYour Name 		goto fail;
844*5113495bSYour Name 	}
845*5113495bSYour Name 
846*5113495bSYour Name 	if (event->params.num_additional_twt_params != 0)
847*5113495bSYour Name 		additional_params_present = true;
848*5113495bSYour Name 
849*5113495bSYour Name 	data_len = osif_twt_get_setup_event_len(additional_params_present);
850*5113495bSYour Name 	twt_vendor_event = wlan_cfg80211_vendor_event_alloc(
851*5113495bSYour Name 				wdev->wiphy, wdev, data_len,
852*5113495bSYour Name 				QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT_INDEX,
853*5113495bSYour Name 				GFP_KERNEL);
854*5113495bSYour Name 	if (!twt_vendor_event) {
855*5113495bSYour Name 		osif_err("TWT: Alloc setup resp skb fail");
856*5113495bSYour Name 		goto fail;
857*5113495bSYour Name 	}
858*5113495bSYour Name 
859*5113495bSYour Name 	status = osif_twt_setup_pack_resp_nlmsg(twt_vendor_event, event);
860*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
861*5113495bSYour Name 		osif_err("Failed to pack nl add dialog response");
862*5113495bSYour Name 		wlan_cfg80211_vendor_free_skb(twt_vendor_event);
863*5113495bSYour Name 		goto fail;
864*5113495bSYour Name 	}
865*5113495bSYour Name 
866*5113495bSYour Name 	wlan_cfg80211_vendor_event(twt_vendor_event, GFP_KERNEL);
867*5113495bSYour Name 
868*5113495bSYour Name fail:
869*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
870*5113495bSYour Name }
871*5113495bSYour Name 
872*5113495bSYour Name static void
osif_twt_teardown_response(struct wlan_objmgr_psoc * psoc,struct twt_del_dialog_complete_event_param * event)873*5113495bSYour Name osif_twt_teardown_response(struct wlan_objmgr_psoc *psoc,
874*5113495bSYour Name 			   struct twt_del_dialog_complete_event_param *event)
875*5113495bSYour Name {
876*5113495bSYour Name 	struct sk_buff *twt_vendor_event;
877*5113495bSYour Name 	struct wireless_dev *wdev;
878*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
879*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
880*5113495bSYour Name 	size_t data_len;
881*5113495bSYour Name 	QDF_STATUS status;
882*5113495bSYour Name 
883*5113495bSYour Name 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
884*5113495bSYour Name 						event->vdev_id, WLAN_TWT_ID);
885*5113495bSYour Name 	if (!vdev) {
886*5113495bSYour Name 		osif_err("vdev is null");
887*5113495bSYour Name 		return;
888*5113495bSYour Name 	}
889*5113495bSYour Name 
890*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
891*5113495bSYour Name 	if (!osif_priv) {
892*5113495bSYour Name 		osif_err("osif_priv is null");
893*5113495bSYour Name 		goto fail;
894*5113495bSYour Name 	}
895*5113495bSYour Name 
896*5113495bSYour Name 	wdev = osif_priv->wdev;
897*5113495bSYour Name 	if (!wdev) {
898*5113495bSYour Name 		osif_err("wireless dev is null");
899*5113495bSYour Name 		goto fail;
900*5113495bSYour Name 	}
901*5113495bSYour Name 
902*5113495bSYour Name 	data_len = osif_twt_get_event_len() + nla_total_size(sizeof(u8));
903*5113495bSYour Name 	data_len += NLA_HDRLEN;
904*5113495bSYour Name 	twt_vendor_event = wlan_cfg80211_vendor_event_alloc(
905*5113495bSYour Name 				wdev->wiphy, wdev, data_len,
906*5113495bSYour Name 				QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT_INDEX,
907*5113495bSYour Name 				GFP_KERNEL);
908*5113495bSYour Name 	if (!twt_vendor_event) {
909*5113495bSYour Name 		osif_err("TWT: Alloc teardown resp skb fail");
910*5113495bSYour Name 		goto fail;
911*5113495bSYour Name 	}
912*5113495bSYour Name 
913*5113495bSYour Name 	status = osif_twt_teardown_pack_resp_nlmsg(twt_vendor_event, event);
914*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
915*5113495bSYour Name 		osif_err("Failed to pack nl del dialog response");
916*5113495bSYour Name 		wlan_cfg80211_vendor_free_skb(twt_vendor_event);
917*5113495bSYour Name 		goto fail;
918*5113495bSYour Name 	}
919*5113495bSYour Name 
920*5113495bSYour Name 	wlan_cfg80211_vendor_event(twt_vendor_event, GFP_KERNEL);
921*5113495bSYour Name 
922*5113495bSYour Name fail:
923*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
924*5113495bSYour Name }
925*5113495bSYour Name 
926*5113495bSYour Name QDF_STATUS
osif_twt_setup_complete_cb(struct wlan_objmgr_psoc * psoc,struct twt_add_dialog_complete_event * event,bool renego_fail)927*5113495bSYour Name osif_twt_setup_complete_cb(struct wlan_objmgr_psoc *psoc,
928*5113495bSYour Name 			   struct twt_add_dialog_complete_event *event,
929*5113495bSYour Name 			   bool renego_fail)
930*5113495bSYour Name {
931*5113495bSYour Name 	uint32_t vdev_id = event->params.vdev_id;
932*5113495bSYour Name 
933*5113495bSYour Name 	osif_debug("TWT: add dialog_id:%d, status:%d vdev_id:%d renego_fail:%d peer mac_addr "
934*5113495bSYour Name 		  QDF_MAC_ADDR_FMT, event->params.dialog_id,
935*5113495bSYour Name 		  event->params.status, vdev_id, renego_fail,
936*5113495bSYour Name 		  QDF_MAC_ADDR_REF(event->params.peer_macaddr.bytes));
937*5113495bSYour Name 
938*5113495bSYour Name 	osif_twt_setup_response(psoc, event);
939*5113495bSYour Name 
940*5113495bSYour Name 	if (renego_fail)
941*5113495bSYour Name 		osif_twt_handle_renego_failure(psoc, event);
942*5113495bSYour Name 
943*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
944*5113495bSYour Name }
945*5113495bSYour Name 
946*5113495bSYour Name QDF_STATUS
osif_twt_teardown_complete_cb(struct wlan_objmgr_psoc * psoc,struct twt_del_dialog_complete_event_param * event)947*5113495bSYour Name osif_twt_teardown_complete_cb(struct wlan_objmgr_psoc *psoc,
948*5113495bSYour Name 			      struct twt_del_dialog_complete_event_param *event)
949*5113495bSYour Name {
950*5113495bSYour Name 	uint32_t vdev_id = event->vdev_id;
951*5113495bSYour Name 
952*5113495bSYour Name 	osif_debug("TWT: del dialog_id:%d status:%d vdev_id:%d peer mac_addr "
953*5113495bSYour Name 		  QDF_MAC_ADDR_FMT, event->dialog_id,
954*5113495bSYour Name 		  event->status, vdev_id,
955*5113495bSYour Name 		  QDF_MAC_ADDR_REF(event->peer_macaddr.bytes));
956*5113495bSYour Name 
957*5113495bSYour Name 	osif_twt_teardown_response(psoc, event);
958*5113495bSYour Name 
959*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
960*5113495bSYour Name }
961*5113495bSYour Name 
962*5113495bSYour Name QDF_STATUS
osif_twt_resume_complete_cb(struct wlan_objmgr_psoc * psoc,struct twt_resume_dialog_complete_event_param * event)963*5113495bSYour Name osif_twt_resume_complete_cb(struct wlan_objmgr_psoc *psoc,
964*5113495bSYour Name 			   struct twt_resume_dialog_complete_event_param *event)
965*5113495bSYour Name {
966*5113495bSYour Name 	struct wireless_dev *wdev;
967*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
968*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
969*5113495bSYour Name 	uint32_t vdev_id = event->vdev_id;
970*5113495bSYour Name 	struct sk_buff *twt_vendor_event;
971*5113495bSYour Name 	size_t data_len;
972*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
973*5113495bSYour Name 
974*5113495bSYour Name 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, event->vdev_id,
975*5113495bSYour Name 						    WLAN_TWT_ID);
976*5113495bSYour Name 	if (!vdev) {
977*5113495bSYour Name 		osif_err("vdev is null");
978*5113495bSYour Name 		return status;
979*5113495bSYour Name 	}
980*5113495bSYour Name 
981*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
982*5113495bSYour Name 	if (!osif_priv) {
983*5113495bSYour Name 		osif_err("osif_priv is null");
984*5113495bSYour Name 		goto fail;
985*5113495bSYour Name 	}
986*5113495bSYour Name 
987*5113495bSYour Name 	wdev = osif_priv->wdev;
988*5113495bSYour Name 	if (!wdev) {
989*5113495bSYour Name 		osif_err("wireless dev is null");
990*5113495bSYour Name 		goto fail;
991*5113495bSYour Name 	}
992*5113495bSYour Name 
993*5113495bSYour Name 	osif_debug("TWT: resume dialog_id:%d status:%d vdev_id:%d peer macaddr "
994*5113495bSYour Name 		   QDF_MAC_ADDR_FMT, event->dialog_id,
995*5113495bSYour Name 		   event->status, vdev_id,
996*5113495bSYour Name 		   QDF_MAC_ADDR_REF(event->peer_macaddr.bytes));
997*5113495bSYour Name 
998*5113495bSYour Name 	data_len = osif_twt_get_event_len() + nla_total_size(sizeof(u8));
999*5113495bSYour Name 	data_len += NLA_HDRLEN;
1000*5113495bSYour Name 
1001*5113495bSYour Name 	twt_vendor_event = wlan_cfg80211_vendor_event_alloc(
1002*5113495bSYour Name 				wdev->wiphy, wdev, data_len,
1003*5113495bSYour Name 				QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT_INDEX,
1004*5113495bSYour Name 				GFP_KERNEL);
1005*5113495bSYour Name 	if (!twt_vendor_event) {
1006*5113495bSYour Name 		osif_err("TWT: Alloc resume resp skb fail");
1007*5113495bSYour Name 		goto fail;
1008*5113495bSYour Name 	}
1009*5113495bSYour Name 
1010*5113495bSYour Name 	status = osif_twt_resume_pack_resp_nlmsg(twt_vendor_event, event);
1011*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
1012*5113495bSYour Name 		osif_err("Failed to pack nl resume dialog response");
1013*5113495bSYour Name 		wlan_cfg80211_vendor_free_skb(twt_vendor_event);
1014*5113495bSYour Name 		goto fail;
1015*5113495bSYour Name 	}
1016*5113495bSYour Name 	wlan_cfg80211_vendor_event(twt_vendor_event, GFP_KERNEL);
1017*5113495bSYour Name 
1018*5113495bSYour Name fail:
1019*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
1020*5113495bSYour Name 	return status;
1021*5113495bSYour Name }
1022*5113495bSYour Name 
1023*5113495bSYour Name QDF_STATUS
osif_twt_nudge_complete_cb(struct wlan_objmgr_psoc * psoc,struct twt_nudge_dialog_complete_event_param * event)1024*5113495bSYour Name osif_twt_nudge_complete_cb(struct wlan_objmgr_psoc *psoc,
1025*5113495bSYour Name 			   struct twt_nudge_dialog_complete_event_param *event)
1026*5113495bSYour Name {
1027*5113495bSYour Name 	struct wireless_dev *wdev;
1028*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
1029*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1030*5113495bSYour Name 	uint32_t vdev_id = event->vdev_id;
1031*5113495bSYour Name 	struct sk_buff *twt_vendor_event;
1032*5113495bSYour Name 	size_t data_len;
1033*5113495bSYour Name 	QDF_STATUS  status = QDF_STATUS_E_FAILURE;
1034*5113495bSYour Name 
1035*5113495bSYour Name 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, event->vdev_id,
1036*5113495bSYour Name 						    WLAN_TWT_ID);
1037*5113495bSYour Name 	if (!vdev) {
1038*5113495bSYour Name 		osif_err("vdev is null");
1039*5113495bSYour Name 		return status;
1040*5113495bSYour Name 	}
1041*5113495bSYour Name 
1042*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
1043*5113495bSYour Name 	if (!osif_priv) {
1044*5113495bSYour Name 		osif_err("osif_priv is null");
1045*5113495bSYour Name 		goto fail;
1046*5113495bSYour Name 	}
1047*5113495bSYour Name 
1048*5113495bSYour Name 	wdev = osif_priv->wdev;
1049*5113495bSYour Name 	if (!wdev) {
1050*5113495bSYour Name 		osif_err("wireless dev is null");
1051*5113495bSYour Name 		goto fail;
1052*5113495bSYour Name 	}
1053*5113495bSYour Name 
1054*5113495bSYour Name 	osif_debug("TWT: nudge dialog_id:%d status:%d vdev_id:%d peer macaddr "
1055*5113495bSYour Name 		   QDF_MAC_ADDR_FMT, event->dialog_id,
1056*5113495bSYour Name 		   event->status, vdev_id,
1057*5113495bSYour Name 		   QDF_MAC_ADDR_REF(event->peer_macaddr.bytes));
1058*5113495bSYour Name 
1059*5113495bSYour Name 	data_len = osif_twt_get_event_len() + nla_total_size(sizeof(u8)) +
1060*5113495bSYour Name 		   nla_total_size(sizeof(u64));
1061*5113495bSYour Name 	data_len += NLA_HDRLEN;
1062*5113495bSYour Name 
1063*5113495bSYour Name 	twt_vendor_event = wlan_cfg80211_vendor_event_alloc(
1064*5113495bSYour Name 				wdev->wiphy, wdev, data_len,
1065*5113495bSYour Name 				QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT_INDEX,
1066*5113495bSYour Name 				GFP_KERNEL);
1067*5113495bSYour Name 	if (!twt_vendor_event) {
1068*5113495bSYour Name 		osif_err("TWT: Alloc nudge resp skb fail");
1069*5113495bSYour Name 		goto fail;
1070*5113495bSYour Name 	}
1071*5113495bSYour Name 
1072*5113495bSYour Name 	status = osif_twt_nudge_pack_resp_nlmsg(twt_vendor_event, event);
1073*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
1074*5113495bSYour Name 		osif_err("Failed to pack nl add dialog response");
1075*5113495bSYour Name 		wlan_cfg80211_vendor_free_skb(twt_vendor_event);
1076*5113495bSYour Name 		goto fail;
1077*5113495bSYour Name 	}
1078*5113495bSYour Name 	wlan_cfg80211_vendor_event(twt_vendor_event, GFP_KERNEL);
1079*5113495bSYour Name 
1080*5113495bSYour Name fail:
1081*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
1082*5113495bSYour Name 	return status;
1083*5113495bSYour Name 
1084*5113495bSYour Name }
1085*5113495bSYour Name 
1086*5113495bSYour Name /**
1087*5113495bSYour Name  * osif_twt_get_notify_event_len() - calculates the length of twt
1088*5113495bSYour Name  * notify nl response
1089*5113495bSYour Name  *
1090*5113495bSYour Name  * Return: Length of twt notify nl response
1091*5113495bSYour Name  */
1092*5113495bSYour Name static
osif_twt_get_notify_event_len(void)1093*5113495bSYour Name uint32_t osif_twt_get_notify_event_len(void)
1094*5113495bSYour Name {
1095*5113495bSYour Name 	uint32_t len = 0;
1096*5113495bSYour Name 
1097*5113495bSYour Name 	len += NLMSG_HDRLEN;
1098*5113495bSYour Name 
1099*5113495bSYour Name 	/* QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION */
1100*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
1101*5113495bSYour Name 
1102*5113495bSYour Name 	/* QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_NOTIFY_STATUS */
1103*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
1104*5113495bSYour Name 
1105*5113495bSYour Name 	return len;
1106*5113495bSYour Name }
1107*5113495bSYour Name 
1108*5113495bSYour Name QDF_STATUS
osif_twt_notify_complete_cb(struct wlan_objmgr_psoc * psoc,struct twt_notify_event_param * event)1109*5113495bSYour Name osif_twt_notify_complete_cb(struct wlan_objmgr_psoc *psoc,
1110*5113495bSYour Name 			    struct twt_notify_event_param *event)
1111*5113495bSYour Name {
1112*5113495bSYour Name 	struct wireless_dev *wdev;
1113*5113495bSYour Name 	struct sk_buff *twt_vendor_event;
1114*5113495bSYour Name 	size_t data_len;
1115*5113495bSYour Name 	QDF_STATUS status;
1116*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
1117*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1118*5113495bSYour Name 
1119*5113495bSYour Name 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, event->vdev_id,
1120*5113495bSYour Name 						    WLAN_TWT_ID);
1121*5113495bSYour Name 	if (!vdev) {
1122*5113495bSYour Name 		osif_err("vdev is null");
1123*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1124*5113495bSYour Name 	}
1125*5113495bSYour Name 
1126*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
1127*5113495bSYour Name 	if (!osif_priv) {
1128*5113495bSYour Name 		osif_err("osif_priv is null");
1129*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
1130*5113495bSYour Name 		goto end;
1131*5113495bSYour Name 	}
1132*5113495bSYour Name 
1133*5113495bSYour Name 	wdev = osif_priv->wdev;
1134*5113495bSYour Name 	if (!wdev) {
1135*5113495bSYour Name 		osif_err("wireless dev is null");
1136*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
1137*5113495bSYour Name 		goto end;
1138*5113495bSYour Name 	}
1139*5113495bSYour Name 
1140*5113495bSYour Name 	data_len = osif_twt_get_notify_event_len();
1141*5113495bSYour Name 	data_len += NLA_HDRLEN;
1142*5113495bSYour Name 
1143*5113495bSYour Name 	twt_vendor_event = wlan_cfg80211_vendor_event_alloc(
1144*5113495bSYour Name 				wdev->wiphy, wdev, data_len,
1145*5113495bSYour Name 				QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT_INDEX,
1146*5113495bSYour Name 				GFP_KERNEL);
1147*5113495bSYour Name 	if (!twt_vendor_event) {
1148*5113495bSYour Name 		osif_err("Notify skb alloc failed");
1149*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
1150*5113495bSYour Name 		goto end;
1151*5113495bSYour Name 	}
1152*5113495bSYour Name 
1153*5113495bSYour Name 	osif_debug("TWT: twt Notify vdev_id: %d, status: %d", event->vdev_id,
1154*5113495bSYour Name 		   event->status);
1155*5113495bSYour Name 
1156*5113495bSYour Name 	status = osif_twt_notify_pack_nlmsg(twt_vendor_event, event);
1157*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
1158*5113495bSYour Name 		osif_err("Failed to pack nl notify event");
1159*5113495bSYour Name 		wlan_cfg80211_vendor_free_skb(twt_vendor_event);
1160*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
1161*5113495bSYour Name 		goto end;
1162*5113495bSYour Name 	}
1163*5113495bSYour Name 
1164*5113495bSYour Name 	wlan_cfg80211_vendor_event(twt_vendor_event, GFP_KERNEL);
1165*5113495bSYour Name 	status = QDF_STATUS_SUCCESS;
1166*5113495bSYour Name 
1167*5113495bSYour Name end:
1168*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
1169*5113495bSYour Name 	return status;
1170*5113495bSYour Name }
1171*5113495bSYour Name 
1172*5113495bSYour Name /**
1173*5113495bSYour Name  * twt_pause_status_to_vendor_twt_status() - convert from
1174*5113495bSYour Name  * HOST_TWT_PAUSE_STATUS to qca_wlan_vendor_twt_status
1175*5113495bSYour Name  * @status: HOST_TWT_PAUSE_STATUS value from firmware
1176*5113495bSYour Name  *
1177*5113495bSYour Name  * Return: qca_wlan_vendor_twt_status values corresponding
1178*5113495bSYour Name  * to the firmware failure status
1179*5113495bSYour Name  */
1180*5113495bSYour Name static int
twt_pause_status_to_vendor_twt_status(enum HOST_TWT_PAUSE_STATUS status)1181*5113495bSYour Name twt_pause_status_to_vendor_twt_status(enum HOST_TWT_PAUSE_STATUS status)
1182*5113495bSYour Name {
1183*5113495bSYour Name 	switch (status) {
1184*5113495bSYour Name 	case HOST_TWT_PAUSE_STATUS_OK:
1185*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_OK;
1186*5113495bSYour Name 	case HOST_TWT_PAUSE_STATUS_DIALOG_ID_NOT_EXIST:
1187*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST;
1188*5113495bSYour Name 	case HOST_TWT_PAUSE_STATUS_INVALID_PARAM:
1189*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM;
1190*5113495bSYour Name 	case HOST_TWT_PAUSE_STATUS_DIALOG_ID_BUSY:
1191*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_SESSION_BUSY;
1192*5113495bSYour Name 	case HOST_TWT_PAUSE_STATUS_ALREADY_PAUSED:
1193*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED;
1194*5113495bSYour Name 	case HOST_TWT_PAUSE_STATUS_NO_RESOURCE:
1195*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE;
1196*5113495bSYour Name 	case HOST_TWT_PAUSE_STATUS_NO_ACK:
1197*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK;
1198*5113495bSYour Name 	case HOST_TWT_PAUSE_STATUS_UNKNOWN_ERROR:
1199*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR;
1200*5113495bSYour Name 	case HOST_TWT_PAUSE_STATUS_CHAN_SW_IN_PROGRESS:
1201*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS;
1202*5113495bSYour Name 	case HOST_TWT_PAUSE_STATUS_ROAM_IN_PROGRESS:
1203*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS;
1204*5113495bSYour Name 	default:
1205*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR;
1206*5113495bSYour Name 	}
1207*5113495bSYour Name }
1208*5113495bSYour Name 
1209*5113495bSYour Name /**
1210*5113495bSYour Name  * osif_twt_pause_pack_resp_nlmsg() - pack the skb with
1211*5113495bSYour Name  * firmware response for twt pause command
1212*5113495bSYour Name  * @reply_skb: skb to store the response
1213*5113495bSYour Name  * @event: Pointer to pause dialog complete event buffer
1214*5113495bSYour Name  *
1215*5113495bSYour Name  * Return: QDF_STATUS
1216*5113495bSYour Name  */
1217*5113495bSYour Name static QDF_STATUS
osif_twt_pause_pack_resp_nlmsg(struct sk_buff * reply_skb,struct twt_pause_dialog_complete_event_param * event)1218*5113495bSYour Name osif_twt_pause_pack_resp_nlmsg(struct sk_buff *reply_skb,
1219*5113495bSYour Name 			struct twt_pause_dialog_complete_event_param *event)
1220*5113495bSYour Name {
1221*5113495bSYour Name 	struct nlattr *config_attr;
1222*5113495bSYour Name 	int vendor_status, attr;
1223*5113495bSYour Name 
1224*5113495bSYour Name 	if (nla_put_u8(reply_skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION,
1225*5113495bSYour Name 		       QCA_WLAN_TWT_SUSPEND)) {
1226*5113495bSYour Name 		osif_err("Failed to put TWT operation");
1227*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1228*5113495bSYour Name 	}
1229*5113495bSYour Name 
1230*5113495bSYour Name 	config_attr = nla_nest_start(reply_skb,
1231*5113495bSYour Name 				     QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
1232*5113495bSYour Name 	if (!config_attr) {
1233*5113495bSYour Name 		osif_err("nla_nest_start error");
1234*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1235*5113495bSYour Name 	}
1236*5113495bSYour Name 
1237*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID;
1238*5113495bSYour Name 	if (nla_put_u8(reply_skb, attr, event->dialog_id)) {
1239*5113495bSYour Name 		osif_debug("Failed to put dialog_id");
1240*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1241*5113495bSYour Name 	}
1242*5113495bSYour Name 
1243*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS;
1244*5113495bSYour Name 	vendor_status = twt_pause_status_to_vendor_twt_status(event->status);
1245*5113495bSYour Name 	if (nla_put_u8(reply_skb, attr, vendor_status)) {
1246*5113495bSYour Name 		osif_err("Failed to put QCA_WLAN_TWT_PAUSE status");
1247*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1248*5113495bSYour Name 	}
1249*5113495bSYour Name 
1250*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR;
1251*5113495bSYour Name 	if (nla_put(reply_skb, attr, QDF_MAC_ADDR_SIZE,
1252*5113495bSYour Name 		    event->peer_macaddr.bytes)) {
1253*5113495bSYour Name 		osif_err("Failed to put mac_addr");
1254*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1255*5113495bSYour Name 	}
1256*5113495bSYour Name 
1257*5113495bSYour Name 	nla_nest_end(reply_skb, config_attr);
1258*5113495bSYour Name 
1259*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1260*5113495bSYour Name }
1261*5113495bSYour Name 
1262*5113495bSYour Name QDF_STATUS
osif_twt_pause_complete_cb(struct wlan_objmgr_psoc * psoc,struct twt_pause_dialog_complete_event_param * event)1263*5113495bSYour Name osif_twt_pause_complete_cb(struct wlan_objmgr_psoc *psoc,
1264*5113495bSYour Name 			   struct twt_pause_dialog_complete_event_param *event)
1265*5113495bSYour Name 
1266*5113495bSYour Name {
1267*5113495bSYour Name 	struct wireless_dev *wdev;
1268*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
1269*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1270*5113495bSYour Name 	uint32_t vdev_id = event->vdev_id;
1271*5113495bSYour Name 	struct sk_buff *twt_vendor_event;
1272*5113495bSYour Name 	size_t data_len;
1273*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1274*5113495bSYour Name 
1275*5113495bSYour Name 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, event->vdev_id,
1276*5113495bSYour Name 						    WLAN_TWT_ID);
1277*5113495bSYour Name 	if (!vdev) {
1278*5113495bSYour Name 		osif_err("vdev is null");
1279*5113495bSYour Name 		return status;
1280*5113495bSYour Name 	}
1281*5113495bSYour Name 
1282*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
1283*5113495bSYour Name 	if (!osif_priv) {
1284*5113495bSYour Name 		osif_err("osif_priv is null");
1285*5113495bSYour Name 		goto fail;
1286*5113495bSYour Name 	}
1287*5113495bSYour Name 
1288*5113495bSYour Name 	wdev = osif_priv->wdev;
1289*5113495bSYour Name 	if (!wdev) {
1290*5113495bSYour Name 		osif_err("wireless dev is null");
1291*5113495bSYour Name 		goto fail;
1292*5113495bSYour Name 	}
1293*5113495bSYour Name 
1294*5113495bSYour Name 	osif_debug("TWT: pause dialog_id:%d status:%d vdev_id:%d peer macaddr "
1295*5113495bSYour Name 		   QDF_MAC_ADDR_FMT, event->dialog_id,
1296*5113495bSYour Name 		   event->status, vdev_id,
1297*5113495bSYour Name 		   QDF_MAC_ADDR_REF(event->peer_macaddr.bytes));
1298*5113495bSYour Name 
1299*5113495bSYour Name 	data_len = osif_twt_get_event_len() + nla_total_size(sizeof(u8));
1300*5113495bSYour Name 	data_len += NLA_HDRLEN;
1301*5113495bSYour Name 
1302*5113495bSYour Name 	twt_vendor_event = wlan_cfg80211_vendor_event_alloc(
1303*5113495bSYour Name 				wdev->wiphy, wdev, data_len,
1304*5113495bSYour Name 				QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT_INDEX,
1305*5113495bSYour Name 				GFP_KERNEL);
1306*5113495bSYour Name 	if (!twt_vendor_event) {
1307*5113495bSYour Name 		osif_err("TWT: Alloc pause resp skb fail");
1308*5113495bSYour Name 		goto fail;
1309*5113495bSYour Name 	}
1310*5113495bSYour Name 
1311*5113495bSYour Name 	status = osif_twt_pause_pack_resp_nlmsg(twt_vendor_event, event);
1312*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
1313*5113495bSYour Name 		osif_err("Failed to pack nl add dialog response");
1314*5113495bSYour Name 		wlan_cfg80211_vendor_free_skb(twt_vendor_event);
1315*5113495bSYour Name 		goto fail;
1316*5113495bSYour Name 	}
1317*5113495bSYour Name 	wlan_cfg80211_vendor_event(twt_vendor_event, GFP_KERNEL);
1318*5113495bSYour Name 
1319*5113495bSYour Name fail:
1320*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID);
1321*5113495bSYour Name 	return status;
1322*5113495bSYour Name }
1323*5113495bSYour Name 
1324*5113495bSYour Name QDF_STATUS
osif_twt_ack_complete_cb(struct wlan_objmgr_psoc * psoc,struct twt_ack_complete_event_param * params,void * context)1325*5113495bSYour Name osif_twt_ack_complete_cb(struct wlan_objmgr_psoc *psoc,
1326*5113495bSYour Name 			 struct twt_ack_complete_event_param *params,
1327*5113495bSYour Name 			 void *context)
1328*5113495bSYour Name {
1329*5113495bSYour Name 	struct osif_request *request = NULL;
1330*5113495bSYour Name 	struct twt_ack_context *status_priv;
1331*5113495bSYour Name 
1332*5113495bSYour Name 	request = osif_request_get(context);
1333*5113495bSYour Name 	if (!request) {
1334*5113495bSYour Name 		osif_err("obsolete request");
1335*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1336*5113495bSYour Name 	}
1337*5113495bSYour Name 
1338*5113495bSYour Name 	status_priv = osif_request_priv(request);
1339*5113495bSYour Name 	if (!status_priv) {
1340*5113495bSYour Name 		osif_err("obsolete status_priv");
1341*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1342*5113495bSYour Name 	}
1343*5113495bSYour Name 
1344*5113495bSYour Name 	if (status_priv->twt_cmd_ack == params->twt_cmd_ack) {
1345*5113495bSYour Name 		status_priv->vdev_id = params->vdev_id;
1346*5113495bSYour Name 		qdf_copy_macaddr(&status_priv->peer_macaddr,
1347*5113495bSYour Name 				 &params->peer_macaddr);
1348*5113495bSYour Name 		status_priv->dialog_id = params->dialog_id;
1349*5113495bSYour Name 		status_priv->status = params->status;
1350*5113495bSYour Name 		osif_request_complete(request);
1351*5113495bSYour Name 	} else {
1352*5113495bSYour Name 		osif_err("Invalid TWT ack. Expected cmd: %d Actual cmd: %d",
1353*5113495bSYour Name 				status_priv->twt_cmd_ack, params->twt_cmd_ack);
1354*5113495bSYour Name 	}
1355*5113495bSYour Name 
1356*5113495bSYour Name 	osif_request_put(request);
1357*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1358*5113495bSYour Name }
1359*5113495bSYour Name 
1360*5113495bSYour Name static uint32_t
osif_get_session_wake_duration(struct wlan_objmgr_vdev * vdev,uint32_t dialog_id,struct qdf_mac_addr * peer_macaddr)1361*5113495bSYour Name osif_get_session_wake_duration(struct wlan_objmgr_vdev *vdev,
1362*5113495bSYour Name 			       uint32_t dialog_id,
1363*5113495bSYour Name 			       struct qdf_mac_addr *peer_macaddr)
1364*5113495bSYour Name {
1365*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
1366*5113495bSYour Name 	struct twt_session_stats_info params = {0};
1367*5113495bSYour Name 	int num_twt_session = 0;
1368*5113495bSYour Name 
1369*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
1370*5113495bSYour Name 	params.dialog_id = dialog_id;
1371*5113495bSYour Name 	qdf_copy_macaddr(&params.peer_mac, peer_macaddr);
1372*5113495bSYour Name 
1373*5113495bSYour Name 	osif_debug("Get_params peer mac_addr " QDF_MAC_ADDR_FMT,
1374*5113495bSYour Name 		   QDF_MAC_ADDR_REF(params.peer_mac.bytes));
1375*5113495bSYour Name 
1376*5113495bSYour Name 	num_twt_session = ucfg_cp_stats_twt_get_peer_session_params(psoc,
1377*5113495bSYour Name 								    &params);
1378*5113495bSYour Name 	if (num_twt_session)
1379*5113495bSYour Name 		return params.wake_dura_us;
1380*5113495bSYour Name 
1381*5113495bSYour Name 	return 0;
1382*5113495bSYour Name }
1383*5113495bSYour Name 
1384*5113495bSYour Name static int
twt_get_stats_status_to_vendor_twt_status(enum HOST_TWT_GET_STATS_STATUS status)1385*5113495bSYour Name twt_get_stats_status_to_vendor_twt_status(enum HOST_TWT_GET_STATS_STATUS status)
1386*5113495bSYour Name {
1387*5113495bSYour Name 	switch (status) {
1388*5113495bSYour Name 	case HOST_TWT_GET_STATS_STATUS_OK:
1389*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_OK;
1390*5113495bSYour Name 	case HOST_TWT_GET_STATS_STATUS_DIALOG_ID_NOT_EXIST:
1391*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST;
1392*5113495bSYour Name 	case HOST_TWT_GET_STATS_STATUS_INVALID_PARAM:
1393*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM;
1394*5113495bSYour Name 	default:
1395*5113495bSYour Name 		return QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR;
1396*5113495bSYour Name 	}
1397*5113495bSYour Name }
1398*5113495bSYour Name 
1399*5113495bSYour Name /**
1400*5113495bSYour Name  * osif_twt_pack_get_stats_resp_nlmsg() - Packs and sends twt get stats response
1401*5113495bSYour Name  * @vdev: vdev
1402*5113495bSYour Name  * @reply_skb: pointer to response skb buffer
1403*5113495bSYour Name  * @params: Pointer to twt session parameter buffer
1404*5113495bSYour Name  * @num_session_stats: number of twt statistics
1405*5113495bSYour Name  *
1406*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, else other qdf error values
1407*5113495bSYour Name  */
1408*5113495bSYour Name static QDF_STATUS
osif_twt_pack_get_stats_resp_nlmsg(struct wlan_objmgr_vdev * vdev,struct sk_buff * reply_skb,struct twt_infra_cp_stats_event * params,uint32_t num_session_stats)1409*5113495bSYour Name osif_twt_pack_get_stats_resp_nlmsg(struct wlan_objmgr_vdev *vdev,
1410*5113495bSYour Name 				   struct sk_buff *reply_skb,
1411*5113495bSYour Name 				   struct twt_infra_cp_stats_event *params,
1412*5113495bSYour Name 				   uint32_t num_session_stats)
1413*5113495bSYour Name {
1414*5113495bSYour Name 	struct nlattr *config_attr, *nla_params;
1415*5113495bSYour Name 	int i, attr;
1416*5113495bSYour Name 	int vendor_status;
1417*5113495bSYour Name 	uint32_t duration;
1418*5113495bSYour Name 
1419*5113495bSYour Name 	config_attr = nla_nest_start(reply_skb,
1420*5113495bSYour Name 				     QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
1421*5113495bSYour Name 
1422*5113495bSYour Name 	if (!config_attr) {
1423*5113495bSYour Name 		osif_err("get_params nla_nest_start error");
1424*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1425*5113495bSYour Name 	}
1426*5113495bSYour Name 
1427*5113495bSYour Name 	for (i = 0; i < num_session_stats; i++) {
1428*5113495bSYour Name 		nla_params = nla_nest_start(reply_skb, i);
1429*5113495bSYour Name 		if (!nla_params) {
1430*5113495bSYour Name 			osif_err("get_stats nla_nest_start error");
1431*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1432*5113495bSYour Name 		}
1433*5113495bSYour Name 
1434*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR;
1435*5113495bSYour Name 		if (nla_put(reply_skb, attr, QDF_MAC_ADDR_SIZE,
1436*5113495bSYour Name 			    params[i].peer_macaddr.bytes)) {
1437*5113495bSYour Name 			osif_err("get_stats failed to put mac_addr");
1438*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1439*5113495bSYour Name 		}
1440*5113495bSYour Name 
1441*5113495bSYour Name 		osif_debug("get_stats peer mac_addr " QDF_MAC_ADDR_FMT,
1442*5113495bSYour Name 			   QDF_MAC_ADDR_REF(params[i].peer_macaddr.bytes));
1443*5113495bSYour Name 
1444*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID;
1445*5113495bSYour Name 		if (nla_put_u8(reply_skb, attr, params[i].dialog_id)) {
1446*5113495bSYour Name 			osif_err("get_stats failed to put dialog_id");
1447*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1448*5113495bSYour Name 		}
1449*5113495bSYour Name 
1450*5113495bSYour Name 		duration = osif_get_session_wake_duration(vdev,
1451*5113495bSYour Name 						params[i].dialog_id,
1452*5113495bSYour Name 						&params[i].peer_macaddr);
1453*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION;
1454*5113495bSYour Name 		if (nla_put_u32(reply_skb, attr, duration)) {
1455*5113495bSYour Name 			osif_err("get_params failed to put Wake duration");
1456*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1457*5113495bSYour Name 		}
1458*5113495bSYour Name 
1459*5113495bSYour Name 		osif_debug("dialog_id %d wake duration %d num sp cycles %d",
1460*5113495bSYour Name 			   params[i].dialog_id, duration,
1461*5113495bSYour Name 			   params[i].num_sp_cycles);
1462*5113495bSYour Name 
1463*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS;
1464*5113495bSYour Name 		if (nla_put_u32(reply_skb, attr, params[i].num_sp_cycles)) {
1465*5113495bSYour Name 			osif_err("get_params failed to put num_sp_cycles");
1466*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1467*5113495bSYour Name 		}
1468*5113495bSYour Name 
1469*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION;
1470*5113495bSYour Name 		if (nla_put_u32(reply_skb, attr, params[i].avg_sp_dur_us)) {
1471*5113495bSYour Name 			osif_err("get_params failed to put avg_sp_dur_us");
1472*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1473*5113495bSYour Name 		}
1474*5113495bSYour Name 
1475*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION;
1476*5113495bSYour Name 		if (nla_put_u32(reply_skb, attr, params[i].min_sp_dur_us)) {
1477*5113495bSYour Name 			osif_err("get_params failed to put min_sp_dur_us");
1478*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1479*5113495bSYour Name 		}
1480*5113495bSYour Name 
1481*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION;
1482*5113495bSYour Name 		if (nla_put_u32(reply_skb, attr, params[i].max_sp_dur_us)) {
1483*5113495bSYour Name 			osif_err("get_params failed to put max_sp_dur_us");
1484*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1485*5113495bSYour Name 		}
1486*5113495bSYour Name 
1487*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU;
1488*5113495bSYour Name 		if (nla_put_u32(reply_skb, attr, params[i].tx_mpdu_per_sp)) {
1489*5113495bSYour Name 			osif_err("get_params failed to put tx_mpdu_per_sp");
1490*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1491*5113495bSYour Name 		}
1492*5113495bSYour Name 
1493*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU;
1494*5113495bSYour Name 		if (nla_put_u32(reply_skb, attr, params[i].rx_mpdu_per_sp)) {
1495*5113495bSYour Name 			osif_err("get_params failed to put rx_mpdu_per_sp");
1496*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1497*5113495bSYour Name 		}
1498*5113495bSYour Name 
1499*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE;
1500*5113495bSYour Name 		if (nla_put_u32(reply_skb, attr, params[i].tx_bytes_per_sp)) {
1501*5113495bSYour Name 			osif_err("get_params failed to put tx_bytes_per_sp");
1502*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1503*5113495bSYour Name 		}
1504*5113495bSYour Name 
1505*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE;
1506*5113495bSYour Name 		if (nla_put_u32(reply_skb, attr, params[i].rx_bytes_per_sp)) {
1507*5113495bSYour Name 			osif_err("get_params failed to put rx_bytes_per_sp");
1508*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1509*5113495bSYour Name 		}
1510*5113495bSYour Name 
1511*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_STATUS;
1512*5113495bSYour Name 		vendor_status =
1513*5113495bSYour Name 		    twt_get_stats_status_to_vendor_twt_status(params[i].status);
1514*5113495bSYour Name 		if (nla_put_u32(reply_skb, attr, vendor_status)) {
1515*5113495bSYour Name 			osif_err("get_params failed to put status");
1516*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1517*5113495bSYour Name 		}
1518*5113495bSYour Name 
1519*5113495bSYour Name 		nla_nest_end(reply_skb, nla_params);
1520*5113495bSYour Name 	}
1521*5113495bSYour Name 
1522*5113495bSYour Name 	nla_nest_end(reply_skb, config_attr);
1523*5113495bSYour Name 
1524*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1525*5113495bSYour Name }
1526*5113495bSYour Name 
1527*5113495bSYour Name /**
1528*5113495bSYour Name  * osif_get_twt_get_stats_event_len() - calculate length of skb
1529*5113495bSYour Name  * required for sending twt get statistics command responses.
1530*5113495bSYour Name  *
1531*5113495bSYour Name  * Return: length of skb
1532*5113495bSYour Name  */
osif_get_twt_get_stats_event_len(void)1533*5113495bSYour Name static uint32_t osif_get_twt_get_stats_event_len(void)
1534*5113495bSYour Name {
1535*5113495bSYour Name 	uint32_t len = 0;
1536*5113495bSYour Name 
1537*5113495bSYour Name 	len += NLMSG_HDRLEN;
1538*5113495bSYour Name 
1539*5113495bSYour Name 	/* QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID */
1540*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
1541*5113495bSYour Name 
1542*5113495bSYour Name 	/* QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS */
1543*5113495bSYour Name 	len += nla_total_size(sizeof(u8));
1544*5113495bSYour Name 
1545*5113495bSYour Name 	return len;
1546*5113495bSYour Name }
1547*5113495bSYour Name 
osif_twt_get_stats_response(struct wlan_objmgr_vdev * vdev,struct twt_infra_cp_stats_event * params,uint32_t num_session_stats)1548*5113495bSYour Name QDF_STATUS osif_twt_get_stats_response(struct wlan_objmgr_vdev *vdev,
1549*5113495bSYour Name 				       struct twt_infra_cp_stats_event *params,
1550*5113495bSYour Name 				       uint32_t num_session_stats)
1551*5113495bSYour Name {
1552*5113495bSYour Name 	int skb_len;
1553*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
1554*5113495bSYour Name 	struct wireless_dev *wdev;
1555*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_INVAL;
1556*5113495bSYour Name 	struct sk_buff *reply_skb;
1557*5113495bSYour Name 	int ret;
1558*5113495bSYour Name 
1559*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
1560*5113495bSYour Name 	if (!osif_priv) {
1561*5113495bSYour Name 		osif_err("osif_priv is null");
1562*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1563*5113495bSYour Name 	}
1564*5113495bSYour Name 
1565*5113495bSYour Name 	wdev = osif_priv->wdev;
1566*5113495bSYour Name 	if (!wdev) {
1567*5113495bSYour Name 		osif_err("wireless dev is null");
1568*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1569*5113495bSYour Name 	}
1570*5113495bSYour Name 
1571*5113495bSYour Name 	skb_len = osif_get_twt_get_stats_event_len();
1572*5113495bSYour Name 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wdev->wiphy,
1573*5113495bSYour Name 							     skb_len);
1574*5113495bSYour Name 	if (!reply_skb) {
1575*5113495bSYour Name 		osif_err("Get stats - alloc reply_skb failed");
1576*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
1577*5113495bSYour Name 	}
1578*5113495bSYour Name 
1579*5113495bSYour Name 	status = osif_twt_pack_get_stats_resp_nlmsg(vdev, reply_skb, params,
1580*5113495bSYour Name 						    num_session_stats);
1581*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
1582*5113495bSYour Name 		osif_err("Get stats - Failed to pack nl response");
1583*5113495bSYour Name 		wlan_cfg80211_vendor_free_skb(reply_skb);
1584*5113495bSYour Name 		return qdf_status_to_os_return(status);
1585*5113495bSYour Name 	}
1586*5113495bSYour Name 
1587*5113495bSYour Name 	ret = wlan_cfg80211_vendor_cmd_reply(reply_skb);
1588*5113495bSYour Name 	return qdf_status_from_os_return(ret);
1589*5113495bSYour Name }
1590*5113495bSYour Name 
1591