Commit | Line | Data |
---|---|---|
1b4a7c03 LJ |
1 | /* |
2 | * bcmiov.h | |
3 | * Common iovar handling/parsing support - batching, parsing, sub-cmd dispatch etc. | |
4 | * To be used in firmware and host apps or dhd - reducing code size, | |
5 | * duplication, and maintenance overhead. | |
6 | * | |
7 | * Copyright (C) 2020, Broadcom. | |
8 | * | |
9 | * Unless you and Broadcom execute a separate written software license | |
10 | * agreement governing use of this software, this software is licensed to you | |
11 | * under the terms of the GNU General Public License version 2 (the "GPL"), | |
12 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the | |
13 | * following added to such license: | |
14 | * | |
15 | * As a special exception, the copyright holders of this software give you | |
16 | * permission to link this software with independent modules, and to copy and | |
17 | * distribute the resulting executable under terms of your choice, provided that | |
18 | * you also meet, for each linked independent module, the terms and conditions of | |
19 | * the license of that module. An independent module is a module which is not | |
20 | * derived from this software. The special exception does not apply to any | |
21 | * modifications of the software. | |
22 | * | |
23 | * | |
24 | * <<Broadcom-WL-IPTag/Dual:>> | |
25 | */ | |
26 | ||
27 | #ifndef _bcmiov_h_ | |
28 | #define _bcmiov_h_ | |
29 | ||
30 | #include <typedefs.h> | |
31 | #include <bcmutils.h> | |
32 | #include <wlioctl.h> | |
33 | #ifdef BCMDRIVER | |
34 | #include <osl.h> | |
35 | #else | |
36 | #include <stddef.h> /* For size_t */ | |
37 | #endif /* BCMDRIVER */ | |
38 | ||
39 | /* Forward declarations */ | |
40 | typedef uint16 bcm_iov_cmd_id_t; | |
41 | typedef uint16 bcm_iov_cmd_flags_t; | |
42 | typedef uint16 bcm_iov_cmd_mflags_t; | |
43 | typedef struct bcm_iov_cmd_info bcm_iov_cmd_info_t; | |
44 | typedef struct bcm_iov_cmd_digest bcm_iov_cmd_digest_t; | |
45 | typedef struct bcm_iov_cmd_tlv_info bcm_iov_cmd_tlv_info_t; | |
46 | typedef struct bcm_iov_buf bcm_iov_buf_t; | |
47 | typedef struct bcm_iov_batch_buf bcm_iov_batch_buf_t; | |
48 | typedef struct bcm_iov_parse_context bcm_iov_parse_context_t; | |
49 | typedef struct bcm_iov_sub_cmd_context bcm_iov_sub_cmd_context_t; | |
50 | ||
51 | typedef void* (*bcm_iov_malloc_t)(void* alloc_ctx, size_t len); | |
52 | typedef void (*bcm_iov_free_t)(void* alloc_ctx, void *buf, size_t len); | |
53 | ||
54 | typedef uint8 bcm_iov_tlp_data_type_t; | |
55 | typedef struct bcm_iov_tlp bcm_iov_tlp_t; | |
56 | typedef struct bcm_iov_tlp_node bcm_iov_tlp_node_t; | |
57 | typedef struct bcm_iov_batch_subcmd bcm_iov_batch_subcmd_t; | |
58 | ||
59 | /* | |
60 | * iov validation handler - All the common checks that are required | |
61 | * for processing of iovars for any given command. | |
62 | */ | |
63 | typedef int (*bcm_iov_cmd_validate_t)(const bcm_iov_cmd_digest_t *dig, | |
64 | uint32 actionid, const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen); | |
65 | ||
66 | /* iov get handler - process subcommand specific input and return output. | |
67 | * input and output may overlap, so the callee needs to check if | |
68 | * that is supported. For xtlv data a tlv digest is provided to make | |
69 | * parsing simpler. Output tlvs may be packed into output buffer using | |
70 | * bcm xtlv support. olen is input/output parameter. On input contains | |
71 | * max available obuf length and callee must fill the correct length | |
72 | * to represent the length of output returned. | |
73 | */ | |
74 | typedef int (*bcm_iov_cmd_get_t)(const bcm_iov_cmd_digest_t *dig, | |
75 | const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen); | |
76 | ||
77 | /* iov set handler - process subcommand specific input and return output | |
78 | * input and output may overlap, so the callee needs to check if | |
79 | * that is supported. olen is input/output parameter. On input contains | |
80 | * max available obuf length and callee must fill the correct length | |
81 | * to represent the length of output returned. | |
82 | */ | |
83 | typedef int (*bcm_iov_cmd_set_t)(const bcm_iov_cmd_digest_t *dig, | |
84 | const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen); | |
85 | ||
86 | /* iov (sub-cmd) batch - a vector of commands. count can be zero | |
87 | * to support a version query. Each command is a tlv - whose data | |
88 | * portion may have an optional return status, followed by a fixed | |
89 | * length data header, optionally followed by tlvs. | |
90 | * cmd = type|length|<status|options>[header][tlvs] | |
91 | */ | |
92 | ||
93 | /* | |
94 | * Batch sub-commands have status length included in the | |
95 | * response length packed in TLV. | |
96 | */ | |
97 | #define BCM_IOV_STATUS_LEN sizeof(uint32) | |
98 | ||
99 | /* batch version is indicated by setting high bit. */ | |
100 | #define BCM_IOV_BATCH_MASK 0x8000 | |
101 | ||
102 | /* | |
103 | * Batched commands will have the following memory layout | |
104 | * +--------+---------+--------+-------+ | |
105 | * |version |count | is_set |sub-cmd| | |
106 | * +--------+---------+--------+-------+ | |
107 | * version >= 0x8000 | |
108 | * count = number of sub-commands encoded in the iov buf | |
109 | * sub-cmd one or more sub-commands for processing | |
110 | * Where sub-cmd is padded byte buffer with memory layout as follows | |
111 | * +--------+---------+-----------------------+-------------+------ | |
112 | * |cmd-id |length |IN(options) OUT(status)|command data |...... | |
113 | * +--------+---------+-----------------------+-------------+------ | |
114 | * cmd-id =sub-command ID | |
115 | * length = length of this sub-command | |
116 | * IN(options) = On input processing options/flags for this command | |
117 | * OUT(status) on output processing status for this command | |
118 | * command data = encapsulated IOVAR data as a single structure or packed TLVs for each | |
119 | * individual sub-command. | |
120 | */ | |
121 | struct bcm_iov_batch_subcmd { | |
122 | uint16 id; | |
123 | uint16 len; | |
124 | union { | |
125 | uint32 options; | |
126 | uint32 status; | |
127 | } u; | |
128 | uint8 data[1]; | |
129 | }; | |
130 | ||
131 | struct bcm_iov_batch_buf { | |
132 | uint16 version; | |
133 | uint8 count; | |
134 | uint8 is_set; /* to differentiate set or get */ | |
135 | struct bcm_iov_batch_subcmd cmds[0]; | |
136 | }; | |
137 | ||
138 | /* non-batched command version = major|minor w/ major <= 127 */ | |
139 | struct bcm_iov_buf { | |
140 | uint16 version; | |
141 | uint16 len; | |
142 | bcm_iov_cmd_id_t id; | |
143 | uint16 data[1]; /* 32 bit alignment may be repurposed by the command */ | |
144 | /* command specific data follows */ | |
145 | }; | |
146 | ||
147 | /* iov options flags */ | |
148 | enum { | |
149 | BCM_IOV_CMD_OPT_ALIGN_NONE = 0x0000, | |
150 | BCM_IOV_CMD_OPT_ALIGN32 = 0x0001, | |
151 | BCM_IOV_CMD_OPT_TERMINATE_SUB_CMDS = 0x0002 | |
152 | }; | |
153 | ||
154 | /* iov command flags */ | |
155 | enum { | |
156 | BCM_IOV_CMD_FLAG_NONE = 0, | |
157 | BCM_IOV_CMD_FLAG_STATUS_PRESENT = (1 << 0), /* status present at data start - output only */ | |
158 | BCM_IOV_CMD_FLAG_XTLV_DATA = (1 << 1), /* data is a set of xtlvs */ | |
159 | BCM_IOV_CMD_FLAG_HDR_IN_LEN = (1 << 2), /* length starts at version - non-bacthed only */ | |
160 | BCM_IOV_CMD_FLAG_NOPAD = (1 << 3) /* No padding needed after iov_buf */ | |
161 | }; | |
162 | ||
163 | /* information about the command, xtlv options and xtlvs_off are meaningful | |
164 | * only if XTLV_DATA cmd flag is selected | |
165 | */ | |
166 | struct bcm_iov_cmd_info { | |
167 | bcm_iov_cmd_id_t cmd; /* the (sub)command - module specific */ | |
168 | bcm_iov_cmd_flags_t flags; /* checked by bcmiov but set by module */ | |
169 | bcm_iov_cmd_mflags_t mflags; /* owned and checked by module */ | |
170 | bcm_xtlv_opts_t xtlv_opts; | |
171 | bcm_iov_cmd_validate_t validate_h; /* command validation handler */ | |
172 | bcm_iov_cmd_get_t get_h; | |
173 | bcm_iov_cmd_set_t set_h; | |
174 | uint16 xtlvs_off; /* offset to beginning of xtlvs in cmd data */ | |
175 | uint16 min_len_set; | |
176 | uint16 max_len_set; | |
177 | uint16 min_len_get; | |
178 | uint16 max_len_get; | |
179 | }; | |
180 | ||
181 | /* tlv digest to support parsing of xtlvs for commands w/ tlv data; the tlv | |
182 | * digest is available in the handler for the command. The count and order in | |
183 | * which tlvs appear in the digest are exactly the same as the order of tlvs | |
184 | * passed in the registration for the command. Unknown tlvs are ignored. | |
185 | * If registered tlvs are missing datap will be NULL. common iov rocessing | |
186 | * acquires an input digest to process input buffer. The handler is responsible | |
187 | * for constructing an output digest and use packing functions to generate | |
188 | * the output buffer. The handler may use the input digest as output digest once | |
189 | * the tlv data is extracted and used. Multiple tlv support involves allocation of | |
190 | * tlp nodes, except the first, as required, | |
191 | */ | |
192 | ||
193 | /* tlp data type indicates if the data is not used/invalid, input or output */ | |
194 | enum { | |
195 | BCM_IOV_TLP_NODE_INVALID = 0, | |
196 | BCM_IOV_TLP_NODE_IN = 1, | |
197 | BCM_IOV_TLP_NODE_OUT = 2 | |
198 | }; | |
199 | ||
200 | struct bcm_iov_tlp { | |
201 | uint16 type; | |
202 | uint16 len; | |
203 | uint16 nodeix; /* node index */ | |
204 | }; | |
205 | ||
206 | /* tlp data for a given tlv - multiple tlvs of same type chained */ | |
207 | struct bcm_iov_tlp_node { | |
208 | uint8 *next; /* multiple tlv support */ | |
209 | bcm_iov_tlp_data_type_t type; | |
210 | uint8 *data; /* pointer to data in buffer or state */ | |
211 | }; | |
212 | ||
213 | struct bcm_iov_cmd_digest { | |
214 | uint32 version; /* Version */ | |
215 | void *cmd_ctx; | |
216 | struct wlc_bsscfg *bsscfg; | |
217 | const bcm_iov_cmd_info_t *cmd_info; | |
218 | uint16 max_tlps; /* number of tlps allocated */ | |
219 | uint16 max_nodes; /* number of nods allocated */ | |
220 | uint16 num_tlps; /* number of tlps valid */ | |
221 | uint16 num_nodes; /* number of nods valid */ | |
222 | uint16 tlps_off; /* offset to tlps */ | |
223 | uint16 nodes_off; /* offset to nodes */ | |
224 | /* | |
225 | * bcm_iov_tlp_t tlps[max_tlps]; | |
226 | * bcm_iov_tlp_node_t nodes[max_nodes] | |
227 | */ | |
228 | }; | |
229 | ||
230 | /* get length callback - default length is min_len taken from digest */ | |
231 | typedef size_t (*bcm_iov_xtlv_get_len_t)(const bcm_iov_cmd_digest_t *dig, | |
232 | const bcm_iov_cmd_tlv_info_t *tlv_info); | |
233 | ||
234 | /* pack to buffer data callback. under some conditions it might | |
235 | * not be a straight copy and can refer to context(ual) information and | |
236 | * endian conversions... | |
237 | */ | |
238 | typedef void (*bcm_iov_xtlv_pack_t)(const bcm_iov_cmd_digest_t *dig, | |
239 | const bcm_iov_cmd_tlv_info_t *tlv_info, | |
240 | uint8 *out_buf, const uint8 *in_data, size_t len); | |
241 | ||
242 | struct bcm_iov_cmd_tlv_info { | |
243 | uint16 id; | |
244 | uint16 min_len; /* inclusive */ | |
245 | uint16 max_len; /* inclusive */ | |
246 | bcm_iov_xtlv_get_len_t get_len; | |
247 | bcm_iov_xtlv_pack_t pack; | |
248 | }; | |
249 | ||
250 | /* | |
251 | * module private parse context. Default version type len is uint16 | |
252 | */ | |
253 | ||
254 | /* Command parsing options with respect to validation */ | |
255 | /* Possible values for parse context options */ | |
256 | /* Bit 0 - Validate only */ | |
257 | #define BCM_IOV_PARSE_OPT_BATCH_VALIDATE 0x00000001 | |
258 | ||
259 | typedef uint32 bcm_iov_parse_opts_t; | |
260 | ||
261 | /* get digest callback */ | |
262 | typedef int (*bcm_iov_get_digest_t)(void *cmd_ctx, bcm_iov_cmd_digest_t **dig); | |
263 | ||
264 | typedef struct bcm_iov_parse_config { | |
265 | bcm_iov_parse_opts_t options; /* to handle different ver lengths */ | |
266 | bcm_iov_malloc_t alloc_fn; | |
267 | bcm_iov_free_t free_fn; | |
268 | bcm_iov_get_digest_t dig_fn; | |
269 | int max_regs; | |
270 | void *alloc_ctx; | |
271 | } bcm_iov_parse_config_t; | |
272 | ||
273 | /* API */ | |
274 | ||
275 | /* All calls return an integer status code BCME_* unless otherwise indicated */ | |
276 | ||
277 | /* return length of allocation for 'num_cmds' commands. data_len | |
278 | * includes length of data for all the commands excluding the headers | |
279 | */ | |
280 | size_t bcm_iov_get_alloc_len(int num_cmds, size_t data_len); | |
281 | ||
282 | /* create parsing context using allocator provided; max_regs provides | |
283 | * the number of allowed registrations for commands using the context | |
284 | * sub-components of a module may register their own commands indepdently | |
285 | * using the parsing context. If digest callback is NULL or returns NULL, | |
286 | * the (input) digest is allocated using the provided allocators and released on | |
287 | * completion of processing. | |
288 | */ | |
289 | int bcm_iov_create_parse_context(const bcm_iov_parse_config_t *parse_cfg, | |
290 | bcm_iov_parse_context_t **parse_ctx); | |
291 | ||
292 | /* free the parsing context; ctx is set to NULL on exit */ | |
293 | int bcm_iov_free_parse_context(bcm_iov_parse_context_t **ctx, bcm_iov_free_t free_fn); | |
294 | ||
295 | /* Return the command context for the module */ | |
296 | void *bcm_iov_get_cmd_ctx_info(bcm_iov_parse_context_t *parse_ctx); | |
297 | ||
298 | /* register a command info vector along with supported tlvs. Each command | |
299 | * may support a subset of tlvs | |
300 | */ | |
301 | int bcm_iov_register_commands(bcm_iov_parse_context_t *parse_ctx, void *cmd_ctx, | |
302 | const bcm_iov_cmd_info_t *info, size_t num_cmds, | |
303 | const bcm_iov_cmd_tlv_info_t *tlv_info, size_t num_tlvs); | |
304 | ||
305 | /* pack the xtlvs provided in the digest. may returns BCME_BUFTOOSHORT, but the | |
306 | * out_len is set to required length in that case. | |
307 | */ | |
308 | int bcm_iov_pack_xtlvs(const bcm_iov_cmd_digest_t *dig, bcm_xtlv_opts_t xtlv_opts, | |
309 | uint8 *out_buf, size_t out_size, size_t *out_len); | |
310 | ||
311 | #ifdef BCMDRIVER | |
312 | /* wlc modules register their iovar(s) using the parsing context w/ wlc layer | |
313 | * during attach. | |
314 | */ | |
315 | struct wlc_if; | |
316 | struct wlc_info; | |
317 | extern struct wlc_bsscfg *bcm_iov_bsscfg_find_from_wlcif(struct wlc_info *wlc, | |
318 | struct wlc_if *wlcif); | |
319 | int bcm_iov_doiovar(void *parse_ctx, uint32 id, void *params, uint params_len, | |
320 | void *arg, uint arg_len, uint vsize, struct wlc_if *intf); | |
321 | #endif /* BCMDRIVER */ | |
322 | ||
323 | /* parsing context helpers */ | |
324 | ||
325 | /* get the maximum number of tlvs - can be used to allocate digest for all | |
326 | * commands. the digest can be shared. Negative values are BCM_*, >=0, the | |
327 | * number of tlvs | |
328 | */ | |
329 | int bcm_iov_parse_get_max_tlvs(const bcm_iov_parse_context_t *ctx); | |
330 | ||
331 | /* common packing support */ | |
332 | ||
333 | /* pack a buffer of uint8s - memcpy wrapper */ | |
334 | int bcm_iov_pack_buf(const bcm_iov_cmd_digest_t *dig, uint8 *buf, | |
335 | const uint8 *data, size_t len); | |
336 | ||
337 | #define bcm_iov_packv_u8 bcm_iov_pack_buf | |
338 | ||
339 | /* | |
340 | * pack a buffer with uint16s - serialized in LE order, data points to uint16 | |
341 | * length is not checked. | |
342 | */ | |
343 | int bcm_iov_packv_u16(const bcm_iov_cmd_digest_t *dig, uint8 *buf, | |
344 | const uint16 *data, int n); | |
345 | ||
346 | /* | |
347 | * pack a buffer with uint32s - serialized in LE order - data points to uint32 | |
348 | * length is not checked. | |
349 | */ | |
350 | int bcm_iov_packv_u32(const bcm_iov_cmd_digest_t *dig, uint8 *buf, | |
351 | const uint32 *data, int n); | |
352 | ||
353 | #endif /* _bcmiov_h_ */ |