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