Browse Source

qcacld-3.0: Remove SAP connection from policy manager upon stopbss

If SAP has no channel left to move then it will issue stop bss. In this
scenario, SAP is not cleaning up its entry from policy manager table
which causes stale entry left over in table.

Fix this situation by stopping the bss successfully and deleting entry
from policy manager table.

Change-Id: I7c7d305936fe16b0deebb9b7a67f7753cbf243e6
CRs-Fixed: 2112932
Krunal Soni 7 years ago
parent
commit
22208393bb

+ 1 - 0
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 {

+ 50 - 0
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

+ 1 - 0
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);

+ 1 - 0
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,

+ 3 - 1
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;

+ 7 - 0
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"),