xref: /wlan-dirver/qca-wifi-host-cmn/cfg/inc/cfg_ucfg_api.h (revision 1cd103900e099fe63bbc374fe97251bd80dd0b06)
1 /*
2  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: UCFG APIs for the configuration component.
21  *
22  * Logically, configuration exists at the psoc level. This means, each psoc can
23  * have its own custom configuration, and calls to lookup configuration take a
24  * psoc parameter for reference. E.g.
25  *
26  *	int32_t value = cfg_get(psoc, WLAN_SOME_INTEGER_CONFIG_ID);
27  *
28  * Configuration is cascading, and lookups happen in this order:
29  *
30  *	1) use psoc value, if configured
31  *	2) use global value, if configured
32  *	3) fallback to the default value for the configuration item
33  *
34  * This means a psoc configuration is a specialization of the global
35  * configuration, and does not need to explicitly set the same values if they
36  * would match the global config.
37  *
38  * In order to load and parse the global config, call cfg_parse(). In order to
39  * load and parse psoc configs, call cfg_psoc_parse(). cfg_parse() MUST be
40  * called before cfg_psoc_parse(), as global configuration will be consulted
41  * during the psoc parsing process.
42  *
43  * There are two basic lifecycles supported:
44  *
45  * 1) The type and number of psocs is *not* known at load time
46  *
47  *	// driver is loading
48  *	cfg_parse("/path/to/config");
49  *
50  *	...
51  *
52  *	// a psoc has just been created
53  *	cfg_psoc_parse(psoc, "/path/to/psoc/config");
54  *
55  *	...
56  *
57  *	// driver is unloading
58  *	cfg_release();
59  *
60  * 2) The type and number of psocs *is* known at load time
61  *
62  *	// driver is loading
63  *	cfg_parse("/path/to/config");
64  *
65  *	...
66  *
67  *	// for each psoc
68  *		cfg_psoc_parse(psoc, "/path/to/psoc/config");
69  *
70  *	// no further psocs will be created after this point
71  *	cfg_release();
72  *
73  *	...
74  *
75  *	// driver is unloaded later
76  *
77  * Each configuration store is reference counted to reduce memory footprint, and
78  * the configuration component itself will hold one ref count on the global
79  * config store. All psocs for which psoc-specific configurations have *not*
80  * been provided will reference the global config store. Psocs for which psoc-
81  * specific configurations *have* been provded will check for existings stores
82  * with a matching path to use, before parsing the specified configuration file.
83  *
84  * If, at some point in time, it is known that no further psocs will ever be
85  * created, a call to cfg_release() will release the global ref count held by
86  * the configuration component. For systems which specify psoc-specific configs
87  * for all psocs, this will release the unnecessary memory used by the global
88  * config store. Otherwise, calling cfg_release() at unload time will ensure
89  * the global config store is properly freed.
90  */
91 
92 #ifndef __CFG_UCFG_H
93 #define __CFG_UCFG_H
94 
95 #include "cfg_all.h"
96 #include "cfg_define.h"
97 #include "i_cfg.h"
98 #include "qdf_status.h"
99 #include "qdf_str.h"
100 #include "qdf_types.h"
101 #include "wlan_objmgr_psoc_obj.h"
102 
103 /**
104  * cfg_parse() - parse an ini file, and populate the global config storei
105  * @path: The full file path of the ini file to parse
106  *
107  * Note: A matching cfg_release() call is required to release allocated
108  * resources.
109  *
110  * The *.ini file format is a simple format consiting of a list of key/value
111  * pairs, separated by an '=' character. e.g.
112  *
113  *	gConfigItem1=some string value
114  *	gConfigItem2=0xabc
115  *
116  * Comments are also supported, initiated with the '#' character:
117  *
118  *	# This is a comment. It will be ignored by the *.ini parser
119  *	gConfigItem3=aa:bb:cc:dd:ee:ff # this is also a comment
120  *
121  * Several datatypes are natively supported:
122  *
123  *	gInt=-123 # bin (0b), octal (0o), hex (0x), and decimal supported
124  *	gUint=123 # a non-negative integer value
125  *	gBool=y # (1, Y, y) -> true; (0, N, n) -> false
126  *	gString=any string # strings are useful for representing complex types
127  *	gMacAddr=aa:bb:cc:dd:ee:ff # colons are optional, upper and lower case
128  *	gIpv4Addr=127.0.0.1 # uses typical dot-decimal notation
129  *	gIpv6Addr=::1 # typical notation, supporting zero-compression
130  *
131  * Return: QDF_STATUS
132  */
133 QDF_STATUS cfg_parse(const char *path);
134 
135 /**
136  * cfg_release() - release the global configuration store
137  *
138  * This API releases the configuration component's reference to the global
139  * config store.
140  *
141  * See also: this file's DOC section.
142  *
143  * Return: None
144  */
145 void cfg_release(void);
146 
147 /**
148  * cfg_psoc_parse() - specialize the config store for @psoc by parsing @path
149  * @psoc: The psoc whose config store should be specialized
150  * @path: The full file path of the ini file to parse
151  *
152  * See also: cfg_parse(), and this file's DOC section.
153  *
154  * Return: QDF_STATUS
155  */
156 QDF_STATUS cfg_psoc_parse(struct wlan_objmgr_psoc *psoc, const char *path);
157 
158 /**
159  * cfg_parse_to_psoc_store() - Parse file @path and update psoc ini store
160  * @psoc: The psoc whose config store should be updated
161  * @path: The full file path of the ini file to parse
162  *
163  * Return: QDF_STATUS
164  */
165 QDF_STATUS cfg_parse_to_psoc_store(struct wlan_objmgr_psoc *psoc,
166 				   const char *path);
167 
168 /**
169  * cfg_parse_to_global_store() Parse file @path and update global ini store
170  * @path: The full file path of the ini file to parse
171  *
172  * Return: QDF_STATUS
173  */
174 QDF_STATUS cfg_parse_to_global_store(const char *path);
175 
176 /**
177  * cfg_ucfg_store_print() prints the cfg ini/non ini logs
178  * @psoc: psoc
179  *
180  * Return: QDF_STATUS
181  */
182 QDF_STATUS ucfg_cfg_store_print(struct wlan_objmgr_psoc *psoc);
183 
184 /**
185  * ucfg_cfg_ini_config_print() prints the cfg ini/non ini to buffer
186  * @psoc: psoc
187  * @buf: cache to save ini config
188  * @plen: the pointer to length
189  * @buflen: total buf length
190  *
191  * Return: QDF_STATUS
192  */
193 QDF_STATUS ucfg_cfg_ini_config_print(struct wlan_objmgr_psoc *psoc,
194 				     uint8_t *buf, ssize_t *plen,
195 				     ssize_t buflen);
196 
197 /**
198  * cfg_get() - lookup the configured value for @id from @psoc
199  * @psoc: The psoc from which to lookup the configured value
200  * @id: The id of the configured value to lookup
201  *
202  * E.g.
203  *
204  *	int32_t value = cfg_get(psoc, WLAN_SOME_INTEGER_CONFIG_ID);
205  *
206  * Return: The configured value
207  */
208 #define cfg_get(psoc, id) __cfg_get(psoc, __##id)
209 
210 /* Configuration Access APIs */
211 #define __do_call(op, args...) op(args)
212 #define do_call(op, args) __do_call(op, rm_parens args)
213 
214 #define cfg_id(id) #id
215 
216 #define __cfg_mtype(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
217 	mtype
218 #define cfg_mtype(id) do_call(__cfg_mtype, id)
219 
220 #define __cfg_type(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
221 	ctype
222 #define cfg_type(id) do_call(__cfg_type, id)
223 
224 #define __cfg_name(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
225 	name
226 #define cfg_name(id) do_call(__cfg_name, id)
227 
228 #define __cfg_min(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
229 	min
230 #define cfg_min(id) do_call(__cfg_min, id)
231 
232 #define __cfg_max(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
233 	max
234 #define cfg_max(id) do_call(__cfg_max, id)
235 
236 #define __cfg_fb(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
237 	fallback
238 #define cfg_fallback(id) do_call(__cfg_fb, id)
239 
240 #define __cfg_desc(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
241 	desc
242 #define cfg_description(id) do_call(__cfg_desc, id)
243 
244 #define __cfg_def(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
245 	def
246 #define cfg_default(id) do_call(__cfg_def, id)
247 
248 #define __cfg_str(id...) #id
249 #define cfg_str(id) #id __cfg_str(id)
250 
251 /* validate APIs */
252 static inline bool
253 cfg_string_in_range(const char *value, qdf_size_t min_len, qdf_size_t max_len)
254 {
255 	qdf_size_t len = qdf_str_len(value);
256 
257 	return len >= min_len && len <= max_len;
258 }
259 
260 #define __cfg_INT_in_range(value, min, max) (value >= min && value <= max)
261 #define __cfg_UINT_in_range(value, min, max) (value >= min && value <= max)
262 #define __cfg_STRING_in_range(value, min_len, max_len) \
263 	cfg_string_in_range(value, min_len, max_len)
264 
265 #define __cfg_in_range(id, value, mtype) \
266 	__cfg_ ## mtype ## _in_range(value, cfg_min(id), cfg_max(id))
267 
268 /* this may look redundant, but forces @mtype to be expanded */
269 #define __cfg_in_range_type(id, value, mtype) \
270 	__cfg_in_range(id, value, mtype)
271 
272 #define cfg_in_range(id, value) __cfg_in_range_type(id, value, cfg_mtype(id))
273 
274 /* Value-or-Default APIs */
275 #define __cfg_value_or_default(id, value, def) \
276 	(cfg_in_range(id, value) ? value : def)
277 
278 #define cfg_value_or_default(id, value) \
279 	__cfg_value_or_default(id, value, cfg_default(id))
280 
281 /* Value-or-Clamped APIs */
282 #define __cfg_clamp(val, min, max) (val < min ? min : (val > max ? max : val))
283 #define cfg_clamp(id, value) __cfg_clamp(value, cfg_min(id), cfg_max(id))
284 
285 #endif /* __CFG_UCFG_H */
286 
287