xref: /wlan-driver/qca-wifi-host-cmn/cfg/src/cfg.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-2023 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 #include "cfg_all.h"
21*5113495bSYour Name #include "cfg_define.h"
22*5113495bSYour Name #include "cfg_dispatcher.h"
23*5113495bSYour Name #include "cfg_ucfg_api.h"
24*5113495bSYour Name #include "i_cfg.h"
25*5113495bSYour Name #include "i_cfg_objmgr.h"
26*5113495bSYour Name #include "qdf_atomic.h"
27*5113495bSYour Name #include "qdf_list.h"
28*5113495bSYour Name #include "qdf_mem.h"
29*5113495bSYour Name #include "qdf_module.h"
30*5113495bSYour Name #include "qdf_parse.h"
31*5113495bSYour Name #include "qdf_status.h"
32*5113495bSYour Name #include "qdf_str.h"
33*5113495bSYour Name #include "qdf_trace.h"
34*5113495bSYour Name #include "qdf_types.h"
35*5113495bSYour Name #include "wlan_objmgr_psoc_obj.h"
36*5113495bSYour Name 
37*5113495bSYour Name /**
38*5113495bSYour Name  * struct cfg_value_store - backing store for an ini file
39*5113495bSYour Name  * @path: file path of the ini file
40*5113495bSYour Name  * @node: internal list node for keeping track of all the allocated stores
41*5113495bSYour Name  * @users: number of references on the store
42*5113495bSYour Name  * @values: a values struct containing the parsed values from the ini file
43*5113495bSYour Name  */
44*5113495bSYour Name struct cfg_value_store {
45*5113495bSYour Name 	char *path;
46*5113495bSYour Name 	qdf_list_node_t node;
47*5113495bSYour Name 	qdf_atomic_t users;
48*5113495bSYour Name 	struct cfg_values values;
49*5113495bSYour Name };
50*5113495bSYour Name 
51*5113495bSYour Name /**
52*5113495bSYour Name  * enum cfg_type - Enum for CFG/INI types
53*5113495bSYour Name  * @CFG_INT_ITEM: Integer CFG/INI
54*5113495bSYour Name  * @CFG_UINT_ITEM: Unsigned integer CFG/INI
55*5113495bSYour Name  * @CFG_BOOL_ITEM: Boolean CFG/INI
56*5113495bSYour Name  * @CFG_STRING_ITEM: String CFG/INI
57*5113495bSYour Name  * @CFG_MAC_ITEM: Mac address CFG/INI
58*5113495bSYour Name  * @CFG_IPV4_ITEM: IPV4 address CFG/INI
59*5113495bSYour Name  * @CFG_IPV6_ITEM: IPV6 address CFG/INI
60*5113495bSYour Name  * @CFG_MAX_ITEM: Max CFG type
61*5113495bSYour Name  */
62*5113495bSYour Name enum cfg_type {
63*5113495bSYour Name 	CFG_INT_ITEM,
64*5113495bSYour Name 	CFG_UINT_ITEM,
65*5113495bSYour Name 	CFG_BOOL_ITEM,
66*5113495bSYour Name 	CFG_STRING_ITEM,
67*5113495bSYour Name 	CFG_MAC_ITEM,
68*5113495bSYour Name 	CFG_IPV4_ITEM,
69*5113495bSYour Name 	CFG_IPV6_ITEM,
70*5113495bSYour Name 	CFG_MAX_ITEM,
71*5113495bSYour Name };
72*5113495bSYour Name 
73*5113495bSYour Name #define CFG_META_NAME_LENGTH_MAX 256
74*5113495bSYour Name #define CFG_INI_LENGTH_MAX 128
75*5113495bSYour Name 
76*5113495bSYour Name /* define/populate dynamic metadata lookup table */
77*5113495bSYour Name 
78*5113495bSYour Name /**
79*5113495bSYour Name  * struct cfg_meta - configuration item metadata for dynamic lookup during parse
80*5113495bSYour Name  * @name: name of the config item used in the ini file (i.e. "gScanDwellTime")
81*5113495bSYour Name  * @item_handler: parsing callback based on the type of the config item
82*5113495bSYour Name  * @min: minimum value for use in bounds checking (min_len for strings)
83*5113495bSYour Name  * @max: maximum value for use in bounds checking (max_len for strings)
84*5113495bSYour Name  * @fallback: the fallback behavior to use when configured values are invalid
85*5113495bSYour Name  */
86*5113495bSYour Name struct cfg_meta {
87*5113495bSYour Name 	const char *name;
88*5113495bSYour Name 	const uint32_t field_offset;
89*5113495bSYour Name 	const enum cfg_type cfg_type;
90*5113495bSYour Name 	void (*const item_handler)(struct cfg_value_store *store,
91*5113495bSYour Name 				   const struct cfg_meta *meta,
92*5113495bSYour Name 				   const char *value);
93*5113495bSYour Name 	const int32_t min;
94*5113495bSYour Name 	const int32_t max;
95*5113495bSYour Name 	const enum cfg_fallback_behavior fallback;
96*5113495bSYour Name };
97*5113495bSYour Name 
98*5113495bSYour Name /* ini item handler functions */
99*5113495bSYour Name 
100*5113495bSYour Name #define cfg_value_ptr(store, meta) \
101*5113495bSYour Name 	((void *)&(store)->values + (meta)->field_offset)
102*5113495bSYour Name 
103*5113495bSYour Name static __attribute__((unused)) void
cfg_int_item_handler(struct cfg_value_store * store,const struct cfg_meta * meta,const char * str_value)104*5113495bSYour Name cfg_int_item_handler(struct cfg_value_store *store,
105*5113495bSYour Name 		     const struct cfg_meta *meta,
106*5113495bSYour Name 		     const char *str_value)
107*5113495bSYour Name {
108*5113495bSYour Name 	QDF_STATUS status;
109*5113495bSYour Name 	int32_t *store_value = cfg_value_ptr(store, meta);
110*5113495bSYour Name 	int32_t value;
111*5113495bSYour Name 
112*5113495bSYour Name 	status = qdf_int32_parse(str_value, &value);
113*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
114*5113495bSYour Name 		cfg_err("%s=%s - Invalid format (status %d); Using default %d",
115*5113495bSYour Name 			meta->name, str_value, status, *store_value);
116*5113495bSYour Name 		return;
117*5113495bSYour Name 	}
118*5113495bSYour Name 
119*5113495bSYour Name 	QDF_BUG(meta->min <= meta->max);
120*5113495bSYour Name 	if (meta->min > meta->max) {
121*5113495bSYour Name 		cfg_err("Invalid config item meta for %s", meta->name);
122*5113495bSYour Name 		return;
123*5113495bSYour Name 	}
124*5113495bSYour Name 
125*5113495bSYour Name 	if (value >= meta->min && value <= meta->max) {
126*5113495bSYour Name 		*store_value = value;
127*5113495bSYour Name 		return;
128*5113495bSYour Name 	}
129*5113495bSYour Name 
130*5113495bSYour Name 	switch (meta->fallback) {
131*5113495bSYour Name 	default:
132*5113495bSYour Name 		QDF_DEBUG_PANIC("Unknown fallback method %d for cfg item '%s'",
133*5113495bSYour Name 				meta->fallback, meta->name);
134*5113495bSYour Name 		fallthrough;
135*5113495bSYour Name 	case CFG_VALUE_OR_DEFAULT:
136*5113495bSYour Name 		/* store already contains default */
137*5113495bSYour Name 		break;
138*5113495bSYour Name 	case CFG_VALUE_OR_CLAMP:
139*5113495bSYour Name 		*store_value = __cfg_clamp(value, meta->min, meta->max);
140*5113495bSYour Name 		break;
141*5113495bSYour Name 	}
142*5113495bSYour Name 
143*5113495bSYour Name 	cfg_err("%s=%d - Out of range [%d, %d]; Using %d",
144*5113495bSYour Name 		meta->name, value, meta->min, meta->max, *store_value);
145*5113495bSYour Name }
146*5113495bSYour Name 
147*5113495bSYour Name static __attribute__((unused)) void
cfg_uint_item_handler(struct cfg_value_store * store,const struct cfg_meta * meta,const char * str_value)148*5113495bSYour Name cfg_uint_item_handler(struct cfg_value_store *store,
149*5113495bSYour Name 		      const struct cfg_meta *meta,
150*5113495bSYour Name 		      const char *str_value)
151*5113495bSYour Name {
152*5113495bSYour Name 	QDF_STATUS status;
153*5113495bSYour Name 	uint32_t *store_value = cfg_value_ptr(store, meta);
154*5113495bSYour Name 	uint32_t value;
155*5113495bSYour Name 	uint32_t min;
156*5113495bSYour Name 	uint32_t max;
157*5113495bSYour Name 
158*5113495bSYour Name 	/**
159*5113495bSYour Name 	 * Since meta min and max are of type int32_t
160*5113495bSYour Name 	 * We need explicit type casting to avoid
161*5113495bSYour Name 	 * implicit wrap around for uint32_t type cfg data.
162*5113495bSYour Name 	*/
163*5113495bSYour Name 	min = (uint32_t)meta->min;
164*5113495bSYour Name 	max = (uint32_t)meta->max;
165*5113495bSYour Name 
166*5113495bSYour Name 	status = qdf_uint32_parse(str_value, &value);
167*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
168*5113495bSYour Name 		cfg_err("%s=%s - Invalid format (status %d); Using default %u",
169*5113495bSYour Name 			meta->name, str_value, status, *store_value);
170*5113495bSYour Name 		return;
171*5113495bSYour Name 	}
172*5113495bSYour Name 
173*5113495bSYour Name 	QDF_BUG(min <= max);
174*5113495bSYour Name 	if (min > max) {
175*5113495bSYour Name 		cfg_err("Invalid config item meta for %s", meta->name);
176*5113495bSYour Name 		return;
177*5113495bSYour Name 	}
178*5113495bSYour Name 
179*5113495bSYour Name 	if (value >= min && value <= max) {
180*5113495bSYour Name 		*store_value = value;
181*5113495bSYour Name 		return;
182*5113495bSYour Name 	}
183*5113495bSYour Name 
184*5113495bSYour Name 	switch (meta->fallback) {
185*5113495bSYour Name 	default:
186*5113495bSYour Name 		QDF_DEBUG_PANIC("Unknown fallback method %d for cfg item '%s'",
187*5113495bSYour Name 				meta->fallback, meta->name);
188*5113495bSYour Name 		fallthrough;
189*5113495bSYour Name 	case CFG_VALUE_OR_DEFAULT:
190*5113495bSYour Name 		/* store already contains default */
191*5113495bSYour Name 		break;
192*5113495bSYour Name 	case CFG_VALUE_OR_CLAMP:
193*5113495bSYour Name 		*store_value = __cfg_clamp(value, min, max);
194*5113495bSYour Name 		break;
195*5113495bSYour Name 	}
196*5113495bSYour Name 
197*5113495bSYour Name 	cfg_err("%s=%u - Out of range [%d, %d]; Using %u",
198*5113495bSYour Name 		meta->name, value, min, max, *store_value);
199*5113495bSYour Name }
200*5113495bSYour Name 
201*5113495bSYour Name static __attribute__((unused)) void
cfg_bool_item_handler(struct cfg_value_store * store,const struct cfg_meta * meta,const char * str_value)202*5113495bSYour Name cfg_bool_item_handler(struct cfg_value_store *store,
203*5113495bSYour Name 		      const struct cfg_meta *meta,
204*5113495bSYour Name 		      const char *str_value)
205*5113495bSYour Name {
206*5113495bSYour Name 	QDF_STATUS status;
207*5113495bSYour Name 	bool *store_value = cfg_value_ptr(store, meta);
208*5113495bSYour Name 
209*5113495bSYour Name 	status = qdf_bool_parse(str_value, store_value);
210*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(status))
211*5113495bSYour Name 		return;
212*5113495bSYour Name 
213*5113495bSYour Name 	cfg_err("%s=%s - Invalid format (status %d); Using default '%s'",
214*5113495bSYour Name 		meta->name, str_value, status, *store_value ? "true" : "false");
215*5113495bSYour Name }
216*5113495bSYour Name 
217*5113495bSYour Name static __attribute__((unused)) void
cfg_string_item_handler(struct cfg_value_store * store,const struct cfg_meta * meta,const char * str_value)218*5113495bSYour Name cfg_string_item_handler(struct cfg_value_store *store,
219*5113495bSYour Name 			const struct cfg_meta *meta,
220*5113495bSYour Name 			const char *str_value)
221*5113495bSYour Name {
222*5113495bSYour Name 	char *store_value = cfg_value_ptr(store, meta);
223*5113495bSYour Name 	qdf_size_t len;
224*5113495bSYour Name 
225*5113495bSYour Name 	QDF_BUG(meta->min >= 0);
226*5113495bSYour Name 	QDF_BUG(meta->min <= meta->max);
227*5113495bSYour Name 	if (meta->min < 0 || meta->min > meta->max) {
228*5113495bSYour Name 		cfg_err("Invalid config item meta for %s", meta->name);
229*5113495bSYour Name 		return;
230*5113495bSYour Name 	}
231*5113495bSYour Name 
232*5113495bSYour Name 	/* ensure min length */
233*5113495bSYour Name 	len = qdf_str_nlen(str_value, meta->min);
234*5113495bSYour Name 	if (len < meta->min) {
235*5113495bSYour Name 		cfg_err("%s=%s - Too short; Using default '%s'",
236*5113495bSYour Name 			meta->name, str_value, store_value);
237*5113495bSYour Name 		return;
238*5113495bSYour Name 	}
239*5113495bSYour Name 
240*5113495bSYour Name 	/* check max length */
241*5113495bSYour Name 	len += qdf_str_nlen(str_value + meta->min, meta->max - meta->min + 1);
242*5113495bSYour Name 	if (len > meta->max) {
243*5113495bSYour Name 		cfg_err("%s=%s - Too long; Using default '%s'",
244*5113495bSYour Name 			meta->name, str_value, store_value);
245*5113495bSYour Name 		return;
246*5113495bSYour Name 	}
247*5113495bSYour Name 
248*5113495bSYour Name 	qdf_str_lcopy(store_value, str_value, meta->max + 1);
249*5113495bSYour Name }
250*5113495bSYour Name 
251*5113495bSYour Name static __attribute__((unused)) void
cfg_mac_item_handler(struct cfg_value_store * store,const struct cfg_meta * meta,const char * str_value)252*5113495bSYour Name cfg_mac_item_handler(struct cfg_value_store *store,
253*5113495bSYour Name 		     const struct cfg_meta *meta,
254*5113495bSYour Name 		     const char *str_value)
255*5113495bSYour Name {
256*5113495bSYour Name 	QDF_STATUS status;
257*5113495bSYour Name 	struct qdf_mac_addr *store_value = cfg_value_ptr(store, meta);
258*5113495bSYour Name 
259*5113495bSYour Name 	status = qdf_mac_parse(str_value, store_value);
260*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(status))
261*5113495bSYour Name 		return;
262*5113495bSYour Name 
263*5113495bSYour Name 	cfg_err("%s=%s - Invalid format (status %d); Using default "
264*5113495bSYour Name 		QDF_MAC_ADDR_FMT, meta->name, str_value, status,
265*5113495bSYour Name 		QDF_MAC_ADDR_REF(store_value->bytes));
266*5113495bSYour Name }
267*5113495bSYour Name 
268*5113495bSYour Name static __attribute__((unused)) void
cfg_ipv4_item_handler(struct cfg_value_store * store,const struct cfg_meta * meta,const char * str_value)269*5113495bSYour Name cfg_ipv4_item_handler(struct cfg_value_store *store,
270*5113495bSYour Name 		      const struct cfg_meta *meta,
271*5113495bSYour Name 		      const char *str_value)
272*5113495bSYour Name {
273*5113495bSYour Name 	QDF_STATUS status;
274*5113495bSYour Name 	struct qdf_ipv4_addr *store_value = cfg_value_ptr(store, meta);
275*5113495bSYour Name 
276*5113495bSYour Name 	status = qdf_ipv4_parse(str_value, store_value);
277*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(status))
278*5113495bSYour Name 		return;
279*5113495bSYour Name 
280*5113495bSYour Name 	cfg_err("%s=%s - Invalid format (status %d); Using default "
281*5113495bSYour Name 		QDF_IPV4_ADDR_STR, meta->name, str_value, status,
282*5113495bSYour Name 		QDF_IPV4_ADDR_ARRAY(store_value->bytes));
283*5113495bSYour Name }
284*5113495bSYour Name 
285*5113495bSYour Name static __attribute__((unused)) void
cfg_ipv6_item_handler(struct cfg_value_store * store,const struct cfg_meta * meta,const char * str_value)286*5113495bSYour Name cfg_ipv6_item_handler(struct cfg_value_store *store,
287*5113495bSYour Name 		      const struct cfg_meta *meta,
288*5113495bSYour Name 		      const char *str_value)
289*5113495bSYour Name {
290*5113495bSYour Name 	QDF_STATUS status;
291*5113495bSYour Name 	struct qdf_ipv6_addr *store_value = cfg_value_ptr(store, meta);
292*5113495bSYour Name 
293*5113495bSYour Name 	status = qdf_ipv6_parse(str_value, store_value);
294*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(status))
295*5113495bSYour Name 		return;
296*5113495bSYour Name 
297*5113495bSYour Name 	cfg_err("%s=%s - Invalid format (status %d); Using default "
298*5113495bSYour Name 		QDF_IPV6_ADDR_STR, meta->name, str_value, status,
299*5113495bSYour Name 		QDF_IPV6_ADDR_ARRAY(store_value->bytes));
300*5113495bSYour Name }
301*5113495bSYour Name 
302*5113495bSYour Name /* populate metadata lookup table */
303*5113495bSYour Name #undef __CFG_INI
304*5113495bSYour Name #define __CFG_INI(_id, _mtype, _ctype, _name, _min, _max, _fallback, ...) \
305*5113495bSYour Name { \
306*5113495bSYour Name 	.name = _name, \
307*5113495bSYour Name 	.field_offset = qdf_offsetof(struct cfg_values, _id##_internal), \
308*5113495bSYour Name 	.cfg_type = CFG_ ##_mtype ## _ITEM, \
309*5113495bSYour Name 	.item_handler = cfg_ ## _mtype ## _item_handler, \
310*5113495bSYour Name 	.min = _min, \
311*5113495bSYour Name 	.max = _max, \
312*5113495bSYour Name 	.fallback = _fallback, \
313*5113495bSYour Name },
314*5113495bSYour Name 
315*5113495bSYour Name #define cfg_INT_item_handler cfg_int_item_handler
316*5113495bSYour Name #define cfg_UINT_item_handler cfg_uint_item_handler
317*5113495bSYour Name #define cfg_BOOL_item_handler cfg_bool_item_handler
318*5113495bSYour Name #define cfg_STRING_item_handler cfg_string_item_handler
319*5113495bSYour Name #define cfg_MAC_item_handler cfg_mac_item_handler
320*5113495bSYour Name #define cfg_IPV4_item_handler cfg_ipv4_item_handler
321*5113495bSYour Name #define cfg_IPV6_item_handler cfg_ipv6_item_handler
322*5113495bSYour Name 
323*5113495bSYour Name static const struct cfg_meta cfg_meta_lookup_table[] = {
324*5113495bSYour Name 	CFG_ALL
325*5113495bSYour Name };
326*5113495bSYour Name 
327*5113495bSYour Name /* default store initializer */
328*5113495bSYour Name 
cfg_store_set_defaults(struct cfg_value_store * store)329*5113495bSYour Name static void cfg_store_set_defaults(struct cfg_value_store *store)
330*5113495bSYour Name {
331*5113495bSYour Name #undef __CFG_INI
332*5113495bSYour Name #define __CFG_INI(id, mtype, ctype, name, min, max, fallback, desc, def...) \
333*5113495bSYour Name 	ctype id = def;
334*5113495bSYour Name 
335*5113495bSYour Name 	CFG_ALL
336*5113495bSYour Name 
337*5113495bSYour Name #undef __CFG_INI_STRING
338*5113495bSYour Name #define __CFG_INI_STRING(id, mtype, ctype, name, min_len, max_len, ...) \
339*5113495bSYour Name 	qdf_str_lcopy((char *)&store->values.id##_internal, id, (max_len) + 1);
340*5113495bSYour Name 
341*5113495bSYour Name #undef __CFG_INI
342*5113495bSYour Name #define __CFG_INI(id, mtype, ctype, name, min, max, fallback, desc, def...) \
343*5113495bSYour Name 	*(ctype *)&store->values.id##_internal = id;
344*5113495bSYour Name 
345*5113495bSYour Name 	CFG_ALL
346*5113495bSYour Name }
347*5113495bSYour Name 
cfg_lookup_meta(const char * name)348*5113495bSYour Name static const struct cfg_meta *cfg_lookup_meta(const char *name)
349*5113495bSYour Name {
350*5113495bSYour Name 	int i;
351*5113495bSYour Name 	char *param1;
352*5113495bSYour Name 	char param[CFG_META_NAME_LENGTH_MAX];
353*5113495bSYour Name 	uint8_t ini_name[CFG_INI_LENGTH_MAX];
354*5113495bSYour Name 
355*5113495bSYour Name 	QDF_BUG(name);
356*5113495bSYour Name 	if (!name)
357*5113495bSYour Name 		return NULL;
358*5113495bSYour Name 
359*5113495bSYour Name 	/* linear search for now; optimize in the future if needed */
360*5113495bSYour Name 	for (i = 0; i < QDF_ARRAY_SIZE(cfg_meta_lookup_table); i++) {
361*5113495bSYour Name 		const struct cfg_meta *meta = &cfg_meta_lookup_table[i];
362*5113495bSYour Name 
363*5113495bSYour Name 		qdf_mem_zero(ini_name, CFG_INI_LENGTH_MAX);
364*5113495bSYour Name 
365*5113495bSYour Name 		qdf_mem_zero(param, CFG_META_NAME_LENGTH_MAX);
366*5113495bSYour Name 		if (strlen(meta->name) >= CFG_META_NAME_LENGTH_MAX) {
367*5113495bSYour Name 			cfg_err("Invalid meta name %s", meta->name);
368*5113495bSYour Name 			continue;
369*5113495bSYour Name 		}
370*5113495bSYour Name 
371*5113495bSYour Name 		qdf_mem_copy(param, meta->name, strlen(meta->name));
372*5113495bSYour Name 		param[strlen(meta->name)] = '\0';
373*5113495bSYour Name 		param1 = param;
374*5113495bSYour Name 		if (!sscanf(param1, "%s", ini_name)) {
375*5113495bSYour Name 			cfg_err("Cannot get ini name %s", param1);
376*5113495bSYour Name 			return NULL;
377*5113495bSYour Name 		}
378*5113495bSYour Name 		if (qdf_str_eq(name, ini_name))
379*5113495bSYour Name 			return meta;
380*5113495bSYour Name 
381*5113495bSYour Name 		param1 = strpbrk(param, " ");
382*5113495bSYour Name 		while (param1) {
383*5113495bSYour Name 			param1++;
384*5113495bSYour Name 			if (!sscanf(param1, "%s ", ini_name)) {
385*5113495bSYour Name 				cfg_err("Invalid ini name %s", meta->name);
386*5113495bSYour Name 				return NULL;
387*5113495bSYour Name 			}
388*5113495bSYour Name 			if (qdf_str_eq(name, ini_name))
389*5113495bSYour Name 				return meta;
390*5113495bSYour Name 			param1 = strpbrk(param1, " ");
391*5113495bSYour Name 		}
392*5113495bSYour Name 	}
393*5113495bSYour Name 	return NULL;
394*5113495bSYour Name }
395*5113495bSYour Name 
396*5113495bSYour Name static QDF_STATUS
cfg_ini_item_handler(void * context,const char * key,const char * value)397*5113495bSYour Name cfg_ini_item_handler(void *context, const char *key, const char *value)
398*5113495bSYour Name {
399*5113495bSYour Name 	struct cfg_value_store *store = context;
400*5113495bSYour Name 	const struct cfg_meta *meta;
401*5113495bSYour Name 
402*5113495bSYour Name 	meta = cfg_lookup_meta(key);
403*5113495bSYour Name 	if (!meta) {
404*5113495bSYour Name 		/* TODO: promote to 'err' or 'warn' once legacy is ported */
405*5113495bSYour Name 		cfg_debug("Unknown config item '%s'", key);
406*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
407*5113495bSYour Name 	}
408*5113495bSYour Name 
409*5113495bSYour Name 	QDF_BUG(meta->item_handler);
410*5113495bSYour Name 	if (!meta->item_handler)
411*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
412*5113495bSYour Name 
413*5113495bSYour Name 	meta->item_handler(store, meta, value);
414*5113495bSYour Name 
415*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
416*5113495bSYour Name }
417*5113495bSYour Name 
cfg_ini_section_handler(void * context,const char * name)418*5113495bSYour Name static QDF_STATUS cfg_ini_section_handler(void *context, const char *name)
419*5113495bSYour Name {
420*5113495bSYour Name 	cfg_err("Unexpected section '%s'. Sections are not supported.", name);
421*5113495bSYour Name 
422*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
423*5113495bSYour Name }
424*5113495bSYour Name 
425*5113495bSYour Name #define cfg_assert_success(expr) \
426*5113495bSYour Name do { \
427*5113495bSYour Name 	QDF_STATUS __assert_status = (expr); \
428*5113495bSYour Name 	QDF_BUG(QDF_IS_STATUS_SUCCESS(__assert_status)); \
429*5113495bSYour Name } while (0)
430*5113495bSYour Name 
431*5113495bSYour Name static bool __cfg_is_init;
432*5113495bSYour Name static struct cfg_value_store *__cfg_global_store;
433*5113495bSYour Name static qdf_list_t __cfg_stores_list;
434*5113495bSYour Name static qdf_spinlock_t __cfg_stores_lock;
435*5113495bSYour Name 
436*5113495bSYour Name struct cfg_psoc_ctx {
437*5113495bSYour Name 	struct cfg_value_store *store;
438*5113495bSYour Name };
439*5113495bSYour Name 
440*5113495bSYour Name static QDF_STATUS
cfg_store_alloc(const char * path,struct cfg_value_store ** out_store)441*5113495bSYour Name cfg_store_alloc(const char *path, struct cfg_value_store **out_store)
442*5113495bSYour Name {
443*5113495bSYour Name 	QDF_STATUS status;
444*5113495bSYour Name 	struct cfg_value_store *store;
445*5113495bSYour Name 
446*5113495bSYour Name 	cfg_enter();
447*5113495bSYour Name 
448*5113495bSYour Name 	store = qdf_mem_common_alloc(sizeof(*store));
449*5113495bSYour Name 	if (!store)
450*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
451*5113495bSYour Name 
452*5113495bSYour Name 	status = qdf_str_dup(&store->path, path);
453*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
454*5113495bSYour Name 		goto free_store;
455*5113495bSYour Name 
456*5113495bSYour Name 	status = qdf_atomic_init(&store->users);
457*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
458*5113495bSYour Name 		goto free_path;
459*5113495bSYour Name 	qdf_atomic_inc(&store->users);
460*5113495bSYour Name 
461*5113495bSYour Name 	qdf_spin_lock_bh(&__cfg_stores_lock);
462*5113495bSYour Name 	status = qdf_list_insert_back(&__cfg_stores_list, &store->node);
463*5113495bSYour Name 	qdf_spin_unlock_bh(&__cfg_stores_lock);
464*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
465*5113495bSYour Name 		goto free_path;
466*5113495bSYour Name 
467*5113495bSYour Name 	*out_store = store;
468*5113495bSYour Name 
469*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
470*5113495bSYour Name 
471*5113495bSYour Name free_path:
472*5113495bSYour Name 	qdf_mem_free(store->path);
473*5113495bSYour Name 
474*5113495bSYour Name free_store:
475*5113495bSYour Name 	qdf_mem_common_free(store);
476*5113495bSYour Name 
477*5113495bSYour Name 	return status;
478*5113495bSYour Name }
479*5113495bSYour Name 
cfg_store_free(struct cfg_value_store * store)480*5113495bSYour Name static void cfg_store_free(struct cfg_value_store *store)
481*5113495bSYour Name {
482*5113495bSYour Name 	QDF_STATUS status;
483*5113495bSYour Name 
484*5113495bSYour Name 	cfg_enter();
485*5113495bSYour Name 
486*5113495bSYour Name 	qdf_spin_lock_bh(&__cfg_stores_lock);
487*5113495bSYour Name 	status = qdf_list_remove_node(&__cfg_stores_list, &store->node);
488*5113495bSYour Name 	qdf_spin_unlock_bh(&__cfg_stores_lock);
489*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
490*5113495bSYour Name 		QDF_DEBUG_PANIC("Failed config store list removal; status:%d",
491*5113495bSYour Name 				status);
492*5113495bSYour Name 
493*5113495bSYour Name 	qdf_mem_free(store->path);
494*5113495bSYour Name 	qdf_mem_common_free(store);
495*5113495bSYour Name }
496*5113495bSYour Name 
497*5113495bSYour Name static QDF_STATUS
cfg_store_get(const char * path,struct cfg_value_store ** out_store)498*5113495bSYour Name cfg_store_get(const char *path, struct cfg_value_store **out_store)
499*5113495bSYour Name {
500*5113495bSYour Name 	QDF_STATUS status;
501*5113495bSYour Name 	qdf_list_node_t *node;
502*5113495bSYour Name 
503*5113495bSYour Name 	*out_store = NULL;
504*5113495bSYour Name 
505*5113495bSYour Name 	qdf_spin_lock_bh(&__cfg_stores_lock);
506*5113495bSYour Name 	status = qdf_list_peek_front(&__cfg_stores_list, &node);
507*5113495bSYour Name 	while (QDF_IS_STATUS_SUCCESS(status)) {
508*5113495bSYour Name 		struct cfg_value_store *store =
509*5113495bSYour Name 			qdf_container_of(node, struct cfg_value_store, node);
510*5113495bSYour Name 
511*5113495bSYour Name 		if (qdf_str_eq(path, store->path)) {
512*5113495bSYour Name 			qdf_atomic_inc(&store->users);
513*5113495bSYour Name 			*out_store = store;
514*5113495bSYour Name 			break;
515*5113495bSYour Name 		}
516*5113495bSYour Name 
517*5113495bSYour Name 		status = qdf_list_peek_next(&__cfg_stores_list, node, &node);
518*5113495bSYour Name 	}
519*5113495bSYour Name 	qdf_spin_unlock_bh(&__cfg_stores_lock);
520*5113495bSYour Name 
521*5113495bSYour Name 	return status;
522*5113495bSYour Name }
523*5113495bSYour Name 
cfg_store_put(struct cfg_value_store * store)524*5113495bSYour Name static void cfg_store_put(struct cfg_value_store *store)
525*5113495bSYour Name {
526*5113495bSYour Name 	if (qdf_atomic_dec_and_test(&store->users))
527*5113495bSYour Name 		cfg_store_free(store);
528*5113495bSYour Name }
529*5113495bSYour Name 
cfg_psoc_get_ctx(struct wlan_objmgr_psoc * psoc)530*5113495bSYour Name static struct cfg_psoc_ctx *cfg_psoc_get_ctx(struct wlan_objmgr_psoc *psoc)
531*5113495bSYour Name {
532*5113495bSYour Name 	struct cfg_psoc_ctx *psoc_ctx;
533*5113495bSYour Name 
534*5113495bSYour Name 	psoc_ctx = cfg_psoc_get_priv(psoc);
535*5113495bSYour Name 	QDF_BUG(psoc_ctx);
536*5113495bSYour Name 
537*5113495bSYour Name 	return psoc_ctx;
538*5113495bSYour Name }
539*5113495bSYour Name 
cfg_psoc_get_values(struct wlan_objmgr_psoc * psoc)540*5113495bSYour Name struct cfg_values *cfg_psoc_get_values(struct wlan_objmgr_psoc *psoc)
541*5113495bSYour Name {
542*5113495bSYour Name 	return &cfg_psoc_get_ctx(psoc)->store->values;
543*5113495bSYour Name }
544*5113495bSYour Name qdf_export_symbol(cfg_psoc_get_values);
545*5113495bSYour Name 
546*5113495bSYour Name static QDF_STATUS
cfg_ini_parse_to_store(const char * path,struct cfg_value_store * store)547*5113495bSYour Name cfg_ini_parse_to_store(const char *path, struct cfg_value_store *store)
548*5113495bSYour Name {
549*5113495bSYour Name 	QDF_STATUS status;
550*5113495bSYour Name 
551*5113495bSYour Name 	status = qdf_ini_parse(path, store, cfg_ini_item_handler,
552*5113495bSYour Name 			       cfg_ini_section_handler);
553*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
554*5113495bSYour Name 		cfg_err("Failed to parse *.ini file @ %s; status:%d",
555*5113495bSYour Name 			path, status);
556*5113495bSYour Name 
557*5113495bSYour Name 	return status;
558*5113495bSYour Name }
559*5113495bSYour Name 
560*5113495bSYour Name static QDF_STATUS
cfg_ini_section_parse_to_store(const char * path,const char * section_name,struct cfg_value_store * store)561*5113495bSYour Name cfg_ini_section_parse_to_store(const char *path, const char *section_name,
562*5113495bSYour Name 			       struct cfg_value_store *store)
563*5113495bSYour Name {
564*5113495bSYour Name 	QDF_STATUS status;
565*5113495bSYour Name 
566*5113495bSYour Name 	status = qdf_ini_section_parse(path, store, cfg_ini_item_handler,
567*5113495bSYour Name 				       section_name);
568*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
569*5113495bSYour Name 		cfg_err("Failed to parse *.ini file @ %s; status:%d",
570*5113495bSYour Name 			path, status);
571*5113495bSYour Name 
572*5113495bSYour Name 	return status;
573*5113495bSYour Name }
574*5113495bSYour Name 
cfg_parse_to_psoc_store(struct wlan_objmgr_psoc * psoc,const char * path)575*5113495bSYour Name QDF_STATUS cfg_parse_to_psoc_store(struct wlan_objmgr_psoc *psoc,
576*5113495bSYour Name 				   const char *path)
577*5113495bSYour Name {
578*5113495bSYour Name 	return cfg_ini_parse_to_store(path, cfg_psoc_get_ctx(psoc)->store);
579*5113495bSYour Name }
580*5113495bSYour Name 
581*5113495bSYour Name qdf_export_symbol(cfg_parse_to_psoc_store);
582*5113495bSYour Name 
cfg_section_parse_to_psoc_store(struct wlan_objmgr_psoc * psoc,const char * path,const char * section_name)583*5113495bSYour Name QDF_STATUS cfg_section_parse_to_psoc_store(struct wlan_objmgr_psoc *psoc,
584*5113495bSYour Name 					   const char *path,
585*5113495bSYour Name 					   const char *section_name)
586*5113495bSYour Name {
587*5113495bSYour Name 	return cfg_ini_section_parse_to_store(path, section_name,
588*5113495bSYour Name 			cfg_psoc_get_ctx(psoc)->store);
589*5113495bSYour Name }
590*5113495bSYour Name 
591*5113495bSYour Name qdf_export_symbol(cfg_section_parse_to_psoc_store);
592*5113495bSYour Name 
cfg_parse_to_global_store(const char * path)593*5113495bSYour Name QDF_STATUS cfg_parse_to_global_store(const char *path)
594*5113495bSYour Name {
595*5113495bSYour Name 	if (!__cfg_global_store) {
596*5113495bSYour Name 		cfg_err("Global INI store is not valid");
597*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
598*5113495bSYour Name 	}
599*5113495bSYour Name 
600*5113495bSYour Name 	return cfg_ini_parse_to_store(path, __cfg_global_store);
601*5113495bSYour Name }
602*5113495bSYour Name 
603*5113495bSYour Name qdf_export_symbol(cfg_parse_to_global_store);
604*5113495bSYour Name 
605*5113495bSYour Name static QDF_STATUS
cfg_store_print(struct wlan_objmgr_psoc * psoc)606*5113495bSYour Name cfg_store_print(struct wlan_objmgr_psoc *psoc)
607*5113495bSYour Name {
608*5113495bSYour Name 	struct cfg_value_store *store;
609*5113495bSYour Name 	struct cfg_psoc_ctx *psoc_ctx;
610*5113495bSYour Name 	void *offset;
611*5113495bSYour Name 	uint32_t i;
612*5113495bSYour Name 
613*5113495bSYour Name 	cfg_enter();
614*5113495bSYour Name 
615*5113495bSYour Name 	psoc_ctx = cfg_psoc_get_ctx(psoc);
616*5113495bSYour Name 	if (!psoc_ctx)
617*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
618*5113495bSYour Name 
619*5113495bSYour Name 	store = psoc_ctx->store;
620*5113495bSYour Name 	if (!store)
621*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
622*5113495bSYour Name 
623*5113495bSYour Name 	for (i = 0; i < QDF_ARRAY_SIZE(cfg_meta_lookup_table); i++) {
624*5113495bSYour Name 		const struct cfg_meta *meta = &cfg_meta_lookup_table[i];
625*5113495bSYour Name 
626*5113495bSYour Name 		offset = cfg_value_ptr(store, meta);
627*5113495bSYour Name 
628*5113495bSYour Name 		switch (meta->cfg_type) {
629*5113495bSYour Name 		case CFG_INT_ITEM:
630*5113495bSYour Name 			cfg_nofl_debug("%pK %s %d", offset, meta->name,
631*5113495bSYour Name 				       *((int32_t *)offset));
632*5113495bSYour Name 			break;
633*5113495bSYour Name 		case CFG_UINT_ITEM:
634*5113495bSYour Name 			cfg_nofl_debug("%pK %s %d", offset, meta->name,
635*5113495bSYour Name 				       *((uint32_t *)offset));
636*5113495bSYour Name 			break;
637*5113495bSYour Name 		case CFG_BOOL_ITEM:
638*5113495bSYour Name 			cfg_nofl_debug("%pK %s %d", offset, meta->name,
639*5113495bSYour Name 				       *((bool *)offset));
640*5113495bSYour Name 			break;
641*5113495bSYour Name 		case CFG_STRING_ITEM:
642*5113495bSYour Name 			cfg_nofl_debug("%pK %s %s", offset, meta->name,
643*5113495bSYour Name 				       (char *)offset);
644*5113495bSYour Name 			break;
645*5113495bSYour Name 		case CFG_MAC_ITEM:
646*5113495bSYour Name 			cfg_nofl_debug("%pK %s " QDF_MAC_ADDR_FMT,
647*5113495bSYour Name 				       offset, meta->name,
648*5113495bSYour Name 				       QDF_MAC_ADDR_REF((uint8_t *)offset));
649*5113495bSYour Name 			break;
650*5113495bSYour Name 		case CFG_IPV4_ITEM:
651*5113495bSYour Name 			cfg_nofl_debug("%pK %s %pI4",
652*5113495bSYour Name 				       offset, meta->name,
653*5113495bSYour Name 				       offset);
654*5113495bSYour Name 			break;
655*5113495bSYour Name 		case CFG_IPV6_ITEM:
656*5113495bSYour Name 			cfg_nofl_debug("%pK %s %pI6c",
657*5113495bSYour Name 				       offset, meta->name,
658*5113495bSYour Name 				       offset);
659*5113495bSYour Name 			break;
660*5113495bSYour Name 		default:
661*5113495bSYour Name 			continue;
662*5113495bSYour Name 		}
663*5113495bSYour Name 	}
664*5113495bSYour Name 
665*5113495bSYour Name 	cfg_exit();
666*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
667*5113495bSYour Name }
668*5113495bSYour Name 
669*5113495bSYour Name static QDF_STATUS
cfg_ini_config_print(struct wlan_objmgr_psoc * psoc,uint8_t * buf,ssize_t * plen,ssize_t buflen)670*5113495bSYour Name cfg_ini_config_print(struct wlan_objmgr_psoc *psoc, uint8_t *buf,
671*5113495bSYour Name 		     ssize_t *plen, ssize_t buflen)
672*5113495bSYour Name {
673*5113495bSYour Name 	struct cfg_value_store *store;
674*5113495bSYour Name 	struct cfg_psoc_ctx *psoc_ctx;
675*5113495bSYour Name 	ssize_t len;
676*5113495bSYour Name 	ssize_t total_len = buflen;
677*5113495bSYour Name 	uint32_t i;
678*5113495bSYour Name 	void *offset;
679*5113495bSYour Name 
680*5113495bSYour Name 	cfg_enter();
681*5113495bSYour Name 
682*5113495bSYour Name 	psoc_ctx = cfg_psoc_get_ctx(psoc);
683*5113495bSYour Name 	if (!psoc_ctx)
684*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
685*5113495bSYour Name 
686*5113495bSYour Name 	store = psoc_ctx->store;
687*5113495bSYour Name 	if (!store)
688*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
689*5113495bSYour Name 
690*5113495bSYour Name 	for (i = 0; i < QDF_ARRAY_SIZE(cfg_meta_lookup_table); i++) {
691*5113495bSYour Name 		const struct cfg_meta *meta = &cfg_meta_lookup_table[i];
692*5113495bSYour Name 
693*5113495bSYour Name 		offset = cfg_value_ptr(store, meta);
694*5113495bSYour Name 
695*5113495bSYour Name 		switch (meta->cfg_type) {
696*5113495bSYour Name 		case CFG_INT_ITEM:
697*5113495bSYour Name 			len = qdf_scnprintf(buf, buflen, "%s %d\n", meta->name,
698*5113495bSYour Name 					    *((int32_t *)offset));
699*5113495bSYour Name 			buf += len;
700*5113495bSYour Name 			buflen -= len;
701*5113495bSYour Name 			break;
702*5113495bSYour Name 		case CFG_UINT_ITEM:
703*5113495bSYour Name 			len = qdf_scnprintf(buf, buflen, "%s %d\n", meta->name,
704*5113495bSYour Name 					    *((uint32_t *)offset));
705*5113495bSYour Name 			buf += len;
706*5113495bSYour Name 			buflen -= len;
707*5113495bSYour Name 			break;
708*5113495bSYour Name 		case CFG_BOOL_ITEM:
709*5113495bSYour Name 			len = qdf_scnprintf(buf, buflen, "%s %d\n", meta->name,
710*5113495bSYour Name 					    *((bool *)offset));
711*5113495bSYour Name 			buf += len;
712*5113495bSYour Name 			buflen -= len;
713*5113495bSYour Name 			break;
714*5113495bSYour Name 		case CFG_STRING_ITEM:
715*5113495bSYour Name 			len = qdf_scnprintf(buf, buflen, "%s %s\n", meta->name,
716*5113495bSYour Name 					    (char *)offset);
717*5113495bSYour Name 			buf += len;
718*5113495bSYour Name 			buflen -= len;
719*5113495bSYour Name 			break;
720*5113495bSYour Name 		case CFG_MAC_ITEM:
721*5113495bSYour Name 			len = qdf_scnprintf(buf, buflen,
722*5113495bSYour Name 					    "%s " QDF_MAC_ADDR_FMT "\n",
723*5113495bSYour Name 					    meta->name,
724*5113495bSYour Name 					    QDF_MAC_ADDR_REF(
725*5113495bSYour Name 						(uint8_t *)offset));
726*5113495bSYour Name 			buf += len;
727*5113495bSYour Name 			buflen -= len;
728*5113495bSYour Name 			break;
729*5113495bSYour Name 		case CFG_IPV4_ITEM:
730*5113495bSYour Name 			len = qdf_scnprintf(buf, buflen, "%s %pI4\n",
731*5113495bSYour Name 					    meta->name,
732*5113495bSYour Name 					    offset);
733*5113495bSYour Name 			buf += len;
734*5113495bSYour Name 			buflen -= len;
735*5113495bSYour Name 			break;
736*5113495bSYour Name 		case CFG_IPV6_ITEM:
737*5113495bSYour Name 			len = qdf_scnprintf(buf, buflen, "%s %pI6c\n",
738*5113495bSYour Name 					    meta->name,
739*5113495bSYour Name 					    offset);
740*5113495bSYour Name 			buf += len;
741*5113495bSYour Name 			buflen -= len;
742*5113495bSYour Name 			break;
743*5113495bSYour Name 		default:
744*5113495bSYour Name 			continue;
745*5113495bSYour Name 		}
746*5113495bSYour Name 	}
747*5113495bSYour Name 
748*5113495bSYour Name 	*plen = total_len - buflen;
749*5113495bSYour Name 	cfg_exit();
750*5113495bSYour Name 
751*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
752*5113495bSYour Name }
753*5113495bSYour Name 
ucfg_cfg_store_print(struct wlan_objmgr_psoc * psoc)754*5113495bSYour Name QDF_STATUS ucfg_cfg_store_print(struct wlan_objmgr_psoc *psoc)
755*5113495bSYour Name {
756*5113495bSYour Name 	return cfg_store_print(psoc);
757*5113495bSYour Name }
758*5113495bSYour Name 
759*5113495bSYour Name qdf_export_symbol(ucfg_cfg_store_print);
760*5113495bSYour Name 
ucfg_cfg_ini_config_print(struct wlan_objmgr_psoc * psoc,uint8_t * buf,ssize_t * plen,ssize_t buflen)761*5113495bSYour Name QDF_STATUS ucfg_cfg_ini_config_print(struct wlan_objmgr_psoc *psoc,
762*5113495bSYour Name 				     uint8_t *buf, ssize_t *plen,
763*5113495bSYour Name 				     ssize_t buflen)
764*5113495bSYour Name {
765*5113495bSYour Name 	return cfg_ini_config_print(psoc, buf, plen, buflen);
766*5113495bSYour Name }
767*5113495bSYour Name 
768*5113495bSYour Name static QDF_STATUS
cfg_on_psoc_create(struct wlan_objmgr_psoc * psoc,void * context)769*5113495bSYour Name cfg_on_psoc_create(struct wlan_objmgr_psoc *psoc, void *context)
770*5113495bSYour Name {
771*5113495bSYour Name 	QDF_STATUS status;
772*5113495bSYour Name 	struct cfg_psoc_ctx *psoc_ctx;
773*5113495bSYour Name 
774*5113495bSYour Name 	cfg_enter();
775*5113495bSYour Name 
776*5113495bSYour Name 	QDF_BUG(__cfg_global_store);
777*5113495bSYour Name 	if (!__cfg_global_store)
778*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
779*5113495bSYour Name 
780*5113495bSYour Name 	psoc_ctx = qdf_mem_malloc(sizeof(*psoc_ctx));
781*5113495bSYour Name 	if (!psoc_ctx)
782*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
783*5113495bSYour Name 
784*5113495bSYour Name 	qdf_atomic_inc(&__cfg_global_store->users);
785*5113495bSYour Name 	psoc_ctx->store = __cfg_global_store;
786*5113495bSYour Name 
787*5113495bSYour Name 	status = cfg_psoc_set_priv(psoc, psoc_ctx);
788*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
789*5113495bSYour Name 		goto put_store;
790*5113495bSYour Name 
791*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
792*5113495bSYour Name 
793*5113495bSYour Name put_store:
794*5113495bSYour Name 	cfg_store_put(__cfg_global_store);
795*5113495bSYour Name 	qdf_mem_free(psoc_ctx);
796*5113495bSYour Name 
797*5113495bSYour Name 	return status;
798*5113495bSYour Name }
799*5113495bSYour Name 
800*5113495bSYour Name static QDF_STATUS
cfg_on_psoc_destroy(struct wlan_objmgr_psoc * psoc,void * context)801*5113495bSYour Name cfg_on_psoc_destroy(struct wlan_objmgr_psoc *psoc, void *context)
802*5113495bSYour Name {
803*5113495bSYour Name 	QDF_STATUS status;
804*5113495bSYour Name 	struct cfg_psoc_ctx *psoc_ctx;
805*5113495bSYour Name 
806*5113495bSYour Name 	cfg_enter();
807*5113495bSYour Name 
808*5113495bSYour Name 	psoc_ctx = cfg_psoc_get_ctx(psoc);
809*5113495bSYour Name 	status = cfg_psoc_unset_priv(psoc, psoc_ctx);
810*5113495bSYour Name 
811*5113495bSYour Name 	cfg_store_put(psoc_ctx->store);
812*5113495bSYour Name 	qdf_mem_free(psoc_ctx);
813*5113495bSYour Name 
814*5113495bSYour Name 	return status;
815*5113495bSYour Name }
816*5113495bSYour Name 
cfg_dispatcher_init(void)817*5113495bSYour Name QDF_STATUS cfg_dispatcher_init(void)
818*5113495bSYour Name {
819*5113495bSYour Name 	QDF_STATUS status;
820*5113495bSYour Name 
821*5113495bSYour Name 	cfg_enter();
822*5113495bSYour Name 
823*5113495bSYour Name 	QDF_BUG(!__cfg_is_init);
824*5113495bSYour Name 	if (__cfg_is_init)
825*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
826*5113495bSYour Name 
827*5113495bSYour Name 	qdf_list_create(&__cfg_stores_list, 0);
828*5113495bSYour Name 	qdf_spinlock_create(&__cfg_stores_lock);
829*5113495bSYour Name 
830*5113495bSYour Name 	status = cfg_psoc_register_create(cfg_on_psoc_create);
831*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
832*5113495bSYour Name 		return status;
833*5113495bSYour Name 
834*5113495bSYour Name 	status = cfg_psoc_register_destroy(cfg_on_psoc_destroy);
835*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
836*5113495bSYour Name 		goto unreg_create;
837*5113495bSYour Name 
838*5113495bSYour Name 	__cfg_is_init = true;
839*5113495bSYour Name 
840*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
841*5113495bSYour Name 
842*5113495bSYour Name unreg_create:
843*5113495bSYour Name 	cfg_assert_success(cfg_psoc_unregister_create(cfg_on_psoc_create));
844*5113495bSYour Name 
845*5113495bSYour Name 	return status;
846*5113495bSYour Name }
847*5113495bSYour Name 
cfg_dispatcher_deinit(void)848*5113495bSYour Name QDF_STATUS cfg_dispatcher_deinit(void)
849*5113495bSYour Name {
850*5113495bSYour Name 	cfg_enter();
851*5113495bSYour Name 
852*5113495bSYour Name 	QDF_BUG(__cfg_is_init);
853*5113495bSYour Name 	if (!__cfg_is_init)
854*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
855*5113495bSYour Name 
856*5113495bSYour Name 	__cfg_is_init = false;
857*5113495bSYour Name 
858*5113495bSYour Name 	cfg_assert_success(cfg_psoc_unregister_create(cfg_on_psoc_create));
859*5113495bSYour Name 	cfg_assert_success(cfg_psoc_unregister_destroy(cfg_on_psoc_destroy));
860*5113495bSYour Name 
861*5113495bSYour Name 	qdf_spin_lock_bh(&__cfg_stores_lock);
862*5113495bSYour Name 	QDF_BUG(qdf_list_empty(&__cfg_stores_list));
863*5113495bSYour Name 	qdf_spin_unlock_bh(&__cfg_stores_lock);
864*5113495bSYour Name 
865*5113495bSYour Name 	qdf_spinlock_destroy(&__cfg_stores_lock);
866*5113495bSYour Name 	qdf_list_destroy(&__cfg_stores_list);
867*5113495bSYour Name 
868*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
869*5113495bSYour Name }
870*5113495bSYour Name 
cfg_parse(const char * path)871*5113495bSYour Name QDF_STATUS cfg_parse(const char *path)
872*5113495bSYour Name {
873*5113495bSYour Name 	QDF_STATUS status;
874*5113495bSYour Name 	struct cfg_value_store *store;
875*5113495bSYour Name 
876*5113495bSYour Name 	cfg_enter();
877*5113495bSYour Name 
878*5113495bSYour Name 	if (!__cfg_global_store) {
879*5113495bSYour Name 		status = cfg_store_alloc(path, &store);
880*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
881*5113495bSYour Name 			return status;
882*5113495bSYour Name 
883*5113495bSYour Name 		cfg_store_set_defaults(store);
884*5113495bSYour Name 		status = cfg_ini_parse_to_store(path, store);
885*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
886*5113495bSYour Name 			goto free_store;
887*5113495bSYour Name 		__cfg_global_store = store;
888*5113495bSYour Name 
889*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
890*5113495bSYour Name 	}
891*5113495bSYour Name 	store = __cfg_global_store;
892*5113495bSYour Name 	status = cfg_ini_parse_to_store(path, store);
893*5113495bSYour Name 	return status;
894*5113495bSYour Name 
895*5113495bSYour Name free_store:
896*5113495bSYour Name 	cfg_store_free(store);
897*5113495bSYour Name 
898*5113495bSYour Name 	return status;
899*5113495bSYour Name }
900*5113495bSYour Name 
cfg_valid_ini_check(const char * path)901*5113495bSYour Name bool cfg_valid_ini_check(const char *path)
902*5113495bSYour Name {
903*5113495bSYour Name 	cfg_enter();
904*5113495bSYour Name 
905*5113495bSYour Name 	return qdf_valid_ini_check(path);
906*5113495bSYour Name }
907*5113495bSYour Name 
cfg_release(void)908*5113495bSYour Name void cfg_release(void)
909*5113495bSYour Name {
910*5113495bSYour Name 	cfg_enter();
911*5113495bSYour Name 
912*5113495bSYour Name 	QDF_BUG(__cfg_global_store);
913*5113495bSYour Name 	if (!__cfg_global_store)
914*5113495bSYour Name 		return;
915*5113495bSYour Name 
916*5113495bSYour Name 	cfg_store_put(__cfg_global_store);
917*5113495bSYour Name 	__cfg_global_store = NULL;
918*5113495bSYour Name }
919*5113495bSYour Name 
cfg_psoc_parse(struct wlan_objmgr_psoc * psoc,const char * path)920*5113495bSYour Name QDF_STATUS cfg_psoc_parse(struct wlan_objmgr_psoc *psoc, const char *path)
921*5113495bSYour Name {
922*5113495bSYour Name 	QDF_STATUS status;
923*5113495bSYour Name 	struct cfg_value_store *store;
924*5113495bSYour Name 	struct cfg_psoc_ctx *psoc_ctx;
925*5113495bSYour Name 
926*5113495bSYour Name 	cfg_enter();
927*5113495bSYour Name 
928*5113495bSYour Name 	QDF_BUG(__cfg_global_store);
929*5113495bSYour Name 	if (!__cfg_global_store)
930*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
931*5113495bSYour Name 
932*5113495bSYour Name 	QDF_BUG(__cfg_is_init);
933*5113495bSYour Name 	if (!__cfg_is_init)
934*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
935*5113495bSYour Name 
936*5113495bSYour Name 	QDF_BUG(psoc);
937*5113495bSYour Name 	if (!psoc)
938*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
939*5113495bSYour Name 
940*5113495bSYour Name 	QDF_BUG(path);
941*5113495bSYour Name 	if (!path)
942*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
943*5113495bSYour Name 
944*5113495bSYour Name 	psoc_ctx = cfg_psoc_get_ctx(psoc);
945*5113495bSYour Name 
946*5113495bSYour Name 	QDF_BUG(psoc_ctx->store == __cfg_global_store);
947*5113495bSYour Name 	if (psoc_ctx->store != __cfg_global_store)
948*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
949*5113495bSYour Name 
950*5113495bSYour Name 	/* check if @path has been parsed before */
951*5113495bSYour Name 	status = cfg_store_get(path, &store);
952*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
953*5113495bSYour Name 		status = cfg_store_alloc(path, &store);
954*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
955*5113495bSYour Name 			return status;
956*5113495bSYour Name 
957*5113495bSYour Name 		/* inherit global configuration */
958*5113495bSYour Name 		qdf_mem_copy(&store->values, &__cfg_global_store->values,
959*5113495bSYour Name 			     sizeof(store->values));
960*5113495bSYour Name 
961*5113495bSYour Name 		status = cfg_ini_parse_to_store(path, store);
962*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
963*5113495bSYour Name 			goto put_store;
964*5113495bSYour Name 	}
965*5113495bSYour Name 
966*5113495bSYour Name 	psoc_ctx->store = store;
967*5113495bSYour Name 	cfg_store_put(__cfg_global_store);
968*5113495bSYour Name 
969*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
970*5113495bSYour Name 
971*5113495bSYour Name put_store:
972*5113495bSYour Name 	cfg_store_put(store);
973*5113495bSYour Name 
974*5113495bSYour Name 	return status;
975*5113495bSYour Name }
976*5113495bSYour Name 
977*5113495bSYour Name qdf_export_symbol(cfg_psoc_parse);
978