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