From 107ee764b84dcd8a350ad54e0575efb1dc7b0d9c Mon Sep 17 00:00:00 2001 From: Samuel Ahn Date: Tue, 20 Sep 2016 20:24:18 +0530 Subject: qcacld-3.0: Add support for default TX params in OCB mode Propagation from qcacld-2.0 to qcacld-3.0. When OCB mode is configured, default TX parameters can be provided. These default TX parameters are used if a packet is sent without a TX control header. Change-Id: I72b3799cb0a9e00a60548facf25e57be241d82d7 CRs-Fixed: 964279 --- core/dp/ol/inc/ol_txrx_ctrl_api.h | 12 ++++++ core/dp/txrx/ol_tx.c | 65 ++++++++++++++++++++++++++++- core/dp/txrx/ol_txrx.c | 86 +++++++++++++++++++++++++++++++++++++++ core/dp/txrx/ol_txrx_types.h | 3 ++ core/hdd/src/wlan_hdd_ocb.c | 17 +++++++- core/hdd/src/wlan_hdd_ocb.h | 7 +++- core/mac/inc/sir_api.h | 6 ++- core/sme/src/common/sme_api.c | 9 +++- core/wma/src/wma_ocb.c | 7 ++++ 9 files changed, 205 insertions(+), 7 deletions(-) diff --git a/core/dp/ol/inc/ol_txrx_ctrl_api.h b/core/dp/ol/inc/ol_txrx_ctrl_api.h index f4228b71e279..29166be61464 100644 --- a/core/dp/ol/inc/ol_txrx_ctrl_api.h +++ b/core/dp/ol/inc/ol_txrx_ctrl_api.h @@ -605,6 +605,18 @@ void ol_txrx_set_ocb_peer(struct ol_txrx_pdev_t *pdev, bool ol_txrx_get_ocb_peer(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t **peer); +/** + * ol_txrx_set_ocb_def_tx_param() - Set the default OCB TX parameters + * @vdev: The OCB vdev that will use these defaults. + * @_def_tx_param: The default TX parameters. + * @def_tx_param_size: The size of the _def_tx_param buffer. + * + * Return: true if the default parameters were set correctly, false if there + * is an error, for example an invalid parameter. In the case that false is + * returned, see the kernel log for the error description. + */ +bool ol_txrx_set_ocb_def_tx_param(ol_txrx_vdev_handle vdev, + void *def_tx_param, uint32_t def_tx_param_size); void ol_tx_set_is_mgmt_over_wmi_enabled(uint8_t value); uint8_t ol_tx_get_is_mgmt_over_wmi_enabled(void); diff --git a/core/dp/txrx/ol_tx.c b/core/dp/txrx/ol_tx.c index 1f171c07e9e0..1318c8d8b735 100644 --- a/core/dp/txrx/ol_tx.c +++ b/core/dp/txrx/ol_tx.c @@ -1160,10 +1160,12 @@ ol_tx_non_std_ll(ol_txrx_vdev_handle vdev, */ #define OCB_HEADER_VERSION 1 bool parse_ocb_tx_header(qdf_nbuf_t msdu, - struct ocb_tx_ctrl_hdr_t *tx_ctrl) + struct ocb_tx_ctrl_hdr_t *tx_ctrl, + bool *tx_ctrl_header_found) { struct ether_header *eth_hdr_p; struct ocb_tx_ctrl_hdr_t *tx_ctrl_hdr; + *tx_ctrl_header_found = false; /* Check if TX control header is present */ eth_hdr_p = (struct ether_header *)qdf_nbuf_data(msdu); @@ -1178,6 +1180,7 @@ bool parse_ocb_tx_header(qdf_nbuf_t msdu, tx_ctrl_hdr = (struct ocb_tx_ctrl_hdr_t *)qdf_nbuf_data(msdu); if (tx_ctrl_hdr->version == OCB_HEADER_VERSION) { + *tx_ctrl_header_found = true; if (tx_ctrl) qdf_mem_copy(tx_ctrl, tx_ctrl_hdr, sizeof(*tx_ctrl_hdr)); @@ -1191,6 +1194,50 @@ bool parse_ocb_tx_header(qdf_nbuf_t msdu, return true; } +/** + * merge_ocb_tx_ctrl_hdr() - merge the default TX ctrl parameters into + * @tx_ctrl: The destination TX control header. + * @def_ctrl_hdr: The default TX control header. + * + * For each parameter in tx_ctrl, if the parameter is unspecified, the + * equivalent parameter in def_ctrl_hdr will be copied to tx_ctrl. + */ +static void merge_ocb_tx_ctrl_hdr(struct ocb_tx_ctrl_hdr_t *tx_ctrl, + struct ocb_tx_ctrl_hdr_t *def_ctrl_hdr) +{ + if (!tx_ctrl || !def_ctrl_hdr) + return; + + if (!tx_ctrl->channel_freq && def_ctrl_hdr->channel_freq) + tx_ctrl->channel_freq = def_ctrl_hdr->channel_freq; + if (!tx_ctrl->valid_pwr && def_ctrl_hdr->valid_pwr) { + tx_ctrl->pwr = def_ctrl_hdr->pwr; + tx_ctrl->valid_pwr = 1; + } + if (!tx_ctrl->valid_datarate && def_ctrl_hdr->valid_datarate) { + tx_ctrl->datarate = def_ctrl_hdr->datarate; + tx_ctrl->valid_datarate = 1; + } + if (!tx_ctrl->valid_retries && def_ctrl_hdr->valid_retries) { + tx_ctrl->retry_limit = def_ctrl_hdr->retry_limit; + tx_ctrl->valid_retries = 1; + } + if (!tx_ctrl->valid_chain_mask && def_ctrl_hdr->valid_chain_mask) { + tx_ctrl->chain_mask = def_ctrl_hdr->chain_mask; + tx_ctrl->valid_chain_mask = 1; + } + if (!tx_ctrl->valid_expire_tsf && def_ctrl_hdr->valid_expire_tsf) { + tx_ctrl->expire_tsf_hi = def_ctrl_hdr->expire_tsf_hi; + tx_ctrl->expire_tsf_lo = def_ctrl_hdr->expire_tsf_lo; + tx_ctrl->valid_expire_tsf = 1; + } + if (!tx_ctrl->valid_tid && def_ctrl_hdr->valid_tid) { + tx_ctrl->ext_tid = def_ctrl_hdr->ext_tid; + tx_ctrl->valid_tid = 1; + } +} + + #if defined(CONFIG_HL_SUPPORT) && defined(CONFIG_TX_DESC_HI_PRIO_RESERVE) @@ -1491,12 +1538,26 @@ ol_tx_hl_base( * parse the tx control header. */ if (vdev->opmode == wlan_op_mode_ocb) { - if (!parse_ocb_tx_header(msdu, &tx_ctrl)) { + bool tx_ctrl_header_found = false; + + if (!parse_ocb_tx_header(msdu, &tx_ctrl, + &tx_ctrl_header_found)) { /* There was an error parsing * the header.Skip this packet. */ goto MSDU_LOOP_BOTTOM; } + /* If the TX control header was not found, + just use the defaults */ + if (!tx_ctrl_header_found && vdev->ocb_def_tx_param) + qdf_mem_copy(&tx_ctrl, vdev->ocb_def_tx_param, + sizeof(tx_ctrl)); + /* If the TX control header was found, merge the + defaults into it */ + else if (tx_ctrl_header_found && vdev->ocb_def_tx_param) + merge_ocb_tx_ctrl_hdr(&tx_ctrl, + vdev->ocb_def_tx_param); + } txq = ol_tx_classify(vdev, tx_desc, msdu, diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 74845898908e..1be546b1f6d6 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -4591,6 +4591,92 @@ bool ol_txrx_get_ocb_peer(struct ol_txrx_pdev_t *pdev, exit: return rc; } +#define MAX_TID 15 +#define MAX_DATARATE 7 +#define OCB_HEADER_VERSION 1 + +/** + * ol_txrx_set_ocb_def_tx_param() - Set the default OCB TX parameters + * @vdev: The OCB vdev that will use these defaults. + * @_def_tx_param: The default TX parameters. + * @def_tx_param_size: The size of the _def_tx_param buffer. + * + * Return: true if the default parameters were set correctly, false if there + * is an error, for example an invalid parameter. In the case that false is + * returned, see the kernel log for the error description. + */ +bool ol_txrx_set_ocb_def_tx_param(ol_txrx_vdev_handle vdev, + void *_def_tx_param, uint32_t def_tx_param_size) +{ + struct ocb_tx_ctrl_hdr_t *def_tx_param = + (struct ocb_tx_ctrl_hdr_t *)_def_tx_param; + + if (def_tx_param) { + /* + * Default TX parameters are provided. + * Validate the contents and + * save them in the vdev. + */ + if (def_tx_param_size != sizeof(struct ocb_tx_ctrl_hdr_t)) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%sInvalid size of OCB default TX params", __func__); + return false; + } + + if (def_tx_param->version != OCB_HEADER_VERSION) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%sInvalid version of OCB default TX params", __func__); + return false; + } + + if (def_tx_param->channel_freq) { + int i; + + for (i = 0; i < vdev->ocb_channel_count; i++) { + if (vdev->ocb_channel_info[i].chan_freq == + def_tx_param->channel_freq) + break; + } + if (i == vdev->ocb_channel_count) { + QDF_TRACE(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_ERROR, + "%sInvalid default channel frequency", __func__); + return false; + } + } + + if (def_tx_param->valid_datarate && + def_tx_param->datarate > MAX_DATARATE) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%sInvalid default datarate", __func__); + return false; + } + + if (def_tx_param->valid_tid && + def_tx_param->ext_tid > MAX_TID) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%sInvalid default TID", __func__); + return false; + } + + if (vdev->ocb_def_tx_param == NULL) + vdev->ocb_def_tx_param = + qdf_mem_malloc(sizeof(*vdev->ocb_def_tx_param)); + qdf_mem_copy(vdev->ocb_def_tx_param, def_tx_param, + sizeof(*vdev->ocb_def_tx_param)); + } else { + /* + * Default TX parameters are not provided. + * Delete the old defaults. + */ + if (vdev->ocb_def_tx_param) { + qdf_mem_free(vdev->ocb_def_tx_param); + vdev->ocb_def_tx_param = NULL; + } + } + + return true; +} #ifdef QCA_LL_TX_FLOW_CONTROL_V2 /** diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index cc0dd07387e5..aee5e4b96572 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -1066,6 +1066,9 @@ struct ol_txrx_vdev_t { /* Information about the schedules in the schedule */ struct ol_txrx_ocb_chan_info *ocb_channel_info; uint32_t ocb_channel_count; + /* Default OCB TX parameter */ + struct ocb_tx_ctrl_hdr_t *ocb_def_tx_param; + #ifdef QCA_LL_TX_FLOW_CONTROL_V2 struct ol_tx_flow_pool_t *pool; diff --git a/core/hdd/src/wlan_hdd_ocb.c b/core/hdd/src/wlan_hdd_ocb.c index 64ac5a0ebb42..f59fc30f5c5f 100644 --- a/core/hdd/src/wlan_hdd_ocb.c +++ b/core/hdd/src/wlan_hdd_ocb.c @@ -645,6 +645,10 @@ static const struct nla_policy qca_wlan_vendor_ocb_set_config_policy[ [QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_DEF_TX_PARAM] = { + .type = NLA_BINARY + }, + }; static const struct nla_policy qca_wlan_vendor_ocb_set_utc_time_policy[ @@ -791,6 +795,8 @@ static int __wlan_hdd_cfg80211_ocb_set_config(struct wiphy *wiphy, struct nlattr *ndl_active_state_list; uint32_t ndl_active_state_list_len; uint32_t flags = 0; + void *def_tx_param = NULL; + uint32_t def_tx_param_size = 0; int i; uint32_t channel_count, schedule_size; struct sir_ocb_config *config; @@ -841,10 +847,17 @@ static int __wlan_hdd_cfg80211_ocb_set_config(struct wiphy *wiphy, ndl_active_state_list_len = (ndl_active_state_list ? nla_len(ndl_active_state_list) : 0); - /* Get the flags */ + /* Get the flags. This parameter is optional.*/ if (tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS]) flags = nla_get_u32(tb[ QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS]); +/* Get the default TX parameters. This parameter is optional. */ + if (tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_DEF_TX_PARAM]) { + def_tx_param_size = nla_len(tb[ + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_DEF_TX_PARAM]); + def_tx_param = nla_data(tb[ + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_DEF_TX_PARAM]); + } config = hdd_ocb_config_new(channel_count, schedule_size, ndl_chan_list_len, @@ -857,6 +870,8 @@ static int __wlan_hdd_cfg80211_ocb_set_config(struct wiphy *wiphy, config->channel_count = channel_count; config->schedule_size = schedule_size; config->flags = flags; + config->def_tx_param = def_tx_param; + config->def_tx_param_size = def_tx_param_size; /* Read the channel array */ channel_array = tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_ARRAY]; diff --git a/core/hdd/src/wlan_hdd_ocb.h b/core/hdd/src/wlan_hdd_ocb.h index 2074511a15d3..b76c7fd0c495 100644 --- a/core/hdd/src/wlan_hdd_ocb.h +++ b/core/hdd/src/wlan_hdd_ocb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -93,6 +93,10 @@ struct dot11p_channel_sched { * array of NDL active state configuration * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS: * flag to set the absolute expiry + * configuration flags such as OCB_CONFIG_FLAG_80211_FRAME_MODE + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_DEF_TX_PARAM: + * default TX parameters to use in the case that a packet is sent without + * a TX control header */ enum qca_wlan_vendor_attr_ocb_set_config { QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_INVALID = 0, @@ -103,6 +107,7 @@ enum qca_wlan_vendor_attr_ocb_set_config { QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_DEF_TX_PARAM, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_MAX = QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_AFTER_LAST - 1, diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 4791ea95c4eb..e9102d005b8b 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -5600,8 +5600,8 @@ struct sir_ocb_config_sched { * @dcc_ndl_chan_list: array of dcc channel info * @dcc_ndl_active_state_list_len: size of the active state array * @dcc_ndl_active_state_list: array of active states - * @adapter: the OCB adapter - * @dcc_stats_callback: callback for the response event + * @def_tx_param: default TX parameters + * @def_tx_param_size: size of the default TX parameters */ struct sir_ocb_config { uint8_t session_id; @@ -5614,6 +5614,8 @@ struct sir_ocb_config { void *dcc_ndl_chan_list; uint32_t dcc_ndl_active_state_list_len; void *dcc_ndl_active_state_list; + void *def_tx_param; + uint32_t def_tx_param_size; }; /* The size of the utc time in bytes. */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 0d5c1489edf8..da2de765dc89 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -11280,7 +11280,8 @@ static struct sir_ocb_config *sme_copy_sir_ocb_config( src->channel_count * sizeof(*src->channels) + src->schedule_size * sizeof(*src->schedule) + src->dcc_ndl_chan_list_len + - src->dcc_ndl_active_state_list_len; + src->dcc_ndl_active_state_list_len + + src->def_tx_param_size; dst = qdf_mem_malloc(length); if (!dst) @@ -11307,6 +11308,12 @@ static struct sir_ocb_config *sme_copy_sir_ocb_config( qdf_mem_copy(dst->dcc_ndl_active_state_list, src->dcc_ndl_active_state_list, src->dcc_ndl_active_state_list_len); + cursor += src->dcc_ndl_active_state_list_len; + if (src->def_tx_param && src->def_tx_param_size) { + dst->def_tx_param = cursor; + qdf_mem_copy(dst->def_tx_param, src->def_tx_param, + src->def_tx_param_size); + } return dst; } diff --git a/core/wma/src/wma_ocb.c b/core/wma/src/wma_ocb.c index 2485c6648ed3..0a4dcfb395e4 100644 --- a/core/wma/src/wma_ocb.c +++ b/core/wma/src/wma_ocb.c @@ -82,6 +82,13 @@ int wma_ocb_set_config_resp(tp_wma_handle wma_handle, uint8_t status) ocb_set_chan.ocb_channel_info = 0; ocb_set_chan.ocb_channel_count = 0; } + /* Default TX parameter */ + if (!ol_txrx_set_ocb_def_tx_param(vdev, + req->def_tx_param, req->def_tx_param_size)) { + /* Setting the default param failed */ + WMA_LOGE(FL("Invalid default TX parameters")); + status = QDF_STATUS_E_INVAL; + } ol_txrx_set_ocb_chan_info(vdev, ocb_set_chan); } -- cgit v1.2.3