qcacld-3.0: Add vendor cmd to support antenna diversity

qcacld-2.0 to qcacld-3.0 propagation

Add qca_wlan_vendor_config attr to config antenna diversity.
Add vendor subcmd QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI
to get chain rssi value.

Change-Id: I75c4c8016b15772b0c52be91e446f69580475496
CRs-fixed: 1071075
This commit is contained in:
lifeng
2017-05-09 19:44:16 +08:00
committed by Anjaneedevi Kapparapu
parent a37a0bea97
commit d217d19d7e
9 changed files with 444 additions and 0 deletions

View File

@@ -5113,6 +5113,10 @@ wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
.type = NLA_UNSPEC, .type = NLA_UNSPEC,
.len = QDF_MAC_ADDR_SIZE}, .len = QDF_MAC_ADDR_SIZE},
[RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32}, [RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32},
[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA] = {.type = NLA_U32 },
[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN] = {.type = NLA_U32 },
[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST] = {.type = NLA_U32 },
[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL] = {.type = NLA_U32 },
}; };
/** /**
@@ -5438,6 +5442,8 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
int param_id; int param_id;
uint32_t tx_fail_count; uint32_t tx_fail_count;
uint32_t ant_div_usrcfg; uint32_t ant_div_usrcfg;
uint32_t antdiv_enable, antdiv_chain;
uint32_t antdiv_selftest, antdiv_selftest_intvl;
ENTER_DEV(dev); ENTER_DEV(dev);
@@ -5840,6 +5846,59 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
if (ret_val != 0) if (ret_val != 0)
return ret_val; return ret_val;
if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA]) {
antdiv_enable = nla_get_u32(
tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA]);
hdd_debug("antdiv_enable: %d", antdiv_enable);
ret_val = wma_cli_set_command((int)adapter->sessionId,
(int)WMI_PDEV_PARAM_ENA_ANT_DIV,
antdiv_enable, PDEV_CMD);
if (ret_val) {
hdd_err("Failed to set antdiv_enable");
return ret_val;
}
}
if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN]) {
antdiv_chain = nla_get_u32(
tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN]);
hdd_debug("antdiv_chain: %d", antdiv_chain);
ret_val = wma_cli_set_command((int)adapter->sessionId,
(int)WMI_PDEV_PARAM_FORCE_CHAIN_ANT,
antdiv_chain, PDEV_CMD);
if (ret_val) {
hdd_err("Failed to set antdiv_chain");
return ret_val;
}
}
if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST]) {
antdiv_selftest = nla_get_u32(
tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST]);
hdd_debug("antdiv_selftest: %d", antdiv_selftest);
ret_val = wma_cli_set_command((int)adapter->sessionId,
(int)WMI_PDEV_PARAM_ANT_DIV_SELFTEST,
antdiv_selftest, PDEV_CMD);
if (ret_val) {
hdd_err("Failed to set antdiv_selftest");
return ret_val;
}
}
if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL]) {
antdiv_selftest_intvl = nla_get_u32(
tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL]);
hdd_debug("antdiv_selftest_intvl: %d",
antdiv_selftest_intvl);
ret_val = wma_cli_set_command((int)adapter->sessionId,
(int)WMI_PDEV_PARAM_ANT_DIV_SELFTEST_INTVL,
antdiv_selftest_intvl, PDEV_CMD);
if (ret_val) {
hdd_err("Failed to set antdiv_selftest_intvl");
return ret_val;
}
}
return ret_val; return ret_val;
} }
@@ -10649,6 +10708,184 @@ static inline bool wlan_hdd_is_bt_in_progress(hdd_context_t *hdd_ctx)
return false; return false;
} }
struct chain_rssi_priv {
struct chain_rssi_result chain_rssi;
};
/**
* hdd_get_chain_rssi_cb() - Callback function to get chain rssi
* @context: opaque context originally passed to SME. HDD always passes
* a cookie for the request context
* @data: struct for get chain rssi
*
* This function receives the response/data from the lower layer and
* checks to see if the thread is still waiting then post the results to
* upper layer, if the request has timed out then ignore.
*
* Return: None
*/
static void hdd_get_chain_rssi_cb(void *context,
struct chain_rssi_result *data)
{
struct hdd_request *request;
struct chain_rssi_priv *priv;
ENTER();
request = hdd_request_get(context);
if (!request) {
hdd_err("Obsolete request");
return;
}
priv = hdd_request_priv(request);
priv->chain_rssi = *data;
hdd_request_complete(request);
hdd_request_put(request);
}
/**
* hdd_post_get_chain_rssi_rsp - send rsp to user space
* @hdd_ctx: pointer to hdd context
* @result: chain rssi result
*
* Return: 0 for success, non-zero for failure
*/
static int hdd_post_get_chain_rssi_rsp(hdd_context_t *hdd_ctx,
struct chain_rssi_result *result)
{
struct sk_buff *skb;
int data_len = sizeof(result->chain_rssi);
skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
data_len + NLA_HDRLEN + NLMSG_HDRLEN);
if (!skb) {
hdd_err("cfg80211_vendor_event_alloc failed");
return -ENOMEM;
}
if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI, data_len,
result->chain_rssi)) {
hdd_err("put fail");
goto nla_put_failure;
}
cfg80211_vendor_cmd_reply(skb);
return 0;
nla_put_failure:
kfree_skb(skb);
return -EINVAL;
}
/**
* __wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
* @wiphy: wiphy pointer
* @wdev: pointer to struct wireless_dev
* @data: pointer to incoming NL vendor data
* @data_len: length of @data
*
* Return: 0 on success; error number otherwise.
*/
static int __wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
struct wireless_dev *wdev,
const void *data,
int data_len)
{
hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
struct get_chain_rssi_req_params req_msg;
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
QDF_STATUS status;
int retval;
void *cookie;
struct hdd_request *request;
struct chain_rssi_priv *priv;
static const struct hdd_request_params params = {
.priv_size = sizeof(*priv),
.timeout_ms = WLAN_WAIT_TIME_STATS,
};
ENTER();
retval = wlan_hdd_validate_context(hdd_ctx);
if (0 != retval)
return retval;
if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, NULL)) {
hdd_err("Invalid ATTR");
return -EINVAL;
}
if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
hdd_err("attr mac addr failed");
return -EINVAL;
}
if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) !=
QDF_MAC_ADDR_SIZE) {
hdd_err("incorrect mac size");
return -EINVAL;
}
memcpy(&req_msg.peer_macaddr,
nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
QDF_MAC_ADDR_SIZE);
req_msg.session_id = adapter->sessionId;
request = hdd_request_alloc(&params);
if (!request) {
hdd_err("Request allocation failure");
return -ENOMEM;
}
cookie = hdd_request_cookie(request);
status = sme_get_chain_rssi(hdd_ctx->hHal,
&req_msg,
hdd_get_chain_rssi_cb,
cookie);
if (QDF_STATUS_SUCCESS != status) {
hdd_err("Unable to get chain rssi");
retval = qdf_status_to_os_return(status);
} else {
retval = hdd_request_wait_for_response(request);
if (retval) {
hdd_err("Target response timed out");
} else {
priv = hdd_request_priv(request);
retval = hdd_post_get_chain_rssi_rsp(hdd_ctx,
&priv->chain_rssi);
if (retval)
hdd_err("Failed to post chain rssi");
}
}
hdd_request_put(request);
EXIT();
return retval;
}
/**
* wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
* @wiphy: wiphy pointer
* @wdev: pointer to struct wireless_dev
* @data: pointer to incoming NL vendor data
* @data_len: length of @data
*
* Return: 0 on success; error number otherwise.
*/
static int wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
struct wireless_dev *wdev,
const void *data,
int data_len)
{
int ret;
cds_ssr_protect(__func__);
ret = __wlan_hdd_cfg80211_get_chain_rssi(wiphy, wdev, data, data_len);
cds_ssr_unprotect(__func__);
return ret;
}
const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
{ {
@@ -11312,6 +11549,15 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
COMMON_VENDOR_COMMANDS COMMON_VENDOR_COMMANDS
#endif #endif
FEATURE_11AX_VENDOR_COMMANDS FEATURE_11AX_VENDOR_COMMANDS
{
.info.vendor_id = QCA_NL80211_VENDOR_ID,
.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI,
.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
WIPHY_VENDOR_CMD_NEED_NETDEV |
WIPHY_VENDOR_CMD_NEED_RUNNING,
.doit = wlan_hdd_cfg80211_get_chain_rssi
},
}; };
#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \ #if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \

View File

@@ -7452,4 +7452,24 @@ struct sir_rssi_disallow_lst {
int8_t expected_rssi; int8_t expected_rssi;
qdf_time_t time_during_rejection; qdf_time_t time_during_rejection;
}; };
/**
* struct chain_rssi_result - chain rssi result
* @chain_rssi: chain rssi result as dBm unit
*/
#define CHAIN_RSSI_NUM 8
struct chain_rssi_result {
int32_t chain_rssi[CHAIN_RSSI_NUM];
};
/**
* struct get_chain_rssi_req_params - get chain rssi req params
* @peer_macaddr: specific peer mac address
* @session_id: session id
*/
struct get_chain_rssi_req_params {
struct qdf_mac_addr peer_macaddr;
uint8_t session_id;
};
#endif /* __SIR_API_H */ #endif /* __SIR_API_H */

View File

@@ -1665,4 +1665,21 @@ QDF_STATUS sme_get_peer_info_ext(tHalHandle hal,
void sme_set_5g_band_pref(tHalHandle hal_handle, void sme_set_5g_band_pref(tHalHandle hal_handle,
struct sme_5g_band_pref_params *pref_params); struct sme_5g_band_pref_params *pref_params);
/**
* sme_get_chain_rssi() - Get chain rssi
* @hal: Global HAL handle
* @input: get chain rssi req params
* @callback: Callback function to be called with the result
* @context: Opaque context to be used by the caller to associate the
* request with the response
*
* This function constructs the cds message and fill in message type,
* post the same to WDA.
*
* Return: QDF_STATUS enumeration
*/
QDF_STATUS sme_get_chain_rssi(tHalHandle hal,
struct get_chain_rssi_req_params *input,
get_chain_rssi_callback callback,
void *context);
#endif /* #if !defined( __SME_API_H ) */ #endif /* #if !defined( __SME_API_H ) */

View File

@@ -160,6 +160,16 @@ typedef void (*sme_encrypt_decrypt_callback)(
void *context, void *context,
struct sir_encrypt_decrypt_rsp_params *response); struct sir_encrypt_decrypt_rsp_params *response);
/**
* typedef get_chain_rssi_callback - get chain rssi callback
* @context: Opaque context that the client can use to associate the
* callback with the request
* @data: chain rssi result reported by firmware
*/
struct chain_rssi_result;
typedef void (*get_chain_rssi_callback)(void *context,
struct chain_rssi_result *data);
typedef struct tagSmeStruct { typedef struct tagSmeStruct {
eSmeState state; eSmeState state;
qdf_mutex_t lkSmeGlobalLock; qdf_mutex_t lkSmeGlobalLock;
@@ -258,6 +268,8 @@ typedef struct tagSmeStruct {
void (*chip_power_save_fail_cb)(void *, void (*chip_power_save_fail_cb)(void *,
struct chip_pwr_save_fail_detected_params *); struct chip_pwr_save_fail_detected_params *);
void (*bt_activity_info_cb)(void *context, uint32_t bt_activity); void (*bt_activity_info_cb)(void *context, uint32_t bt_activity);
get_chain_rssi_callback get_chain_rssi_cb;
void *get_chain_rssi_context;
} tSmeStruct, *tpSmeStruct; } tSmeStruct, *tpSmeStruct;
#endif /* #if !defined( __SMEINTERNAL_H ) */ #endif /* #if !defined( __SMEINTERNAL_H ) */

View File

@@ -16507,3 +16507,26 @@ QDF_STATUS sme_set_bt_activity_info_cb(tHalHandle hal,
return status; return status;
} }
QDF_STATUS sme_get_chain_rssi(tHalHandle hal,
struct get_chain_rssi_req_params *input,
get_chain_rssi_callback callback,
void *context)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
SME_ENTER();
if (NULL == input) {
sme_err("Invalid req params");
return QDF_STATUS_E_INVAL;
}
mac_ctx->sme.get_chain_rssi_cb = callback;
mac_ctx->sme.get_chain_rssi_context = context;
wma_get_chain_rssi(hal, input);
SME_EXIT();
return status;
}

View File

@@ -2586,4 +2586,15 @@ QDF_STATUS wma_configure_smps_params(uint32_t vdev_id, uint32_t param_id,
int wma_chip_power_save_failure_detected_handler(void *handle, int wma_chip_power_save_failure_detected_handler(void *handle,
uint8_t *cmd_param_info, uint8_t *cmd_param_info,
uint32_t len); uint32_t len);
/**
* wma_get_chain_rssi() - send wmi cmd to get chain rssi
* @wma_handle: wma handler
* @req_params: requset params
*
* Return: Return QDF_STATUS
*/
QDF_STATUS wma_get_chain_rssi(tp_wma_handle wma_handle,
struct get_chain_rssi_req_params *req_params);
#endif #endif

View File

@@ -1327,4 +1327,19 @@ int wma_rx_aggr_failure_event_handler(void *handle, u_int8_t *event_buf,
*/ */
int wma_wlan_bt_activity_evt_handler(void *handle, uint8_t *event, int wma_wlan_bt_activity_evt_handler(void *handle, uint8_t *event,
uint32_t len); uint32_t len);
/**
* wma_peer_ant_info_evt_handler - event handler to handle antenna info
* @handle: the wma handle
* @event: buffer with event
* @len: buffer length
*
* This function receives antenna info from firmware and passes the event
* to upper layer
*
* Return: 0 on success
*/
int wma_peer_ant_info_evt_handler(void *handle, u_int8_t *event,
u_int32_t len);
#endif #endif

View File

@@ -5373,3 +5373,58 @@ int wma_wlan_bt_activity_evt_handler(void *handle, uint8_t *event, uint32_t len)
return 0; return 0;
} }
int wma_peer_ant_info_evt_handler(void *handle, u_int8_t *event,
u_int32_t len)
{
wmi_peer_antdiv_info *peer_ant_info;
WMI_PEER_ANTDIV_INFO_EVENTID_param_tlvs *param_buf;
wmi_peer_antdiv_info_event_fixed_param *fix_param;
struct chain_rssi_result *chain_rssi_result;
u_int32_t chain_index;
tpAniSirGlobal pmac = (tpAniSirGlobal)cds_get_context(
QDF_MODULE_ID_PE);
if (!pmac) {
WMA_LOGE("%s: Invalid pmac", __func__);
return -EINVAL;
}
param_buf = (WMI_PEER_ANTDIV_INFO_EVENTID_param_tlvs *) event;
if (!param_buf) {
WMA_LOGE("Invalid peer_ant_info event buffer");
return -EINVAL;
}
fix_param = param_buf->fixed_param;
peer_ant_info = param_buf->peer_info;
WMA_LOGD("num_peers=%d\tvdev_id=%d",
fix_param->num_peers, fix_param->vdev_id);
WMA_LOGD("peer_ant_info: %p", peer_ant_info);
if (!peer_ant_info) {
WMA_LOGE("Invalid peer_ant_info ptr");
return -EINVAL;
}
chain_rssi_result = qdf_mem_malloc(sizeof(*chain_rssi_result));
if (!chain_rssi_result) {
WMA_LOGE("%s: Failed to malloc", __func__);
return -ENOMEM;
}
for (chain_index = 0; chain_index < CHAIN_RSSI_NUM; chain_index++)
WMA_LOGD("chain%d rssi: %x", chain_index,
peer_ant_info->chain_rssi[chain_index]);
qdf_mem_copy(chain_rssi_result->chain_rssi,
peer_ant_info->chain_rssi,
sizeof(peer_ant_info->chain_rssi));
pmac->sme.get_chain_rssi_cb(pmac->sme.get_chain_rssi_context,
chain_rssi_result);
qdf_mem_free(chain_rssi_result);
return 0;
}

View File

@@ -2707,6 +2707,11 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, void *cds_context,
} }
wma_ndp_register_all_event_handlers(wma_handle); wma_ndp_register_all_event_handlers(wma_handle);
wmi_unified_register_event_handler(wma_handle->wmi_handle,
WMI_PEER_ANTDIV_INFO_EVENTID,
wma_peer_ant_info_evt_handler,
WMA_RX_WORK_CTX);
wma_register_debug_callback(); wma_register_debug_callback();
/* Register callback with PMO so PMO can update the vdev pause bitmap*/ /* Register callback with PMO so PMO can update the vdev pause bitmap*/
@@ -6674,6 +6679,46 @@ QDF_STATUS wma_set_rx_blocksize(tp_wma_handle wma_handle,
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }
QDF_STATUS wma_get_chain_rssi(tp_wma_handle wma_handle,
struct get_chain_rssi_req_params *req_params)
{
wmi_peer_antdiv_info_req_cmd_fixed_param *cmd;
wmi_buf_t wmi_buf;
uint32_t len = sizeof(wmi_peer_antdiv_info_req_cmd_fixed_param);
u_int8_t *buf_ptr;
if (!wma_handle) {
WMA_LOGE(FL("WMA is closed, can not issue cmd"));
return QDF_STATUS_E_INVAL;
}
wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
if (!wmi_buf) {
WMA_LOGE(FL("wmi_buf_alloc failed"));
return QDF_STATUS_E_NOMEM;
}
buf_ptr = (u_int8_t *)wmi_buf_data(wmi_buf);
cmd = (wmi_peer_antdiv_info_req_cmd_fixed_param *)buf_ptr;
WMITLV_SET_HDR(&cmd->tlv_header,
WMITLV_TAG_STRUC_wmi_peer_antdiv_info_req_cmd_fixed_param,
WMITLV_GET_STRUCT_TLVLEN(
wmi_peer_antdiv_info_req_cmd_fixed_param));
cmd->vdev_id = req_params->session_id;
WMI_CHAR_ARRAY_TO_MAC_ADDR(req_params->peer_macaddr.bytes,
&cmd->peer_mac_address);
if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
WMI_PEER_ANTDIV_INFO_REQ_CMDID)) {
WMA_LOGE(FL("failed to send get chain rssi command"));
wmi_buf_free(wmi_buf);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/** /**
* wma_mc_process_msg() - process wma messages and call appropriate function. * wma_mc_process_msg() - process wma messages and call appropriate function.
* @cds_context: cds context * @cds_context: cds context