xref: /wlan-driver/qcacld-3.0/core/hdd/src/wlan_hdd_cfg.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  * DOC:  wlan_hdd_cfg.c
22*5113495bSYour Name  *
23*5113495bSYour Name  * WLAN Host Device Driver configuration interface implementation
24*5113495bSYour Name  */
25*5113495bSYour Name 
26*5113495bSYour Name /* Include Files */
27*5113495bSYour Name 
28*5113495bSYour Name #include <linux/firmware.h>
29*5113495bSYour Name #include <linux/string.h>
30*5113495bSYour Name #include <wlan_hdd_includes.h>
31*5113495bSYour Name #include <wlan_hdd_main.h>
32*5113495bSYour Name #include <wlan_hdd_assoc.h>
33*5113495bSYour Name #include <wlan_hdd_cfg.h>
34*5113495bSYour Name #include <linux/string.h>
35*5113495bSYour Name #include <qdf_types.h>
36*5113495bSYour Name #include <csr_api.h>
37*5113495bSYour Name #include <wlan_hdd_misc.h>
38*5113495bSYour Name #include <wlan_hdd_napi.h>
39*5113495bSYour Name #include <cds_api.h>
40*5113495bSYour Name #include <wlan_hdd_regulatory.h>
41*5113495bSYour Name #include "wlan_hdd_he.h"
42*5113495bSYour Name #include <wlan_policy_mgr_api.h>
43*5113495bSYour Name #include "wifi_pos_api.h"
44*5113495bSYour Name #include "wlan_hdd_green_ap.h"
45*5113495bSYour Name #include "wlan_hdd_twt.h"
46*5113495bSYour Name #include "wlan_policy_mgr_ucfg.h"
47*5113495bSYour Name #include "wlan_mlme_ucfg_api.h"
48*5113495bSYour Name #include "wlan_mlme_public_struct.h"
49*5113495bSYour Name #include "wlan_fwol_ucfg_api.h"
50*5113495bSYour Name #include "cfg_ucfg_api.h"
51*5113495bSYour Name #include "hdd_dp_cfg.h"
52*5113495bSYour Name #include <wma_api.h>
53*5113495bSYour Name #include "wlan_hdd_object_manager.h"
54*5113495bSYour Name #include "wlan_dp_ucfg_api.h"
55*5113495bSYour Name #include "wlan_cmn.h"
56*5113495bSYour Name 
57*5113495bSYour Name #ifndef WLAN_MAC_ADDR_UPDATE_DISABLE
58*5113495bSYour Name /**
59*5113495bSYour Name  * get_next_line() - find and locate the new line pointer
60*5113495bSYour Name  * @str: pointer to string
61*5113495bSYour Name  *
62*5113495bSYour Name  * This function returns a pointer to the character after the occurrence
63*5113495bSYour Name  * of a new line character. It also modifies the original string by replacing
64*5113495bSYour Name  * the '\n' character with the null character.
65*5113495bSYour Name  *
66*5113495bSYour Name  * Return: the pointer to the character at new line,
67*5113495bSYour Name  *            or NULL if no new line character was found
68*5113495bSYour Name  */
get_next_line(char * str)69*5113495bSYour Name static char *get_next_line(char *str)
70*5113495bSYour Name {
71*5113495bSYour Name 	char c;
72*5113495bSYour Name 
73*5113495bSYour Name 	if (!str || *str == '\0')
74*5113495bSYour Name 		return NULL;
75*5113495bSYour Name 
76*5113495bSYour Name 	c = *str;
77*5113495bSYour Name 	while (c != '\n' && c != '\0' && c != 0xd) {
78*5113495bSYour Name 		str = str + 1;
79*5113495bSYour Name 		c = *str;
80*5113495bSYour Name 	}
81*5113495bSYour Name 
82*5113495bSYour Name 	if (c == '\0')
83*5113495bSYour Name 		return NULL;
84*5113495bSYour Name 
85*5113495bSYour Name 	*str = '\0';
86*5113495bSYour Name 	return str + 1;
87*5113495bSYour Name }
88*5113495bSYour Name 
89*5113495bSYour Name /** look for space. Ascii values to look are
90*5113495bSYour Name  * 0x09 == horizontal tab
91*5113495bSYour Name  * 0x0a == Newline ("\n")
92*5113495bSYour Name  * 0x0b == vertical tab
93*5113495bSYour Name  * 0x0c == Newpage or feed form.
94*5113495bSYour Name  * 0x0d == carriage return (CR or "\r")
95*5113495bSYour Name  * Null ('\0') should not considered as space.
96*5113495bSYour Name  */
97*5113495bSYour Name #define i_isspace(ch)  (((ch) >= 0x09 && (ch) <= 0x0d) || (ch) == ' ')
98*5113495bSYour Name 
99*5113495bSYour Name /**
100*5113495bSYour Name  * i_trim() - trims any leading and trailing white spaces
101*5113495bSYour Name  * @str: pointer to string
102*5113495bSYour Name  *
103*5113495bSYour Name  * Return: the pointer of the string
104*5113495bSYour Name  */
i_trim(char * str)105*5113495bSYour Name static char *i_trim(char *str)
106*5113495bSYour Name {
107*5113495bSYour Name 	char *ptr;
108*5113495bSYour Name 
109*5113495bSYour Name 	if (*str == '\0')
110*5113495bSYour Name 		return str;
111*5113495bSYour Name 
112*5113495bSYour Name 	/* Find the first non white-space */
113*5113495bSYour Name 	ptr = str;
114*5113495bSYour Name 	while (i_isspace(*ptr))
115*5113495bSYour Name 		ptr++;
116*5113495bSYour Name 
117*5113495bSYour Name 	if (*ptr == '\0')
118*5113495bSYour Name 		return str;
119*5113495bSYour Name 
120*5113495bSYour Name 	/* This is the new start of the string */
121*5113495bSYour Name 	str = ptr;
122*5113495bSYour Name 
123*5113495bSYour Name 	/* Find the last non white-space */
124*5113495bSYour Name 	ptr += strlen(ptr) - 1;
125*5113495bSYour Name 
126*5113495bSYour Name 	while (ptr != str && i_isspace(*ptr))
127*5113495bSYour Name 		ptr--;
128*5113495bSYour Name 
129*5113495bSYour Name 	/* Null terminate the following character */
130*5113495bSYour Name 	ptr[1] = '\0';
131*5113495bSYour Name 
132*5113495bSYour Name 	return str;
133*5113495bSYour Name }
134*5113495bSYour Name 
135*5113495bSYour Name /** struct hdd_cfg_entry - ini configuration entry
136*5113495bSYour Name  * @name: name of the entry
137*5113495bSYour Name  * @value: value of the entry
138*5113495bSYour Name  */
139*5113495bSYour Name struct hdd_cfg_entry {
140*5113495bSYour Name 	char *name;
141*5113495bSYour Name 	char *value;
142*5113495bSYour Name };
143*5113495bSYour Name 
144*5113495bSYour Name /**
145*5113495bSYour Name  * update_mac_from_string() - convert string to 6 bytes mac address
146*5113495bSYour Name  * @hdd_ctx: the pointer to hdd context
147*5113495bSYour Name  * @mac_table: the mac_table to carry the conversion
148*5113495bSYour Name  * @num: number of the interface
149*5113495bSYour Name  *
150*5113495bSYour Name  * 00AA00BB00CC -> 0x00 0xAA 0x00 0xBB 0x00 0xCC
151*5113495bSYour Name  *
152*5113495bSYour Name  * Return: QDF_STATUS
153*5113495bSYour Name  */
update_mac_from_string(struct hdd_context * hdd_ctx,struct hdd_cfg_entry * mac_table,int num)154*5113495bSYour Name static QDF_STATUS update_mac_from_string(struct hdd_context *hdd_ctx,
155*5113495bSYour Name 					 struct hdd_cfg_entry *mac_table,
156*5113495bSYour Name 					 int num)
157*5113495bSYour Name {
158*5113495bSYour Name 	int i = 0, j = 0, res = 0;
159*5113495bSYour Name 	char *candidate = NULL;
160*5113495bSYour Name 	struct qdf_mac_addr macaddr[QDF_MAX_CONCURRENCY_PERSONA];
161*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
162*5113495bSYour Name 
163*5113495bSYour Name 	memset(macaddr, 0, sizeof(macaddr));
164*5113495bSYour Name 
165*5113495bSYour Name 	for (i = 0; i < num; i++) {
166*5113495bSYour Name 		candidate = mac_table[i].value;
167*5113495bSYour Name 		for (j = 0; j < QDF_MAC_ADDR_SIZE; j++) {
168*5113495bSYour Name 			res =
169*5113495bSYour Name 				hex2bin(&macaddr[i].bytes[j], &candidate[(j << 1)],
170*5113495bSYour Name 					1);
171*5113495bSYour Name 			if (res < 0)
172*5113495bSYour Name 				break;
173*5113495bSYour Name 		}
174*5113495bSYour Name 		if (res == 0 && !qdf_is_macaddr_zero(&macaddr[i])) {
175*5113495bSYour Name 			qdf_mem_copy((uint8_t *)&hdd_ctx->
176*5113495bSYour Name 				     provisioned_mac_addr[i].bytes[0],
177*5113495bSYour Name 				     (uint8_t *) &macaddr[i].bytes[0],
178*5113495bSYour Name 				     QDF_MAC_ADDR_SIZE);
179*5113495bSYour Name 		} else {
180*5113495bSYour Name 			status = QDF_STATUS_E_FAILURE;
181*5113495bSYour Name 			break;
182*5113495bSYour Name 		}
183*5113495bSYour Name 	}
184*5113495bSYour Name 	return status;
185*5113495bSYour Name }
186*5113495bSYour Name 
187*5113495bSYour Name #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
188*5113495bSYour Name static inline
hdd_firmware_request_nowarn(const struct firmware ** fw,const char * name,struct device * device)189*5113495bSYour Name int hdd_firmware_request_nowarn(const struct firmware **fw,
190*5113495bSYour Name 				const char *name,
191*5113495bSYour Name 				struct device *device)
192*5113495bSYour Name {
193*5113495bSYour Name 	return firmware_request_nowarn(fw, name, device);
194*5113495bSYour Name }
195*5113495bSYour Name #else
196*5113495bSYour Name static inline
hdd_firmware_request_nowarn(const struct firmware ** fw,const char * name,struct device * device)197*5113495bSYour Name int hdd_firmware_request_nowarn(const struct firmware **fw,
198*5113495bSYour Name 				const char *name,
199*5113495bSYour Name 				struct device *device)
200*5113495bSYour Name {
201*5113495bSYour Name 	return request_firmware(fw, name, device);
202*5113495bSYour Name }
203*5113495bSYour Name #endif
204*5113495bSYour Name 
205*5113495bSYour Name /**
206*5113495bSYour Name  * hdd_update_mac_config() - update MAC address from cfg file
207*5113495bSYour Name  * @hdd_ctx: the pointer to hdd context
208*5113495bSYour Name  *
209*5113495bSYour Name  * It overwrites the MAC address if config file exist.
210*5113495bSYour Name  *
211*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS if the MAC address is found from cfg file
212*5113495bSYour Name  *      and overwritten, otherwise QDF_STATUS_E_INVAL
213*5113495bSYour Name  */
hdd_update_mac_config(struct hdd_context * hdd_ctx)214*5113495bSYour Name QDF_STATUS hdd_update_mac_config(struct hdd_context *hdd_ctx)
215*5113495bSYour Name {
216*5113495bSYour Name 	int status, i = 0;
217*5113495bSYour Name 	const struct firmware *fw = NULL;
218*5113495bSYour Name 	char *line, *buffer = NULL;
219*5113495bSYour Name 	char *temp = NULL;
220*5113495bSYour Name 	char *name, *value;
221*5113495bSYour Name 	int max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
222*5113495bSYour Name 	struct hdd_cfg_entry mac_table[QDF_MAX_CONCURRENCY_PERSONA];
223*5113495bSYour Name 	struct qdf_mac_addr custom_mac_addr;
224*5113495bSYour Name 
225*5113495bSYour Name 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
226*5113495bSYour Name 
227*5113495bSYour Name 	if (!hdd_ctx->config->read_mac_addr_from_mac_file) {
228*5113495bSYour Name 		hdd_debug("Reading MAC address from MAC file is not enabled.");
229*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
230*5113495bSYour Name 	}
231*5113495bSYour Name 
232*5113495bSYour Name 	memset(mac_table, 0, sizeof(mac_table));
233*5113495bSYour Name 	status = hdd_firmware_request_nowarn(&fw, WLAN_MAC_FILE,
234*5113495bSYour Name 					     hdd_ctx->parent_dev);
235*5113495bSYour Name 	if (status) {
236*5113495bSYour Name 		/*
237*5113495bSYour Name 		 * request_firmware "fails" if the file is not found, which is a
238*5113495bSYour Name 		 * valid setup for us, so log using debug instead of error
239*5113495bSYour Name 		 */
240*5113495bSYour Name 		hdd_debug("request_firmware failed; status:%d", status);
241*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
242*5113495bSYour Name 	}
243*5113495bSYour Name 
244*5113495bSYour Name 	if (!fw || !fw->data || !fw->size) {
245*5113495bSYour Name 		hdd_alert("invalid firmware");
246*5113495bSYour Name 		qdf_status = QDF_STATUS_E_INVAL;
247*5113495bSYour Name 		goto config_exit;
248*5113495bSYour Name 	}
249*5113495bSYour Name 
250*5113495bSYour Name 	hdd_debug("wlan_mac.bin size %zu", fw->size);
251*5113495bSYour Name 
252*5113495bSYour Name 	temp = qdf_mem_malloc(fw->size + 1);
253*5113495bSYour Name 	if (!temp) {
254*5113495bSYour Name 		qdf_status = QDF_STATUS_E_NOMEM;
255*5113495bSYour Name 		goto config_exit;
256*5113495bSYour Name 	}
257*5113495bSYour Name 	buffer = temp;
258*5113495bSYour Name 	qdf_mem_copy(buffer, fw->data, fw->size);
259*5113495bSYour Name 	buffer[fw->size] = 0x0;
260*5113495bSYour Name 
261*5113495bSYour Name 	/* data format:
262*5113495bSYour Name 	 * Intf0MacAddress=00AA00BB00CC
263*5113495bSYour Name 	 * Intf1MacAddress=00AA00BB00CD
264*5113495bSYour Name 	 * END
265*5113495bSYour Name 	 */
266*5113495bSYour Name 	while (buffer) {
267*5113495bSYour Name 		line = get_next_line(buffer);
268*5113495bSYour Name 		buffer = i_trim(buffer);
269*5113495bSYour Name 
270*5113495bSYour Name 		if (strlen((char *)buffer) == 0 || *buffer == '#') {
271*5113495bSYour Name 			buffer = line;
272*5113495bSYour Name 			continue;
273*5113495bSYour Name 		}
274*5113495bSYour Name 		if (strncmp(buffer, "END", 3) == 0)
275*5113495bSYour Name 			break;
276*5113495bSYour Name 
277*5113495bSYour Name 		name = buffer;
278*5113495bSYour Name 		buffer = strnchr(buffer, strlen(buffer), '=');
279*5113495bSYour Name 		if (buffer) {
280*5113495bSYour Name 			*buffer++ = '\0';
281*5113495bSYour Name 			i_trim(name);
282*5113495bSYour Name 			if (strlen(name) != 0) {
283*5113495bSYour Name 				buffer = i_trim(buffer);
284*5113495bSYour Name 				if (strlen(buffer) == 12) {
285*5113495bSYour Name 					value = buffer;
286*5113495bSYour Name 					mac_table[i].name = name;
287*5113495bSYour Name 					mac_table[i++].value = value;
288*5113495bSYour Name 					if (i >= QDF_MAX_CONCURRENCY_PERSONA)
289*5113495bSYour Name 						break;
290*5113495bSYour Name 				}
291*5113495bSYour Name 			}
292*5113495bSYour Name 		}
293*5113495bSYour Name 		buffer = line;
294*5113495bSYour Name 	}
295*5113495bSYour Name 
296*5113495bSYour Name 	if (i != 0 && i <= QDF_MAX_CONCURRENCY_PERSONA) {
297*5113495bSYour Name 		hdd_debug("%d Mac addresses provided", i);
298*5113495bSYour Name 	} else {
299*5113495bSYour Name 		hdd_err("invalid number of Mac address provided, nMac = %d", i);
300*5113495bSYour Name 		qdf_status = QDF_STATUS_E_INVAL;
301*5113495bSYour Name 		goto config_exit;
302*5113495bSYour Name 	}
303*5113495bSYour Name 
304*5113495bSYour Name 	qdf_status = update_mac_from_string(hdd_ctx, &mac_table[0], i);
305*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
306*5113495bSYour Name 		hdd_err("Invalid MAC addresses provided");
307*5113495bSYour Name 		goto config_exit;
308*5113495bSYour Name 	}
309*5113495bSYour Name 	hdd_ctx->num_provisioned_addr = i;
310*5113495bSYour Name 	hdd_debug("Populating remaining %d Mac addresses",
311*5113495bSYour Name 		   max_mac_addr - i);
312*5113495bSYour Name 	hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr - i);
313*5113495bSYour Name 
314*5113495bSYour Name 	if (hdd_ctx->num_provisioned_addr)
315*5113495bSYour Name 		qdf_mem_copy(custom_mac_addr.bytes,
316*5113495bSYour Name 			     &hdd_ctx->provisioned_mac_addr[0].bytes[0],
317*5113495bSYour Name 			     sizeof(custom_mac_addr));
318*5113495bSYour Name 	else
319*5113495bSYour Name 		qdf_mem_copy(custom_mac_addr.bytes,
320*5113495bSYour Name 			     &hdd_ctx->derived_mac_addr[0].bytes[0],
321*5113495bSYour Name 			     sizeof(custom_mac_addr));
322*5113495bSYour Name 
323*5113495bSYour Name 	qdf_status = sme_set_custom_mac_addr(custom_mac_addr.bytes);
324*5113495bSYour Name 
325*5113495bSYour Name config_exit:
326*5113495bSYour Name 	qdf_mem_free(temp);
327*5113495bSYour Name 	release_firmware(fw);
328*5113495bSYour Name 	return qdf_status;
329*5113495bSYour Name }
330*5113495bSYour Name #else
hdd_update_mac_config(struct hdd_context * hdd_ctx)331*5113495bSYour Name QDF_STATUS hdd_update_mac_config(struct hdd_context *hdd_ctx)
332*5113495bSYour Name {
333*5113495bSYour Name 	return QDF_STATUS_E_NOSUPPORT;
334*5113495bSYour Name }
335*5113495bSYour Name #endif
336*5113495bSYour Name 
337*5113495bSYour Name /**
338*5113495bSYour Name  * hdd_set_power_save_offload_config() - set power save offload configuration
339*5113495bSYour Name  * @hdd_ctx: the pointer to hdd context
340*5113495bSYour Name  *
341*5113495bSYour Name  * Return: none
342*5113495bSYour Name  */
hdd_set_power_save_offload_config(struct hdd_context * hdd_ctx)343*5113495bSYour Name static void hdd_set_power_save_offload_config(struct hdd_context *hdd_ctx)
344*5113495bSYour Name {
345*5113495bSYour Name 	uint32_t listen_interval = 0;
346*5113495bSYour Name 	char *power_usage = NULL;
347*5113495bSYour Name 
348*5113495bSYour Name 	power_usage = ucfg_mlme_get_power_usage(hdd_ctx->psoc);
349*5113495bSYour Name 	if (!power_usage) {
350*5113495bSYour Name 		hdd_err("invalid power usage");
351*5113495bSYour Name 		return;
352*5113495bSYour Name 	}
353*5113495bSYour Name 
354*5113495bSYour Name 	if (strcmp(power_usage, "Min") == 0)
355*5113495bSYour Name 		ucfg_mlme_get_bmps_min_listen_interval(hdd_ctx->psoc,
356*5113495bSYour Name 						       &listen_interval);
357*5113495bSYour Name 	else if (strcmp(power_usage, "Max") == 0)
358*5113495bSYour Name 		ucfg_mlme_get_bmps_max_listen_interval(hdd_ctx->psoc,
359*5113495bSYour Name 						       &listen_interval);
360*5113495bSYour Name 	/*
361*5113495bSYour Name 	 * Based on Mode Set the LI
362*5113495bSYour Name 	 * Otherwise default LI value of 1 will
363*5113495bSYour Name 	 * be taken
364*5113495bSYour Name 	 */
365*5113495bSYour Name 	if (listen_interval) {
366*5113495bSYour Name 		/*
367*5113495bSYour Name 		 * setcfg for listenInterval.
368*5113495bSYour Name 		 * Make sure CFG is updated because PE reads this
369*5113495bSYour Name 		 * from CFG at the time of assoc or reassoc
370*5113495bSYour Name 		 */
371*5113495bSYour Name 		ucfg_mlme_set_sap_listen_interval(hdd_ctx->psoc,
372*5113495bSYour Name 						  listen_interval);
373*5113495bSYour Name 	}
374*5113495bSYour Name }
375*5113495bSYour Name 
376*5113495bSYour Name #ifdef FEATURE_RUNTIME_PM
377*5113495bSYour Name /**
378*5113495bSYour Name  * hdd_disable_runtime_pm() - Override to disable runtime_pm.
379*5113495bSYour Name  * @cfg_ini: Handle to struct hdd_config
380*5113495bSYour Name  *
381*5113495bSYour Name  * Return: None
382*5113495bSYour Name  */
hdd_disable_runtime_pm(struct hdd_config * cfg_ini)383*5113495bSYour Name static void hdd_disable_runtime_pm(struct hdd_config *cfg_ini)
384*5113495bSYour Name {
385*5113495bSYour Name 	cfg_ini->runtime_pm = 0;
386*5113495bSYour Name }
387*5113495bSYour Name 
388*5113495bSYour Name /**
389*5113495bSYour Name  * hdd_restore_runtime_pm() - Restore runtime_pm configuration.
390*5113495bSYour Name  * @hdd_ctx: HDD context
391*5113495bSYour Name  *
392*5113495bSYour Name  * Return: None
393*5113495bSYour Name  */
hdd_restore_runtime_pm(struct hdd_context * hdd_ctx)394*5113495bSYour Name static void hdd_restore_runtime_pm(struct hdd_context *hdd_ctx)
395*5113495bSYour Name {
396*5113495bSYour Name 	struct hdd_config *cfg_ini = hdd_ctx->config;
397*5113495bSYour Name 
398*5113495bSYour Name 	cfg_ini->runtime_pm = cfg_get(hdd_ctx->psoc, CFG_ENABLE_RUNTIME_PM);
399*5113495bSYour Name }
400*5113495bSYour Name #else
hdd_disable_runtime_pm(struct hdd_config * cfg_ini)401*5113495bSYour Name static void hdd_disable_runtime_pm(struct hdd_config *cfg_ini)
402*5113495bSYour Name {
403*5113495bSYour Name }
404*5113495bSYour Name 
hdd_restore_runtime_pm(struct hdd_context * hdd_ctx)405*5113495bSYour Name static void hdd_restore_runtime_pm(struct hdd_context *hdd_ctx)
406*5113495bSYour Name {
407*5113495bSYour Name }
408*5113495bSYour Name #endif
409*5113495bSYour Name 
410*5113495bSYour Name #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
411*5113495bSYour Name /**
412*5113495bSYour Name  * hdd_disable_auto_shutdown() - Override to disable auto_shutdown.
413*5113495bSYour Name  * @cfg_ini: Handle to struct hdd_config
414*5113495bSYour Name  *
415*5113495bSYour Name  * Return: None
416*5113495bSYour Name  */
hdd_disable_auto_shutdown(struct hdd_config * cfg_ini)417*5113495bSYour Name static void hdd_disable_auto_shutdown(struct hdd_config *cfg_ini)
418*5113495bSYour Name {
419*5113495bSYour Name 	cfg_ini->wlan_auto_shutdown = 0;
420*5113495bSYour Name }
421*5113495bSYour Name 
422*5113495bSYour Name /**
423*5113495bSYour Name  * hdd_restore_auto_shutdown() - Restore auto_shutdown configuration.
424*5113495bSYour Name  * @hdd_ctx: HDD context
425*5113495bSYour Name  *
426*5113495bSYour Name  * Return: None
427*5113495bSYour Name  */
hdd_restore_auto_shutdown(struct hdd_context * hdd_ctx)428*5113495bSYour Name static void hdd_restore_auto_shutdown(struct hdd_context *hdd_ctx)
429*5113495bSYour Name {
430*5113495bSYour Name 	struct hdd_config *cfg_ini = hdd_ctx->config;
431*5113495bSYour Name 
432*5113495bSYour Name 	cfg_ini->wlan_auto_shutdown = cfg_get(hdd_ctx->psoc,
433*5113495bSYour Name 					      CFG_WLAN_AUTO_SHUTDOWN);
434*5113495bSYour Name }
435*5113495bSYour Name #else
hdd_disable_auto_shutdown(struct hdd_config * cfg_ini)436*5113495bSYour Name static void hdd_disable_auto_shutdown(struct hdd_config *cfg_ini)
437*5113495bSYour Name {
438*5113495bSYour Name }
439*5113495bSYour Name 
hdd_restore_auto_shutdown(struct hdd_context * hdd_ctx)440*5113495bSYour Name static void hdd_restore_auto_shutdown(struct hdd_context *hdd_ctx)
441*5113495bSYour Name {
442*5113495bSYour Name }
443*5113495bSYour Name #endif
444*5113495bSYour Name 
hdd_restore_all_ps(struct hdd_context * hdd_ctx)445*5113495bSYour Name void hdd_restore_all_ps(struct hdd_context *hdd_ctx)
446*5113495bSYour Name {
447*5113495bSYour Name 	/*
448*5113495bSYour Name 	 * imps/bmps configuration will be restored in driver mode change
449*5113495bSYour Name 	 * sequence as part of hdd_wlan_start_modules
450*5113495bSYour Name 	 */
451*5113495bSYour Name 
452*5113495bSYour Name 	hdd_restore_runtime_pm(hdd_ctx);
453*5113495bSYour Name 	hdd_restore_auto_shutdown(hdd_ctx);
454*5113495bSYour Name }
455*5113495bSYour Name 
hdd_override_all_ps(struct hdd_context * hdd_ctx)456*5113495bSYour Name void hdd_override_all_ps(struct hdd_context *hdd_ctx)
457*5113495bSYour Name {
458*5113495bSYour Name 	struct hdd_config *cfg_ini = hdd_ctx->config;
459*5113495bSYour Name 
460*5113495bSYour Name 	ucfg_mlme_override_bmps_imps(hdd_ctx->psoc);
461*5113495bSYour Name 	hdd_disable_runtime_pm(cfg_ini);
462*5113495bSYour Name 	hdd_disable_auto_shutdown(cfg_ini);
463*5113495bSYour Name }
464*5113495bSYour Name 
465*5113495bSYour Name /**
466*5113495bSYour Name  * hdd_cfg_xlate_to_csr_phy_mode() - convert PHY mode
467*5113495bSYour Name  * @dot11Mode: the mode to convert
468*5113495bSYour Name  *
469*5113495bSYour Name  * Convert the configuration PHY mode to CSR PHY mode
470*5113495bSYour Name  *
471*5113495bSYour Name  * Return: the CSR phy mode value
472*5113495bSYour Name  */
hdd_cfg_xlate_to_csr_phy_mode(enum hdd_dot11_mode dot11Mode)473*5113495bSYour Name eCsrPhyMode hdd_cfg_xlate_to_csr_phy_mode(enum hdd_dot11_mode dot11Mode)
474*5113495bSYour Name {
475*5113495bSYour Name 	if (cds_is_sub_20_mhz_enabled())
476*5113495bSYour Name 		return eCSR_DOT11_MODE_abg;
477*5113495bSYour Name 
478*5113495bSYour Name 	switch (dot11Mode) {
479*5113495bSYour Name 	case (eHDD_DOT11_MODE_abg):
480*5113495bSYour Name 		return eCSR_DOT11_MODE_abg;
481*5113495bSYour Name 	case (eHDD_DOT11_MODE_11b):
482*5113495bSYour Name 		return eCSR_DOT11_MODE_11b;
483*5113495bSYour Name 	case (eHDD_DOT11_MODE_11g):
484*5113495bSYour Name 		return eCSR_DOT11_MODE_11g;
485*5113495bSYour Name 	default:
486*5113495bSYour Name 	case (eHDD_DOT11_MODE_11n):
487*5113495bSYour Name 		return eCSR_DOT11_MODE_11n;
488*5113495bSYour Name 	case (eHDD_DOT11_MODE_11g_ONLY):
489*5113495bSYour Name 		return eCSR_DOT11_MODE_11g_ONLY;
490*5113495bSYour Name 	case (eHDD_DOT11_MODE_11n_ONLY):
491*5113495bSYour Name 		return eCSR_DOT11_MODE_11n_ONLY;
492*5113495bSYour Name 	case (eHDD_DOT11_MODE_11b_ONLY):
493*5113495bSYour Name 		return eCSR_DOT11_MODE_11b_ONLY;
494*5113495bSYour Name 	case (eHDD_DOT11_MODE_11ac_ONLY):
495*5113495bSYour Name 		return eCSR_DOT11_MODE_11ac_ONLY;
496*5113495bSYour Name 	case (eHDD_DOT11_MODE_11ac):
497*5113495bSYour Name 		return eCSR_DOT11_MODE_11ac;
498*5113495bSYour Name 	case (eHDD_DOT11_MODE_AUTO):
499*5113495bSYour Name 		return eCSR_DOT11_MODE_AUTO;
500*5113495bSYour Name 	case (eHDD_DOT11_MODE_11a):
501*5113495bSYour Name 		return eCSR_DOT11_MODE_11a;
502*5113495bSYour Name 	case (eHDD_DOT11_MODE_11ax_ONLY):
503*5113495bSYour Name 		return eCSR_DOT11_MODE_11ax_ONLY;
504*5113495bSYour Name 	case (eHDD_DOT11_MODE_11ax):
505*5113495bSYour Name 		return eCSR_DOT11_MODE_11ax;
506*5113495bSYour Name #ifdef WLAN_FEATURE_11BE
507*5113495bSYour Name 	case (eHDD_DOT11_MODE_11be):
508*5113495bSYour Name 		return eCSR_DOT11_MODE_11be;
509*5113495bSYour Name 	case (eHDD_DOT11_MODE_11be_ONLY):
510*5113495bSYour Name 		return eCSR_DOT11_MODE_11be_ONLY;
511*5113495bSYour Name #endif
512*5113495bSYour Name 	}
513*5113495bSYour Name 
514*5113495bSYour Name }
515*5113495bSYour Name 
516*5113495bSYour Name /**
517*5113495bSYour Name  * hdd_set_idle_ps_config() - set idle power save configuration
518*5113495bSYour Name  * @hdd_ctx: the pointer to hdd context
519*5113495bSYour Name  * @val: the value to configure
520*5113495bSYour Name  *
521*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS if command set correctly,
522*5113495bSYour Name  *		otherwise the QDF_STATUS return from SME layer
523*5113495bSYour Name  */
hdd_set_idle_ps_config(struct hdd_context * hdd_ctx,bool val)524*5113495bSYour Name QDF_STATUS hdd_set_idle_ps_config(struct hdd_context *hdd_ctx, bool val)
525*5113495bSYour Name {
526*5113495bSYour Name 	QDF_STATUS status;
527*5113495bSYour Name 
528*5113495bSYour Name 	hdd_debug("Enter Val %d", val);
529*5113495bSYour Name 
530*5113495bSYour Name 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
531*5113495bSYour Name 		hdd_debug("Skipping powersave in FTM");
532*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
533*5113495bSYour Name 	}
534*5113495bSYour Name 
535*5113495bSYour Name 	if (hdd_ctx->imps_enabled == val) {
536*5113495bSYour Name 		hdd_nofl_debug("Already in the requested power state:%d", val);
537*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
538*5113495bSYour Name 	}
539*5113495bSYour Name 
540*5113495bSYour Name 	status = sme_set_idle_powersave_config(val);
541*5113495bSYour Name 	if (QDF_STATUS_SUCCESS != status) {
542*5113495bSYour Name 		hdd_err("Fail to Set Idle PS Config val %d", val);
543*5113495bSYour Name 		return status;
544*5113495bSYour Name 	}
545*5113495bSYour Name 
546*5113495bSYour Name 	hdd_ctx->imps_enabled = val;
547*5113495bSYour Name 
548*5113495bSYour Name 	return status;
549*5113495bSYour Name }
550*5113495bSYour Name 
551*5113495bSYour Name /**
552*5113495bSYour Name  * hdd_set_fine_time_meas_cap() - set fine timing measurement capability
553*5113495bSYour Name  * @hdd_ctx: HDD context
554*5113495bSYour Name  *
555*5113495bSYour Name  * This function is used to pass fine timing measurement capability coming
556*5113495bSYour Name  * from INI to SME. This function make sure that configure INI is supported
557*5113495bSYour Name  * by the device. Use bit mask to mask out the unsupported capabilities.
558*5113495bSYour Name  *
559*5113495bSYour Name  * Return: None
560*5113495bSYour Name  */
hdd_set_fine_time_meas_cap(struct hdd_context * hdd_ctx)561*5113495bSYour Name static void hdd_set_fine_time_meas_cap(struct hdd_context *hdd_ctx)
562*5113495bSYour Name {
563*5113495bSYour Name 	uint32_t capability = 0;
564*5113495bSYour Name 
565*5113495bSYour Name 	ucfg_mlme_get_fine_time_meas_cap(hdd_ctx->psoc, &capability);
566*5113495bSYour Name 	ucfg_wifi_pos_set_ftm_cap(hdd_ctx->psoc, capability);
567*5113495bSYour Name 	hdd_debug("fine time meas capability - Enabled: %04x", capability);
568*5113495bSYour Name }
569*5113495bSYour Name 
570*5113495bSYour Name /**
571*5113495bSYour Name  * hdd_set_oem_6g_supported() - set oem 6g support enabled/disable
572*5113495bSYour Name  * @hdd_ctx: HDD context
573*5113495bSYour Name  *
574*5113495bSYour Name  * This function is used to pass oem 6g support enabled/disable value
575*5113495bSYour Name  * coming from INI to SME. This function make sure that configure
576*5113495bSYour Name  * INI is supported by the device.
577*5113495bSYour Name  *
578*5113495bSYour Name  * Return: None
579*5113495bSYour Name  */
hdd_set_oem_6g_supported(struct hdd_context * hdd_ctx)580*5113495bSYour Name static void hdd_set_oem_6g_supported(struct hdd_context *hdd_ctx)
581*5113495bSYour Name {
582*5113495bSYour Name 	bool oem_6g_disable = true;
583*5113495bSYour Name 	bool is_reg_6g_support, set_wifi_pos_6g_disabled;
584*5113495bSYour Name 
585*5113495bSYour Name 	ucfg_mlme_get_oem_6g_supported(hdd_ctx->psoc, &oem_6g_disable);
586*5113495bSYour Name 	is_reg_6g_support = wlan_reg_is_6ghz_supported(hdd_ctx->psoc);
587*5113495bSYour Name 	set_wifi_pos_6g_disabled = (oem_6g_disable || !is_reg_6g_support);
588*5113495bSYour Name 
589*5113495bSYour Name 	/**
590*5113495bSYour Name 	 * Host uses following truth table to set wifi pos 6Ghz disable in
591*5113495bSYour Name 	 * ucfg_wifi_pos_set_oem_6g_supported().
592*5113495bSYour Name 	 * -----------------------------------------------------------------
593*5113495bSYour Name 	 * oem_6g_disable INI value | reg domain 6G support | Disable 6Ghz |
594*5113495bSYour Name 	 * -----------------------------------------------------------------
595*5113495bSYour Name 	 *            1             |           1           |        1     |
596*5113495bSYour Name 	 *            1             |           0           |        1     |
597*5113495bSYour Name 	 *            0             |           1           |        0     |
598*5113495bSYour Name 	 *            0             |           0           |        1     |
599*5113495bSYour Name 	 * -----------------------------------------------------------------
600*5113495bSYour Name 	 */
601*5113495bSYour Name 	ucfg_wifi_pos_set_oem_6g_supported(hdd_ctx->psoc,
602*5113495bSYour Name 					   set_wifi_pos_6g_disabled);
603*5113495bSYour Name 	hdd_debug("oem 6g support is - %s",
604*5113495bSYour Name 		  set_wifi_pos_6g_disabled ? "Disabled" : "Enabled");
605*5113495bSYour Name }
606*5113495bSYour Name 
607*5113495bSYour Name /**
608*5113495bSYour Name  * hdd_convert_string_to_array() - used to convert string into u8 array
609*5113495bSYour Name  * @str: String to be converted
610*5113495bSYour Name  * @array: Array where converted value is stored
611*5113495bSYour Name  * @len: Length of the populated array
612*5113495bSYour Name  * @array_max_len: Maximum length of the array
613*5113495bSYour Name  * @to_hex: true, if conversion required for hex string
614*5113495bSYour Name  *
615*5113495bSYour Name  * This API is called to convert string (each byte separated by
616*5113495bSYour Name  * a comma) into an u8 array
617*5113495bSYour Name  *
618*5113495bSYour Name  * Return: QDF_STATUS
619*5113495bSYour Name  */
620*5113495bSYour Name 
hdd_convert_string_to_array(char * str,uint8_t * array,uint8_t * len,uint16_t array_max_len,bool to_hex)621*5113495bSYour Name static QDF_STATUS hdd_convert_string_to_array(char *str, uint8_t *array,
622*5113495bSYour Name 			     uint8_t *len, uint16_t array_max_len, bool to_hex)
623*5113495bSYour Name {
624*5113495bSYour Name 	char *format, *s = str;
625*5113495bSYour Name 
626*5113495bSYour Name 	if (!str || !array || !len)
627*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
628*5113495bSYour Name 
629*5113495bSYour Name 	format = (to_hex) ? "%02x" : "%d";
630*5113495bSYour Name 
631*5113495bSYour Name 	*len = 0;
632*5113495bSYour Name 	while ((s) && (*len < array_max_len)) {
633*5113495bSYour Name 		int val;
634*5113495bSYour Name 		/* Increment length only if sscanf successfully extracted
635*5113495bSYour Name 		 * one element. Any other return value means error.
636*5113495bSYour Name 		 * Ignore it.
637*5113495bSYour Name 		 */
638*5113495bSYour Name 		if (sscanf(s, format, &val) == 1) {
639*5113495bSYour Name 			array[*len] = (uint8_t) val;
640*5113495bSYour Name 			*len += 1;
641*5113495bSYour Name 		}
642*5113495bSYour Name 
643*5113495bSYour Name 		s = strpbrk(s, ",");
644*5113495bSYour Name 		if (s)
645*5113495bSYour Name 			s++;
646*5113495bSYour Name 	}
647*5113495bSYour Name 
648*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
649*5113495bSYour Name }
650*5113495bSYour Name 
hdd_string_to_u8_array(char * str,uint8_t * array,uint8_t * len,uint16_t array_max_len)651*5113495bSYour Name QDF_STATUS hdd_string_to_u8_array(char *str, uint8_t *array,
652*5113495bSYour Name 				  uint8_t *len, uint16_t array_max_len)
653*5113495bSYour Name {
654*5113495bSYour Name 	return hdd_convert_string_to_array(str, array, len,
655*5113495bSYour Name 					   array_max_len, false);
656*5113495bSYour Name }
657*5113495bSYour Name 
658*5113495bSYour Name /**
659*5113495bSYour Name  * hdd_hex_string_to_u16_array() - convert a hex string to a uint16 array
660*5113495bSYour Name  * @str: input string
661*5113495bSYour Name  * @int_array: pointer to input array of type uint16
662*5113495bSYour Name  * @len: pointer to number of elements which the function adds to the array
663*5113495bSYour Name  * @int_array_max_len: maximum number of elements in input uint16 array
664*5113495bSYour Name  *
665*5113495bSYour Name  * This function is used to convert a space separated hex string to an array of
666*5113495bSYour Name  * uint16_t. For example, an input string str = "a b c d" would be converted to
667*5113495bSYour Name  * a unint16 array, int_array = {0xa, 0xb, 0xc, 0xd}, *len = 4.
668*5113495bSYour Name  * This assumes that input value int_array_max_len >= 4.
669*5113495bSYour Name  *
670*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS - if the conversion is successful
671*5113495bSYour Name  *         non zero value     - if the conversion is a failure
672*5113495bSYour Name  */
hdd_hex_string_to_u16_array(char * str,uint16_t * int_array,uint8_t * len,uint8_t int_array_max_len)673*5113495bSYour Name QDF_STATUS hdd_hex_string_to_u16_array(char *str,
674*5113495bSYour Name 		uint16_t *int_array, uint8_t *len, uint8_t int_array_max_len)
675*5113495bSYour Name {
676*5113495bSYour Name 	char *s = str;
677*5113495bSYour Name 	uint32_t val = 0;
678*5113495bSYour Name 
679*5113495bSYour Name 	if (!str || !int_array || !len)
680*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
681*5113495bSYour Name 
682*5113495bSYour Name 	hdd_debug("str %pK intArray %pK intArrayMaxLen %d",
683*5113495bSYour Name 		s, int_array, int_array_max_len);
684*5113495bSYour Name 
685*5113495bSYour Name 	*len = 0;
686*5113495bSYour Name 
687*5113495bSYour Name 	while ((s) && (*len < int_array_max_len)) {
688*5113495bSYour Name 		/*
689*5113495bSYour Name 		 * Increment length only if sscanf successfully extracted one
690*5113495bSYour Name 		 * element. Any other return value means error. Ignore it.
691*5113495bSYour Name 		 */
692*5113495bSYour Name 		if (sscanf(s, "%x", &val) == 1) {
693*5113495bSYour Name 			int_array[*len] = (uint16_t) val;
694*5113495bSYour Name 			hdd_debug("s %pK val %x intArray[%d]=0x%x",
695*5113495bSYour Name 				s, val, *len, int_array[*len]);
696*5113495bSYour Name 			*len += 1;
697*5113495bSYour Name 		}
698*5113495bSYour Name 		s = strpbrk(s, " ");
699*5113495bSYour Name 		if (s)
700*5113495bSYour Name 			s++;
701*5113495bSYour Name 	}
702*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
703*5113495bSYour Name }
704*5113495bSYour Name 
705*5113495bSYour Name /**
706*5113495bSYour Name  * hdd_update_config_cfg() - API to update INI setting based on hw/fw caps
707*5113495bSYour Name  * @hdd_ctx: pointer to hdd_ctx
708*5113495bSYour Name  *
709*5113495bSYour Name  * This API reads the cfg file which is updated with hardware/firmware
710*5113495bSYour Name  * capabilities and intersect it with INI setting provided by user. After
711*5113495bSYour Name  * taking intersection it adjust cfg it self. For example, if user has enabled
712*5113495bSYour Name  * RX LDPC through INI but hardware/firmware doesn't support it then disable
713*5113495bSYour Name  * it in CFG file here.
714*5113495bSYour Name  *
715*5113495bSYour Name  * Return: true or false based on outcome.
716*5113495bSYour Name  */
hdd_update_config_cfg(struct hdd_context * hdd_ctx)717*5113495bSYour Name bool hdd_update_config_cfg(struct hdd_context *hdd_ctx)
718*5113495bSYour Name {
719*5113495bSYour Name 	bool status = true;
720*5113495bSYour Name 
721*5113495bSYour Name 	/*
722*5113495bSYour Name 	 * During the initialization both 2G and 5G capabilities should be same.
723*5113495bSYour Name 	 * So read 5G HT capability and update 2G and 5G capabilities.
724*5113495bSYour Name 	 */
725*5113495bSYour Name 
726*5113495bSYour Name 	if (0 != hdd_update_he_cap_in_cfg(hdd_ctx)) {
727*5113495bSYour Name 		status = false;
728*5113495bSYour Name 		hdd_err("Couldn't set HE CAP in cfg");
729*5113495bSYour Name 	}
730*5113495bSYour Name 
731*5113495bSYour Name 	return status;
732*5113495bSYour Name }
733*5113495bSYour Name 
734*5113495bSYour Name /**
735*5113495bSYour Name  * hdd_set_policy_mgr_user_cfg() -initializes the policy manager
736*5113495bSYour Name  * configuration parameters
737*5113495bSYour Name  *
738*5113495bSYour Name  * @hdd_ctx: the pointer to hdd context
739*5113495bSYour Name  *
740*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS if configuration is correctly applied,
741*5113495bSYour Name  *		otherwise the appropriate QDF_STATUS would be returned
742*5113495bSYour Name  */
hdd_set_policy_mgr_user_cfg(struct hdd_context * hdd_ctx)743*5113495bSYour Name QDF_STATUS hdd_set_policy_mgr_user_cfg(struct hdd_context *hdd_ctx)
744*5113495bSYour Name {
745*5113495bSYour Name 	QDF_STATUS status;
746*5113495bSYour Name 	struct policy_mgr_user_cfg *user_cfg;
747*5113495bSYour Name 
748*5113495bSYour Name 	user_cfg = qdf_mem_malloc(sizeof(*user_cfg));
749*5113495bSYour Name 	if (!user_cfg)
750*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
751*5113495bSYour Name 
752*5113495bSYour Name 	status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc,
753*5113495bSYour Name 					     &user_cfg->enable2x2);
754*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status))
755*5113495bSYour Name 		hdd_err("unable to get vht_enable2x2");
756*5113495bSYour Name 
757*5113495bSYour Name 	user_cfg->sub_20_mhz_enabled = cds_is_sub_20_mhz_enabled();
758*5113495bSYour Name 	status = policy_mgr_set_user_cfg(hdd_ctx->psoc, user_cfg);
759*5113495bSYour Name 	qdf_mem_free(user_cfg);
760*5113495bSYour Name 
761*5113495bSYour Name 	return status;
762*5113495bSYour Name }
763*5113495bSYour Name 
hdd_to_csr_wmm_mode(uint8_t mode)764*5113495bSYour Name enum wmm_user_mode hdd_to_csr_wmm_mode(uint8_t mode)
765*5113495bSYour Name {
766*5113495bSYour Name 	switch (mode) {
767*5113495bSYour Name 	case HDD_WMM_USER_MODE_QBSS_ONLY:
768*5113495bSYour Name 		return WMM_USER_MODE_QBSS_ONLY;
769*5113495bSYour Name 	case HDD_WMM_USER_MODE_NO_QOS:
770*5113495bSYour Name 		return WMM_USER_MODE_NO_QOS;
771*5113495bSYour Name 	case HDD_WMM_USER_MODE_AUTO:
772*5113495bSYour Name 	default:
773*5113495bSYour Name 		return WMM_USER_MODE_AUTO;
774*5113495bSYour Name 	}
775*5113495bSYour Name }
776*5113495bSYour Name 
777*5113495bSYour Name static QDF_STATUS
hdd_set_sme_cfgs_related_to_plcy_mgr(struct hdd_context * hdd_ctx,struct sme_config_params * sme_cfg)778*5113495bSYour Name hdd_set_sme_cfgs_related_to_plcy_mgr(struct hdd_context *hdd_ctx,
779*5113495bSYour Name 				     struct sme_config_params *sme_cfg)
780*5113495bSYour Name {
781*5113495bSYour Name 	uint8_t mcc_to_scc_switch = 0, is_force_1x1 = 0, allow_diff_bi = 0;
782*5113495bSYour Name 	uint8_t conc_rule1 = 0, conc_rule2 = 0, sta_cxn_5g = 0;
783*5113495bSYour Name 
784*5113495bSYour Name 	if (QDF_STATUS_SUCCESS !=
785*5113495bSYour Name 	    ucfg_policy_mgr_get_mcc_scc_switch(hdd_ctx->psoc,
786*5113495bSYour Name 					       &mcc_to_scc_switch)) {
787*5113495bSYour Name 		hdd_err("can't get mcc to scc switch");
788*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
789*5113495bSYour Name 	}
790*5113495bSYour Name 	sme_cfg->csr_config.cc_switch_mode = mcc_to_scc_switch;
791*5113495bSYour Name 
792*5113495bSYour Name 	if (QDF_STATUS_SUCCESS !=
793*5113495bSYour Name 	    ucfg_policy_mgr_get_conc_rule1(hdd_ctx->psoc,
794*5113495bSYour Name 					   &conc_rule1)) {
795*5113495bSYour Name 		hdd_err("can't get conc rule1");
796*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
797*5113495bSYour Name 	}
798*5113495bSYour Name 	sme_cfg->csr_config.conc_custom_rule1 = conc_rule1;
799*5113495bSYour Name 
800*5113495bSYour Name 	if (QDF_STATUS_SUCCESS !=
801*5113495bSYour Name 	    ucfg_policy_mgr_get_conc_rule2(hdd_ctx->psoc,
802*5113495bSYour Name 					   &conc_rule2)) {
803*5113495bSYour Name 		hdd_err("can't get conc rule2");
804*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
805*5113495bSYour Name 	}
806*5113495bSYour Name 	sme_cfg->csr_config.conc_custom_rule2 = conc_rule2;
807*5113495bSYour Name 
808*5113495bSYour Name 	if (QDF_STATUS_SUCCESS !=
809*5113495bSYour Name 	    ucfg_policy_mgr_get_sta_cxn_5g_band(hdd_ctx->psoc,
810*5113495bSYour Name 						&sta_cxn_5g)) {
811*5113495bSYour Name 		hdd_err("can't get conc rule2");
812*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
813*5113495bSYour Name 	}
814*5113495bSYour Name 	sme_cfg->csr_config.is_sta_connection_in_5gz_enabled = sta_cxn_5g;
815*5113495bSYour Name 
816*5113495bSYour Name 	if (QDF_STATUS_SUCCESS !=
817*5113495bSYour Name 	    ucfg_policy_mgr_get_force_1x1(hdd_ctx->psoc,
818*5113495bSYour Name 					  &is_force_1x1)) {
819*5113495bSYour Name 		hdd_err("can't get force 1x1 flag");
820*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
821*5113495bSYour Name 	}
822*5113495bSYour Name 	sme_cfg->csr_config.is_force_1x1 = is_force_1x1;
823*5113495bSYour Name 
824*5113495bSYour Name 	if (QDF_STATUS_SUCCESS !=
825*5113495bSYour Name 	    ucfg_policy_mgr_get_allow_mcc_go_diff_bi(hdd_ctx->psoc,
826*5113495bSYour Name 						     &allow_diff_bi)) {
827*5113495bSYour Name 		hdd_err("can't get allow mcc go diff BI flag");
828*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
829*5113495bSYour Name 	}
830*5113495bSYour Name 	sme_cfg->csr_config.fAllowMCCGODiffBI = allow_diff_bi;
831*5113495bSYour Name 
832*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
833*5113495bSYour Name }
834*5113495bSYour Name 
835*5113495bSYour Name #ifdef FEATURE_AP_MCC_CH_AVOIDANCE
hdd_set_sap_mcc_chnl_avoid(struct sme_config_params * sme_cfg,uint8_t val)836*5113495bSYour Name static QDF_STATUS hdd_set_sap_mcc_chnl_avoid(struct sme_config_params *sme_cfg,
837*5113495bSYour Name 					     uint8_t val)
838*5113495bSYour Name {
839*5113495bSYour Name 	sme_cfg->csr_config.sap_channel_avoidance = val;
840*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
841*5113495bSYour Name }
842*5113495bSYour Name #else
hdd_set_sap_mcc_chnl_avoid(struct sme_config_params * sme_cfg,uint8_t val)843*5113495bSYour Name static QDF_STATUS hdd_set_sap_mcc_chnl_avoid(struct sme_config_params *sme_cfg,
844*5113495bSYour Name 					     uint8_t val)
845*5113495bSYour Name {
846*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
847*5113495bSYour Name }
848*5113495bSYour Name #endif
849*5113495bSYour Name 
850*5113495bSYour Name static
hdd_set_sme_cfgs_related_to_mlme(struct hdd_context * hdd_ctx,struct sme_config_params * sme_cfg)851*5113495bSYour Name QDF_STATUS hdd_set_sme_cfgs_related_to_mlme(struct hdd_context *hdd_ctx,
852*5113495bSYour Name 					    struct sme_config_params *sme_cfg)
853*5113495bSYour Name {
854*5113495bSYour Name 	QDF_STATUS status;
855*5113495bSYour Name 	uint8_t wmm_mode = 0, enable_mcc = 0, sap_mcc_avoid = 0;
856*5113495bSYour Name 	uint8_t mcc_rts_cts = 0, mcc_bcast_prob_rsp = 0;
857*5113495bSYour Name 	uint32_t mcast_mcc_rest_time = 0;
858*5113495bSYour Name 	bool b80211e_enabled = 0;
859*5113495bSYour Name 
860*5113495bSYour Name 	status = ucfg_mlme_get_80211e_is_enabled(hdd_ctx->psoc,
861*5113495bSYour Name 						 &b80211e_enabled);
862*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status)) {
863*5113495bSYour Name 		hdd_err("Get b80211e_enabled failed");
864*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
865*5113495bSYour Name 	}
866*5113495bSYour Name 	sme_cfg->csr_config.Is11eSupportEnabled = b80211e_enabled;
867*5113495bSYour Name 
868*5113495bSYour Name 	status = ucfg_mlme_get_wmm_mode(hdd_ctx->psoc, &wmm_mode);
869*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status)) {
870*5113495bSYour Name 		hdd_err("Get wmm_mode failed");
871*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
872*5113495bSYour Name 	}
873*5113495bSYour Name 	sme_cfg->csr_config.WMMSupportMode = hdd_to_csr_wmm_mode(wmm_mode);
874*5113495bSYour Name 	hdd_debug("wmm_mode=%d 802_11e_enabled=%d", wmm_mode, b80211e_enabled);
875*5113495bSYour Name 
876*5113495bSYour Name 	status = ucfg_mlme_get_mcc_feature(hdd_ctx->psoc, &enable_mcc);
877*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status)) {
878*5113495bSYour Name 		hdd_err("ucfg_mlme_get_mcc_feature fail, use def");
879*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
880*5113495bSYour Name 	}
881*5113495bSYour Name 	sme_cfg->csr_config.fEnableMCCMode = enable_mcc;
882*5113495bSYour Name 
883*5113495bSYour Name 	status = ucfg_mlme_get_mcc_rts_cts_prot(hdd_ctx->psoc, &mcc_rts_cts);
884*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status)) {
885*5113495bSYour Name 		hdd_err("ucfg_mlme_get_mcc_rts_cts_prot fail, use def");
886*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
887*5113495bSYour Name 	}
888*5113495bSYour Name 	sme_cfg->csr_config.mcc_rts_cts_prot_enable = mcc_rts_cts;
889*5113495bSYour Name 
890*5113495bSYour Name 	status = ucfg_mlme_get_mcc_bcast_prob_resp(hdd_ctx->psoc,
891*5113495bSYour Name 						   &mcc_bcast_prob_rsp);
892*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status)) {
893*5113495bSYour Name 		hdd_err("ucfg_mlme_get_mcc_bcast_prob_resp fail, use def");
894*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
895*5113495bSYour Name 	}
896*5113495bSYour Name 	sme_cfg->csr_config.mcc_bcast_prob_resp_enable = mcc_bcast_prob_rsp;
897*5113495bSYour Name 
898*5113495bSYour Name 	status = ucfg_mlme_get_sta_miracast_mcc_rest_time(hdd_ctx->psoc,
899*5113495bSYour Name 							  &mcast_mcc_rest_time);
900*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status)) {
901*5113495bSYour Name 		hdd_err("ucfg_mlme_get_sta_miracast_mcc_rest_time, use def");
902*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
903*5113495bSYour Name 	}
904*5113495bSYour Name 	sme_cfg->csr_config.f_sta_miracast_mcc_rest_time_val =
905*5113495bSYour Name 							mcast_mcc_rest_time;
906*5113495bSYour Name 	status = ucfg_mlme_get_sap_mcc_chnl_avoid(hdd_ctx->psoc,
907*5113495bSYour Name 						  &sap_mcc_avoid);
908*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status)) {
909*5113495bSYour Name 		hdd_err("ucfg_mlme_get_sap_mcc_chnl_avoid, use def");
910*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
911*5113495bSYour Name 	}
912*5113495bSYour Name 	status = hdd_set_sap_mcc_chnl_avoid(sme_cfg, sap_mcc_avoid);
913*5113495bSYour Name 
914*5113495bSYour Name 	return status;
915*5113495bSYour Name }
916*5113495bSYour Name 
917*5113495bSYour Name /**
918*5113495bSYour Name  * hdd_set_sme_config() -initializes the sme configuration parameters
919*5113495bSYour Name  *
920*5113495bSYour Name  * @hdd_ctx: the pointer to hdd context
921*5113495bSYour Name  *
922*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS if configuration is correctly applied,
923*5113495bSYour Name  *		otherwise the appropriate QDF_STATUS would be returned
924*5113495bSYour Name  */
hdd_set_sme_config(struct hdd_context * hdd_ctx)925*5113495bSYour Name QDF_STATUS hdd_set_sme_config(struct hdd_context *hdd_ctx)
926*5113495bSYour Name {
927*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
928*5113495bSYour Name 	struct sme_config_params *sme_config;
929*5113495bSYour Name 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
930*5113495bSYour Name 	bool roam_scan_enabled;
931*5113495bSYour Name 	bool enable_dfs_scan = true;
932*5113495bSYour Name 	bool disconnect_nud;
933*5113495bSYour Name 	uint32_t channel_bonding_mode;
934*5113495bSYour Name 
935*5113495bSYour Name #ifdef FEATURE_WLAN_ESE
936*5113495bSYour Name 	bool ese_enabled;
937*5113495bSYour Name #endif
938*5113495bSYour Name 	struct hdd_config *config = hdd_ctx->config;
939*5113495bSYour Name 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
940*5113495bSYour Name 
941*5113495bSYour Name 	mlme_obj = mlme_get_psoc_ext_obj(hdd_ctx->psoc);
942*5113495bSYour Name 	if (!mlme_obj)
943*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
944*5113495bSYour Name 
945*5113495bSYour Name 	sme_config = qdf_mem_malloc(sizeof(*sme_config));
946*5113495bSYour Name 	if (!sme_config)
947*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
948*5113495bSYour Name 
949*5113495bSYour Name 	/* Config params obtained from the registry
950*5113495bSYour Name 	 * To Do: set regulatory information here
951*5113495bSYour Name 	 */
952*5113495bSYour Name 	sme_config->csr_config.phyMode =
953*5113495bSYour Name 		hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
954*5113495bSYour Name 
955*5113495bSYour Name 	if (config->dot11Mode == eHDD_DOT11_MODE_abg ||
956*5113495bSYour Name 	    config->dot11Mode == eHDD_DOT11_MODE_11b ||
957*5113495bSYour Name 	    config->dot11Mode == eHDD_DOT11_MODE_11g ||
958*5113495bSYour Name 	    config->dot11Mode == eHDD_DOT11_MODE_11b_ONLY ||
959*5113495bSYour Name 	    config->dot11Mode == eHDD_DOT11_MODE_11g_ONLY) {
960*5113495bSYour Name 		sme_config->csr_config.channelBondingMode24GHz = 0;
961*5113495bSYour Name 		sme_config->csr_config.channelBondingMode5GHz = 0;
962*5113495bSYour Name 	} else {
963*5113495bSYour Name 		ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
964*5113495bSYour Name 						    &channel_bonding_mode);
965*5113495bSYour Name 		sme_config->csr_config.channelBondingMode24GHz =
966*5113495bSYour Name 			channel_bonding_mode;
967*5113495bSYour Name 		ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc,
968*5113495bSYour Name 						   &channel_bonding_mode);
969*5113495bSYour Name 		sme_config->csr_config.channelBondingMode5GHz =
970*5113495bSYour Name 			channel_bonding_mode;
971*5113495bSYour Name 	}
972*5113495bSYour Name 	/* Remaining config params not obtained from registry
973*5113495bSYour Name 	 * On RF EVB beacon using channel 1.
974*5113495bSYour Name 	 */
975*5113495bSYour Name 	/* This param cannot be configured from INI */
976*5113495bSYour Name 	sme_config->csr_config.send_smps_action = true;
977*5113495bSYour Name 	sme_config->csr_config.ProprietaryRatesEnabled = 0;
978*5113495bSYour Name 	sme_config->csr_config.HeartbeatThresh50 = 40;
979*5113495bSYour Name 	ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
980*5113495bSYour Name 						&enable_dfs_scan);
981*5113495bSYour Name 	sme_config->csr_config.fEnableDFSChnlScan = enable_dfs_scan;
982*5113495bSYour Name 	sme_config->csr_config.Csr11dinfo.Channels.numChannels = 0;
983*5113495bSYour Name 	hdd_set_power_save_offload_config(hdd_ctx);
984*5113495bSYour Name 
985*5113495bSYour Name #ifdef FEATURE_WLAN_ESE
986*5113495bSYour Name 	ucfg_mlme_is_ese_enabled(hdd_ctx->psoc, &ese_enabled);
987*5113495bSYour Name 	if (ese_enabled)
988*5113495bSYour Name 		ucfg_mlme_set_fast_transition_enabled(hdd_ctx->psoc, true);
989*5113495bSYour Name #endif
990*5113495bSYour Name 
991*5113495bSYour Name 	ucfg_mlme_is_roam_scan_offload_enabled(hdd_ctx->psoc,
992*5113495bSYour Name 					       &roam_scan_enabled);
993*5113495bSYour Name 
994*5113495bSYour Name 	if (!roam_scan_enabled) {
995*5113495bSYour Name 		/* Disable roaming in concurrency if roam scan
996*5113495bSYour Name 		 * offload is disabled
997*5113495bSYour Name 		 */
998*5113495bSYour Name 		ucfg_mlme_set_fast_roam_in_concurrency_enabled(
999*5113495bSYour Name 					hdd_ctx->psoc, false);
1000*5113495bSYour Name 	}
1001*5113495bSYour Name 
1002*5113495bSYour Name 	/* Update maximum interfaces information */
1003*5113495bSYour Name 	sme_config->csr_config.max_intf_count = hdd_ctx->max_intf_count;
1004*5113495bSYour Name 
1005*5113495bSYour Name 	hdd_set_fine_time_meas_cap(hdd_ctx);
1006*5113495bSYour Name 	hdd_set_oem_6g_supported(hdd_ctx);
1007*5113495bSYour Name 
1008*5113495bSYour Name 	cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
1009*5113495bSYour Name 
1010*5113495bSYour Name 	mlme_obj->cfg.lfr.rso_user_config.policy_params.dfs_mode =
1011*5113495bSYour Name 		STA_ROAM_POLICY_DFS_ENABLED;
1012*5113495bSYour Name 	mlme_obj->cfg.lfr.rso_user_config.policy_params.skip_unsafe_channels = 0;
1013*5113495bSYour Name 
1014*5113495bSYour Name 	disconnect_nud = ucfg_dp_is_disconect_after_roam_fail(hdd_ctx->psoc);
1015*5113495bSYour Name 	mlme_obj->cfg.lfr.disconnect_on_nud_roam_invoke_fail = disconnect_nud;
1016*5113495bSYour Name 
1017*5113495bSYour Name 	status = hdd_set_sme_cfgs_related_to_mlme(hdd_ctx, sme_config);
1018*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status))
1019*5113495bSYour Name 		hdd_err("hdd_set_sme_cfgs_related_to_mlme() fail: %d", status);
1020*5113495bSYour Name 	status = hdd_set_sme_cfgs_related_to_plcy_mgr(hdd_ctx, sme_config);
1021*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status))
1022*5113495bSYour Name 		hdd_err("hdd_set_sme_cfgs_related_to_plcy_mgr fail: %d",
1023*5113495bSYour Name 			status);
1024*5113495bSYour Name 	hdd_debug("dot11Mode=%d", config->dot11Mode);
1025*5113495bSYour Name 	status = sme_update_config(mac_handle, sme_config);
1026*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(status))
1027*5113495bSYour Name 		hdd_err("sme_update_config() failure: %d", status);
1028*5113495bSYour Name 
1029*5113495bSYour Name 	qdf_mem_free(sme_config);
1030*5113495bSYour Name 	return status;
1031*5113495bSYour Name }
1032*5113495bSYour Name 
1033*5113495bSYour Name /**
1034*5113495bSYour Name  * hdd_cfg_get_global_config() - get the configuration table
1035*5113495bSYour Name  * @hdd_ctx: pointer to hdd context
1036*5113495bSYour Name  * @buf: buffer to store the configuration
1037*5113495bSYour Name  * @buflen: size of the buffer
1038*5113495bSYour Name  *
1039*5113495bSYour Name  * Return: none
1040*5113495bSYour Name  */
hdd_cfg_get_global_config(struct hdd_context * hdd_ctx,char * buf,int buflen)1041*5113495bSYour Name void hdd_cfg_get_global_config(struct hdd_context *hdd_ctx, char *buf,
1042*5113495bSYour Name 			       int buflen)
1043*5113495bSYour Name {
1044*5113495bSYour Name 	ucfg_cfg_store_print(hdd_ctx->psoc);
1045*5113495bSYour Name 
1046*5113495bSYour Name 	snprintf(buf, buflen,
1047*5113495bSYour Name 		 "WLAN configuration written to debug log");
1048*5113495bSYour Name }
1049*5113495bSYour Name 
1050*5113495bSYour Name /**
1051*5113495bSYour Name  * hdd_cfg_print_global_config() - print the configuration table
1052*5113495bSYour Name  * @hdd_ctx: pointer to hdd context
1053*5113495bSYour Name  *
1054*5113495bSYour Name  * Return: none
1055*5113495bSYour Name  */
hdd_cfg_print_global_config(struct hdd_context * hdd_ctx)1056*5113495bSYour Name void hdd_cfg_print_global_config(struct hdd_context *hdd_ctx)
1057*5113495bSYour Name {
1058*5113495bSYour Name 	QDF_STATUS status;
1059*5113495bSYour Name 
1060*5113495bSYour Name 	status = ucfg_cfg_store_print(hdd_ctx->psoc);
1061*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
1062*5113495bSYour Name 		hdd_err("Failed to log cfg ini");
1063*5113495bSYour Name }
1064*5113495bSYour Name 
1065*5113495bSYour Name /**
1066*5113495bSYour Name  * hdd_get_pmkid_modes() - returns PMKID mode bits
1067*5113495bSYour Name  * @hdd_ctx: the pointer to hdd context
1068*5113495bSYour Name  * @pmkid_modes: struct to update with current PMKID modes
1069*5113495bSYour Name  *
1070*5113495bSYour Name  * Return: value of pmkid_modes
1071*5113495bSYour Name  */
hdd_get_pmkid_modes(struct hdd_context * hdd_ctx,struct pmkid_mode_bits * pmkid_modes)1072*5113495bSYour Name void hdd_get_pmkid_modes(struct hdd_context *hdd_ctx,
1073*5113495bSYour Name 			 struct pmkid_mode_bits *pmkid_modes)
1074*5113495bSYour Name {
1075*5113495bSYour Name 	uint32_t cur_pmkid_modes;
1076*5113495bSYour Name 	QDF_STATUS status;
1077*5113495bSYour Name 
1078*5113495bSYour Name 	status = ucfg_mlme_get_pmkid_modes(hdd_ctx->psoc, &cur_pmkid_modes);
1079*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS)
1080*5113495bSYour Name 		hdd_err("get pmkid modes fail");
1081*5113495bSYour Name 
1082*5113495bSYour Name 	pmkid_modes->fw_okc = (cur_pmkid_modes &
1083*5113495bSYour Name 			       CFG_PMKID_MODES_OKC) ? 1 : 0;
1084*5113495bSYour Name 	pmkid_modes->fw_pmksa_cache = (cur_pmkid_modes &
1085*5113495bSYour Name 				       CFG_PMKID_MODES_PMKSA_CACHING) ? 1 : 0;
1086*5113495bSYour Name }
1087*5113495bSYour Name 
1088*5113495bSYour Name static void
hdd_populate_vdev_nss(struct wlan_mlme_nss_chains * user_cfg,uint8_t tx_nss,uint8_t rx_nss,enum nss_chains_band_info band)1089*5113495bSYour Name hdd_populate_vdev_nss(struct wlan_mlme_nss_chains *user_cfg,
1090*5113495bSYour Name 		      uint8_t tx_nss,
1091*5113495bSYour Name 		      uint8_t rx_nss,
1092*5113495bSYour Name 		      enum nss_chains_band_info  band)
1093*5113495bSYour Name {
1094*5113495bSYour Name 	user_cfg->rx_nss[band] = rx_nss;
1095*5113495bSYour Name 	user_cfg->tx_nss[band] = tx_nss;
1096*5113495bSYour Name }
1097*5113495bSYour Name 
hdd_set_nss_params(struct wlan_hdd_link_info * link_info,uint8_t tx_nss,uint8_t rx_nss)1098*5113495bSYour Name static QDF_STATUS hdd_set_nss_params(struct wlan_hdd_link_info *link_info,
1099*5113495bSYour Name 				     uint8_t tx_nss, uint8_t rx_nss)
1100*5113495bSYour Name {
1101*5113495bSYour Name 	enum nss_chains_band_info band;
1102*5113495bSYour Name 	struct wlan_mlme_nss_chains user_cfg;
1103*5113495bSYour Name 	mac_handle_t mac_handle;
1104*5113495bSYour Name 	struct hdd_adapter *adapter = link_info->adapter;
1105*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1106*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1107*5113495bSYour Name 
1108*5113495bSYour Name 	qdf_mem_zero(&user_cfg, sizeof(user_cfg));
1109*5113495bSYour Name 
1110*5113495bSYour Name 	mac_handle = hdd_ctx->mac_handle;
1111*5113495bSYour Name 	if (!mac_handle) {
1112*5113495bSYour Name 		hdd_err("NULL MAC handle");
1113*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1114*5113495bSYour Name 	}
1115*5113495bSYour Name 
1116*5113495bSYour Name 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(hdd_ctx->pdev,
1117*5113495bSYour Name 						    link_info->vdev_id,
1118*5113495bSYour Name 						    WLAN_HDD_ID_OBJ_MGR);
1119*5113495bSYour Name 	if (!vdev) {
1120*5113495bSYour Name 		hdd_err("vdev is NULL %d", link_info->vdev_id);
1121*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1122*5113495bSYour Name 	}
1123*5113495bSYour Name 
1124*5113495bSYour Name 	/* For STA tx/rx nss value is updated at the time of connection,
1125*5113495bSYour Name 	 * for SAP case nss values will not get update, so can skip check
1126*5113495bSYour Name 	 * for SAP/P2P_GO mode.
1127*5113495bSYour Name 	 */
1128*5113495bSYour Name 	if (adapter->device_mode != QDF_SAP_MODE &&
1129*5113495bSYour Name 	    adapter->device_mode != QDF_P2P_GO_MODE &&
1130*5113495bSYour Name 	    (tx_nss > wlan_vdev_mlme_get_nss(vdev) ||
1131*5113495bSYour Name 	    rx_nss > wlan_vdev_mlme_get_nss(vdev))) {
1132*5113495bSYour Name 		hdd_err("Given tx nss/rx nss is greater than intersected nss = %d",
1133*5113495bSYour Name 			wlan_vdev_mlme_get_nss(vdev));
1134*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_HDD_ID_OBJ_MGR);
1135*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1136*5113495bSYour Name 	}
1137*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_HDD_ID_OBJ_MGR);
1138*5113495bSYour Name 
1139*5113495bSYour Name 	for (band = NSS_CHAINS_BAND_2GHZ; band < NSS_CHAINS_BAND_MAX; band++)
1140*5113495bSYour Name 		hdd_populate_vdev_nss(&user_cfg, tx_nss, rx_nss, band);
1141*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(
1142*5113495bSYour Name 		sme_nss_chains_update(mac_handle, &user_cfg,
1143*5113495bSYour Name 				      link_info->vdev_id)))
1144*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1145*5113495bSYour Name 
1146*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1147*5113495bSYour Name }
1148*5113495bSYour Name 
hdd_update_nss_in_vdev(struct wlan_hdd_link_info * link_info,mac_handle_t mac_handle,uint8_t tx_nss,uint8_t rx_nss)1149*5113495bSYour Name static void hdd_update_nss_in_vdev(struct wlan_hdd_link_info *link_info,
1150*5113495bSYour Name 				   mac_handle_t mac_handle, uint8_t tx_nss,
1151*5113495bSYour Name 				   uint8_t rx_nss)
1152*5113495bSYour Name {
1153*5113495bSYour Name 	uint8_t band, max_supp_nss = MAX_VDEV_NSS;
1154*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1155*5113495bSYour Name 	struct hdd_adapter *adapter = link_info->adapter;
1156*5113495bSYour Name 
1157*5113495bSYour Name 	for (band = NSS_CHAINS_BAND_2GHZ; band < NSS_CHAINS_BAND_MAX;
1158*5113495bSYour Name 	     band++) {
1159*5113495bSYour Name 		/* This API will change the global ini in mlme cfg */
1160*5113495bSYour Name 		sme_update_nss_in_mlme_cfg(mac_handle, rx_nss, tx_nss,
1161*5113495bSYour Name 					   adapter->device_mode, band);
1162*5113495bSYour Name 		/*
1163*5113495bSYour Name 		 * This API will change the vdev nss params in mac
1164*5113495bSYour Name 		 * context
1165*5113495bSYour Name 		 */
1166*5113495bSYour Name 		sme_update_vdev_type_nss(mac_handle, max_supp_nss, band);
1167*5113495bSYour Name 	}
1168*5113495bSYour Name 	/*
1169*5113495bSYour Name 	 * This API will change the ini and dynamic nss params in
1170*5113495bSYour Name 	 * mlme vdev priv obj.
1171*5113495bSYour Name 	 */
1172*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
1173*5113495bSYour Name 	if (!vdev)
1174*5113495bSYour Name 		return;
1175*5113495bSYour Name 
1176*5113495bSYour Name 	hdd_store_nss_chains_cfg_in_vdev(adapter->hdd_ctx, vdev);
1177*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1178*5113495bSYour Name }
1179*5113495bSYour Name 
hdd_set_sap_nss_params(struct wlan_hdd_link_info * link_info,mac_handle_t mac_handle,uint8_t tx_nss,uint8_t rx_nss)1180*5113495bSYour Name static void hdd_set_sap_nss_params(struct wlan_hdd_link_info *link_info,
1181*5113495bSYour Name 				   mac_handle_t mac_handle,
1182*5113495bSYour Name 				   uint8_t tx_nss, uint8_t rx_nss)
1183*5113495bSYour Name {
1184*5113495bSYour Name 	hdd_update_nss_in_vdev(link_info, mac_handle, tx_nss, rx_nss);
1185*5113495bSYour Name 	hdd_restart_sap(link_info);
1186*5113495bSYour Name }
1187*5113495bSYour Name 
1188*5113495bSYour Name /**
1189*5113495bSYour Name  * hdd_get_sap_rx_nss() - get the sap rx nss
1190*5113495bSYour Name  * @link_info: Pointer to link_info
1191*5113495bSYour Name  * @rx_nss: pointer to rx_nss
1192*5113495bSYour Name  *
1193*5113495bSYour Name  * get the sap tx nss
1194*5113495bSYour Name  *
1195*5113495bSYour Name  * Return: None
1196*5113495bSYour Name  */
1197*5113495bSYour Name static QDF_STATUS
hdd_get_sap_rx_nss(struct wlan_hdd_link_info * link_info,uint8_t * rx_nss)1198*5113495bSYour Name hdd_get_sap_rx_nss(struct wlan_hdd_link_info *link_info, uint8_t *rx_nss)
1199*5113495bSYour Name {
1200*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
1201*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1202*5113495bSYour Name 	struct wlan_mlme_nss_chains *dynamic_cfg;
1203*5113495bSYour Name 	enum band_info operating_band;
1204*5113495bSYour Name 	mac_handle_t mac_handle;
1205*5113495bSYour Name 	uint8_t vdev_nss;
1206*5113495bSYour Name 
1207*5113495bSYour Name 	mac_handle = hdd_ctx->mac_handle;
1208*5113495bSYour Name 	if (!mac_handle) {
1209*5113495bSYour Name 		hdd_debug("NULL MAC handle");
1210*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1211*5113495bSYour Name 	}
1212*5113495bSYour Name 
1213*5113495bSYour Name 	operating_band = hdd_get_sap_operating_band_by_link_info(link_info);
1214*5113495bSYour Name 	if (operating_band == BAND_UNKNOWN)
1215*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1216*5113495bSYour Name 
1217*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
1218*5113495bSYour Name 	if (!vdev)
1219*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1220*5113495bSYour Name 
1221*5113495bSYour Name 	sme_get_sap_vdev_type_nss(mac_handle, &vdev_nss, operating_band);
1222*5113495bSYour Name 	if (hdd_ctx->dynamic_nss_chains_support) {
1223*5113495bSYour Name 		dynamic_cfg = mlme_get_dynamic_vdev_config(vdev);
1224*5113495bSYour Name 		if (!dynamic_cfg) {
1225*5113495bSYour Name 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1226*5113495bSYour Name 			hdd_debug("nss chain dynamic config NULL");
1227*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1228*5113495bSYour Name 		}
1229*5113495bSYour Name 		switch (operating_band) {
1230*5113495bSYour Name 		case BAND_2G:
1231*5113495bSYour Name 			*rx_nss = dynamic_cfg->rx_nss[NSS_CHAINS_BAND_2GHZ];
1232*5113495bSYour Name 			break;
1233*5113495bSYour Name 		case BAND_5G:
1234*5113495bSYour Name 			*rx_nss = dynamic_cfg->rx_nss[NSS_CHAINS_BAND_5GHZ];
1235*5113495bSYour Name 			break;
1236*5113495bSYour Name 		default:
1237*5113495bSYour Name 			hdd_debug("Band %d Not 2G or 5G", operating_band);
1238*5113495bSYour Name 			break;
1239*5113495bSYour Name 		}
1240*5113495bSYour Name 	} else {
1241*5113495bSYour Name 		*rx_nss = vdev_nss;
1242*5113495bSYour Name 	}
1243*5113495bSYour Name 
1244*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1245*5113495bSYour Name 	return  QDF_STATUS_SUCCESS;
1246*5113495bSYour Name }
1247*5113495bSYour Name 
1248*5113495bSYour Name /**
1249*5113495bSYour Name  * hdd_get_sap_tx_nss() - get the sap tx nss
1250*5113495bSYour Name  * @link_info: Pointer of link_info
1251*5113495bSYour Name  * @tx_nss: pointer to tx_nss
1252*5113495bSYour Name  *
1253*5113495bSYour Name  * get the sap tx nss
1254*5113495bSYour Name  *
1255*5113495bSYour Name  * Return: None
1256*5113495bSYour Name  */
1257*5113495bSYour Name static QDF_STATUS
hdd_get_sap_tx_nss(struct wlan_hdd_link_info * link_info,uint8_t * tx_nss)1258*5113495bSYour Name hdd_get_sap_tx_nss(struct wlan_hdd_link_info *link_info, uint8_t *tx_nss)
1259*5113495bSYour Name {
1260*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
1261*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1262*5113495bSYour Name 	struct wlan_mlme_nss_chains *dynamic_cfg;
1263*5113495bSYour Name 	enum band_info operating_band;
1264*5113495bSYour Name 	mac_handle_t mac_handle;
1265*5113495bSYour Name 	uint8_t vdev_nss;
1266*5113495bSYour Name 
1267*5113495bSYour Name 	mac_handle = hdd_ctx->mac_handle;
1268*5113495bSYour Name 	if (!mac_handle) {
1269*5113495bSYour Name 		hdd_debug("NULL MAC handle");
1270*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1271*5113495bSYour Name 	}
1272*5113495bSYour Name 
1273*5113495bSYour Name 	operating_band = hdd_get_sap_operating_band_by_link_info(link_info);
1274*5113495bSYour Name 	if (operating_band == BAND_UNKNOWN)
1275*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1276*5113495bSYour Name 
1277*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
1278*5113495bSYour Name 	if (!vdev)
1279*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1280*5113495bSYour Name 
1281*5113495bSYour Name 	sme_get_sap_vdev_type_nss(mac_handle, &vdev_nss, operating_band);
1282*5113495bSYour Name 	if (hdd_ctx->dynamic_nss_chains_support) {
1283*5113495bSYour Name 		dynamic_cfg = mlme_get_dynamic_vdev_config(vdev);
1284*5113495bSYour Name 		if (!dynamic_cfg) {
1285*5113495bSYour Name 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1286*5113495bSYour Name 			hdd_debug("nss chain dynamic config NULL");
1287*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1288*5113495bSYour Name 		}
1289*5113495bSYour Name 		switch (operating_band) {
1290*5113495bSYour Name 		case BAND_2G:
1291*5113495bSYour Name 			*tx_nss = dynamic_cfg->tx_nss[NSS_CHAINS_BAND_2GHZ];
1292*5113495bSYour Name 			break;
1293*5113495bSYour Name 		case BAND_5G:
1294*5113495bSYour Name 			*tx_nss = dynamic_cfg->tx_nss[NSS_CHAINS_BAND_5GHZ];
1295*5113495bSYour Name 			break;
1296*5113495bSYour Name 		default:
1297*5113495bSYour Name 			hdd_debug("Band %d Not 2G or 5G", operating_band);
1298*5113495bSYour Name 			break;
1299*5113495bSYour Name 		}
1300*5113495bSYour Name 	} else {
1301*5113495bSYour Name 		*tx_nss = vdev_nss;
1302*5113495bSYour Name 	}
1303*5113495bSYour Name 
1304*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1305*5113495bSYour Name 	return  QDF_STATUS_SUCCESS;
1306*5113495bSYour Name }
1307*5113495bSYour Name 
1308*5113495bSYour Name static bool
hdd_get_sap_restart_required_for_nss(struct wlan_hdd_link_info * link_info,uint8_t tx_nss,uint8_t rx_nss)1309*5113495bSYour Name hdd_get_sap_restart_required_for_nss(struct wlan_hdd_link_info *link_info,
1310*5113495bSYour Name 				     uint8_t tx_nss, uint8_t rx_nss)
1311*5113495bSYour Name {
1312*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
1313*5113495bSYour Name 	uint8_t rx_prev, tx_prev;
1314*5113495bSYour Name 	bool restart_sap = 0;
1315*5113495bSYour Name 
1316*5113495bSYour Name 	ucfg_mlme_get_restart_sap_on_dynamic_nss_chains_cfg(hdd_ctx->psoc,
1317*5113495bSYour Name 							    &restart_sap);
1318*5113495bSYour Name 
1319*5113495bSYour Name 	if (!restart_sap)
1320*5113495bSYour Name 		return false;
1321*5113495bSYour Name 
1322*5113495bSYour Name 	hdd_get_sap_rx_nss(link_info, &rx_prev);
1323*5113495bSYour Name 	hdd_get_sap_tx_nss(link_info, &tx_prev);
1324*5113495bSYour Name 
1325*5113495bSYour Name 	if (rx_prev != rx_nss && tx_prev != tx_nss)
1326*5113495bSYour Name 		return true;
1327*5113495bSYour Name 	return false;
1328*5113495bSYour Name }
1329*5113495bSYour Name 
hdd_update_nss(struct wlan_hdd_link_info * link_info,uint8_t tx_nss,uint8_t rx_nss)1330*5113495bSYour Name QDF_STATUS hdd_update_nss(struct wlan_hdd_link_info *link_info,
1331*5113495bSYour Name 			  uint8_t tx_nss, uint8_t rx_nss)
1332*5113495bSYour Name {
1333*5113495bSYour Name 	struct hdd_adapter *adapter = link_info->adapter;
1334*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1335*5113495bSYour Name 	uint32_t rx_supp_data_rate, tx_supp_data_rate;
1336*5113495bSYour Name 	bool status = true;
1337*5113495bSYour Name 	QDF_STATUS qdf_status;
1338*5113495bSYour Name 	qdf_size_t val_len;
1339*5113495bSYour Name 	struct mlme_ht_capabilities_info ht_cap_info;
1340*5113495bSYour Name 	uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET] = {0};
1341*5113495bSYour Name 	uint8_t mcs_set_temp[SIZE_OF_SUPPORTED_MCS_SET];
1342*5113495bSYour Name 	uint8_t enable2x2;
1343*5113495bSYour Name 	mac_handle_t mac_handle;
1344*5113495bSYour Name 	bool bval = 0, restart_sap = 0;
1345*5113495bSYour Name 
1346*5113495bSYour Name 	if ((tx_nss == 2 || rx_nss == 2) && (hdd_ctx->num_rf_chains != 2)) {
1347*5113495bSYour Name 		hdd_err("No support for 2 spatial streams");
1348*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1349*5113495bSYour Name 	}
1350*5113495bSYour Name 
1351*5113495bSYour Name 	if (tx_nss > MAX_VDEV_NSS || rx_nss > MAX_VDEV_NSS) {
1352*5113495bSYour Name 		hdd_debug("Cannot support tx_nss: %d rx_nss: %d", tx_nss,
1353*5113495bSYour Name 			  rx_nss);
1354*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1355*5113495bSYour Name 	}
1356*5113495bSYour Name 
1357*5113495bSYour Name 	qdf_status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval);
1358*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1359*5113495bSYour Name 		hdd_err("unable to get vht_enable2x2");
1360*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1361*5113495bSYour Name 	}
1362*5113495bSYour Name 
1363*5113495bSYour Name 	mac_handle = hdd_ctx->mac_handle;
1364*5113495bSYour Name 	if (!mac_handle) {
1365*5113495bSYour Name 		hdd_err("NULL MAC handle");
1366*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1367*5113495bSYour Name 	}
1368*5113495bSYour Name 
1369*5113495bSYour Name 	/*
1370*5113495bSYour Name 	 * If FW is supporting the dynamic nss update, this command is meant to
1371*5113495bSYour Name 	 * be per vdev, so update only the ini params of that particular vdev
1372*5113495bSYour Name 	 * and not the global param enable2x2
1373*5113495bSYour Name 	 */
1374*5113495bSYour Name 	if (hdd_ctx->dynamic_nss_chains_support) {
1375*5113495bSYour Name 		restart_sap =
1376*5113495bSYour Name 		hdd_get_sap_restart_required_for_nss(link_info, tx_nss, rx_nss);
1377*5113495bSYour Name 
1378*5113495bSYour Name 		if ((adapter->device_mode == QDF_SAP_MODE ||
1379*5113495bSYour Name 		     adapter->device_mode == QDF_P2P_GO_MODE) && restart_sap) {
1380*5113495bSYour Name 			if ((tx_nss == 2 && rx_nss == 2) ||
1381*5113495bSYour Name 			    (tx_nss == 1 && rx_nss == 1)) {
1382*5113495bSYour Name 				hdd_set_sap_nss_params(link_info, mac_handle,
1383*5113495bSYour Name 						       tx_nss, rx_nss);
1384*5113495bSYour Name 				return QDF_STATUS_SUCCESS;
1385*5113495bSYour Name 			}
1386*5113495bSYour Name 			hdd_err("tx_nss %d rx_nss %d not supported ",
1387*5113495bSYour Name 				tx_nss, rx_nss);
1388*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1389*5113495bSYour Name 		}
1390*5113495bSYour Name 
1391*5113495bSYour Name 		if (hdd_is_vdev_in_conn_state(link_info))
1392*5113495bSYour Name 			return hdd_set_nss_params(link_info, tx_nss, rx_nss);
1393*5113495bSYour Name 
1394*5113495bSYour Name 		if (tx_nss != rx_nss) {
1395*5113495bSYour Name 			hdd_err("TX NSS = %d, RX NSS  = %d value mismatch, doesn't support asymmetric config in disconnected state",
1396*5113495bSYour Name 				tx_nss, rx_nss);
1397*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1398*5113495bSYour Name 		}
1399*5113495bSYour Name 		hdd_debug("Vdev %d in disconnect state, changing ini nss params",
1400*5113495bSYour Name 			  link_info->vdev_id);
1401*5113495bSYour Name 		if (!bval) {
1402*5113495bSYour Name 			hdd_err("Nss in 1x1, no change required, 2x2 mode disabled");
1403*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
1404*5113495bSYour Name 		}
1405*5113495bSYour Name 
1406*5113495bSYour Name 		hdd_update_nss_in_vdev(link_info, mac_handle, tx_nss, rx_nss);
1407*5113495bSYour Name 		sme_set_nss_capability(mac_handle, link_info->vdev_id,
1408*5113495bSYour Name 				       rx_nss, adapter->device_mode);
1409*5113495bSYour Name 
1410*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1411*5113495bSYour Name 	}
1412*5113495bSYour Name 
1413*5113495bSYour Name 	/*
1414*5113495bSYour Name 	 * The code below is executed only when fw doesn't support dynamic
1415*5113495bSYour Name 	 * update of nss and chains per vdev feature, for the upcoming
1416*5113495bSYour Name 	 * connection
1417*5113495bSYour Name 	 */
1418*5113495bSYour Name 	enable2x2 = (rx_nss == 2) ? 1 : 0;
1419*5113495bSYour Name 
1420*5113495bSYour Name 	if (bval == enable2x2) {
1421*5113495bSYour Name 		hdd_debug("NSS same as requested");
1422*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1423*5113495bSYour Name 	}
1424*5113495bSYour Name 
1425*5113495bSYour Name 	if (sme_is_any_session_in_connected_state(mac_handle)) {
1426*5113495bSYour Name 		hdd_err("Connected sessions present, Do not change NSS");
1427*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1428*5113495bSYour Name 	}
1429*5113495bSYour Name 
1430*5113495bSYour Name 	qdf_status = ucfg_mlme_set_vht_enable2x2(hdd_ctx->psoc, enable2x2);
1431*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1432*5113495bSYour Name 		hdd_err("Failed to set vht_enable2x2");
1433*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1434*5113495bSYour Name 	}
1435*5113495bSYour Name 
1436*5113495bSYour Name 	if (tx_nss == 1 && rx_nss == 2) {
1437*5113495bSYour Name 		/* 1x2 */
1438*5113495bSYour Name 		rx_supp_data_rate = VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2;
1439*5113495bSYour Name 		tx_supp_data_rate = VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
1440*5113495bSYour Name 	} else if (enable2x2) {
1441*5113495bSYour Name 		/* 2x2 */
1442*5113495bSYour Name 		rx_supp_data_rate = VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2;
1443*5113495bSYour Name 		tx_supp_data_rate = VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2;
1444*5113495bSYour Name 	} else {
1445*5113495bSYour Name 		/* 1x1 */
1446*5113495bSYour Name 		rx_supp_data_rate = VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
1447*5113495bSYour Name 		tx_supp_data_rate = VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
1448*5113495bSYour Name 	}
1449*5113495bSYour Name 
1450*5113495bSYour Name 	/* Update Rx Highest Long GI data Rate */
1451*5113495bSYour Name 	qdf_status =
1452*5113495bSYour Name 		ucfg_mlme_cfg_set_vht_rx_supp_data_rate(hdd_ctx->psoc,
1453*5113495bSYour Name 							rx_supp_data_rate);
1454*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1455*5113495bSYour Name 		hdd_err("Failed to set rx_supp_data_rate");
1456*5113495bSYour Name 		status = false;
1457*5113495bSYour Name 	}
1458*5113495bSYour Name 	/* Update Tx Highest Long GI data Rate */
1459*5113495bSYour Name 	qdf_status =
1460*5113495bSYour Name 		ucfg_mlme_cfg_set_vht_tx_supp_data_rate(hdd_ctx->psoc,
1461*5113495bSYour Name 							tx_supp_data_rate);
1462*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1463*5113495bSYour Name 		hdd_err("Failed to set tx_supp_data_rate");
1464*5113495bSYour Name 		status = false;
1465*5113495bSYour Name 	}
1466*5113495bSYour Name 
1467*5113495bSYour Name 	qdf_status = ucfg_mlme_get_ht_cap_info(hdd_ctx->psoc, &ht_cap_info);
1468*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1469*5113495bSYour Name 		hdd_err("Failed to get HT Cap info");
1470*5113495bSYour Name 		goto skip_ht_cap_update;
1471*5113495bSYour Name 	}
1472*5113495bSYour Name 
1473*5113495bSYour Name 	if (!(hdd_ctx->ht_tx_stbc_supported && enable2x2)) {
1474*5113495bSYour Name 		ht_cap_info.tx_stbc = 0;
1475*5113495bSYour Name 	} else {
1476*5113495bSYour Name 		qdf_status =
1477*5113495bSYour Name 			ucfg_mlme_cfg_get_vht_tx_stbc(hdd_ctx->psoc, &bval);
1478*5113495bSYour Name 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1479*5113495bSYour Name 			hdd_err("Failed to get vht_tx_stbc");
1480*5113495bSYour Name 			ht_cap_info.tx_stbc = bval;
1481*5113495bSYour Name 		}
1482*5113495bSYour Name 	}
1483*5113495bSYour Name 
1484*5113495bSYour Name 	qdf_status = ucfg_mlme_set_ht_cap_info(hdd_ctx->psoc, ht_cap_info);
1485*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1486*5113495bSYour Name 		hdd_err("Could not set the HT_CAP_INFO");
1487*5113495bSYour Name 	}
1488*5113495bSYour Name skip_ht_cap_update:
1489*5113495bSYour Name 	qdf_status = ucfg_mlme_update_nss_vht_cap(hdd_ctx->psoc);
1490*5113495bSYour Name 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1491*5113495bSYour Name 		hdd_err("Failed to set update_nss_vht_cap");
1492*5113495bSYour Name 		status = false;
1493*5113495bSYour Name 	}
1494*5113495bSYour Name 
1495*5113495bSYour Name #define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
1496*5113495bSYour Name 	val_len = SIZE_OF_SUPPORTED_MCS_SET;
1497*5113495bSYour Name 	qdf_status = ucfg_mlme_get_supported_mcs_set(hdd_ctx->psoc,
1498*5113495bSYour Name 						     mcs_set_temp,
1499*5113495bSYour Name 						     &val_len);
1500*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
1501*5113495bSYour Name 		mcs_set[0] = mcs_set_temp[0];
1502*5113495bSYour Name 		if (enable2x2)
1503*5113495bSYour Name 			for (val_len = 0; val_len < rx_nss; val_len++)
1504*5113495bSYour Name 				mcs_set[val_len] =
1505*5113495bSYour Name 				WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
1506*5113495bSYour Name 		if (ucfg_mlme_set_supported_mcs_set(
1507*5113495bSYour Name 			hdd_ctx->psoc, mcs_set,
1508*5113495bSYour Name 			(qdf_size_t)SIZE_OF_SUPPORTED_MCS_SET) ==
1509*5113495bSYour Name 			QDF_STATUS_E_FAILURE) {
1510*5113495bSYour Name 			status = false;
1511*5113495bSYour Name 			hdd_err("Could not pass on MCS SET to CFG");
1512*5113495bSYour Name 		}
1513*5113495bSYour Name 	} else {
1514*5113495bSYour Name 		status = false;
1515*5113495bSYour Name 		hdd_err("Could not get MCS SET from CFG");
1516*5113495bSYour Name 	}
1517*5113495bSYour Name 	sme_set_nss_capability(mac_handle, link_info->vdev_id,
1518*5113495bSYour Name 			       rx_nss, adapter->device_mode);
1519*5113495bSYour Name #undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
1520*5113495bSYour Name 
1521*5113495bSYour Name 	if (QDF_STATUS_SUCCESS != sme_update_nss(mac_handle, rx_nss))
1522*5113495bSYour Name 		status = false;
1523*5113495bSYour Name 
1524*5113495bSYour Name 	hdd_set_policy_mgr_user_cfg(hdd_ctx);
1525*5113495bSYour Name 
1526*5113495bSYour Name 	return (status == false) ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS;
1527*5113495bSYour Name }
1528*5113495bSYour Name 
hdd_get_nss(struct hdd_adapter * adapter,uint8_t * nss)1529*5113495bSYour Name QDF_STATUS hdd_get_nss(struct hdd_adapter *adapter, uint8_t *nss)
1530*5113495bSYour Name {
1531*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1532*5113495bSYour Name 	bool bval;
1533*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1534*5113495bSYour Name 
1535*5113495bSYour Name 	/*
1536*5113495bSYour Name 	 * If FW is supporting the dynamic nss update, this command is meant to
1537*5113495bSYour Name 	 * be per vdev, so get nss in the ini params of that particular vdev
1538*5113495bSYour Name 	 * otherwise get it from the global param enable2x2
1539*5113495bSYour Name 	 */
1540*5113495bSYour Name 	if (hdd_ctx->dynamic_nss_chains_support) {
1541*5113495bSYour Name 		uint8_t nss_2g, nss_5g;
1542*5113495bSYour Name 
1543*5113495bSYour Name 		sme_get_vdev_type_nss(adapter->device_mode, &nss_2g, &nss_5g);
1544*5113495bSYour Name 		/* Different settings in 2G and 5G is not supported */
1545*5113495bSYour Name 		*nss = nss_2g;
1546*5113495bSYour Name 	} else {
1547*5113495bSYour Name 		status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval);
1548*5113495bSYour Name 		if (!QDF_IS_STATUS_SUCCESS(status)) {
1549*5113495bSYour Name 			hdd_err("unable to get vht_enable2x2");
1550*5113495bSYour Name 			return status;
1551*5113495bSYour Name 		}
1552*5113495bSYour Name 
1553*5113495bSYour Name 		*nss = (bval) ? 2 : 1;
1554*5113495bSYour Name 		if (!policy_mgr_is_hw_dbs_2x2_capable(hdd_ctx->psoc) &&
1555*5113495bSYour Name 		    policy_mgr_is_current_hwmode_dbs(hdd_ctx->psoc))
1556*5113495bSYour Name 			*nss = *nss - 1;
1557*5113495bSYour Name 	}
1558*5113495bSYour Name 
1559*5113495bSYour Name 	return status;
1560*5113495bSYour Name }
1561*5113495bSYour Name 
1562*5113495bSYour Name /**
1563*5113495bSYour Name  * hdd_get_sap_num_tx_chains() - get the sap num tx chains
1564*5113495bSYour Name  * @link_info: Pointer of link_info
1565*5113495bSYour Name  * @tx_chains: pointer to tx_chains
1566*5113495bSYour Name  *
1567*5113495bSYour Name  * get the sap num tx chains
1568*5113495bSYour Name  *
1569*5113495bSYour Name  * Return: None
1570*5113495bSYour Name  */
1571*5113495bSYour Name static QDF_STATUS
hdd_get_sap_num_tx_chains(struct wlan_hdd_link_info * link_info,uint8_t * tx_chains)1572*5113495bSYour Name hdd_get_sap_num_tx_chains(struct wlan_hdd_link_info *link_info,
1573*5113495bSYour Name 			  uint8_t *tx_chains)
1574*5113495bSYour Name {
1575*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
1576*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1577*5113495bSYour Name 	struct wlan_mlme_nss_chains *dynamic_cfg;
1578*5113495bSYour Name 	enum band_info operating_band;
1579*5113495bSYour Name 	mac_handle_t mac_handle;
1580*5113495bSYour Name 
1581*5113495bSYour Name 	mac_handle = hdd_ctx->mac_handle;
1582*5113495bSYour Name 	if (!mac_handle) {
1583*5113495bSYour Name 		hdd_debug("NULL MAC handle");
1584*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1585*5113495bSYour Name 	}
1586*5113495bSYour Name 
1587*5113495bSYour Name 	operating_band = hdd_get_sap_operating_band_by_link_info(link_info);
1588*5113495bSYour Name 	if (operating_band == BAND_UNKNOWN)
1589*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1590*5113495bSYour Name 
1591*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
1592*5113495bSYour Name 	if (!vdev)
1593*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1594*5113495bSYour Name 
1595*5113495bSYour Name 	if (hdd_ctx->dynamic_nss_chains_support) {
1596*5113495bSYour Name 		dynamic_cfg = mlme_get_dynamic_vdev_config(vdev);
1597*5113495bSYour Name 		if (!dynamic_cfg) {
1598*5113495bSYour Name 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1599*5113495bSYour Name 			hdd_debug("nss chain dynamic config NULL");
1600*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1601*5113495bSYour Name 		}
1602*5113495bSYour Name 		switch (operating_band) {
1603*5113495bSYour Name 		case BAND_2G:
1604*5113495bSYour Name 			*tx_chains =
1605*5113495bSYour Name 			dynamic_cfg->num_tx_chains[NSS_CHAINS_BAND_2GHZ];
1606*5113495bSYour Name 			break;
1607*5113495bSYour Name 		case BAND_5G:
1608*5113495bSYour Name 			*tx_chains =
1609*5113495bSYour Name 			dynamic_cfg->num_tx_chains[NSS_CHAINS_BAND_5GHZ];
1610*5113495bSYour Name 			break;
1611*5113495bSYour Name 		default:
1612*5113495bSYour Name 			hdd_debug("Band %d Not 2G or 5G", operating_band);
1613*5113495bSYour Name 			break;
1614*5113495bSYour Name 		}
1615*5113495bSYour Name 	}
1616*5113495bSYour Name 
1617*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1618*5113495bSYour Name 	return  QDF_STATUS_SUCCESS;
1619*5113495bSYour Name }
1620*5113495bSYour Name 
1621*5113495bSYour Name /**
1622*5113495bSYour Name  * hdd_get_sta_num_tx_chains() - get the sta num tx chains
1623*5113495bSYour Name  * @link_info: Pointer of link_info
1624*5113495bSYour Name  * @tx_chains: pointer to tx_chains
1625*5113495bSYour Name  *
1626*5113495bSYour Name  * get the STA num tx chains
1627*5113495bSYour Name  *
1628*5113495bSYour Name  * Return: None
1629*5113495bSYour Name  */
1630*5113495bSYour Name static QDF_STATUS
hdd_get_sta_num_tx_chains(struct wlan_hdd_link_info * link_info,uint8_t * tx_chains)1631*5113495bSYour Name hdd_get_sta_num_tx_chains(struct wlan_hdd_link_info *link_info,
1632*5113495bSYour Name 			  uint8_t *tx_chains)
1633*5113495bSYour Name {
1634*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
1635*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1636*5113495bSYour Name 	QDF_STATUS status;
1637*5113495bSYour Name 
1638*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
1639*5113495bSYour Name 	if (!vdev)
1640*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1641*5113495bSYour Name 
1642*5113495bSYour Name 	status = ucfg_mlme_get_sta_num_tx_chains(hdd_ctx->psoc, vdev,
1643*5113495bSYour Name 						 tx_chains);
1644*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
1645*5113495bSYour Name 		hdd_err("Failed to get sta_tx_nss");
1646*5113495bSYour Name 
1647*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1648*5113495bSYour Name 
1649*5113495bSYour Name 	return status;
1650*5113495bSYour Name }
1651*5113495bSYour Name 
1652*5113495bSYour Name /**
1653*5113495bSYour Name  * hdd_get_sta_tx_nss() - get the sta tx nss
1654*5113495bSYour Name  * @link_info: Pointer of link_info
1655*5113495bSYour Name  * @tx_nss: pointer to tx_nss
1656*5113495bSYour Name  *
1657*5113495bSYour Name  * get the STA tx nss
1658*5113495bSYour Name  *
1659*5113495bSYour Name  * Return: None
1660*5113495bSYour Name  */
1661*5113495bSYour Name static QDF_STATUS
hdd_get_sta_tx_nss(struct wlan_hdd_link_info * link_info,uint8_t * tx_nss)1662*5113495bSYour Name hdd_get_sta_tx_nss(struct wlan_hdd_link_info *link_info, uint8_t *tx_nss)
1663*5113495bSYour Name {
1664*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
1665*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1666*5113495bSYour Name 	QDF_STATUS status;
1667*5113495bSYour Name 
1668*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
1669*5113495bSYour Name 	if (!vdev)
1670*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1671*5113495bSYour Name 
1672*5113495bSYour Name 	status = ucfg_mlme_get_sta_tx_nss(hdd_ctx->psoc, vdev, tx_nss);
1673*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
1674*5113495bSYour Name 		hdd_err("Failed to get sta_tx_nss");
1675*5113495bSYour Name 
1676*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1677*5113495bSYour Name 
1678*5113495bSYour Name 	return status;
1679*5113495bSYour Name }
1680*5113495bSYour Name 
hdd_get_num_tx_chains(struct wlan_hdd_link_info * link_info,uint8_t * tx_chains)1681*5113495bSYour Name QDF_STATUS hdd_get_num_tx_chains(struct wlan_hdd_link_info *link_info,
1682*5113495bSYour Name 				 uint8_t *tx_chains)
1683*5113495bSYour Name {
1684*5113495bSYour Name 	struct hdd_adapter *adapter = link_info->adapter;
1685*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1686*5113495bSYour Name 
1687*5113495bSYour Name 	if (adapter->device_mode == QDF_SAP_MODE ||
1688*5113495bSYour Name 	    adapter->device_mode == QDF_P2P_GO_MODE)
1689*5113495bSYour Name 		status = hdd_get_sap_num_tx_chains(link_info, tx_chains);
1690*5113495bSYour Name 	else
1691*5113495bSYour Name 		status = hdd_get_sta_num_tx_chains(link_info, tx_chains);
1692*5113495bSYour Name 
1693*5113495bSYour Name 	return status;
1694*5113495bSYour Name }
1695*5113495bSYour Name 
hdd_get_tx_nss(struct wlan_hdd_link_info * link_info,uint8_t * tx_nss)1696*5113495bSYour Name QDF_STATUS hdd_get_tx_nss(struct wlan_hdd_link_info *link_info, uint8_t *tx_nss)
1697*5113495bSYour Name {
1698*5113495bSYour Name 	struct hdd_adapter *adapter = link_info->adapter;
1699*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1700*5113495bSYour Name 
1701*5113495bSYour Name 	if (adapter->device_mode == QDF_SAP_MODE ||
1702*5113495bSYour Name 	    adapter->device_mode == QDF_P2P_GO_MODE)
1703*5113495bSYour Name 		status = hdd_get_sap_tx_nss(link_info, tx_nss);
1704*5113495bSYour Name 	else
1705*5113495bSYour Name 		status = hdd_get_sta_tx_nss(link_info, tx_nss);
1706*5113495bSYour Name 
1707*5113495bSYour Name 	return status;
1708*5113495bSYour Name }
1709*5113495bSYour Name 
1710*5113495bSYour Name /**
1711*5113495bSYour Name  * hdd_get_sap_num_rx_chains() - get the sap num rx chains
1712*5113495bSYour Name  * @link_info: Pointer to link_info
1713*5113495bSYour Name  * @rx_chains: pointer to rx_chains
1714*5113495bSYour Name  *
1715*5113495bSYour Name  * get the sap num rx chains
1716*5113495bSYour Name  *
1717*5113495bSYour Name  * Return: None
1718*5113495bSYour Name  */
1719*5113495bSYour Name static QDF_STATUS
hdd_get_sap_num_rx_chains(struct wlan_hdd_link_info * link_info,uint8_t * rx_chains)1720*5113495bSYour Name hdd_get_sap_num_rx_chains(struct wlan_hdd_link_info *link_info,
1721*5113495bSYour Name 			  uint8_t *rx_chains)
1722*5113495bSYour Name {
1723*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
1724*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1725*5113495bSYour Name 	struct wlan_mlme_nss_chains *dynamic_cfg;
1726*5113495bSYour Name 	enum band_info operating_band;
1727*5113495bSYour Name 	mac_handle_t mac_handle;
1728*5113495bSYour Name 
1729*5113495bSYour Name 	mac_handle = hdd_ctx->mac_handle;
1730*5113495bSYour Name 	if (!mac_handle) {
1731*5113495bSYour Name 		hdd_debug("NULL MAC handle");
1732*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1733*5113495bSYour Name 	}
1734*5113495bSYour Name 
1735*5113495bSYour Name 	operating_band = hdd_get_sap_operating_band_by_link_info(link_info);
1736*5113495bSYour Name 	if (operating_band == BAND_UNKNOWN)
1737*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1738*5113495bSYour Name 
1739*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
1740*5113495bSYour Name 	if (!vdev)
1741*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1742*5113495bSYour Name 
1743*5113495bSYour Name 	if (hdd_ctx->dynamic_nss_chains_support) {
1744*5113495bSYour Name 		dynamic_cfg = mlme_get_dynamic_vdev_config(vdev);
1745*5113495bSYour Name 		if (!dynamic_cfg) {
1746*5113495bSYour Name 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1747*5113495bSYour Name 			hdd_debug("nss chain dynamic config NULL");
1748*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1749*5113495bSYour Name 		}
1750*5113495bSYour Name 		switch (operating_band) {
1751*5113495bSYour Name 		case BAND_2G:
1752*5113495bSYour Name 			*rx_chains =
1753*5113495bSYour Name 			dynamic_cfg->num_rx_chains[NSS_CHAINS_BAND_2GHZ];
1754*5113495bSYour Name 			break;
1755*5113495bSYour Name 		case BAND_5G:
1756*5113495bSYour Name 			*rx_chains =
1757*5113495bSYour Name 			dynamic_cfg->num_rx_chains[NSS_CHAINS_BAND_5GHZ];
1758*5113495bSYour Name 			break;
1759*5113495bSYour Name 		default:
1760*5113495bSYour Name 			hdd_debug("Band %d Not 2G or 5G", operating_band);
1761*5113495bSYour Name 			break;
1762*5113495bSYour Name 		}
1763*5113495bSYour Name 	}
1764*5113495bSYour Name 
1765*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1766*5113495bSYour Name 	return  QDF_STATUS_SUCCESS;
1767*5113495bSYour Name }
1768*5113495bSYour Name 
1769*5113495bSYour Name /**
1770*5113495bSYour Name  * hdd_get_sta_num_rx_chains() - get the sta num rx chains
1771*5113495bSYour Name  * @link_info: Pointer to link_info in adapter
1772*5113495bSYour Name  * @rx_chains: pointer to rx_chains
1773*5113495bSYour Name  *
1774*5113495bSYour Name  * get the STA num rx chains
1775*5113495bSYour Name  *
1776*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS if the RX NSS is returned, otherwise a suitable
1777*5113495bSYour Name  *         QDF_STATUS_E_* error code
1778*5113495bSYour Name  */
1779*5113495bSYour Name static QDF_STATUS
hdd_get_sta_num_rx_chains(struct wlan_hdd_link_info * link_info,uint8_t * rx_chains)1780*5113495bSYour Name hdd_get_sta_num_rx_chains(struct wlan_hdd_link_info *link_info,
1781*5113495bSYour Name 			  uint8_t *rx_chains)
1782*5113495bSYour Name {
1783*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
1784*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1785*5113495bSYour Name 	QDF_STATUS status;
1786*5113495bSYour Name 
1787*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
1788*5113495bSYour Name 	if (!vdev)
1789*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1790*5113495bSYour Name 
1791*5113495bSYour Name 	status = ucfg_mlme_get_sta_num_rx_chains(hdd_ctx->psoc, vdev,
1792*5113495bSYour Name 						 rx_chains);
1793*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
1794*5113495bSYour Name 		hdd_err("Failed to get sta_rx_nss");
1795*5113495bSYour Name 
1796*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1797*5113495bSYour Name 
1798*5113495bSYour Name 	return status;
1799*5113495bSYour Name }
1800*5113495bSYour Name 
1801*5113495bSYour Name /**
1802*5113495bSYour Name  * hdd_get_sta_rx_nss() - get the sta rx nss
1803*5113495bSYour Name  * @link_info: Pointer to link_info in adapter
1804*5113495bSYour Name  * @rx_nss: pointer to rx_nss
1805*5113495bSYour Name  *
1806*5113495bSYour Name  * get the STA rx nss
1807*5113495bSYour Name  *
1808*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS if the RX NSS is returned, otherwise a suitable
1809*5113495bSYour Name  *         QDF_STATUS_E_* error code
1810*5113495bSYour Name  */
1811*5113495bSYour Name static QDF_STATUS
hdd_get_sta_rx_nss(struct wlan_hdd_link_info * link_info,uint8_t * rx_nss)1812*5113495bSYour Name hdd_get_sta_rx_nss(struct wlan_hdd_link_info *link_info, uint8_t *rx_nss)
1813*5113495bSYour Name {
1814*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
1815*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1816*5113495bSYour Name 	QDF_STATUS status;
1817*5113495bSYour Name 
1818*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
1819*5113495bSYour Name 	if (!vdev)
1820*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1821*5113495bSYour Name 
1822*5113495bSYour Name 	status = wlan_mlme_get_sta_rx_nss(hdd_ctx->psoc, vdev, rx_nss);
1823*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
1824*5113495bSYour Name 		hdd_err("Failed to get sta_rx_nss");
1825*5113495bSYour Name 
1826*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1827*5113495bSYour Name 
1828*5113495bSYour Name 	return status;
1829*5113495bSYour Name }
1830*5113495bSYour Name 
hdd_get_num_rx_chains(struct wlan_hdd_link_info * link_info,uint8_t * rx_chains)1831*5113495bSYour Name QDF_STATUS hdd_get_num_rx_chains(struct wlan_hdd_link_info *link_info,
1832*5113495bSYour Name 				 uint8_t *rx_chains)
1833*5113495bSYour Name {
1834*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1835*5113495bSYour Name 	struct hdd_adapter *adapter = link_info->adapter;
1836*5113495bSYour Name 
1837*5113495bSYour Name 	if (adapter->device_mode == QDF_SAP_MODE ||
1838*5113495bSYour Name 	    adapter->device_mode == QDF_P2P_GO_MODE)
1839*5113495bSYour Name 		status = hdd_get_sap_num_rx_chains(link_info, rx_chains);
1840*5113495bSYour Name 	else
1841*5113495bSYour Name 		status = hdd_get_sta_num_rx_chains(link_info, rx_chains);
1842*5113495bSYour Name 
1843*5113495bSYour Name 	return status;
1844*5113495bSYour Name }
1845*5113495bSYour Name 
hdd_get_rx_nss(struct wlan_hdd_link_info * link_info,uint8_t * rx_nss)1846*5113495bSYour Name QDF_STATUS hdd_get_rx_nss(struct wlan_hdd_link_info *link_info, uint8_t *rx_nss)
1847*5113495bSYour Name {
1848*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1849*5113495bSYour Name 	struct hdd_adapter *adapter = link_info->adapter;
1850*5113495bSYour Name 
1851*5113495bSYour Name 	if (adapter->device_mode == QDF_SAP_MODE ||
1852*5113495bSYour Name 	    adapter->device_mode == QDF_P2P_GO_MODE)
1853*5113495bSYour Name 		status = hdd_get_sap_rx_nss(link_info, rx_nss);
1854*5113495bSYour Name 	else
1855*5113495bSYour Name 		status = hdd_get_sta_rx_nss(link_info, rx_nss);
1856*5113495bSYour Name 
1857*5113495bSYour Name 	return status;
1858*5113495bSYour Name }
1859*5113495bSYour Name 
hdd_phymode_to_vendor_mode(eCsrPhyMode csr_phy_mode,enum qca_wlan_vendor_phy_mode * vendor_phy_mode)1860*5113495bSYour Name int hdd_phymode_to_vendor_mode(eCsrPhyMode csr_phy_mode,
1861*5113495bSYour Name 			       enum qca_wlan_vendor_phy_mode *vendor_phy_mode)
1862*5113495bSYour Name {
1863*5113495bSYour Name 	switch (csr_phy_mode) {
1864*5113495bSYour Name 	case eCSR_DOT11_MODE_AUTO:
1865*5113495bSYour Name 	case eCSR_DOT11_MODE_11be:
1866*5113495bSYour Name 	case eCSR_DOT11_MODE_11be_ONLY:
1867*5113495bSYour Name 		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_AUTO;
1868*5113495bSYour Name 		break;
1869*5113495bSYour Name 	case eCSR_DOT11_MODE_11a:
1870*5113495bSYour Name 		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_11A;
1871*5113495bSYour Name 		break;
1872*5113495bSYour Name 	case eCSR_DOT11_MODE_11b:
1873*5113495bSYour Name 	case eCSR_DOT11_MODE_11b_ONLY:
1874*5113495bSYour Name 		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_11B;
1875*5113495bSYour Name 		break;
1876*5113495bSYour Name 	case eCSR_DOT11_MODE_11g:
1877*5113495bSYour Name 	case eCSR_DOT11_MODE_11g_ONLY:
1878*5113495bSYour Name 		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_11G;
1879*5113495bSYour Name 		break;
1880*5113495bSYour Name 	case eCSR_DOT11_MODE_11n:
1881*5113495bSYour Name 	case eCSR_DOT11_MODE_11n_ONLY:
1882*5113495bSYour Name 		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_11AGN;
1883*5113495bSYour Name 		break;
1884*5113495bSYour Name 	case eCSR_DOT11_MODE_11ac:
1885*5113495bSYour Name 	case eCSR_DOT11_MODE_11ac_ONLY:
1886*5113495bSYour Name 		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160;
1887*5113495bSYour Name 		break;
1888*5113495bSYour Name 	case eCSR_DOT11_MODE_11ax:
1889*5113495bSYour Name 	case eCSR_DOT11_MODE_11ax_ONLY:
1890*5113495bSYour Name 		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160;
1891*5113495bSYour Name 		break;
1892*5113495bSYour Name 	case eCSR_DOT11_MODE_abg:
1893*5113495bSYour Name 	default:
1894*5113495bSYour Name 		hdd_err("Not supported mode %d", csr_phy_mode);
1895*5113495bSYour Name 		return -EINVAL;
1896*5113495bSYour Name 	}
1897*5113495bSYour Name 
1898*5113495bSYour Name 	return 0;
1899*5113495bSYour Name }
1900*5113495bSYour Name 
hdd_vendor_mode_to_phymode(enum qca_wlan_vendor_phy_mode vendor_phy_mode,eCsrPhyMode * csr_phy_mode)1901*5113495bSYour Name int hdd_vendor_mode_to_phymode(enum qca_wlan_vendor_phy_mode vendor_phy_mode,
1902*5113495bSYour Name 			       eCsrPhyMode *csr_phy_mode)
1903*5113495bSYour Name {
1904*5113495bSYour Name 	switch (vendor_phy_mode) {
1905*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_AUTO:
1906*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_2G_AUTO:
1907*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_5G_AUTO:
1908*5113495bSYour Name 		*csr_phy_mode = eCSR_DOT11_MODE_AUTO;
1909*5113495bSYour Name 		break;
1910*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11A:
1911*5113495bSYour Name 		*csr_phy_mode = eCSR_DOT11_MODE_11a;
1912*5113495bSYour Name 		break;
1913*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11B:
1914*5113495bSYour Name 		*csr_phy_mode = eCSR_DOT11_MODE_11b;
1915*5113495bSYour Name 		break;
1916*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11G:
1917*5113495bSYour Name 		*csr_phy_mode = eCSR_DOT11_MODE_11g;
1918*5113495bSYour Name 		break;
1919*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20:
1920*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40:
1921*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS:
1922*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS:
1923*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20:
1924*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40:
1925*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS:
1926*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS:
1927*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AGN:
1928*5113495bSYour Name 		*csr_phy_mode = eCSR_DOT11_MODE_11n;
1929*5113495bSYour Name 		break;
1930*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20:
1931*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40:
1932*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS:
1933*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS:
1934*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80:
1935*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80:
1936*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160:
1937*5113495bSYour Name 		*csr_phy_mode = eCSR_DOT11_MODE_11ac;
1938*5113495bSYour Name 		break;
1939*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20:
1940*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40:
1941*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS:
1942*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS:
1943*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80:
1944*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80:
1945*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160:
1946*5113495bSYour Name 		*csr_phy_mode = eCSR_DOT11_MODE_11ax;
1947*5113495bSYour Name 		break;
1948*5113495bSYour Name 	default:
1949*5113495bSYour Name 		hdd_err("Not supported mode %d", vendor_phy_mode);
1950*5113495bSYour Name 		return -EINVAL;
1951*5113495bSYour Name 	}
1952*5113495bSYour Name 
1953*5113495bSYour Name 	return 0;
1954*5113495bSYour Name }
1955*5113495bSYour Name 
hdd_vendor_mode_to_band(enum qca_wlan_vendor_phy_mode vendor_phy_mode,uint8_t * supported_band,bool is_6ghz_supported)1956*5113495bSYour Name int hdd_vendor_mode_to_band(enum qca_wlan_vendor_phy_mode vendor_phy_mode,
1957*5113495bSYour Name 			    uint8_t *supported_band, bool is_6ghz_supported)
1958*5113495bSYour Name {
1959*5113495bSYour Name 	switch (vendor_phy_mode) {
1960*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_AUTO:
1961*5113495bSYour Name 		if (is_6ghz_supported)
1962*5113495bSYour Name 			*supported_band = REG_BAND_MASK_ALL;
1963*5113495bSYour Name 		else
1964*5113495bSYour Name 			*supported_band =
1965*5113495bSYour Name 				BIT(REG_BAND_2G) | BIT(REG_BAND_5G);
1966*5113495bSYour Name 		break;
1967*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20:
1968*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40:
1969*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS:
1970*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS:
1971*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80:
1972*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80:
1973*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160:
1974*5113495bSYour Name 		*supported_band = BIT(REG_BAND_2G) | BIT(REG_BAND_5G);
1975*5113495bSYour Name 		break;
1976*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20:
1977*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40:
1978*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS:
1979*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS:
1980*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80:
1981*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80:
1982*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160:
1983*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AGN:
1984*5113495bSYour Name 		if (is_6ghz_supported)
1985*5113495bSYour Name 			*supported_band = REG_BAND_MASK_ALL;
1986*5113495bSYour Name 		else
1987*5113495bSYour Name 			*supported_band = BIT(REG_BAND_2G) | BIT(REG_BAND_5G);
1988*5113495bSYour Name 		break;
1989*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11A:
1990*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20:
1991*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40:
1992*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS:
1993*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS:
1994*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_5G_AUTO:
1995*5113495bSYour Name 		*supported_band = BIT(REG_BAND_5G);
1996*5113495bSYour Name 		break;
1997*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11B:
1998*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11G:
1999*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20:
2000*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40:
2001*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS:
2002*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS:
2003*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_2G_AUTO:
2004*5113495bSYour Name 		*supported_band = BIT(REG_BAND_2G);
2005*5113495bSYour Name 		break;
2006*5113495bSYour Name 	default:
2007*5113495bSYour Name 		hdd_err("Not supported mode %d", vendor_phy_mode);
2008*5113495bSYour Name 		return -EINVAL;
2009*5113495bSYour Name 	}
2010*5113495bSYour Name 
2011*5113495bSYour Name 	return 0;
2012*5113495bSYour Name }
2013*5113495bSYour Name 
2014*5113495bSYour Name int
hdd_vendor_mode_to_bonding_mode(enum qca_wlan_vendor_phy_mode vendor_phy_mode,uint32_t * bonding_mode)2015*5113495bSYour Name hdd_vendor_mode_to_bonding_mode(enum qca_wlan_vendor_phy_mode vendor_phy_mode,
2016*5113495bSYour Name 				uint32_t *bonding_mode)
2017*5113495bSYour Name {
2018*5113495bSYour Name 	switch (vendor_phy_mode) {
2019*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_AUTO:
2020*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40:
2021*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS:
2022*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS:
2023*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40:
2024*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS:
2025*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS:
2026*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40:
2027*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS:
2028*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS:
2029*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80:
2030*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80:
2031*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160:
2032*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40:
2033*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS:
2034*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS:
2035*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80:
2036*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80:
2037*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160:
2038*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_2G_AUTO:
2039*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_5G_AUTO:
2040*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AGN:
2041*5113495bSYour Name 		*bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE;
2042*5113495bSYour Name 		break;
2043*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11A:
2044*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11B:
2045*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11G:
2046*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20:
2047*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20:
2048*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20:
2049*5113495bSYour Name 	case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20:
2050*5113495bSYour Name 		*bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
2051*5113495bSYour Name 		break;
2052*5113495bSYour Name 	default:
2053*5113495bSYour Name 		hdd_err("Not supported mode %d", vendor_phy_mode);
2054*5113495bSYour Name 		return -EINVAL;
2055*5113495bSYour Name 	}
2056*5113495bSYour Name 
2057*5113495bSYour Name 	return 0;
2058*5113495bSYour Name }
2059*5113495bSYour Name 
hdd_phymode_to_dot11_mode(eCsrPhyMode phymode,enum hdd_dot11_mode * dot11_mode)2060*5113495bSYour Name int hdd_phymode_to_dot11_mode(eCsrPhyMode phymode,
2061*5113495bSYour Name 			      enum hdd_dot11_mode *dot11_mode)
2062*5113495bSYour Name {
2063*5113495bSYour Name 	switch (phymode) {
2064*5113495bSYour Name 	case eCSR_DOT11_MODE_AUTO:
2065*5113495bSYour Name 	case eCSR_DOT11_MODE_11be:
2066*5113495bSYour Name 		*dot11_mode = eHDD_DOT11_MODE_AUTO;
2067*5113495bSYour Name 		break;
2068*5113495bSYour Name 	case eCSR_DOT11_MODE_11a:
2069*5113495bSYour Name 		*dot11_mode = eHDD_DOT11_MODE_11a;
2070*5113495bSYour Name 		break;
2071*5113495bSYour Name 	case eCSR_DOT11_MODE_11b:
2072*5113495bSYour Name 		*dot11_mode = eHDD_DOT11_MODE_11b;
2073*5113495bSYour Name 		break;
2074*5113495bSYour Name 	case eCSR_DOT11_MODE_11g:
2075*5113495bSYour Name 		*dot11_mode = eHDD_DOT11_MODE_11g;
2076*5113495bSYour Name 		break;
2077*5113495bSYour Name 	case eCSR_DOT11_MODE_11n:
2078*5113495bSYour Name 		*dot11_mode = eHDD_DOT11_MODE_11n;
2079*5113495bSYour Name 		break;
2080*5113495bSYour Name 	case eCSR_DOT11_MODE_11ac:
2081*5113495bSYour Name 		*dot11_mode = eHDD_DOT11_MODE_11ac;
2082*5113495bSYour Name 		break;
2083*5113495bSYour Name 	case eCSR_DOT11_MODE_11ax:
2084*5113495bSYour Name 		*dot11_mode = eHDD_DOT11_MODE_11ax;
2085*5113495bSYour Name 		break;
2086*5113495bSYour Name 	default:
2087*5113495bSYour Name 		hdd_err("Not supported mode %d", phymode);
2088*5113495bSYour Name 		return -EINVAL;
2089*5113495bSYour Name 	}
2090*5113495bSYour Name 
2091*5113495bSYour Name 	return 0;
2092*5113495bSYour Name }
2093*5113495bSYour Name 
2094*5113495bSYour Name #ifdef QCA_HT_2040_COEX
2095*5113495bSYour Name static QDF_STATUS
hdd_set_ht2040_mode(struct hdd_adapter * adapter,struct csr_config_params * csr_config,uint32_t bonding_mode)2096*5113495bSYour Name hdd_set_ht2040_mode(struct hdd_adapter *adapter,
2097*5113495bSYour Name 		    struct csr_config_params *csr_config,
2098*5113495bSYour Name 		    uint32_t bonding_mode)
2099*5113495bSYour Name {
2100*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2101*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2102*5113495bSYour Name 
2103*5113495bSYour Name 	if (csr_config->phyMode == eCSR_DOT11_MODE_11n) {
2104*5113495bSYour Name 		if (bonding_mode == WNI_CFG_CHANNEL_BONDING_MODE_ENABLE)
2105*5113495bSYour Name 			csr_config->obssEnabled = true;
2106*5113495bSYour Name 		else
2107*5113495bSYour Name 			csr_config->obssEnabled = false;
2108*5113495bSYour Name 		status = sme_set_ht2040_mode(hdd_ctx->mac_handle,
2109*5113495bSYour Name 					     adapter->deflink->vdev_id,
2110*5113495bSYour Name 					     eHT_CHAN_HT20,
2111*5113495bSYour Name 					     csr_config->obssEnabled);
2112*5113495bSYour Name 	}
2113*5113495bSYour Name 
2114*5113495bSYour Name 	return status;
2115*5113495bSYour Name }
2116*5113495bSYour Name #else
2117*5113495bSYour Name static QDF_STATUS
hdd_set_ht2040_mode(struct hdd_adapter * adapter,struct csr_config_params * csr_config,uint32_t bonding_mode)2118*5113495bSYour Name hdd_set_ht2040_mode(struct hdd_adapter *adapter,
2119*5113495bSYour Name 		    struct csr_config_params *csr_config,
2120*5113495bSYour Name 		    uint32_t bonding_mode)
2121*5113495bSYour Name {
2122*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2123*5113495bSYour Name }
2124*5113495bSYour Name #endif
2125*5113495bSYour Name 
hdd_update_phymode(struct hdd_adapter * adapter,eCsrPhyMode phymode,uint8_t supported_band,uint32_t bonding_mode)2126*5113495bSYour Name int hdd_update_phymode(struct hdd_adapter *adapter, eCsrPhyMode phymode,
2127*5113495bSYour Name 		       uint8_t supported_band, uint32_t bonding_mode)
2128*5113495bSYour Name {
2129*5113495bSYour Name 	struct net_device *net = adapter->dev;
2130*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2131*5113495bSYour Name 	struct sme_config_params *sme_config = NULL;
2132*5113495bSYour Name 	struct csr_config_params *csr_config;
2133*5113495bSYour Name 	eCsrPhyMode old_phymode;
2134*5113495bSYour Name 	enum hdd_dot11_mode hdd_dot11mode;
2135*5113495bSYour Name 	int ret = 0;
2136*5113495bSYour Name 	QDF_STATUS status;
2137*5113495bSYour Name 
2138*5113495bSYour Name 	ret = wlan_hdd_validate_context(hdd_ctx);
2139*5113495bSYour Name 	if (ret < 0)
2140*5113495bSYour Name 		return ret;
2141*5113495bSYour Name 
2142*5113495bSYour Name 	ret = hdd_phymode_to_dot11_mode(phymode, &hdd_dot11mode);
2143*5113495bSYour Name 	if (ret < 0)
2144*5113495bSYour Name 		return ret;
2145*5113495bSYour Name 
2146*5113495bSYour Name 	hdd_debug("phymode=%d bonding_mode=%d supported_band=%d",
2147*5113495bSYour Name 		  phymode, bonding_mode, supported_band);
2148*5113495bSYour Name 
2149*5113495bSYour Name 	old_phymode = sme_get_phy_mode(hdd_ctx->mac_handle);
2150*5113495bSYour Name 
2151*5113495bSYour Name 	sme_set_phy_mode(hdd_ctx->mac_handle, phymode);
2152*5113495bSYour Name 
2153*5113495bSYour Name 	if (hdd_reg_set_band(net, supported_band)) {
2154*5113495bSYour Name 		sme_set_phy_mode(hdd_ctx->mac_handle, old_phymode);
2155*5113495bSYour Name 		return -EIO;
2156*5113495bSYour Name 	}
2157*5113495bSYour Name 
2158*5113495bSYour Name 	sme_config = qdf_mem_malloc(sizeof(*sme_config));
2159*5113495bSYour Name 	if (!sme_config)
2160*5113495bSYour Name 		return -ENOMEM;
2161*5113495bSYour Name 
2162*5113495bSYour Name 	sme_get_config_param(hdd_ctx->mac_handle, sme_config);
2163*5113495bSYour Name 	csr_config = &sme_config->csr_config;
2164*5113495bSYour Name 	csr_config->phyMode = phymode;
2165*5113495bSYour Name 
2166*5113495bSYour Name 	status = hdd_set_ht2040_mode(adapter, csr_config, bonding_mode);
2167*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
2168*5113495bSYour Name 		hdd_err("Failed to set ht2040 mode");
2169*5113495bSYour Name 		ret = -EIO;
2170*5113495bSYour Name 		goto free;
2171*5113495bSYour Name 	}
2172*5113495bSYour Name 
2173*5113495bSYour Name 	status = ucfg_mlme_set_band_capability(hdd_ctx->psoc, supported_band);
2174*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
2175*5113495bSYour Name 		hdd_err("failed to set MLME band capability");
2176*5113495bSYour Name 		ret = -EIO;
2177*5113495bSYour Name 		goto free;
2178*5113495bSYour Name 	}
2179*5113495bSYour Name 
2180*5113495bSYour Name 	if (supported_band == BIT(REG_BAND_2G)) {
2181*5113495bSYour Name 		status = ucfg_mlme_set_11h_enabled(hdd_ctx->psoc, 0);
2182*5113495bSYour Name 		if (!QDF_IS_STATUS_SUCCESS(status)) {
2183*5113495bSYour Name 			hdd_err("Failed to set 11h_enable flag");
2184*5113495bSYour Name 			ret = -EIO;
2185*5113495bSYour Name 			goto free;
2186*5113495bSYour Name 		}
2187*5113495bSYour Name 	}
2188*5113495bSYour Name 	if (supported_band & BIT(REG_BAND_2G))
2189*5113495bSYour Name 		csr_config->channelBondingMode24GHz = bonding_mode;
2190*5113495bSYour Name 
2191*5113495bSYour Name 	if (supported_band & BIT(REG_BAND_5G))
2192*5113495bSYour Name 		csr_config->channelBondingMode5GHz = bonding_mode;
2193*5113495bSYour Name 
2194*5113495bSYour Name 	sme_update_config(hdd_ctx->mac_handle, sme_config);
2195*5113495bSYour Name 
2196*5113495bSYour Name 	hdd_ctx->config->dot11Mode = hdd_dot11mode;
2197*5113495bSYour Name 	ucfg_mlme_set_channel_bonding_24ghz(hdd_ctx->psoc,
2198*5113495bSYour Name 					   csr_config->channelBondingMode24GHz);
2199*5113495bSYour Name 	ucfg_mlme_set_channel_bonding_5ghz(hdd_ctx->psoc,
2200*5113495bSYour Name 					   csr_config->channelBondingMode5GHz);
2201*5113495bSYour Name 	if (hdd_update_config_cfg(hdd_ctx) == false) {
2202*5113495bSYour Name 		hdd_err("could not update config_dat");
2203*5113495bSYour Name 		ret = -EIO;
2204*5113495bSYour Name 		goto free;
2205*5113495bSYour Name 	}
2206*5113495bSYour Name 
2207*5113495bSYour Name 	if (supported_band & BIT(REG_BAND_5G)) {
2208*5113495bSYour Name 		struct ieee80211_supported_band *ieee_band;
2209*5113495bSYour Name 		uint32_t channel_bonding_mode;
2210*5113495bSYour Name 
2211*5113495bSYour Name 		ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc,
2212*5113495bSYour Name 						   &channel_bonding_mode);
2213*5113495bSYour Name 		ieee_band = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ];
2214*5113495bSYour Name 		if (channel_bonding_mode)
2215*5113495bSYour Name 			ieee_band->ht_cap.cap |=
2216*5113495bSYour Name 					IEEE80211_HT_CAP_SUP_WIDTH_20_40;
2217*5113495bSYour Name 		else
2218*5113495bSYour Name 			ieee_band->ht_cap.cap &=
2219*5113495bSYour Name 					~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
2220*5113495bSYour Name 	}
2221*5113495bSYour Name 
2222*5113495bSYour Name free:
2223*5113495bSYour Name 	if (sme_config)
2224*5113495bSYour Name 		qdf_mem_free(sme_config);
2225*5113495bSYour Name 	return ret;
2226*5113495bSYour Name }
2227*5113495bSYour Name 
hdd_get_ldpc(struct hdd_adapter * adapter,int * value)2228*5113495bSYour Name int hdd_get_ldpc(struct hdd_adapter *adapter, int *value)
2229*5113495bSYour Name {
2230*5113495bSYour Name 	mac_handle_t mac_handle = adapter->hdd_ctx->mac_handle;
2231*5113495bSYour Name 	int ret;
2232*5113495bSYour Name 
2233*5113495bSYour Name 	hdd_enter();
2234*5113495bSYour Name 	ret = sme_get_ht_config(mac_handle, adapter->deflink->vdev_id,
2235*5113495bSYour Name 				WNI_CFG_HT_CAP_INFO_ADVANCE_CODING);
2236*5113495bSYour Name 	if (ret < 0) {
2237*5113495bSYour Name 		hdd_err("Failed to get LDPC value");
2238*5113495bSYour Name 	} else {
2239*5113495bSYour Name 		*value = ret;
2240*5113495bSYour Name 		ret = 0;
2241*5113495bSYour Name 	}
2242*5113495bSYour Name 	return ret;
2243*5113495bSYour Name }
2244*5113495bSYour Name 
hdd_set_ldpc(struct wlan_hdd_link_info * link_info,int value)2245*5113495bSYour Name int hdd_set_ldpc(struct wlan_hdd_link_info *link_info, int value)
2246*5113495bSYour Name {
2247*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
2248*5113495bSYour Name 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
2249*5113495bSYour Name 	int ret;
2250*5113495bSYour Name 	QDF_STATUS status;
2251*5113495bSYour Name 	struct mlme_ht_capabilities_info ht_cap_info;
2252*5113495bSYour Name 
2253*5113495bSYour Name 	hdd_debug("%d", value);
2254*5113495bSYour Name 
2255*5113495bSYour Name 	if (!mac_handle) {
2256*5113495bSYour Name 		hdd_err("NULL Mac handle");
2257*5113495bSYour Name 		return -EINVAL;
2258*5113495bSYour Name 	}
2259*5113495bSYour Name 
2260*5113495bSYour Name 	status = ucfg_mlme_get_ht_cap_info(hdd_ctx->psoc, &ht_cap_info);
2261*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
2262*5113495bSYour Name 		hdd_err("Failed to get HT capability info");
2263*5113495bSYour Name 		return -EIO;
2264*5113495bSYour Name 	}
2265*5113495bSYour Name 
2266*5113495bSYour Name 	ht_cap_info.adv_coding_cap = value;
2267*5113495bSYour Name 	status = ucfg_mlme_set_ht_cap_info(hdd_ctx->psoc, ht_cap_info);
2268*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
2269*5113495bSYour Name 		hdd_err("Failed to set HT capability info");
2270*5113495bSYour Name 		return -EIO;
2271*5113495bSYour Name 	}
2272*5113495bSYour Name 	status = ucfg_mlme_cfg_set_vht_ldpc_coding_cap(hdd_ctx->psoc, value);
2273*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
2274*5113495bSYour Name 		hdd_err("Failed to set VHT LDPC capability info");
2275*5113495bSYour Name 		return -EIO;
2276*5113495bSYour Name 	}
2277*5113495bSYour Name 	ret = sme_update_ht_config(mac_handle, link_info->vdev_id,
2278*5113495bSYour Name 				   WNI_CFG_HT_CAP_INFO_ADVANCE_CODING, value);
2279*5113495bSYour Name 	if (ret)
2280*5113495bSYour Name 		hdd_err("Failed to set LDPC value");
2281*5113495bSYour Name 	ret = sme_update_he_ldpc_supp(mac_handle,
2282*5113495bSYour Name 				      link_info->vdev_id, value);
2283*5113495bSYour Name 	if (ret)
2284*5113495bSYour Name 		hdd_err("Failed to set HE LDPC value");
2285*5113495bSYour Name 	ret = sme_set_auto_rate_ldpc(mac_handle, link_info->vdev_id,
2286*5113495bSYour Name 				     (value ? 0 : 1));
2287*5113495bSYour Name 
2288*5113495bSYour Name 	return ret;
2289*5113495bSYour Name }
2290*5113495bSYour Name 
hdd_get_tx_stbc(struct hdd_adapter * adapter,int * value)2291*5113495bSYour Name int hdd_get_tx_stbc(struct hdd_adapter *adapter, int *value)
2292*5113495bSYour Name {
2293*5113495bSYour Name 	mac_handle_t mac_handle = adapter->hdd_ctx->mac_handle;
2294*5113495bSYour Name 	int ret;
2295*5113495bSYour Name 
2296*5113495bSYour Name 	hdd_enter();
2297*5113495bSYour Name 	ret = sme_get_ht_config(mac_handle, adapter->deflink->vdev_id,
2298*5113495bSYour Name 				WNI_CFG_HT_CAP_INFO_TX_STBC);
2299*5113495bSYour Name 	if (ret < 0) {
2300*5113495bSYour Name 		hdd_err("Failed to get TX STBC value");
2301*5113495bSYour Name 	} else {
2302*5113495bSYour Name 		*value = ret;
2303*5113495bSYour Name 		ret = 0;
2304*5113495bSYour Name 	}
2305*5113495bSYour Name 
2306*5113495bSYour Name 	return ret;
2307*5113495bSYour Name }
2308*5113495bSYour Name 
hdd_set_tx_stbc(struct wlan_hdd_link_info * link_info,int value)2309*5113495bSYour Name int hdd_set_tx_stbc(struct wlan_hdd_link_info *link_info, int value)
2310*5113495bSYour Name {
2311*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
2312*5113495bSYour Name 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
2313*5113495bSYour Name 	int ret;
2314*5113495bSYour Name 	QDF_STATUS status;
2315*5113495bSYour Name 	struct mlme_ht_capabilities_info ht_cap_info;
2316*5113495bSYour Name 
2317*5113495bSYour Name 	hdd_debug("%d", value);
2318*5113495bSYour Name 
2319*5113495bSYour Name 	if (!mac_handle) {
2320*5113495bSYour Name 		hdd_err("NULL Mac handle");
2321*5113495bSYour Name 		return -EINVAL;
2322*5113495bSYour Name 	}
2323*5113495bSYour Name 
2324*5113495bSYour Name 	if (value) {
2325*5113495bSYour Name 		/* make sure HT capabilities allow this */
2326*5113495bSYour Name 		status = ucfg_mlme_get_ht_cap_info(hdd_ctx->psoc,
2327*5113495bSYour Name 						   &ht_cap_info);
2328*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
2329*5113495bSYour Name 			hdd_err("Failed to get HT capability info");
2330*5113495bSYour Name 			return -EIO;
2331*5113495bSYour Name 		}
2332*5113495bSYour Name 		if (!ht_cap_info.tx_stbc) {
2333*5113495bSYour Name 			hdd_err("TX STBC not supported");
2334*5113495bSYour Name 			return -EINVAL;
2335*5113495bSYour Name 		}
2336*5113495bSYour Name 	}
2337*5113495bSYour Name 	ret = sme_update_ht_config(mac_handle, link_info->vdev_id,
2338*5113495bSYour Name 				   WNI_CFG_HT_CAP_INFO_TX_STBC,
2339*5113495bSYour Name 				   value);
2340*5113495bSYour Name 	if (ret)
2341*5113495bSYour Name 		hdd_err("Failed to set TX STBC value");
2342*5113495bSYour Name 	ret = sme_update_he_tx_stbc_cap(mac_handle,
2343*5113495bSYour Name 					link_info->vdev_id, value);
2344*5113495bSYour Name 	if (ret)
2345*5113495bSYour Name 		hdd_err("Failed to set HE TX STBC value");
2346*5113495bSYour Name 
2347*5113495bSYour Name 	return ret;
2348*5113495bSYour Name }
2349*5113495bSYour Name 
hdd_get_rx_stbc(struct hdd_adapter * adapter,int * value)2350*5113495bSYour Name int hdd_get_rx_stbc(struct hdd_adapter *adapter, int *value)
2351*5113495bSYour Name {
2352*5113495bSYour Name 	mac_handle_t mac_handle = adapter->hdd_ctx->mac_handle;
2353*5113495bSYour Name 	int ret;
2354*5113495bSYour Name 
2355*5113495bSYour Name 	hdd_enter();
2356*5113495bSYour Name 	ret = sme_get_ht_config(mac_handle, adapter->deflink->vdev_id,
2357*5113495bSYour Name 				WNI_CFG_HT_CAP_INFO_RX_STBC);
2358*5113495bSYour Name 	if (ret < 0) {
2359*5113495bSYour Name 		hdd_err("Failed to get RX STBC value");
2360*5113495bSYour Name 	} else {
2361*5113495bSYour Name 		*value = ret;
2362*5113495bSYour Name 		ret = 0;
2363*5113495bSYour Name 	}
2364*5113495bSYour Name 
2365*5113495bSYour Name 	return ret;
2366*5113495bSYour Name }
2367*5113495bSYour Name 
hdd_set_rx_stbc(struct wlan_hdd_link_info * link_info,int value)2368*5113495bSYour Name int hdd_set_rx_stbc(struct wlan_hdd_link_info *link_info, int value)
2369*5113495bSYour Name {
2370*5113495bSYour Name 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
2371*5113495bSYour Name 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
2372*5113495bSYour Name 	int ret;
2373*5113495bSYour Name 	QDF_STATUS status;
2374*5113495bSYour Name 	struct mlme_ht_capabilities_info ht_cap_info;
2375*5113495bSYour Name 
2376*5113495bSYour Name 	hdd_debug("%d", value);
2377*5113495bSYour Name 
2378*5113495bSYour Name 	if (!mac_handle) {
2379*5113495bSYour Name 		hdd_err("NULL Mac handle");
2380*5113495bSYour Name 		return -EINVAL;
2381*5113495bSYour Name 	}
2382*5113495bSYour Name 
2383*5113495bSYour Name 	if (value) {
2384*5113495bSYour Name 		/* make sure HT capabilities allow this */
2385*5113495bSYour Name 		status = ucfg_mlme_get_ht_cap_info(hdd_ctx->psoc,
2386*5113495bSYour Name 						   &ht_cap_info);
2387*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
2388*5113495bSYour Name 			hdd_err("Failed to get HT capability info");
2389*5113495bSYour Name 			return -EIO;
2390*5113495bSYour Name 		}
2391*5113495bSYour Name 		if (!ht_cap_info.rx_stbc) {
2392*5113495bSYour Name 			hdd_warn("RX STBC not supported");
2393*5113495bSYour Name 			return -EINVAL;
2394*5113495bSYour Name 		}
2395*5113495bSYour Name 	}
2396*5113495bSYour Name 	ret = sme_update_ht_config(mac_handle, link_info->vdev_id,
2397*5113495bSYour Name 				   WNI_CFG_HT_CAP_INFO_RX_STBC,
2398*5113495bSYour Name 				   value);
2399*5113495bSYour Name 	if (ret)
2400*5113495bSYour Name 		hdd_err("Failed to set RX STBC value");
2401*5113495bSYour Name 
2402*5113495bSYour Name 	ret = sme_update_he_rx_stbc_cap(mac_handle,
2403*5113495bSYour Name 					link_info->vdev_id, value);
2404*5113495bSYour Name 	if (ret)
2405*5113495bSYour Name 		hdd_err("Failed to set HE RX STBC value");
2406*5113495bSYour Name 
2407*5113495bSYour Name 	return ret;
2408*5113495bSYour Name }
2409*5113495bSYour Name 
2410*5113495bSYour Name /**
2411*5113495bSYour Name  * hdd_convert_chwidth_to_phy_chwidth() - convert channel width of type enum
2412*5113495bSYour Name  * eSirMacHTChannelWidth to enum phy_ch_width
2413*5113495bSYour Name  * @chwidth: channel width of type enum eSirMacHTChannelWidth
2414*5113495bSYour Name  *
2415*5113495bSYour Name  * Return: channel width of type enum phy_ch_width
2416*5113495bSYour Name  */
2417*5113495bSYour Name static enum phy_ch_width
hdd_convert_chwidth_to_phy_chwidth(enum eSirMacHTChannelWidth chwidth)2418*5113495bSYour Name hdd_convert_chwidth_to_phy_chwidth(enum eSirMacHTChannelWidth chwidth)
2419*5113495bSYour Name {
2420*5113495bSYour Name 	enum phy_ch_width ch_width = CH_WIDTH_INVALID;
2421*5113495bSYour Name 
2422*5113495bSYour Name 	switch (chwidth) {
2423*5113495bSYour Name 	case eHT_CHANNEL_WIDTH_20MHZ:
2424*5113495bSYour Name 		ch_width = CH_WIDTH_20MHZ;
2425*5113495bSYour Name 		break;
2426*5113495bSYour Name 	case eHT_CHANNEL_WIDTH_40MHZ:
2427*5113495bSYour Name 		ch_width = CH_WIDTH_40MHZ;
2428*5113495bSYour Name 		break;
2429*5113495bSYour Name 	case eHT_CHANNEL_WIDTH_80MHZ:
2430*5113495bSYour Name 		ch_width = CH_WIDTH_80MHZ;
2431*5113495bSYour Name 		break;
2432*5113495bSYour Name 	case eHT_CHANNEL_WIDTH_160MHZ:
2433*5113495bSYour Name 		ch_width = CH_WIDTH_160MHZ;
2434*5113495bSYour Name 		break;
2435*5113495bSYour Name 	case eHT_CHANNEL_WIDTH_80P80MHZ:
2436*5113495bSYour Name 		ch_width = CH_WIDTH_80P80MHZ;
2437*5113495bSYour Name 		break;
2438*5113495bSYour Name 	case eHT_CHANNEL_WIDTH_320MHZ:
2439*5113495bSYour Name 		ch_width = CH_WIDTH_320MHZ;
2440*5113495bSYour Name 		break;
2441*5113495bSYour Name 	default:
2442*5113495bSYour Name 		hdd_debug("Invalid channel width %d", chwidth);
2443*5113495bSYour Name 		break;
2444*5113495bSYour Name 	}
2445*5113495bSYour Name 
2446*5113495bSYour Name 	return ch_width;
2447*5113495bSYour Name }
2448*5113495bSYour Name 
2449*5113495bSYour Name /**
2450*5113495bSYour Name  * hdd_update_bss_rate_flags() - update bss rate flag as per new channel width
2451*5113495bSYour Name  * @link_info: Link info in HDD adapter
2452*5113495bSYour Name  * @psoc: psoc common object
2453*5113495bSYour Name  * @cw: channel width for which bss rate flag being updated
2454*5113495bSYour Name  *
2455*5113495bSYour Name  * Return: QDF_STATUS
2456*5113495bSYour Name  */
2457*5113495bSYour Name static QDF_STATUS
hdd_update_bss_rate_flags(struct wlan_hdd_link_info * link_info,struct wlan_objmgr_psoc * psoc,enum phy_ch_width cw)2458*5113495bSYour Name hdd_update_bss_rate_flags(struct wlan_hdd_link_info *link_info,
2459*5113495bSYour Name 			  struct wlan_objmgr_psoc *psoc, enum phy_ch_width cw)
2460*5113495bSYour Name {
2461*5113495bSYour Name 	struct hdd_station_ctx *hdd_sta_ctx;
2462*5113495bSYour Name 	uint8_t eht_present, he_present, vht_present, ht_present;
2463*5113495bSYour Name 
2464*5113495bSYour Name 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
2465*5113495bSYour Name 
2466*5113495bSYour Name 	eht_present = hdd_sta_ctx->conn_info.conn_flag.eht_present;
2467*5113495bSYour Name 	he_present = hdd_sta_ctx->conn_info.conn_flag.he_present;
2468*5113495bSYour Name 	vht_present = hdd_sta_ctx->conn_info.conn_flag.vht_present;
2469*5113495bSYour Name 	ht_present = hdd_sta_ctx->conn_info.conn_flag.ht_present;
2470*5113495bSYour Name 
2471*5113495bSYour Name 	return ucfg_mlme_update_bss_rate_flags(psoc, link_info->vdev_id,
2472*5113495bSYour Name 					       cw, eht_present, he_present,
2473*5113495bSYour Name 					       vht_present, ht_present);
2474*5113495bSYour Name }
2475*5113495bSYour Name 
2476*5113495bSYour Name /**
2477*5113495bSYour Name  * struct sme_config_msg_ctx - sme config update message ctx
2478*5113495bSYour Name  * @vdev: vdev object
2479*5113495bSYour Name  * @chwidth: channel width
2480*5113495bSYour Name  * @is_restore: restore default or not
2481*5113495bSYour Name  * @bonding_mode: bonding mode
2482*5113495bSYour Name  */
2483*5113495bSYour Name struct sme_config_msg_ctx {
2484*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
2485*5113495bSYour Name 	enum eSirMacHTChannelWidth chwidth;
2486*5113495bSYour Name 	bool is_restore;
2487*5113495bSYour Name 	uint32_t bonding_mode;
2488*5113495bSYour Name };
2489*5113495bSYour Name 
2490*5113495bSYour Name /**
2491*5113495bSYour Name  * hdd_restore_sme_config_cb() - restore bonding mode sme config cb
2492*5113495bSYour Name  * @msg: msg data
2493*5113495bSYour Name  *
2494*5113495bSYour Name  * Return: QDF_STATUS
2495*5113495bSYour Name  */
hdd_restore_sme_config_cb(struct scheduler_msg * msg)2496*5113495bSYour Name static QDF_STATUS hdd_restore_sme_config_cb(struct scheduler_msg *msg)
2497*5113495bSYour Name {
2498*5113495bSYour Name 	struct hdd_context *hdd_ctx;
2499*5113495bSYour Name 	mac_handle_t mac_handle;
2500*5113495bSYour Name 	struct sme_config_params *sme_config = NULL;
2501*5113495bSYour Name 	struct sme_config_msg_ctx *sme_config_msg_ctx = NULL;
2502*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = NULL;
2503*5113495bSYour Name 	uint8_t vdev_id;
2504*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
2505*5113495bSYour Name 
2506*5113495bSYour Name 	if (!msg) {
2507*5113495bSYour Name 		hdd_debug("msg is null");
2508*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2509*5113495bSYour Name 	}
2510*5113495bSYour Name 
2511*5113495bSYour Name 	sme_config_msg_ctx = msg->bodyptr;
2512*5113495bSYour Name 	if (!sme_config_msg_ctx) {
2513*5113495bSYour Name 		hdd_debug("bodyptr is null");
2514*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2515*5113495bSYour Name 	}
2516*5113495bSYour Name 
2517*5113495bSYour Name 	vdev = sme_config_msg_ctx->vdev;
2518*5113495bSYour Name 	if (!vdev)
2519*5113495bSYour Name 		goto end;
2520*5113495bSYour Name 
2521*5113495bSYour Name 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
2522*5113495bSYour Name 	if (wlan_hdd_validate_context(hdd_ctx))
2523*5113495bSYour Name 		goto end;
2524*5113495bSYour Name 
2525*5113495bSYour Name 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
2526*5113495bSYour Name 	if (!mac_handle)
2527*5113495bSYour Name 		goto end;
2528*5113495bSYour Name 
2529*5113495bSYour Name 	if (!hdd_ctx->psoc)
2530*5113495bSYour Name 		goto end;
2531*5113495bSYour Name 
2532*5113495bSYour Name 	sme_config = qdf_mem_malloc(sizeof(*sme_config));
2533*5113495bSYour Name 	if (!sme_config)
2534*5113495bSYour Name 		goto end;
2535*5113495bSYour Name 
2536*5113495bSYour Name 	vdev_id = wlan_vdev_get_id(vdev);
2537*5113495bSYour Name 	hdd_debug("vdev id %d is_restore %d bonding_mode %d chwdith %d",
2538*5113495bSYour Name 		  vdev_id,
2539*5113495bSYour Name 		  sme_config_msg_ctx->is_restore,
2540*5113495bSYour Name 		  sme_config_msg_ctx->bonding_mode,
2541*5113495bSYour Name 		  sme_config_msg_ctx->chwidth);
2542*5113495bSYour Name 	sme_get_config_param(mac_handle, sme_config);
2543*5113495bSYour Name 	if (sme_config_msg_ctx->is_restore) {
2544*5113495bSYour Name 		sme_config->csr_config.channelBondingMode5GHz =
2545*5113495bSYour Name 			cfg_get(hdd_ctx->psoc, CFG_CHANNEL_BONDING_MODE_5GHZ);
2546*5113495bSYour Name 		sme_config->csr_config.channelBondingMode24GHz =
2547*5113495bSYour Name 			cfg_get(hdd_ctx->psoc, CFG_CHANNEL_BONDING_MODE_24GHZ);
2548*5113495bSYour Name 	} else {
2549*5113495bSYour Name 		sme_config->csr_config.channelBondingMode5GHz =
2550*5113495bSYour Name 					sme_config_msg_ctx->bonding_mode;
2551*5113495bSYour Name 		sme_config->csr_config.channelBondingMode24GHz =
2552*5113495bSYour Name 					sme_config_msg_ctx->bonding_mode;
2553*5113495bSYour Name 	}
2554*5113495bSYour Name 	sme_update_config(mac_handle, sme_config);
2555*5113495bSYour Name 	sme_set_he_bw_cap(hdd_ctx->mac_handle, vdev_id,
2556*5113495bSYour Name 			  sme_config_msg_ctx->chwidth);
2557*5113495bSYour Name 	sme_set_eht_bw_cap(hdd_ctx->mac_handle, vdev_id,
2558*5113495bSYour Name 			   sme_config_msg_ctx->chwidth);
2559*5113495bSYour Name 
2560*5113495bSYour Name 	status = QDF_STATUS_SUCCESS;
2561*5113495bSYour Name end:
2562*5113495bSYour Name 	qdf_mem_free(sme_config);
2563*5113495bSYour Name 	if (vdev)
2564*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_HDD_ID_OBJ_MGR);
2565*5113495bSYour Name 	qdf_mem_free(sme_config_msg_ctx);
2566*5113495bSYour Name 
2567*5113495bSYour Name 	return status;
2568*5113495bSYour Name }
2569*5113495bSYour Name 
2570*5113495bSYour Name /**
2571*5113495bSYour Name  * hdd_restore_sme_config_flush_cb() - bonding mode sme config flush cb
2572*5113495bSYour Name  * @msg: msg data
2573*5113495bSYour Name  *
2574*5113495bSYour Name  * Return: QDF_STATUS
2575*5113495bSYour Name  */
hdd_restore_sme_config_flush_cb(struct scheduler_msg * msg)2576*5113495bSYour Name static QDF_STATUS hdd_restore_sme_config_flush_cb(struct scheduler_msg *msg)
2577*5113495bSYour Name {
2578*5113495bSYour Name 	struct sme_config_msg_ctx *sme_config_msg_ctx;
2579*5113495bSYour Name 
2580*5113495bSYour Name 	if (!msg) {
2581*5113495bSYour Name 		hdd_debug("msg is null");
2582*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2583*5113495bSYour Name 	}
2584*5113495bSYour Name 
2585*5113495bSYour Name 	sme_config_msg_ctx = msg->bodyptr;
2586*5113495bSYour Name 	if (!sme_config_msg_ctx) {
2587*5113495bSYour Name 		hdd_debug("bodyptr is null");
2588*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2589*5113495bSYour Name 	}
2590*5113495bSYour Name 
2591*5113495bSYour Name 	if (sme_config_msg_ctx->vdev)
2592*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(sme_config_msg_ctx->vdev,
2593*5113495bSYour Name 					    WLAN_HDD_ID_OBJ_MGR);
2594*5113495bSYour Name 	else
2595*5113495bSYour Name 		hdd_debug("vdev is null");
2596*5113495bSYour Name 
2597*5113495bSYour Name 	qdf_mem_free(sme_config_msg_ctx);
2598*5113495bSYour Name 
2599*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2600*5113495bSYour Name }
2601*5113495bSYour Name 
2602*5113495bSYour Name /**
2603*5113495bSYour Name  * hdd_restore_sme_config() - restore bonding mode for sme config
2604*5113495bSYour Name  * @link_info: link info
2605*5113495bSYour Name  * @chwidth: channel width
2606*5113495bSYour Name  * @is_restore: msg data
2607*5113495bSYour Name  * @bonding_mode: bonding mode
2608*5113495bSYour Name  *
2609*5113495bSYour Name  * Return: void
2610*5113495bSYour Name  */
hdd_restore_sme_config(struct wlan_hdd_link_info * link_info,enum eSirMacHTChannelWidth chwidth,bool is_restore,uint32_t bonding_mode)2611*5113495bSYour Name static void hdd_restore_sme_config(struct wlan_hdd_link_info *link_info,
2612*5113495bSYour Name 				   enum eSirMacHTChannelWidth chwidth,
2613*5113495bSYour Name 				   bool is_restore, uint32_t bonding_mode)
2614*5113495bSYour Name {
2615*5113495bSYour Name 	struct scheduler_msg msg = {0};
2616*5113495bSYour Name 	QDF_STATUS status;
2617*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
2618*5113495bSYour Name 	struct sme_config_msg_ctx *sme_config_msg_ctx;
2619*5113495bSYour Name 
2620*5113495bSYour Name 	sme_config_msg_ctx = qdf_mem_malloc(sizeof(*sme_config_msg_ctx));
2621*5113495bSYour Name 	if (!sme_config_msg_ctx)
2622*5113495bSYour Name 		return;
2623*5113495bSYour Name 
2624*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_HDD_ID_OBJ_MGR);
2625*5113495bSYour Name 	if (!vdev) {
2626*5113495bSYour Name 		qdf_mem_free(sme_config_msg_ctx);
2627*5113495bSYour Name 		hdd_debug("no vdev from link info");
2628*5113495bSYour Name 		return;
2629*5113495bSYour Name 	}
2630*5113495bSYour Name 
2631*5113495bSYour Name 	sme_config_msg_ctx->vdev = vdev;
2632*5113495bSYour Name 	sme_config_msg_ctx->chwidth = chwidth;
2633*5113495bSYour Name 	sme_config_msg_ctx->is_restore = is_restore;
2634*5113495bSYour Name 	sme_config_msg_ctx->bonding_mode = bonding_mode;
2635*5113495bSYour Name 	msg.bodyptr = sme_config_msg_ctx;
2636*5113495bSYour Name 	msg.callback = hdd_restore_sme_config_cb;
2637*5113495bSYour Name 	msg.flush_callback = hdd_restore_sme_config_flush_cb;
2638*5113495bSYour Name 
2639*5113495bSYour Name 	status = scheduler_post_message(QDF_MODULE_ID_HDD,
2640*5113495bSYour Name 					QDF_MODULE_ID_OS_IF,
2641*5113495bSYour Name 					QDF_MODULE_ID_OS_IF, &msg);
2642*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
2643*5113495bSYour Name 		hdd_debug("status %d", status);
2644*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_HDD_ID_OBJ_MGR);
2645*5113495bSYour Name 		qdf_mem_free(sme_config_msg_ctx);
2646*5113495bSYour Name 	}
2647*5113495bSYour Name }
2648*5113495bSYour Name 
2649*5113495bSYour Name /**
2650*5113495bSYour Name  * wlan_update_mlo_link_chn_width() - API to update mlo link chn width
2651*5113495bSYour Name  * @adapter: the pointer to adapter
2652*5113495bSYour Name  * @ch_width: channel width to update
2653*5113495bSYour Name  * @link_id: mlo link id
2654*5113495bSYour Name  *
2655*5113495bSYour Name  * Get link id and channel bandwidth from user space and save in link_info.
2656*5113495bSYour Name  * When link switch happen and host driver connect done, if the link change
2657*5113495bSYour Name  * from standby to non-standby, ch_width will send to fw again.
2658*5113495bSYour Name  *
2659*5113495bSYour Name  * Return: QDF_STATUS
2660*5113495bSYour Name  */
2661*5113495bSYour Name 
2662*5113495bSYour Name #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
2663*5113495bSYour Name static struct wlan_hdd_link_info *
wlan_update_mlo_link_chn_width(struct hdd_adapter * adapter,enum phy_ch_width ch_width,uint8_t link_id)2664*5113495bSYour Name wlan_update_mlo_link_chn_width(struct hdd_adapter *adapter,
2665*5113495bSYour Name 			       enum phy_ch_width ch_width,
2666*5113495bSYour Name 			       uint8_t link_id)
2667*5113495bSYour Name {
2668*5113495bSYour Name 	struct wlan_hdd_link_info *link_info;
2669*5113495bSYour Name 	struct hdd_station_ctx *sta_ctx;
2670*5113495bSYour Name 
2671*5113495bSYour Name 	link_info = hdd_get_link_info_by_ieee_link_id(adapter, link_id);
2672*5113495bSYour Name 	if (!link_info)
2673*5113495bSYour Name 		return NULL;
2674*5113495bSYour Name 
2675*5113495bSYour Name 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
2676*5113495bSYour Name 
2677*5113495bSYour Name 	sta_ctx->user_cfg_chn_width = ch_width;
2678*5113495bSYour Name 	hdd_debug("save ch_width:%u to link_id:%u vdev_id:%u",
2679*5113495bSYour Name 		  ch_width, link_id, link_info->vdev_id);
2680*5113495bSYour Name 
2681*5113495bSYour Name 	return link_info;
2682*5113495bSYour Name }
2683*5113495bSYour Name #else
2684*5113495bSYour Name static struct wlan_hdd_link_info *
wlan_update_mlo_link_chn_width(struct hdd_adapter * adapter,enum phy_ch_width ch_width,uint8_t link_id)2685*5113495bSYour Name wlan_update_mlo_link_chn_width(struct hdd_adapter *adapter,
2686*5113495bSYour Name 			       enum phy_ch_width ch_width,
2687*5113495bSYour Name 			       uint8_t link_id)
2688*5113495bSYour Name {
2689*5113495bSYour Name 	return NULL;
2690*5113495bSYour Name }
2691*5113495bSYour Name #endif
2692*5113495bSYour Name 
hdd_update_channel_width(struct wlan_hdd_link_info * link_info,enum eSirMacHTChannelWidth chwidth,uint32_t bonding_mode,uint8_t link_id,bool is_restore)2693*5113495bSYour Name int hdd_update_channel_width(struct wlan_hdd_link_info *link_info,
2694*5113495bSYour Name 			     enum eSirMacHTChannelWidth chwidth,
2695*5113495bSYour Name 			     uint32_t bonding_mode, uint8_t link_id,
2696*5113495bSYour Name 			     bool is_restore)
2697*5113495bSYour Name {
2698*5113495bSYour Name 	struct hdd_context *hdd_ctx;
2699*5113495bSYour Name 	int ret;
2700*5113495bSYour Name 	enum phy_ch_width ch_width;
2701*5113495bSYour Name 	struct wlan_objmgr_vdev *link_vdev;
2702*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
2703*5113495bSYour Name 	struct wlan_hdd_link_info *link_info_t;
2704*5113495bSYour Name 	uint8_t link_vdev_id;
2705*5113495bSYour Name 	enum QDF_OPMODE op_mode;
2706*5113495bSYour Name 	QDF_STATUS status;
2707*5113495bSYour Name 	uint8_t vdev_id = link_info->vdev_id;
2708*5113495bSYour Name 	enum phy_ch_width new_ch_width;
2709*5113495bSYour Name 
2710*5113495bSYour Name 	hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
2711*5113495bSYour Name 	if (!hdd_ctx) {
2712*5113495bSYour Name 		hdd_err("hdd_ctx failure");
2713*5113495bSYour Name 		return -EINVAL;
2714*5113495bSYour Name 	}
2715*5113495bSYour Name 
2716*5113495bSYour Name 	op_mode = link_info->adapter->device_mode;
2717*5113495bSYour Name 	if (op_mode != QDF_STA_MODE) {
2718*5113495bSYour Name 		hdd_debug("vdev %d: op mode %d, CW update not supported",
2719*5113495bSYour Name 			  vdev_id, op_mode);
2720*5113495bSYour Name 		return -EINVAL;
2721*5113495bSYour Name 	}
2722*5113495bSYour Name 
2723*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
2724*5113495bSYour Name 	if (!vdev) {
2725*5113495bSYour Name 		hdd_err("vdev %d: vdev not found", vdev_id);
2726*5113495bSYour Name 		return -EINVAL;
2727*5113495bSYour Name 	}
2728*5113495bSYour Name 
2729*5113495bSYour Name 	ch_width = hdd_convert_chwidth_to_phy_chwidth(chwidth);
2730*5113495bSYour Name 
2731*5113495bSYour Name 	/**
2732*5113495bSYour Name 	 * Link_id check is for disconnect restore process.
2733*5113495bSYour Name 	 * Disconnect will not update channel bandwidth into cache struct.
2734*5113495bSYour Name 	 */
2735*5113495bSYour Name 	if (wlan_vdev_mlme_is_mlo_vdev(vdev) &&
2736*5113495bSYour Name 	    link_id != WLAN_INVALID_LINK_ID) {
2737*5113495bSYour Name 		link_info_t = wlan_update_mlo_link_chn_width(link_info->adapter,
2738*5113495bSYour Name 							     ch_width, link_id);
2739*5113495bSYour Name 		if (!link_info_t) {
2740*5113495bSYour Name 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
2741*5113495bSYour Name 			return -EINVAL;
2742*5113495bSYour Name 		}
2743*5113495bSYour Name 
2744*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
2745*5113495bSYour Name 
2746*5113495bSYour Name 		link_vdev = hdd_objmgr_get_vdev_by_user(link_info_t,
2747*5113495bSYour Name 							WLAN_OSIF_ID);
2748*5113495bSYour Name 		if (!link_vdev)
2749*5113495bSYour Name 			return 0;
2750*5113495bSYour Name 
2751*5113495bSYour Name 		link_vdev_id = link_info_t->vdev_id;
2752*5113495bSYour Name 		status = wlan_mlme_get_bw_no_punct(hdd_ctx->psoc,
2753*5113495bSYour Name 						   link_vdev,
2754*5113495bSYour Name 						   wlan_vdev_mlme_get_des_chan(link_vdev),
2755*5113495bSYour Name 						   &new_ch_width);
2756*5113495bSYour Name 		if (QDF_IS_STATUS_SUCCESS(status) && ch_width > new_ch_width)
2757*5113495bSYour Name 			ch_width = new_ch_width;
2758*5113495bSYour Name 	} else {
2759*5113495bSYour Name 		link_vdev = vdev;
2760*5113495bSYour Name 		link_vdev_id = vdev_id;
2761*5113495bSYour Name 		link_info_t = link_info;
2762*5113495bSYour Name 	}
2763*5113495bSYour Name 
2764*5113495bSYour Name 	if (ucfg_mlme_is_chwidth_with_notify_supported(hdd_ctx->psoc) &&
2765*5113495bSYour Name 	    hdd_cm_is_vdev_connected(link_info_t)) {
2766*5113495bSYour Name 		ch_width = hdd_convert_chwidth_to_phy_chwidth(chwidth);
2767*5113495bSYour Name 		hdd_debug("vdev %d : process update ch width request to %d",
2768*5113495bSYour Name 			  link_vdev_id, ch_width);
2769*5113495bSYour Name 		status = ucfg_mlme_send_ch_width_update_with_notify(hdd_ctx->psoc,
2770*5113495bSYour Name 								    link_vdev,
2771*5113495bSYour Name 								    ch_width,
2772*5113495bSYour Name 								    link_vdev_id);
2773*5113495bSYour Name 
2774*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
2775*5113495bSYour Name 			hdd_objmgr_put_vdev_by_user(link_vdev, WLAN_OSIF_ID);
2776*5113495bSYour Name 			return -EIO;
2777*5113495bSYour Name 		}
2778*5113495bSYour Name 		status = hdd_update_bss_rate_flags(link_info_t, hdd_ctx->psoc,
2779*5113495bSYour Name 						   ch_width);
2780*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
2781*5113495bSYour Name 			hdd_objmgr_put_vdev_by_user(link_vdev, WLAN_OSIF_ID);
2782*5113495bSYour Name 			return -EIO;
2783*5113495bSYour Name 		}
2784*5113495bSYour Name 
2785*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(link_vdev, WLAN_OSIF_ID);
2786*5113495bSYour Name 		return 0;
2787*5113495bSYour Name 	}
2788*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(link_vdev, WLAN_OSIF_ID);
2789*5113495bSYour Name 
2790*5113495bSYour Name 	ret = wma_cli_set_command(link_vdev_id, wmi_vdev_param_chwidth,
2791*5113495bSYour Name 				  chwidth, VDEV_CMD);
2792*5113495bSYour Name 	if (ret)
2793*5113495bSYour Name 		return ret;
2794*5113495bSYour Name 
2795*5113495bSYour Name 	hdd_restore_sme_config(link_info_t, chwidth, is_restore, bonding_mode);
2796*5113495bSYour Name 
2797*5113495bSYour Name 	return 0;
2798*5113495bSYour Name }
2799