qcacld-2.0: Add support for default TX params in OCB mode

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
This commit is contained in:
Samuel Ahn 2016-01-19 17:19:29 -08:00 committed by syphyr
parent a6cf2de288
commit 29164f263f
9 changed files with 206 additions and 9 deletions

View file

@ -552,11 +552,14 @@ ol_tx_non_std_ll(
*/
#define OCB_HEADER_VERSION 1
static bool parse_ocb_tx_header(adf_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 *) adf_nbuf_data(msdu);
if (eth_hdr_p->ether_type != adf_os_htons(ETHERTYPE_OCB_TX))
@ -570,6 +573,7 @@ static bool parse_ocb_tx_header(adf_nbuf_t msdu,
tx_ctrl_hdr = (struct ocb_tx_ctrl_hdr_t*) adf_nbuf_data(msdu);
if (tx_ctrl_hdr->version == OCB_HEADER_VERSION) {
*tx_ctrl_header_found = true;
if (tx_ctrl)
adf_os_mem_copy(tx_ctrl, tx_ctrl_hdr, sizeof(*tx_ctrl_hdr));
} else {
@ -582,6 +586,49 @@ static bool parse_ocb_tx_header(adf_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;
}
}
static inline adf_nbuf_t
ol_tx_hl_base(
ol_txrx_vdev_handle vdev,
@ -669,10 +716,18 @@ ol_tx_hl_base(
/* If the vdev is in OCB mode, 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)
vos_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, &tx_msdu_info);

View file

@ -2634,6 +2634,92 @@ 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)) {
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR,
"Invalid size of OCB default TX params");
return false;
}
if (def_tx_param->version != OCB_HEADER_VERSION) {
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR,
"Invalid version of OCB default TX params");
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) {
VOS_TRACE(VOS_MODULE_ID_TXRX,
VOS_TRACE_LEVEL_ERROR,
"Invalid default channel frequency");
return false;
}
}
if (def_tx_param->valid_datarate &&
def_tx_param->datarate > MAX_DATARATE) {
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR,
"Invalid default datarate");
return false;
}
if (def_tx_param->valid_tid &&
def_tx_param->ext_tid > MAX_TID) {
VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR,
"Invalid default TID");
return false;
}
if (vdev->ocb_def_tx_param == NULL)
vdev->ocb_def_tx_param =
vos_mem_malloc(sizeof(*vdev->ocb_def_tx_param));
vos_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) {
vos_mem_free(vdev->ocb_def_tx_param);
vdev->ocb_def_tx_param = NULL;
}
}
return true;
}
#ifdef IPA_UC_OFFLOAD
void
ol_txrx_ipa_uc_get_resource(

View file

@ -967,6 +967,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;
};
struct ol_rx_reorder_array_elem_t {

View file

@ -753,6 +753,9 @@ 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[
@ -899,6 +902,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;
@ -956,11 +961,19 @@ 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,
ndl_active_state_list_len);
@ -972,6 +985,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];

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2015 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.
*
@ -90,7 +90,12 @@ struct dot11p_channel_sched {
* @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY:
* array of NDL channel information
* @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY:
* array of NDL active state configuration
* array of NDL active state configuration
* @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS:
* 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,
@ -101,6 +106,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,

View file

@ -6298,8 +6298,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;
@ -6312,6 +6312,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. */

View file

@ -1429,6 +1429,19 @@ void ol_txrx_set_ocb_peer(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t *pe
*/
a_bool_t 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_txrx_display_stats(struct ol_txrx_pdev_t *pdev, uint16_t bitmap);
void ol_txrx_clear_stats(struct ol_txrx_pdev_t *pdev, uint16_t bitmap);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015 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.
*
@ -55,6 +55,7 @@ int wma_ocb_set_config_resp(tp_wma_handle wma_handle, uint8_t status)
*/
if (status == VOS_STATUS_SUCCESS) {
if (vdev && req) {
/* Save the channel info in the vdev */
if (vdev->ocb_channel_info)
vos_mem_free(vdev->ocb_channel_info);
vdev->ocb_channel_count =
@ -79,6 +80,14 @@ int wma_ocb_set_config_resp(tp_wma_handle wma_handle, uint8_t status)
} else {
vdev->ocb_channel_info = 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 = VOS_STATUS_E_INVAL;
}
}
}

View file

@ -13276,7 +13276,8 @@ static struct sir_ocb_config *sme_copy_sir_ocb_config(struct sir_ocb_config *src
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 = vos_mem_malloc(length);
if (!dst)
@ -13303,6 +13304,13 @@ static struct sir_ocb_config *sme_copy_sir_ocb_config(struct sir_ocb_config *src
vos_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;
vos_mem_copy(dst->def_tx_param, src->def_tx_param,
src->def_tx_param_size);
}
return dst;
}