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