qcacld-3.0: Send one suspend indication message to wma

Send one suspend indication message to wma after configuring
all the offloads. Reduce context switches and complexity.

Change-Id: I020fc8864dbf7378805361d54dc6cff60b2652e5
CRs-Fixed: 935297
This commit is contained in:
Houston Hoffman
2015-10-05 18:43:07 -07:00
committed by Akash Patel
parent d51b14c377
commit 162f56579e
8 changed files with 236 additions and 187 deletions

View File

@@ -511,16 +511,19 @@ void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, bool fenable)
hdd_conf_gtk_offload(pAdapter, fenable);
/* Configure ARP/NS offload during cfg80211 suspend/resume only
* if active mode offload is disabled
/* Configure ARP/NS offload during cfg80211 suspend/resume and
* Enable MC address filtering during cfg80211 suspend
* only if active mode offload is disabled
*/
if (!pHddCtx->config->active_mode_offload) {
hdd_info("configuring unconfigured active mode offloads");
hdd_conf_arp_offload(pAdapter, fenable);
wlan_hdd_set_mc_addr_list(pAdapter, fenable);
if (pHddCtx->config->fhostNSOffload)
hdd_conf_ns_offload(pAdapter, fenable);
}
EXIT();
EXIT();
return;
}
#endif
@@ -966,6 +969,23 @@ void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set)
}
#endif
/**
* hdd_update_mcastbcast_filter(): cache multi and broadcast filter for suspend
* @hdd_ctx: hdd context
*
* Cache the configured filter to be used in suspend resume.
*/
static void hdd_update_mcastbcast_filter(hdd_context_t *hdd_ctx)
{
if (false == hdd_ctx->sus_res_mcastbcast_filter_valid) {
hdd_ctx->sus_res_mcastbcast_filter =
hdd_ctx->configuredMcastBcastFilter;
hdd_ctx->sus_res_mcastbcast_filter_valid = true;
hdd_info("configuredMCastBcastFilter saved = %d",
hdd_ctx->configuredMcastBcastFilter);
}
}
/**
* hdd_conf_suspend_ind() - Send Suspend notification
* @pHddCtx: HDD Global context
@@ -975,69 +995,26 @@ void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set)
*
* Return: None.
*/
static void hdd_conf_suspend_ind(hdd_context_t *pHddCtx,
hdd_adapter_t *pAdapter,
static void hdd_send_suspend_ind(hdd_context_t *pHddCtx,
uint32_t conn_state_mask,
void (*callback)(void *callbackContext,
bool suspended),
void *callbackContext)
{
CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE;
tpSirWlanSuspendParam wlanSuspendParam =
cdf_mem_malloc(sizeof(tSirWlanSuspendParam));
if (false == pHddCtx->sus_res_mcastbcast_filter_valid) {
pHddCtx->sus_res_mcastbcast_filter =
pHddCtx->configuredMcastBcastFilter;
pHddCtx->sus_res_mcastbcast_filter_valid = true;
hddLog(CDF_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind");
hddLog(CDF_TRACE_LEVEL_INFO,
"configuredMCastBcastFilter saved = %d",
pHddCtx->configuredMcastBcastFilter);
hdd_info("%s: send wlan suspend indication", __func__);
}
if (NULL == wlanSuspendParam) {
hddLog(CDF_TRACE_LEVEL_FATAL,
"%s: cdf_mem_alloc failed ", __func__);
return;
}
hddLog(CDF_TRACE_LEVEL_INFO,
"%s: send wlan suspend indication", __func__);
/* Configure supported OffLoads */
hdd_conf_hostoffload(pAdapter, true);
wlanSuspendParam->configuredMcstBcstFilterSetting =
pHddCtx->configuredMcastBcastFilter;
/* Enable MC address filtering during cfg80211 suspend if active mode
* mode offload is disabled in INI
*/
if (!pHddCtx->config->active_mode_offload) {
hdd_info("enable mc address filtering");
wlan_hdd_set_mc_addr_list(pAdapter, true);
}
if ((eConnectionState_Associated ==
(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) ||
(eConnectionState_IbssConnected ==
(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
wlanSuspendParam->connectedState = true;
else
wlanSuspendParam->connectedState = false;
wlanSuspendParam->sessionId = pAdapter->sessionId;
cdf_ret_status =
sme_configure_suspend_ind(pHddCtx->hHal, wlanSuspendParam,
sme_configure_suspend_ind(pHddCtx->hHal, conn_state_mask,
callback, callbackContext);
if (CDF_STATUS_SUCCESS == cdf_ret_status) {
pHddCtx->hdd_mcastbcast_filter_set = true;
} else {
hddLog(CDF_TRACE_LEVEL_ERROR,
FL("sme_configure_suspend_ind returned failure %d"),
cdf_ret_status);
cdf_mem_free(wlanSuspendParam);
}
}
@@ -1077,14 +1054,27 @@ static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
"offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter");
hddLog(CDF_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d",
pHddCtx->configuredMcastBcastFilter);
/* Disable MC address filtering during cfg80211 suspend if active mode
* mode offload is disabled in INI
*/
if (!pHddCtx->config->active_mode_offload) {
hdd_info("disable mc address filtering");
wlan_hdd_set_mc_addr_list(pAdapter, false);
}
/**
* hdd_update_conn_state_mask(): record info needed by wma_suspend_req
* @adapter: adapter to get info from
* @conn_state_mask: mask of connection info
*
* currently only need to send connection info.
*/
static void
hdd_update_conn_state_mask(hdd_adapter_t *adapter, uint32_t *conn_state_mask)
{
eConnectionState connState;
hdd_station_ctx_t *sta_ctx;
sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
connState = sta_ctx->conn_info.connState;
if (connState == eConnectionState_Associated ||
connState == eConnectionState_IbssConnected)
*conn_state_mask |= (1 << adapter->sessionId);
}
/**
@@ -1103,9 +1093,9 @@ hdd_suspend_wlan(void (*callback)(void *callbackContext, bool suspended),
CDF_STATUS status;
hdd_adapter_t *pAdapter = NULL;
hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
uint32_t conn_state_mask = 0;
hddLog(CDF_TRACE_LEVEL_INFO, "%s: WLAN being suspended by OS",
__func__);
hdd_info("%s: WLAN being suspended by OS", __func__);
pHddCtx = cds_get_context(CDF_MODULE_ID_HDD);
if (!pHddCtx) {
@@ -1120,6 +1110,8 @@ hdd_suspend_wlan(void (*callback)(void *callbackContext, bool suspended),
return;
}
hdd_update_mcastbcast_filter(pHddCtx);
status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
while (NULL != pAdapterNode && CDF_STATUS_SUCCESS == status) {
pAdapter = pAdapterNode->pAdapter;
@@ -1129,20 +1121,19 @@ hdd_suspend_wlan(void (*callback)(void *callbackContext, bool suspended),
wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE,
WLAN_CONTROL_PATH);
/* Send suspend notification down to firmware.
*
* N.B.: Keep this suspend indication at the end
* (before processing next adaptor). This indication
* is considered as trigger point to start WOW (if wow
* is enabled).
*/
hdd_conf_suspend_ind(pHddCtx, pAdapter, callback,
callbackContext);
/* Configure supported OffLoads */
hdd_conf_hostoffload(pAdapter, true);
hdd_update_conn_state_mask(pAdapter, &conn_state_mask);
status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
pAdapterNode = pNext;
}
hdd_send_suspend_ind(pHddCtx, conn_state_mask, callback,
callbackContext);
pHddCtx->hdd_wlan_suspended = true;
return;

View File

@@ -2663,12 +2663,6 @@ typedef struct sSirNoAParam {
uint8_t psSelection;
} tSirNoAParam, *tpSirNoAParam;
typedef struct sSirWlanSuspendParam {
uint8_t configuredMcstBcstFilterSetting;
uint8_t sessionId;
uint8_t connectedState;
} tSirWlanSuspendParam, *tpSirWlanSuspendParam;
typedef struct sSirWlanResumeParam {
uint8_t configuredMcstBcstFilterSetting;
} tSirWlanResumeParam, *tpSirWlanResumeParam;

View File

@@ -461,7 +461,7 @@ CDF_STATUS sme_configure_rxp_filter(tHalHandle hHal,
tpSirWlanSetRxpFilters wlanRxpFilterParam);
CDF_STATUS sme_ConfigureAppsCpuWakeupState(tHalHandle hHal, bool isAppsAwake);
CDF_STATUS sme_configure_suspend_ind(tHalHandle hHal,
tpSirWlanSuspendParam wlanSuspendParam,
uint32_t conn_state_mask,
csr_readyToSuspendCallback,
void *callbackContext);
CDF_STATUS sme_configure_resume_req(tHalHandle hHal,

View File

@@ -6448,7 +6448,7 @@ CDF_STATUS sme_configure_rxp_filter(tHalHandle hHal,
--------------------------------------------------------------------------- */
CDF_STATUS sme_configure_suspend_ind(tHalHandle hHal,
tpSirWlanSuspendParam wlanSuspendParam,
uint32_t conn_state_mask,
csr_readyToSuspendCallback callback,
void *callback_context)
{
@@ -6467,7 +6467,7 @@ CDF_STATUS sme_configure_suspend_ind(tHalHandle hHal,
status = sme_acquire_global_lock(&pMac->sme);
if (CDF_IS_STATUS_SUCCESS(status)) {
/* serialize the req through MC thread */
cds_message.bodyptr = wlanSuspendParam;
cds_message.bodyval = conn_state_mask;
cds_message.type = WMA_WLAN_SUSPEND_IND;
cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {

View File

@@ -736,7 +736,6 @@ struct wma_wow {
bool deauth_enable;
bool disassoc_enable;
bool bmiss_enable;
bool gtk_pdev_enable;
bool gtk_err_enable[WMA_MAX_SUPPORTED_BSS];
#ifdef FEATURE_WLAN_LPHB
/* currently supports only vdev 0.

View File

@@ -993,7 +993,8 @@ CDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info);
CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info);
CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info);
CDF_STATUS wma_suspend_req(tp_wma_handle wma);
void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask);
void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg);

View File

@@ -3901,122 +3901,172 @@ CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
}
/**
* wma_suspend_req() - Handles suspend indication request received from umac.
* wma_update_conn_state(): synchronize wma & hdd
* @wma: wma handle
* @info: suspend params
* @conn_state: boolean array to populate
* @len: validation parameter
*
* Return: CDF status
* populate interfaces conn_state with true if the interface
* is a connected client and wow will configure a pattern.
*/
CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info)
void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask)
{
struct wma_txrx_node *iface;
bool connected = false, pno_in_progress = false;
uint8_t i;
bool extscan_in_progress = false;
wma->no_of_suspend_ind++;
if (info->sessionId > wma->max_bssid) {
WMA_LOGE("Invalid vdev id (%d)", info->sessionId);
cdf_mem_free(info);
return CDF_STATUS_E_INVAL;
int i;
for (i = 0; i < wma->max_bssid; i++) {
if (conn_mask & (1 << i))
wma->interfaces[i].conn_state = true;
else
wma->interfaces[i].conn_state = false;
}
iface = &wma->interfaces[info->sessionId];
if (!iface) {
WMA_LOGD("vdev %d node is not found", info->sessionId);
cdf_mem_free(info);
return CDF_STATUS_SUCCESS;
if (wma->wow.magic_ptrn_enable)
return;
for (i = 0; i < wma->max_bssid; i++) {
if (!wma->interfaces[i].ptrn_match_enable)
wma->interfaces[i].conn_state = false;
}
}
if (!wma->wow.magic_ptrn_enable && !iface->ptrn_match_enable) {
cdf_mem_free(info);
if (wma->no_of_suspend_ind == wma_get_vdev_count(wma)) {
WMA_LOGD("Both magic and pattern byte match are disabled");
wma->no_of_suspend_ind = 0;
goto send_ready_to_suspend;
}
return CDF_STATUS_SUCCESS;
}
iface->conn_state = (info->connectedState) ? true : false;
/*
* Once WOW is enabled in FW, host can't send anymore
* data to fw. umac sends suspend indication on each
* vdev during platform suspend. WMA has to wait until
* suspend indication received on last vdev before
* enabling wow in fw.
/**
* wma_is_beaconning_vdev_up(): check if a beaconning vdev is up
* @wma: wma handle
*
* Return TRUE if beaconning vdev is up
*/
if (wma->no_of_suspend_ind < wma_get_vdev_count(wma)) {
cdf_mem_free(info);
return CDF_STATUS_SUCCESS;
static inline
bool wma_is_beaconning_vdev_up(tp_wma_handle wma)
{
int i;
for (i = 0; i < wma->max_bssid; i++) {
if (wma_is_vdev_in_beaconning_mode(wma, i)
&& wma->interfaces[i].vdev_up)
return true;
}
return false;
}
wma->no_of_suspend_ind = 0;
wma->wow.gtk_pdev_enable = 0;
/*
/**
* wma_support_wow_for_beaconing: wow query for beaconning
* @wma: wma handle
*
* Need to configure wow to enable beaconning offload when
* a beaconing vdev is up and beaonning offload is configured.
*
* Return: true if we need to enable wow for beaconning offload
*/
static inline
bool wma_support_wow_for_beaconing(tp_wma_handle wma)
{
if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
WMI_SERVICE_BEACON_OFFLOAD)) {
if (wma_is_beaconning_vdev_up(wma))
return true;
}
return false;
}
#ifdef FEATURE_WLAN_SCAN_PNO
/**
* wma_is_pnoscan_in_progress(): check if a pnoscan is in progress
* @wma: wma handle
* @vdev_id: vdev_id
*
* Return: TRUE/FALSE
*/
static inline
bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
{
return wma->interfaces[vdev_id].pno_in_progress;
}
#else
/**
* wma_is_pnoscan_in_progress(): dummy
*
* Return: False since no pnoscan can be in progress
* when feature flag is not defined.
*/
bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id)
{
return FALSE;
}
#endif
#ifdef FEATURE_WLAN_EXTSCAN
static inline
/**
* wma_is_extscan_in_progress(): check if an extscan is in progress
* @wma: wma handle
* @vdev_id: vdev_id
*
* Return: TRUE/FALSvE
*/
bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
{
return wma->interfaces[vdev_id].extscan_in_progress;
}
#else
/**
* wma_is_extscan_in_progress(): dummy
*
* Return: False since no extscan can be in progress
* when feature flag is not defined.
*/
bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id)
{
return false;
}
#endif
/**
* wma_is_wow_applicable(): should enable wow
* @wma: wma handle
*
* Enable WOW if any one of the condition meets,
* 1) Is any one of vdev in beaconning mode (in AP mode) ?
* 2) Is any one of vdev in connected state (in STA mode) ?
* 3) Is PNO in progress in any one of vdev ?
* 4) Is Extscan in progress in any one of vdev ?
*
* Return: true if wma needs to configure wow.
*/
for (i = 0; i < wma->max_bssid; i++) {
if ((wma_is_vdev_in_beaconning_mode(wma, i)
) && wma->interfaces[i].vdev_up &&
WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
WMI_SERVICE_BEACON_OFFLOAD)) {
WMA_LOGD("vdev %d is in beaconning mode, enabling wow",
i);
goto enable_wow;
bool wma_is_wow_applicable(tp_wma_handle wma)
{
int vdev_id;
if (wma_support_wow_for_beaconing(wma)) {
WMA_LOGD("vdev is in beaconning mode, enabling wow");
return true;
}
}
for (i = 0; i < wma->max_bssid; i++) {
if (wma->interfaces[i].conn_state) {
connected = true;
break;
}
#ifdef FEATURE_WLAN_SCAN_PNO
if (wma->interfaces[i].pno_in_progress) {
for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) {
if (wma->interfaces[vdev_id].conn_state) {
WMA_LOGD("STA is connected, enabling wow");
return true;
} else if (wma_is_pnoscan_in_progress(wma, vdev_id)) {
WMA_LOGD("PNO is in progress, enabling wow");
pno_in_progress = true;
break;
return true;
} else if (wma_is_extscan_in_progress(wma, vdev_id)) {
WMA_LOGD("EXT is in progress, enabling wow");
return true;
}
#endif /* FEATURE_WLAN_SCAN_PNO */
#ifdef FEATURE_WLAN_EXTSCAN
if (wma->interfaces[i].extscan_in_progress) {
WMA_LOGD("Extscan is in progress, enabling wow");
extscan_in_progress = true;
break;
}
#endif
}
for (i = 0; i < wma->max_bssid; i++) {
wma->wow.gtk_pdev_enable |= wma->wow.gtk_err_enable[i];
WMA_LOGD("VDEV_ID:%d, gtk_err_enable[%d]:%d, gtk_pdev_enable:%d", i,
i, wma->wow.gtk_err_enable[i], wma->wow.gtk_pdev_enable);
}
if (!connected && !pno_in_progress && !extscan_in_progress) {
WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow");
cdf_mem_free(info);
goto send_ready_to_suspend;
return true;
}
enable_wow:
WMA_LOGE("WOW Suspend");
/*
* At this point, suspend indication is received on
* last vdev. It's the time to enable wow in fw.
*/
#ifdef FEATURE_WLAN_LPHB
/* LPHB cache, if any item was enabled, should be
/**
* wma_apply_lphb(): apply cached LPHB settings
* @wma: wma handle
*
* LPHB cache, if any item was enabled, should be
* applied.
*/
static inline
void wma_apply_lphb(tp_wma_handle wma)
{
int i;
WMA_LOGD("%s: checking LPHB cache", __func__);
for (i = 0; i < 2; i++) {
if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) {
@@ -4026,14 +4076,28 @@ enable_wow:
false);
}
}
}
#else
void wma_apply_lphb(tp_wma_handle wma) {}
#endif /* FEATURE_WLAN_LPHB */
/**
* wma_suspend_req() - Handles suspend indication request received from umac.
* @wma: wma handle
* @info: suspend params
*
* Return: CDF status
*/
CDF_STATUS wma_suspend_req(tp_wma_handle wma)
{
if (wma_is_wow_applicable(wma)) {
WMA_LOGE("WOW Suspend");
wma_apply_lphb(wma);
wma->wow.wow_enable = true;
wma->wow.wow_enable_cmd_sent = false;
}
cdf_mem_free(info);
send_ready_to_suspend:
/* Set the Suspend DTIM Parameters */
wma_set_suspend_dtim(wma);
wma_send_status_to_suspend_ind(wma, true);

View File

@@ -4875,8 +4875,8 @@ CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg)
wma_wow_exit(wma_handle, (tpSirHalWowlExitParams) msg->bodyptr);
break;
case WMA_WLAN_SUSPEND_IND:
wma_suspend_req(wma_handle,
(tpSirWlanSuspendParam) msg->bodyptr);
wma_update_conn_state(wma_handle, msg->bodyval);
wma_suspend_req(wma_handle);
break;
case WMA_8023_MULTICAST_LIST_REQ:
wma_process_mcbc_set_filter_req(wma_handle,