summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Ahn <sahn@codeaurora.org>2016-09-20 20:24:18 +0530
committerqcabuildsw <qcabuildsw@localhost>2016-11-21 22:45:10 -0800
commit107ee764b84dcd8a350ad54e0575efb1dc7b0d9c (patch)
tree71216d9122320249da3ec31e3deb13fdca7e490e
parentcd421753df14fd536676f297bb082f51a4eab91d (diff)
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
-rw-r--r--core/dp/ol/inc/ol_txrx_ctrl_api.h12
-rw-r--r--core/dp/txrx/ol_tx.c65
-rw-r--r--core/dp/txrx/ol_txrx.c86
-rw-r--r--core/dp/txrx/ol_txrx_types.h3
-rw-r--r--core/hdd/src/wlan_hdd_ocb.c17
-rw-r--r--core/hdd/src/wlan_hdd_ocb.h7
-rw-r--r--core/mac/inc/sir_api.h6
-rw-r--r--core/sme/src/common/sme_api.c9
-rw-r--r--core/wma/src/wma_ocb.c7
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);
}