diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index fd16ce60e998..65950c9ca6b3 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1149,6 +1149,7 @@ struct hdd_adapter { uint8_t snr; struct work_struct monTxWorkQueue; + struct work_struct sap_stop_bss_work; struct sk_buff *skb_to_tx; union { diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index e211ce5a0754..0d821b69d0f6 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1330,6 +1330,47 @@ static void hdd_fill_station_info(struct hdd_station_info *stainfo, stainfo->tx_mcs_map); } +/** + * hdd_stop_sap_due_to_invalid_channel() - to stop sap in case of invalid chnl + * @work: pointer to work structure + * + * Let's say SAP detected RADAR and trying to select the new channel and if no + * valid channel is found due to none of the channels are available or + * regulatory restriction then SAP needs to be stopped. so SAP state-machine + * will create a work to stop the bss + * + * stop bss has to happen through worker thread because radar indication comes + * from FW through mc thread or main host thread and if same thread is used to + * do stopbss then waiting for stopbss to finish operation will halt mc thread + * to freeze which will trigger stopbss timeout. Instead worker thread can do + * the stopbss operation while mc thread waits for stopbss to finish. + * + * Return: none + */ +static void +hdd_stop_sap_due_to_invalid_channel(struct work_struct *work) +{ + /* + * Extract the adapter from work structure. sap_stop_bss_work + * is part of adapter context. + */ + struct hdd_adapter *sap_adapter = container_of(work, + struct hdd_adapter, + sap_stop_bss_work); + hdd_debug("work started for sap session[%d]", sap_adapter->sessionId); + cds_ssr_protect(__func__); + if (sap_adapter == NULL) { + cds_err("sap_adapter is NULL, no work needed"); + cds_ssr_unprotect(__func__); + return; + } + wlan_hdd_stop_sap(sap_adapter); + wlansap_set_invalid_session(WLAN_HDD_GET_SAP_CTX_PTR(sap_adapter)); + wlansap_cleanup_cac_timer(WLAN_HDD_GET_SAP_CTX_PTR(sap_adapter)); + hdd_debug("work finished for sap"); + cds_ssr_unprotect(__func__); +} + QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, void *usrDataForCallback) { @@ -2368,6 +2409,14 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS); return QDF_STATUS_SUCCESS; + case eSAP_STOP_BSS_DUE_TO_NO_CHNL: + hdd_debug("Stop sap session[%d]", + adapter->sessionId); + INIT_WORK(&adapter->sap_stop_bss_work, + hdd_stop_sap_due_to_invalid_channel); + schedule_work(&adapter->sap_stop_bss_work); + return QDF_STATUS_SUCCESS; + default: hdd_debug("SAP message is not handled"); goto stopbss; @@ -8152,6 +8201,7 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, status = hdd_get_next_adapter(hdd_ctx, pAdapterNode, &pNext); pAdapterNode = pNext; } + cds_flush_work(&adapter->sap_stop_bss_work); /* * When ever stop ap adapter gets called, we need to check * whether any restart AP work is pending. If any restart is pending diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 5a913c6eedb1..a5e817d104fd 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -4409,6 +4409,7 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx, struct hdd_adapter *ada clear_bit(ACS_PENDING, &adapter->event_flags); } } + cds_flush_work(&adapter->sap_stop_bss_work); /* Any softap specific cleanup here... */ if (adapter->device_mode == QDF_P2P_GO_MODE) wlan_hdd_cleanup_remain_on_channel_ctx(adapter); diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index ec4e82d8350c..44d4fcad2ca2 100644 --- a/core/sap/inc/sap_api.h +++ b/core/sap/inc/sap_api.h @@ -177,6 +177,7 @@ typedef enum { eSAP_DFS_NOL_SET, /* No ch available after DFS RADAR detect */ eSAP_DFS_NO_AVAILABLE_CHANNEL, + eSAP_STOP_BSS_DUE_TO_NO_CHNL, eSAP_ACS_SCAN_SUCCESS_EVENT, eSAP_ACS_CHANNEL_SELECTED, eSAP_ECSA_CHANGE_CHAN_IND, diff --git a/core/sap/src/sap_api_link_cntl.c b/core/sap/src/sap_api_link_cntl.c index 723b9e4d1d73..830b4c7fd03b 100644 --- a/core/sap/src/sap_api_link_cntl.c +++ b/core/sap/src/sap_api_link_cntl.c @@ -1077,7 +1077,9 @@ wlansap_roam_callback(void *ctx, tCsrRoamInfo *csr_roam_info, uint32_t roamId, QDF_TRACE_LEVEL_ERROR, FL("sapdfs: no available channel for sapctx[%pK], StopBss"), pSapContext); - wlansap_stop_bss(pSapContext); + sap_signal_hdd_event(sap_ctx, NULL, + eSAP_STOP_BSS_DUE_TO_NO_CHNL, + (void *) eSAP_STATUS_SUCCESS); } } break; diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 85f06febda4d..db0972b7ddd3 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -2669,6 +2669,13 @@ QDF_STATUS sap_signal_hdd_event(struct sap_context *sap_ctx, __func__, "eSAP_DFS_NEXT_CHANNEL_REQ"); sap_ap_event.sapHddEventCode = eSAP_DFS_NEXT_CHANNEL_REQ; break; + case eSAP_STOP_BSS_DUE_TO_NO_CHNL: + sap_ap_event.sapHddEventCode = eSAP_STOP_BSS_DUE_TO_NO_CHNL; + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_DEBUG, + FL("stopping session_id:%d, bssid:%pM, channel:%d"), + sap_ctx->sessionId, sap_ctx->self_mac_addr, + sap_ctx->channel); + break; default: QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, FL("SAP Unknown callback event = %d"),