Kaynağa Gözat

qcacld-3.0: Add support in driver to do sap restart during SSR

qcacld-2.0 to qcacld-3.0 propagation

Presently, during subsystem restart Host is sending sap restart
indication to framework(via carrier off) to do SAP unload/load.
But SAP restart functionality is removed in framework when the
carrier off event is received, leading SAP fails to come-up
after subsystem restart.

Add support in driver to do SAP restart internally without sending
restart indication to framework, during subsystem restart.
This feature is controlled by ini param 'gEnableSapInternalRestart'
and by default it's enabled.

Change-Id: I76cb73c1887d4d8124cd9a1c29b9aac47642072a
CRs-Fixed: 1105651
Arun Khandavalli 8 yıl önce
ebeveyn
işleme
cc544b3909

+ 1 - 1
core/cds/src/cds_concurrency.c

@@ -5375,7 +5375,7 @@ static void cds_sap_restart_handle(struct work_struct *work)
 		cds_ssr_unprotect(__func__);
 		return;
 	}
-	wlan_hdd_start_sap(sap_adapter);
+	wlan_hdd_start_sap(sap_adapter, false);
 
 	cds_change_sap_restart_required_status(false);
 	cds_ssr_unprotect(__func__);

+ 6 - 0
core/hdd/inc/wlan_hdd_cfg.h

@@ -7802,6 +7802,11 @@ enum dot11p_mode {
 #define CFG_TGT_GTX_USR_CFG_MAX     (32)
 #define CFG_TGT_GTX_USR_CFG_DEFAULT (32)
 
+#define CFG_SAP_INTERNAL_RESTART_NAME    "gEnableSapInternalRestart"
+#define CFG_SAP_INTERNAL_RESTART_MIN     (0)
+#define CFG_SAP_INTERNAL_RESTART_MAX     (1)
+#define CFG_SAP_INTERNAL_RESTART_DEFAULT (1)
+
 /*
  * This parameter will avoid updating ap_sta_inactivity from hostapd.conf
  * file. If a station does not send anything in ap_max_inactivity seconds, an
@@ -9369,6 +9374,7 @@ struct hdd_config {
 #endif
 	enum hdd_wext_control standard_wext_control;
 	enum hdd_wext_control private_wext_control;
+	bool sap_internal_restart;
 };
 
 #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var))

+ 3 - 3
core/hdd/inc/wlan_hdd_ipa.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -109,7 +109,7 @@ static inline int hdd_ipa_send_mcc_scc_msg(hdd_context_t *hdd_ctx,
 	return 0;
 }
 #endif
-int hdd_ipa_uc_ssr_reinit(void);
+int hdd_ipa_uc_ssr_reinit(hdd_context_t *hdd_ctx);
 int hdd_ipa_uc_ssr_deinit(void);
 void hdd_ipa_uc_force_pipe_shutdown(hdd_context_t *hdd_ctx);
 struct sk_buff *hdd_ipa_tx_packet_ipa(hdd_context_t *hdd_ctx,
@@ -197,7 +197,7 @@ static inline void hdd_ipa_dump_info(hdd_context_t *hdd_ctx)
 	return;
 }
 
-static inline int hdd_ipa_uc_ssr_reinit(void)
+static inline int hdd_ipa_uc_ssr_reinit(hdd_context_t *hdd_ctx)
 {
 	return false;
 }

+ 2 - 1
core/hdd/inc/wlan_hdd_main.h

@@ -1896,7 +1896,7 @@ QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
 						  tScanResultHandle *scan_cache,
 						  bool *concurrent_chnl_same);
 void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter);
-void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter);
+void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter, bool reinit);
 
 void wlan_hdd_soc_set_antenna_mode_cb(enum set_antenna_mode_status status);
 
@@ -2189,4 +2189,5 @@ void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx);
  * Return: None
  */
 void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx);
+void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter, bool reinit);
 #endif /* end #if !defined(WLAN_HDD_MAIN_H) */

+ 9 - 0
core/hdd/src/wlan_hdd_cfg.c

@@ -4132,6 +4132,12 @@ REG_TABLE_ENTRY g_registry_table[] = {
 		     CFG_PRIVATE_WEXT_CONTROL_DEFAULT,
 		     CFG_PRIVATE_WEXT_CONTROL_MIN,
 		     CFG_PRIVATE_WEXT_CONTROL_MAX),
+	REG_VARIABLE(CFG_SAP_INTERNAL_RESTART_NAME, WLAN_PARAM_Integer,
+		struct hdd_config, sap_internal_restart,
+		VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+		CFG_SAP_INTERNAL_RESTART_DEFAULT,
+		CFG_SAP_INTERNAL_RESTART_MIN,
+		CFG_SAP_INTERNAL_RESTART_MAX),
 };
 
 /**
@@ -5564,6 +5570,9 @@ void hdd_cfg_print(hdd_context_t *pHddCtx)
 	hdd_info("Name = [%s] Value = [%u]",
 		CFG_CRASH_FW_TIMEOUT_NAME,
 		pHddCtx->config->fw_timeout_crash);
+	hdd_info("Name = [%s] Value = [%d]",
+		CFG_SAP_INTERNAL_RESTART_NAME,
+		pHddCtx->config->sap_internal_restart);
 }
 
 

+ 109 - 17
core/hdd/src/wlan_hdd_hostapd.c

@@ -1740,7 +1740,8 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
 			return QDF_STATUS_E_FAILURE;
 		}
 #ifdef IPA_OFFLOAD
-		if (hdd_ipa_is_enabled(pHddCtx)) {
+		if (!cds_is_driver_recovering() &&
+		    hdd_ipa_is_enabled(pHddCtx)) {
 			status = hdd_ipa_wlan_evt(pHostapdAdapter, staId,
 					HDD_IPA_CLIENT_DISCONNECT,
 					pSapEvent->sapevt.
@@ -5817,7 +5818,7 @@ void hdd_set_ap_ops(struct net_device *pWlanHostapdDev)
 	pWlanHostapdDev->netdev_ops = &net_ops_struct;
 }
 
-QDF_STATUS hdd_init_ap_mode(hdd_adapter_t *pAdapter)
+QDF_STATUS hdd_init_ap_mode(hdd_adapter_t *pAdapter, bool reinit)
 {
 	hdd_hostapd_state_t *phostapdBuf;
 	struct net_device *dev = pAdapter->dev;
@@ -5832,18 +5833,24 @@ QDF_STATUS hdd_init_ap_mode(hdd_adapter_t *pAdapter)
 
 	ENTER();
 
-	sapContext = wlansap_open(p_cds_context);
-	if (sapContext == NULL) {
-		hdd_err("ERROR: wlansap_open failed!!");
-		return QDF_STATUS_E_FAULT;
-	}
+	hdd_info("SSR in progress: %d", reinit);
+
+	if (reinit)
+		sapContext = pAdapter->sessionCtx.ap.sapContext;
+	else {
+		sapContext = wlansap_open(p_cds_context);
+		if (sapContext == NULL) {
+			hdd_err("ERROR: wlansap_open failed!!");
+			return QDF_STATUS_E_FAULT;
+		}
 
-	pAdapter->sessionCtx.ap.sapContext = sapContext;
-	pAdapter->sessionCtx.ap.sapConfig.channel =
-		pHddCtx->acs_policy.acs_channel;
-	acs_dfs_mode = pHddCtx->acs_policy.acs_dfs_mode;
-	pAdapter->sessionCtx.ap.sapConfig.acs_dfs_mode =
-		wlan_hdd_get_dfs_mode(acs_dfs_mode);
+		pAdapter->sessionCtx.ap.sapContext = sapContext;
+		pAdapter->sessionCtx.ap.sapConfig.channel =
+			pHddCtx->acs_policy.acs_channel;
+		acs_dfs_mode = pHddCtx->acs_policy.acs_dfs_mode;
+		pAdapter->sessionCtx.ap.sapConfig.acs_dfs_mode =
+			wlan_hdd_get_dfs_mode(acs_dfs_mode);
+	}
 
 	if (pAdapter->device_mode == QDF_P2P_GO_MODE) {
 		mode = QDF_P2P_GO_MODE;
@@ -5935,10 +5942,14 @@ QDF_STATUS hdd_init_ap_mode(hdd_adapter_t *pAdapter)
 	if (0 != ret) {
 		hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d", ret);
 	}
-	pAdapter->sessionCtx.ap.sapConfig.acs_cfg.acs_mode = false;
-	qdf_mem_free(pAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
-	qdf_mem_zero(&pAdapter->sessionCtx.ap.sapConfig.acs_cfg,
-						sizeof(struct sap_acs_cfg));
+
+	if (!reinit) {
+		pAdapter->sessionCtx.ap.sapConfig.acs_cfg.acs_mode = false;
+		qdf_mem_free(pAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
+		qdf_mem_zero(&pAdapter->sessionCtx.ap.sapConfig.acs_cfg,
+			     sizeof(struct sap_acs_cfg));
+	}
+
 	return status;
 
 error_wmm_init:
@@ -8372,3 +8383,84 @@ int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
 
 	return ret;
 }
+
+/**
+ * hdd_sap_indicate_disconnect_for_sta() - Indicate disconnect indication
+ * to supplicant, if there any clients connected to SAP interface.
+ * @adapter: sap adapter context
+ *
+ * Return:   nothing
+ */
+void hdd_sap_indicate_disconnect_for_sta(hdd_adapter_t *adapter)
+{
+	tSap_Event sap_event;
+	int sta_id;
+	ptSapContext sap_ctx;
+
+	ENTER();
+
+	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter);
+	if (!sap_ctx) {
+		hdd_err("invalid sap context");
+		return;
+	}
+
+	for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
+		if (adapter->aStaInfo[sta_id].isUsed) {
+			hdd_info("sta_id: %d isUsed: %d %p",
+				 sta_id, adapter->aStaInfo[sta_id].isUsed,
+				 adapter);
+
+			if (qdf_is_macaddr_broadcast(
+				&adapter->aStaInfo[sta_id].macAddrSTA))
+				continue;
+
+			sap_event.sapHddEventCode = eSAP_STA_DISASSOC_EVENT;
+			qdf_mem_copy(
+				&sap_event.sapevt.
+				sapStationDisassocCompleteEvent.staMac,
+				&adapter->aStaInfo[sta_id].macAddrSTA,
+				sizeof(struct qdf_mac_addr));
+			sap_event.sapevt.sapStationDisassocCompleteEvent.
+			reason =
+				eSAP_MAC_INITATED_DISASSOC;
+			sap_event.sapevt.sapStationDisassocCompleteEvent.
+			statusCode =
+				QDF_STATUS_E_RESOURCES;
+			hdd_hostapd_sap_event_cb(&sap_event,
+					sap_ctx->pUsrContext);
+		}
+	}
+
+	clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
+
+	EXIT();
+}
+
+/**
+ * hdd_sap_destroy_events() - Destroy sap evets
+ * @adapter: sap adapter context
+ *
+ * Return:   nothing
+ */
+void hdd_sap_destroy_events(hdd_adapter_t *adapter)
+{
+	ptSapContext sap_ctx;
+
+	ENTER();
+	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter);
+	if (!sap_ctx) {
+		hdd_err("invalid sap context");
+		return;
+	}
+
+	qdf_event_destroy(&sap_ctx->sap_session_opened_evt);
+	if (!QDF_IS_STATUS_SUCCESS(
+		qdf_mutex_destroy(&sap_ctx->SapGlobalLock))) {
+		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
+			  "wlansap_stop failed destroy lock");
+		return;
+	}
+	EXIT();
+}
+

+ 4 - 2
core/hdd/src/wlan_hdd_hostapd.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -95,7 +95,7 @@ int hdd_softap_unpack_ie(tHalHandle halHandle,
 
 QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
 				    void *usrDataForCallback);
-QDF_STATUS hdd_init_ap_mode(hdd_adapter_t *pAdapter);
+QDF_STATUS hdd_init_ap_mode(hdd_adapter_t *pAdapter, bool reinit);
 void hdd_set_ap_ops(struct net_device *pWlanHostapdDev);
 int hdd_hostapd_stop(struct net_device *dev);
 int hdd_sap_context_init(hdd_context_t *hdd_ctx);
@@ -121,4 +121,6 @@ int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
 				    struct cfg80211_beacon_data *params);
 
 QDF_STATUS wlan_hdd_config_acs(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter);
+void hdd_sap_indicate_disconnect_for_sta(hdd_adapter_t *adapter);
+void hdd_sap_destroy_events(hdd_adapter_t *adapter);
 #endif /* end #if !defined(WLAN_HDD_HOSTAPD_H) */

+ 83 - 12
core/hdd/src/wlan_hdd_ipa.c

@@ -2333,8 +2333,11 @@ static QDF_STATUS hdd_ipa_uc_ol_init(hdd_context_t *hdd_ctx)
 	qdf_mem_zero(&pipe_out, sizeof(struct ipa_wdi_out_params));
 
 	qdf_list_create(&ipa_ctxt->pending_event, 1000);
-	qdf_mutex_create(&ipa_ctxt->event_lock);
-	qdf_mutex_create(&ipa_ctxt->ipa_lock);
+
+	if (!cds_is_driver_recovering()) {
+		qdf_mutex_create(&ipa_ctxt->event_lock);
+		qdf_mutex_create(&ipa_ctxt->ipa_lock);
+	}
 
 	/* TX PIPE */
 	pipe_in.sys.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
@@ -2694,12 +2697,17 @@ static int __hdd_ipa_uc_ssr_deinit(void)
 	struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
 	int idx;
 	struct hdd_ipa_iface_context *iface_context;
+	hdd_context_t *hdd_ctx;
+
+	if (!hdd_ipa)
+		return 0;
 
-	if ((!hdd_ipa) || (!hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)))
+	hdd_ctx = hdd_ipa->hdd_ctx;
+	if (!hdd_ipa_uc_is_enabled(hdd_ctx))
 		return 0;
 
 	/* send disconnect to ipa driver */
-	hdd_ipa_uc_disconnect(hdd_ipa->hdd_ctx);
+	hdd_ipa_uc_disconnect(hdd_ctx);
 
 	/* Clean up HDD IPA interfaces */
 	for (idx = 0; (hdd_ipa->num_iface > 0) &&
@@ -2723,6 +2731,16 @@ static int __hdd_ipa_uc_ssr_deinit(void)
 	}
 	qdf_mutex_release(&hdd_ipa->ipa_lock);
 
+	HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
+		    "%s: Disconnect TX PIPE tx_pipe_handle=0x%x",
+		    __func__, hdd_ipa->tx_pipe_handle);
+	ipa_disconnect_wdi_pipe(hdd_ipa->tx_pipe_handle);
+
+	HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
+		    "%s: Disconnect RX PIPE rx_pipe_handle=0x%x",
+		    __func__, hdd_ipa->rx_pipe_handle);
+	ipa_disconnect_wdi_pipe(hdd_ipa->rx_pipe_handle);
+
 	if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx))
 		hdd_ipa_uc_sta_reset_sta_connected(hdd_ipa);
 
@@ -2759,14 +2777,66 @@ int hdd_ipa_uc_ssr_deinit(void)
  *
  * Return: 0 - Success
  */
-static int __hdd_ipa_uc_ssr_reinit(void)
+static int __hdd_ipa_uc_ssr_reinit(hdd_context_t *hdd_ctx)
 {
 
-	/* After SSR is complete, IPA UC can resume operation. But now wlan
-	 * driver will be unloaded and reloaded, which takes care of IPA cleanup
-	 * and initialization. This is a placeholder func if IPA has to resume
-	 * operations without driver reload.
-	 */
+	struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
+	int i;
+	struct hdd_ipa_iface_context *iface_context = NULL;
+	struct ol_txrx_pdev_t *pdev = NULL;
+
+	if (!hdd_ipa || !hdd_ipa_uc_is_enabled(hdd_ctx))
+		return 0;
+
+	pdev = cds_get_context(QDF_MODULE_ID_TXRX);
+	if (!pdev) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL, "pdev is NULL");
+		return -EINVAL;
+	}
+
+	cdp_ipa_get_resource(cds_get_context(QDF_MODULE_ID_SOC),
+			cds_get_context(QDF_MODULE_ID_TXRX),
+			&hdd_ipa->ipa_resource);
+	if ((hdd_ipa->ipa_resource.ce_sr_base_paddr == 0) ||
+	    (hdd_ipa->ipa_resource.tx_comp_ring_base_paddr == 0) ||
+	    (hdd_ipa->ipa_resource.rx_rdy_ring_base_paddr == 0) ||
+	    (hdd_ipa->ipa_resource.rx2_rdy_ring_base_paddr == 0)) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
+			"IPA UC resource alloc fail");
+		return -EINVAL;
+	}
+
+	/* Create the interface context */
+	for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
+		iface_context = &hdd_ipa->iface_context[i];
+		iface_context->hdd_ipa = hdd_ipa;
+		iface_context->cons_client =
+			hdd_ipa_adapter_2_client[i].cons_client;
+		iface_context->prod_client =
+			hdd_ipa_adapter_2_client[i].prod_client;
+		iface_context->iface_id = i;
+		iface_context->adapter = NULL;
+	}
+	for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
+		hdd_ipa->vdev_to_iface[i] = CSR_ROAM_SESSION_MAX;
+		hdd_ipa->vdev_offload_enabled[i] = false;
+	}
+
+	if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
+		hdd_ipa->resource_loading = false;
+		hdd_ipa->resource_unloading = false;
+		hdd_ipa->sta_connected = 0;
+		hdd_ipa->ipa_pipes_down = true;
+		hdd_ipa->uc_loaded = true;
+
+		if (hdd_ipa_uc_ol_init(hdd_ctx)) {
+			HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
+				    "Failed to setup pipes");
+			return -EINVAL;
+		}
+
+	}
+
 	return 0;
 }
 
@@ -2778,12 +2848,12 @@ static int __hdd_ipa_uc_ssr_reinit(void)
  *
  * Return: 0 - Success
  */
-int hdd_ipa_uc_ssr_reinit(void)
+int hdd_ipa_uc_ssr_reinit(hdd_context_t *hdd_ctx)
 {
 	int ret;
 
 	cds_ssr_protect(__func__);
-	ret = __hdd_ipa_uc_ssr_reinit();
+	ret = __hdd_ipa_uc_ssr_reinit(hdd_ctx);
 	cds_ssr_unprotect(__func__);
 
 	return ret;
@@ -5373,6 +5443,7 @@ QDF_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx)
 	return ret;
 }
 
+
 /**
  * hdd_ipa_cleanup_pending_event() - Cleanup IPA pending event list
  * @hdd_ipa: pointer to HDD IPA struct

+ 21 - 7
core/hdd/src/wlan_hdd_main.c

@@ -1865,6 +1865,12 @@ int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
 			hdd_info("In phase-1 initialization  don't enable modules");
 			break;
 		}
+
+		if (reinit) {
+			if (hdd_ipa_uc_ssr_reinit(hdd_ctx))
+			hdd_err("HDD IPA UC reinit failed");
+		}
+
 	/* Fall through dont add break here */
 	case DRIVER_MODULES_OPENED:
 		if (!adapter) {
@@ -3871,7 +3877,16 @@ QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
 	while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
 		adapter = adapterNode->pAdapter;
 		hdd_notice("Disabling queues");
-		wlan_hdd_netif_queue_control(adapter,
+		if (hdd_ctx->config->sap_internal_restart &&
+		    adapter->device_mode == QDF_SAP_MODE) {
+			wlan_hdd_netif_queue_control(adapter,
+						     WLAN_NETIF_TX_DISABLE,
+						     WLAN_CONTROL_PATH);
+			hdd_sap_indicate_disconnect_for_sta(adapter);
+			hdd_cleanup_actionframe(hdd_ctx, adapter);
+			hdd_sap_destroy_events(adapter);
+		} else
+			wlan_hdd_netif_queue_control(adapter,
 					   WLAN_NETIF_TX_DISABLE_N_CARRIER,
 					   WLAN_CONTROL_PATH);
 
@@ -4124,7 +4139,9 @@ QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
 			break;
 
 		case QDF_SAP_MODE:
-			/* softAP can handle SSR */
+			 if (hdd_ctx->config->sap_internal_restart)
+				hdd_init_ap_mode(adapter, true);
+
 			break;
 
 		case QDF_P2P_GO_MODE:
@@ -7061,7 +7078,7 @@ int hdd_start_ap_adapter(hdd_adapter_t *adapter)
 
 	ENTER();
 
-	status = hdd_init_ap_mode(adapter);
+	status = hdd_init_ap_mode(adapter, false);
 
 	if (QDF_STATUS_SUCCESS != status) {
 		hdd_err("Error Initializing the AP mode: %d", status);
@@ -9294,7 +9311,7 @@ void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
  *
  * Return: None
  */
-void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
+void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter, bool reinit)
 {
 	hdd_ap_ctx_t *hdd_ap_ctx;
 	hdd_hostapd_state_t *hostapd_state;
@@ -9317,9 +9334,6 @@ void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
 	hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
 	sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
 
-	if (wlan_hdd_validate_context(hdd_ctx))
-		return;
-
 	mutex_lock(&hdd_ctx->sap_lock);
 	if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
 		goto end;

+ 31 - 8
core/hdd/src/wlan_hdd_power.c

@@ -1239,6 +1239,34 @@ void hdd_svc_fw_shutdown_ind(struct device *dev)
 					      NULL, 0) : 0;
 }
 
+/**
+ * hdd_ssr_restart_sap() - restart sap on SSR
+ * @hdd_ctx:   hdd context
+ *
+ * Return:     nothing
+ */
+static void hdd_ssr_restart_sap(hdd_context_t *hdd_ctx)
+{
+	QDF_STATUS  status;
+	hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
+	hdd_adapter_t *adapter;
+
+	ENTER();
+
+	status =  hdd_get_front_adapter(hdd_ctx, &adapter_node);
+	while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
+		adapter = adapter_node->pAdapter;
+		if (adapter && adapter->device_mode == QDF_SAP_MODE) {
+			hdd_notice("in sap mode %p", adapter);
+			wlan_hdd_start_sap(adapter, true);
+		}
+		status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
+		adapter_node = next;
+	}
+
+	EXIT();
+}
+
 /**
  * hdd_wlan_shutdown() - HDD SSR shutdown function
  *
@@ -1312,7 +1340,6 @@ QDF_STATUS hdd_wlan_shutdown(void)
 
 	hdd_bus_bandwidth_destroy(pHddCtx);
 
-	wlansap_global_deinit();
 	hdd_wlan_stop_modules(pHddCtx);
 
 	hdd_lpass_notify_stop(pHddCtx);
@@ -1335,7 +1362,6 @@ QDF_STATUS hdd_wlan_re_init(void)
 	v_CONTEXT_t p_cds_context = NULL;
 	hdd_context_t *pHddCtx = NULL;
 	hdd_adapter_t *pAdapter;
-	QDF_STATUS qdf_status;
 	int ret;
 	bool bug_on_reinit_failure = CFG_BUG_ON_REINIT_FAILURE_DEFAULT;
 
@@ -1375,15 +1401,13 @@ QDF_STATUS hdd_wlan_re_init(void)
 
 	hdd_bus_bandwidth_init(pHddCtx);
 
+
 	ret = hdd_wlan_start_modules(pHddCtx, pAdapter, true);
 	if (ret) {
 		hdd_err("Failed to start wlan after error");
 		goto err_wiphy_unregister;
 	}
 
-	if (hdd_ipa_uc_ssr_reinit())
-		hdd_err("HDD IPA UC reinit failed");
-
 	hdd_wlan_get_version(pHddCtx, NULL, NULL);
 
 	wlan_hdd_send_svc_nlink_msg(pHddCtx->radio_index,
@@ -1408,9 +1432,6 @@ QDF_STATUS hdd_wlan_re_init(void)
 	}
 
 	hdd_lpass_notify_start(pHddCtx);
-	qdf_status = wlansap_global_init();
-	if (QDF_IS_STATUS_ERROR(qdf_status))
-		goto err_cds_disable;
 
 	hdd_err("WLAN host driver reinitiation completed!");
 	goto success;
@@ -1441,6 +1462,8 @@ err_re_init:
 	return -EPERM;
 
 success:
+	if (pHddCtx->config->sap_internal_restart)
+		hdd_ssr_restart_sap(pHddCtx);
 	hdd_ssr_timer_del();
 	return QDF_STATUS_SUCCESS;
 }

+ 0 - 6
core/wma/src/wma_scan_roam.c

@@ -5346,12 +5346,6 @@ QDF_STATUS  wma_ipa_offload_enable_disable(tp_wma_handle wma,
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	if (cds_is_driver_recovering()) {
-		WMA_LOGE("%s Recovery in Progress. State: 0x%x Ignore!!!",
-			__func__, cds_get_driver_state());
-		return QDF_STATUS_E_FAILURE;
-	}
-
 	if (ipa_offload->offload_type > STA_RX_DATA_OFFLOAD) {
 		return QDF_STATUS_E_INVAL;
 	}