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