1 /* 2 * Copyright (c) 2018 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_get() - lookup the configured value for @id from @psoc 178 * @psoc: The psoc from which to lookup the configured value 179 * @id: The id of the configured value to lookup 180 * 181 * E.g. 182 * 183 * int32_t value = cfg_get(psoc, WLAN_SOME_INTEGER_CONFIG_ID); 184 * 185 * Return: The configured value 186 */ 187 #define cfg_get(psoc, id) __cfg_get(psoc, __##id) 188 189 /* Configuration Access APIs */ 190 #define __do_call(op, args...) op(args) 191 #define do_call(op, args) __do_call(op, rm_parens args) 192 193 #define cfg_id(id) #id 194 195 #define __cfg_mtype(ini, mtype, ctype, name, min, max, fallback, desc, def...) \ 196 mtype 197 #define cfg_mtype(id) do_call(__cfg_mtype, id) 198 199 #define __cfg_type(ini, mtype, ctype, name, min, max, fallback, desc, def...) \ 200 ctype 201 #define cfg_type(id) do_call(__cfg_type, id) 202 203 #define __cfg_name(ini, mtype, ctype, name, min, max, fallback, desc, def...) \ 204 name 205 #define cfg_name(id) do_call(__cfg_name, id) 206 207 #define __cfg_min(ini, mtype, ctype, name, min, max, fallback, desc, def...) \ 208 min 209 #define cfg_min(id) do_call(__cfg_min, id) 210 211 #define __cfg_max(ini, mtype, ctype, name, min, max, fallback, desc, def...) \ 212 max 213 #define cfg_max(id) do_call(__cfg_max, id) 214 215 #define __cfg_fb(ini, mtype, ctype, name, min, max, fallback, desc, def...) \ 216 fallback 217 #define cfg_fallback(id) do_call(__cfg_fb, id) 218 219 #define __cfg_desc(ini, mtype, ctype, name, min, max, fallback, desc, def...) \ 220 desc 221 #define cfg_description(id) do_call(__cfg_desc, id) 222 223 #define __cfg_def(ini, mtype, ctype, name, min, max, fallback, desc, def...) \ 224 def 225 #define cfg_default(id) do_call(__cfg_def, id) 226 227 #define __cfg_str(id...) #id 228 #define cfg_str(id) #id __cfg_str(id) 229 230 /* validate APIs */ 231 static inline bool 232 cfg_string_in_range(const char *value, qdf_size_t min_len, qdf_size_t max_len) 233 { 234 qdf_size_t len = qdf_str_len(value); 235 236 return len >= min_len && len <= max_len; 237 } 238 239 #define __cfg_INT_in_range(value, min, max) (value >= min && value <= max) 240 #define __cfg_UINT_in_range(value, min, max) (value >= min && value <= max) 241 #define __cfg_STRING_in_range(value, min_len, max_len) \ 242 cfg_string_in_range(value, min_len, max_len) 243 #define __cfg_BOOL_in_range(value, min, max) \ 244 ((value == min) || (value == max)) 245 246 #define __cfg_in_range(id, value, mtype) \ 247 __cfg_ ## mtype ## _in_range(value, cfg_min(id), cfg_max(id)) 248 249 /* this may look redundant, but forces @mtype to be expanded */ 250 #define __cfg_in_range_type(id, value, mtype) \ 251 __cfg_in_range(id, value, mtype) 252 253 #define cfg_in_range(id, value) __cfg_in_range_type(id, value, cfg_mtype(id)) 254 255 /* Value-or-Default APIs */ 256 #define __cfg_value_or_default(id, value, def) \ 257 (cfg_in_range(id, value) ? value : def) 258 259 #define cfg_value_or_default(id, value) \ 260 __cfg_value_or_default(id, value, cfg_default(id)) 261 262 /* Value-or-Clamped APIs */ 263 #define __cfg_clamp(val, min, max) (val < min ? min : (val > max ? max : val)) 264 #define cfg_clamp(id, value) __cfg_clamp(value, cfg_min(id), cfg_max(id)) 265 266 #endif /* __CFG_UCFG_H */ 267 268