blob: b6e77d5e846a38c646af6289f4c48c8569e0fa2a [file] [log] [blame]
/*
* bcmiov.h
* Common iovar handling/parsing support - batching, parsing, sub-cmd dispatch etc.
* To be used in firmware and host apps or dhd - reducing code size,
* duplication, and maintenance overhead.
*
* Copyright (C) 2017, Broadcom. All Rights Reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* <<Broadcom-WL-IPTag/Proprietary:>>
*
* $Id$
*/
#ifndef _bcmiov_h_
#define _bcmiov_h_
#include <typedefs.h>
#include <bcmutils.h>
#include <wlioctl.h>
#ifdef BCMDRIVER
#include <osl.h>
#else
#include <stddef.h> /* For size_t */
#endif /* BCMDRIVER */
/* Forward declarations */
typedef uint16 bcm_iov_cmd_id_t;
typedef uint16 bcm_iov_cmd_flags_t;
typedef uint16 bcm_iov_cmd_iovf_t;
typedef struct bcm_iov_cmd_info bcm_iov_cmd_info_t;
typedef struct bcm_iov_cmd_digest bcm_iov_cmd_digest_t;
typedef struct bcm_iov_cmd_tlv_info bcm_iov_cmd_tlv_info_t;
typedef struct bcm_iov_buf bcm_iov_buf_t;
typedef struct bcm_iov_batch_buf bcm_iov_batch_buf_t;
typedef struct bcm_iov_parse_context bcm_iov_parse_context_t;
typedef struct bcm_iov_sub_cmd_context bcm_iov_sub_cmd_context_t;
typedef void* (*bcm_iov_malloc_t)(void* alloc_ctx, size_t len);
typedef void (*bcm_iov_free_t)(void* alloc_ctx, void *buf, size_t len);
typedef uint8 bcm_iov_tlp_data_type_t;
typedef struct bcm_iov_tlp bcm_iov_tlp_t;
typedef struct bcm_iov_tlp_node bcm_iov_tlp_node_t;
typedef struct bcm_iov_batch_subcmd bcm_iov_batch_subcmd_t;
/*
* iov validation handler - All the common checks that are required
* for processing of iovars for any given command.
*/
typedef int (*bcm_iov_cmd_validate_t)(const bcm_iov_cmd_digest_t *dig,
uint32 actionid, const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen);
/* iov get handler - process subcommand specific input and return output.
* input and output may overlap, so the callee needs to check if
* that is supported. For xtlv data a tlv digest is provided to make
* parsing simpler. Output tlvs may be packed into output buffer using
* bcm xtlv support. olen is input/output parameter. On input contains
* max available obuf length and callee must fill the correct length
* to represent the length of output returned.
*/
typedef int (*bcm_iov_cmd_get_t)(const bcm_iov_cmd_digest_t *dig,
const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen);
/* iov set handler - process subcommand specific input and return output
* input and output may overlap, so the callee needs to check if
* that is supported. olen is input/output parameter. On input contains
* max available obuf length and callee must fill the correct length
* to represent the length of output returned.
*/
typedef int (*bcm_iov_cmd_set_t)(const bcm_iov_cmd_digest_t *dig,
const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen);
/* iov (sub-cmd) batch - a vector of commands. count can be zero
* to support a version query. Each command is a tlv - whose data
* portion may have an optional return status, followed by a fixed
* length data header, optionally followed by tlvs.
* cmd = type|length|<status|options>[header][tlvs]
*/
/*
* Batch sub-commands have status length included in the
* response length packed in TLV.
*/
#define BCM_IOV_STATUS_LEN sizeof(uint32)
/* batch version is indicated by setting high bit. */
#define BCM_IOV_BATCH_MASK 0x8000
/*
* Batched commands will have the following memory layout
* +--------+---------+-----+-------+
* |version |count | pad |sub-cmd|
* +--------+---------+-----+-------+
* version >= 0x8000
* count = number of sub-commands encoded in the iov buf
* sub-cmd one or more sub-commands for processing
* Where sub-cmd is padded byte buffer with memory layout as follows
* +--------+---------+-----------------------+-------------+------
* |cmd-id |length |IN(options) OUT(status)|command data |......
* +--------+---------+-----------------------+-------------+------
* cmd-id =sub-command ID
* length = length of this sub-command
* IN(options) = On input processing options/flags for this command
* OUT(status) on output processing status for this command
* command data = encapsulated IOVAR data as a single structure or packed TLVs for each
* individual sub-command.
*/
struct bcm_iov_batch_buf {
uint16 version;
uint8 count;
uint8 pad; /* Align sub-commands on 32 bit boundary */
bcm_xtlv_t cmds[1];
};
/* non-batched command version = major|minor w/ major <= 127 */
struct bcm_iov_buf {
uint16 version;
uint16 len;
bcm_iov_cmd_id_t id;
uint16 data[1]; /* 32 bit alignment may be repurposed by the command */
/* command specific data follows */
};
struct bcm_iov_batch_subcmd {
uint16 id;
uint16 len;
union {
uint32 options;
uint32 status;
} u;
uint8 data[1];
};
/* iov options flags */
enum {
BCM_IOV_CMD_OPT_ALIGN_NONE = 0x0000,
BCM_IOV_CMD_OPT_ALIGN32 = 0x0001,
BCM_IOV_CMD_OPT_TERMINATE_SUB_CMDS = 0x0002
};
/* iov command flags */
enum {
BCM_IOV_CMD_FLAG_NONE = 0,
BCM_IOV_CMD_FLAG_STATUS_PRESENT = (1 << 0), /* status present at data start - output only */
BCM_IOV_CMD_FLAG_XTLV_DATA = (1 << 1), /* data is a set of xtlvs */
BCM_IOV_CMD_FLAG_HDR_IN_LEN = (1 << 2), /* length starts at version - non-bacthed only */
BCM_IOV_CMD_FLAG_NOPAD = (1 << 3) /* No padding needed after iov_buf */
};
/* information about the command, xtlv options and xtlvs_off are meaningful
* only if XTLV_DATA cmd flag is selected
*/
struct bcm_iov_cmd_info {
bcm_iov_cmd_id_t cmd; /* the (sub)command - module specific */
bcm_iov_cmd_flags_t flags;
bcm_iov_cmd_iovf_t iovf; /* IOV flags - same as for normal iovars */
bcm_xtlv_opts_t xtlv_opts;
bcm_iov_cmd_validate_t validate_h; /* command validation handler */
bcm_iov_cmd_get_t get_h;
bcm_iov_cmd_set_t set_h;
uint16 xtlvs_off; /* offset to beginning of xtlvs in cmd data */
uint16 min_len_set;
uint16 max_len_set;
uint16 min_len_get;
uint16 max_len_get;
};
/* tlv digest to support parsing of xtlvs for commands w/ tlv data; the tlv
* digest is available in the handler for the command. The count and order in
* which tlvs appear in the digest are exactly the same as the order of tlvs
* passed in the registration for the command. Unknown tlvs are ignored.
* If registered tlvs are missing datap will be NULL. common iov rocessing
* acquires an input digest to process input buffer. The handler is responsible
* for constructing an output digest and use packing functions to generate
* the output buffer. The handler may use the input digest as output digest once
* the tlv data is extracted and used. Multiple tlv support involves allocation of
* tlp nodes, except the first, as required,
*/
/* tlp data type indicates if the data is not used/invalid, input or output */
enum {
BCM_IOV_TLP_NODE_INVALID = 0,
BCM_IOV_TLP_NODE_IN = 1,
BCM_IOV_TLP_NODE_OUT = 2
};
struct bcm_iov_tlp {
uint16 type;
uint16 len;
uint16 nodeix; /* node index */
};
/* tlp data for a given tlv - multiple tlvs of same type chained */
struct bcm_iov_tlp_node {
uint8 *next; /* multiple tlv support */
bcm_iov_tlp_data_type_t type;
uint8 *data; /* pointer to data in buffer or state */
};
struct bcm_iov_cmd_digest {
uint32 version; /* Version */
void *cmd_ctx;
struct wlc_bsscfg *bsscfg;
const bcm_iov_cmd_info_t *cmd_info;
uint16 max_tlps; /* number of tlps allocated */
uint16 max_nodes; /* number of nods allocated */
uint16 num_tlps; /* number of tlps valid */
uint16 num_nodes; /* number of nods valid */
uint16 tlps_off; /* offset to tlps */
uint16 nodes_off; /* offset to nodes */
/*
* bcm_iov_tlp_t tlps[max_tlps];
* bcm_iov_tlp_node_t nodes[max_nodes]
*/
};
/* get length callback - default length is min_len taken from digest */
typedef size_t (*bcm_iov_xtlv_get_len_t)(const bcm_iov_cmd_digest_t *dig,
const bcm_iov_cmd_tlv_info_t *tlv_info);
/* pack to buffer data callback. under some conditions it might
* not be a straight copy and can refer to context(ual) information and
* endian conversions...
*/
typedef void (*bcm_iov_xtlv_pack_t)(const bcm_iov_cmd_digest_t *dig,
const bcm_iov_cmd_tlv_info_t *tlv_info,
uint8 *out_buf, const uint8 *in_data, size_t len);
struct bcm_iov_cmd_tlv_info {
uint16 id;
uint16 min_len; /* inclusive */
uint16 max_len; /* inclusive */
bcm_iov_xtlv_get_len_t get_len;
bcm_iov_xtlv_pack_t pack;
};
/*
* module private parse context. Default version type len is uint16
*/
enum {
BCM_IOV_PARSE_CMD_NONE = 0
};
typedef uint32 parse_context_opts_t;
/* get digest callback */
typedef int (*bcm_iov_get_digest_t)(void *cmd_ctx, bcm_iov_cmd_digest_t **dig);
typedef struct bcm_iov_parse_config {
parse_context_opts_t options; /* to handle different ver lengths */
bcm_iov_malloc_t alloc_fn;
bcm_iov_free_t free_fn;
bcm_iov_get_digest_t dig_fn;
int max_regs;
void *alloc_ctx;
} bcm_iov_parse_config_t;
/* API */
/* All calls return an integer status code BCME_* unless otherwise indicated */
/* return length of allocation for 'num_cmds' commands. data_len
* includes length of data for all the commands excluding the headers
*/
size_t bcm_iov_get_alloc_len(int num_cmds, size_t data_len);
/* create parsing context using allocator provided; max_regs provides
* the number of allowed registrations for commands using the context
* sub-components of a module may register their own commands indepdently
* using the parsing context. If digest callback is NULL or returns NULL,
* the (input) digest is allocated using the provided allocators and released on
* completion of processing.
*/
int bcm_iov_create_parse_context(const bcm_iov_parse_config_t *parse_cfg,
bcm_iov_parse_context_t **parse_ctx);
/* free the parsing context; ctx is set to NULL on exit */
int bcm_iov_free_parse_context(bcm_iov_parse_context_t **ctx, bcm_iov_free_t free_fn);
/* Return the command context for the module */
void *bcm_iov_get_cmd_ctx_info(bcm_iov_parse_context_t *parse_ctx);
/* register a command info vector along with supported tlvs. Each command
* may support a subset of tlvs
*/
int bcm_iov_register_commands(bcm_iov_parse_context_t *parse_ctx, void *cmd_ctx,
const bcm_iov_cmd_info_t *info, size_t num_cmds,
const bcm_iov_cmd_tlv_info_t *tlv_info, size_t num_tlvs);
/* pack the xtlvs provided in the digest. may returns BCME_BUFTOOSHORT, but the
* out_len is set to required length in that case.
*/
int bcm_iov_pack_xtlvs(const bcm_iov_cmd_digest_t *dig, bcm_xtlv_opts_t xtlv_opts,
uint8 *out_buf, size_t out_size, size_t *out_len);
#ifdef BCMDRIVER
/* wlc modules register their iovar(s) using the parsing context w/ wlc layer
* during attach.
*/
struct wlc_if;
struct wlc_info;
extern struct wlc_bsscfg *bcm_iov_bsscfg_find_from_wlcif(struct wlc_info *wlc,
struct wlc_if *wlcif);
int bcm_iov_doiovar(void *parse_ctx, uint32 id, void *params, uint params_len,
void *arg, uint arg_len, uint vsize, struct wlc_if *intf);
#endif /* BCMDRIVER */
/* parsing context helpers */
/* get the maximum number of tlvs - can be used to allocate digest for all
* commands. the digest can be shared. Negative values are BCM_*, >=0, the
* number of tlvs
*/
int bcm_iov_parse_get_max_tlvs(const bcm_iov_parse_context_t *ctx);
/* common packing support */
/* pack a buffer of uint8s - memcpy wrapper */
int bcm_iov_pack_buf(const bcm_iov_cmd_digest_t *dig, uint8 *buf,
const uint8 *data, size_t len);
#define bcm_iov_packv_u8 bcm_iov_pack_buf
/*
* pack a buffer with uint16s - serialized in LE order, data points to uint16
* length is not checked.
*/
int bcm_iov_packv_u16(const bcm_iov_cmd_digest_t *dig, uint8 *buf,
const uint16 *data, int n);
/*
* pack a buffer with uint32s - serialized in LE order - data points to uint32
* length is not checked.
*/
int bcm_iov_packv_u32(const bcm_iov_cmd_digest_t *dig, uint8 *buf,
const uint32 *data, int n);
#endif /* _bcmiov_h_ */