Browse Source

qcacld-3.0: Enable green AP for AP stand alone and EGAP disabled

qcacld-2.0 to qcacld-3.0 propagation

When EGAP is enabled, configure EGAP parameters to firmware, and do
nothing for GAP.
When EGAP is disabled, need refine GAP in below situation.
  AP+STA concurrency mode
    When starts STA in case of AP existence, GREEN_AP_PS_STOP_EVENT
    will be triggered, at this time need to set green_ap->ps_enable
    as 0 and send firmware WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID with
    value 0.
    When stops STA in case of AP existence, abandon using of
    GREEN_AP_PS_IDLE_STATE, because once in GREEN_AP_PS_IDLE_STATE,
    more than one GREEN_AP_PS_START_EVENT are needed to achieve
    the GREEN_AP_PS_ON_STATE. Use GREEN_AP_PS_OFF_STATE instead.
  AP mode
    Remove hdd_wlan_green_ap_start_bss/hdd_wlan_green_ap_stop_bss
    in eSAP_START_BSS_EVENT/eSAP_STOP_BSS_EVENT, becasue SME
    session id is invalid in the context of eSAP_STOP_BSS_EVENT.
    Add hdd_wlan_green_ap_start_bss/hdd_wlan_green_ap_stop_bss in
    __wlan_hdd_cfg80211_start_ap/__wlan_hdd_cfg80211_stop_ap instead.
  AP+AP mode
    In hdd_wlan_green_ap_stop_bss, only trigger
    GREEN_AP_PS_STOP_EVENT when the last AP stops.

Change-Id: Ifbf09b870b919d2bd155887bf17a494be07f97b4
CRs-Fixed: 1069300
bings 8 years ago
parent
commit
612b9c4a55

+ 159 - 34
core/hdd/src/wlan_hdd_green_ap.c

@@ -161,8 +161,7 @@ static void hdd_green_ap_mc(struct hdd_context_s *hdd_ctx,
 		break;
 
 	case GREEN_AP_PS_STOP_EVENT:
-		if (!(cds_get_concurrency_mode() & QDF_SAP_MASK))
-			green_ap->ps_enable = 0;
+		green_ap->ps_enable = 0;
 		break;
 
 	case GREEN_AP_ADD_STA_EVENT:
@@ -183,18 +182,20 @@ static void hdd_green_ap_mc(struct hdd_context_s *hdd_ctx,
 		break;
 	}
 
+	adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
+	if (adapter == NULL) {
+		hdd_err("Green-AP no SAP adapter");
+		goto done;
+	}
+
 	/* Confirm that power save is enabled before doing state transitions */
 	if (!green_ap->ps_enable) {
 		hdd_notice("Green-AP is disabled");
 		hdd_green_ap_update(hdd_ctx,
-				    GREEN_AP_PS_IDLE_STATE,
+				    GREEN_AP_PS_OFF_STATE,
 				    GREEN_AP_PS_WAIT_EVENT);
-		goto done;
-	}
-
-	adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
-	if (adapter == NULL) {
-		hdd_err("Green-AP no SAP adapter");
+		if (hdd_green_ap_enable(adapter, 0))
+			hdd_err("failed to set green ap mode");
 		goto done;
 	}
 
@@ -391,39 +392,91 @@ void hdd_green_ap_deinit(struct hdd_context_s *hdd_ctx)
 		hdd_err("Cannot deallocate Green-AP resource");
 }
 
+/*
+ * hdd_is_egap_enabled() - Get Enhance Green AP feature status
+ * @fw_egap_support: flag whether firmware supports egap or not
+ * @cfg: pointer to the struct hdd_config
+ *
+ * Return: true if firmware, feature_flag and ini are all enabled the egap
+ */
+static bool hdd_is_egap_enabled(bool fw_egap_support, struct hdd_config *cfg)
+{
+	/* check if the firmware and ini are both enabled the egap,
+	 * and also the feature_flag enable.
+	 */
+	if (fw_egap_support && cfg->enable_egap &&
+			cfg->egap_feature_flag)
+		return true;
+	return false;
+}
+
+/*
+ * hdd_enable_egap() - Enable Enhance Green AP
+ * @hdd_ctx: HDD global context
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int hdd_enable_egap(struct hdd_context_s *hdd_ctx)
+{
+	struct hdd_config *cfg;
+
+	if (!hdd_ctx) {
+		hdd_err("hdd context is NULL");
+		return -EINVAL;
+	}
+
+	cfg = hdd_ctx->config;
+
+	if (!cfg) {
+		hdd_err("hdd cfg is NULL");
+		return -EINVAL;
+	}
+
+	if (!hdd_ctx->green_ap_ctx) {
+		hdd_err("green ap context is NULL");
+		return -EINVAL;
+	}
+
+	if (!hdd_is_egap_enabled(hdd_ctx->green_ap_ctx->egap_support,
+			hdd_ctx->config))
+		return -ENOTSUPP;
+
+	if (QDF_STATUS_SUCCESS != sme_send_egap_conf_params(cfg->enable_egap,
+			cfg->egap_inact_time,
+			cfg->egap_wait_time,
+			cfg->egap_feature_flag))
+		return -EINVAL;
+	return 0;
+}
+
 /*
  * hdd_green_ap_start_bss() - Notify Green AP of Start BSS event
  * (public function documented in wlan_hdd_green_ap.h)
  */
 void hdd_green_ap_start_bss(struct hdd_context_s *hdd_ctx)
 {
-	struct hdd_config *cfg = hdd_ctx->config;
+	struct hdd_config *cfg;
+
+	if (!hdd_ctx) {
+		hdd_err("hdd context is NULL");
+		return;
+	}
+
+	cfg = hdd_ctx->config;
+
+	if (!cfg) {
+		hdd_err("hdd cfg is NULL");
+		return;
+	}
 
 	if (!hdd_ctx->green_ap_ctx) {
 		hdd_err("Green AP is not enabled. green_ap_ctx = NULL");
-		goto exit;
+		return;
 	}
 
-	/* check if the firmware and ini are both enabled the egap,
-	 * and also the feature_flag enable, then we enable the egap
-	 */
-	if (hdd_ctx->green_ap_ctx->egap_support && cfg->enable_egap &&
-	    cfg->egap_feature_flag) {
-		hdd_notice("Set EGAP - enabled: %d, flag: %x, inact_time: %d, wait_time: %d",
-			   cfg->enable_egap, cfg->egap_feature_flag,
-			   cfg->egap_inact_time, cfg->egap_wait_time);
-		if (!sme_send_egap_conf_params(cfg->enable_egap,
-					       cfg->egap_inact_time,
-					       cfg->egap_wait_time,
-					       cfg->egap_feature_flag)) {
-			/* EGAP is enabled, disable host GAP */
-			hdd_green_ap_mc(hdd_ctx, GREEN_AP_PS_STOP_EVENT);
-			goto exit;
-		}
-		/* fall through, if send_egap_conf_params() failed,
-		 * then check host GAP and enable it accordingly
-		 */
-	}
+	if (hdd_is_egap_enabled(hdd_ctx->green_ap_ctx->egap_support,
+			hdd_ctx->config))
+		return;
 
 	if ((hdd_ctx->concurrency_mode & QDF_SAP_MASK) &&
 			!(hdd_ctx->concurrency_mode & (QDF_SAP_MASK)) &&
@@ -438,8 +491,6 @@ void hdd_green_ap_start_bss(struct hdd_context_s *hdd_ctx)
 			   QDF_STA_MASK & hdd_ctx->concurrency_mode,
 			   cfg->enable2x2, cfg->enableGreenAP);
 	}
-exit:
-	return;
 }
 
 /*
@@ -448,7 +499,35 @@ exit:
  */
 void hdd_green_ap_stop_bss(struct hdd_context_s *hdd_ctx)
 {
-	hdd_green_ap_mc(hdd_ctx, GREEN_AP_PS_STOP_EVENT);
+	struct hdd_config *cfg;
+
+	if (!hdd_ctx) {
+		hdd_err("hdd context is NULL");
+		return;
+	}
+
+	cfg = hdd_ctx->config;
+
+	if (!cfg) {
+		hdd_err("hdd cfg is NULL");
+		return;
+	}
+
+	if (!hdd_ctx->green_ap_ctx) {
+		hdd_err("Green AP is not enabled. green_ap_ctx = NULL");
+		return;
+	}
+
+	if (hdd_is_egap_enabled(hdd_ctx->green_ap_ctx->egap_support,
+			hdd_ctx->config))
+		return;
+
+	/* For AP+AP mode, only trigger GREEN_AP_PS_STOP_EVENT, when the
+	 * last AP stops.
+	 */
+
+	if (1 == (hdd_ctx->no_of_open_sessions[QDF_SAP_MODE]))
+		hdd_green_ap_mc(hdd_ctx, GREEN_AP_PS_STOP_EVENT);
 }
 
 /*
@@ -457,6 +536,29 @@ void hdd_green_ap_stop_bss(struct hdd_context_s *hdd_ctx)
  */
 void hdd_green_ap_add_sta(struct hdd_context_s *hdd_ctx)
 {
+	struct hdd_config *cfg;
+
+	if (!hdd_ctx) {
+		hdd_err("hdd context is NULL");
+		return;
+	}
+
+	cfg = hdd_ctx->config;
+
+	if (!cfg) {
+		hdd_err("hdd cfg is NULL");
+		return;
+	}
+
+	if (!hdd_ctx->green_ap_ctx) {
+		hdd_err("Green AP is not enabled. green_ap_ctx = NULL");
+		return;
+	}
+
+	if (hdd_is_egap_enabled(hdd_ctx->green_ap_ctx->egap_support,
+			hdd_ctx->config))
+		return;
+
 	hdd_green_ap_mc(hdd_ctx, GREEN_AP_ADD_STA_EVENT);
 }
 
@@ -466,6 +568,29 @@ void hdd_green_ap_add_sta(struct hdd_context_s *hdd_ctx)
  */
 void hdd_green_ap_del_sta(struct hdd_context_s *hdd_ctx)
 {
+	struct hdd_config *cfg;
+
+	if (!hdd_ctx) {
+		hdd_err("hdd context is NULL");
+		return;
+	}
+
+	cfg = hdd_ctx->config;
+
+	if (!cfg) {
+		hdd_err("hdd cfg is NULL");
+		return;
+	}
+
+	if (!hdd_ctx->green_ap_ctx) {
+		hdd_err("Green AP is not enabled. green_ap_ctx = NULL");
+		return;
+	}
+
+	if (hdd_is_egap_enabled(hdd_ctx->green_ap_ctx->egap_support,
+			hdd_ctx->config))
+		return;
+
 	hdd_green_ap_mc(hdd_ctx, GREEN_AP_DEL_STA_EVENT);
 }
 

+ 12 - 0
core/hdd/src/wlan_hdd_green_ap.h

@@ -86,6 +86,14 @@ void hdd_green_ap_add_sta(struct hdd_context_s *hdd_ctx);
  */
 void hdd_green_ap_del_sta(struct hdd_context_s *hdd_ctx);
 
+/**
+ * hdd_enable_egap() - Enable Enhance Green AP
+ * @hdd_ctx: HDD global context
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int hdd_enable_egap(struct hdd_context_s *hdd_ctx);
+
 /**
  * hdd_green_ap_target_config() - Handle Green AP target configuration
  * @hdd_ctx: HDD global context where Green AP information is stored
@@ -105,6 +113,10 @@ static inline void hdd_green_ap_start_bss(struct hdd_context_s *hdd_ctx) {}
 static inline void hdd_green_ap_stop_bss(struct hdd_context_s *hdd_ctx) {}
 static inline void hdd_green_ap_add_sta(struct hdd_context_s *hdd_ctx) {}
 static inline void hdd_green_ap_del_sta(struct hdd_context_s *hdd_ctx) {}
+static inline int hdd_enable_egap(struct hdd_context_s *hdd_ctx)
+{
+	return -EINVAL;
+}
 static inline void hdd_green_ap_target_config(struct hdd_context_s *hdd_ctx,
 					      struct wma_tgt_cfg *target_config)
 {

+ 7 - 3
core/hdd/src/wlan_hdd_hostapd.c

@@ -1205,7 +1205,6 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
 						    operatingChannel);
 
 		pHostapdState->bssState = BSS_START;
-		hdd_green_ap_start_bss(pHddCtx);
 
 		/* Set default key index */
 		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
@@ -1313,8 +1312,6 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
 		hdd_hostapd_channel_allow_suspend(pHostapdAdapter,
 						  pHddApCtx->operatingChannel);
 
-		hdd_green_ap_stop_bss(pHddCtx);
-
 		/* Free up Channel List incase if it is set */
 		sap_cleanup_channel_list(
 			WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter));
@@ -7710,6 +7707,9 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy,
 	if (0 != ret)
 		return ret;
 
+	if (QDF_SAP_MODE == pAdapter->device_mode)
+		hdd_green_ap_stop_bss(pHddCtx);
+
 	status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
 	while (NULL != pAdapterNode && QDF_STATUS_SUCCESS == status) {
 		staAdapter = pAdapterNode->pAdapter;
@@ -8011,6 +8011,10 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
 			return -EINVAL;
 		}
 	}
+
+	if (QDF_SAP_MODE == pAdapter->device_mode)
+		hdd_green_ap_start_bss(pHddCtx);
+
 	if (pAdapter->device_mode == QDF_P2P_GO_MODE) {
 		hdd_adapter_t  *p2p_adapter;
 		p2p_adapter = hdd_get_adapter(pHddCtx, QDF_P2P_DEVICE_MODE);

+ 3 - 0
core/hdd/src/wlan_hdd_main.c

@@ -8124,6 +8124,9 @@ int hdd_wlan_startup(struct device *dev)
 	memdump_init();
 	hdd_driver_memdump_init();
 
+	if (hdd_enable_egap(hdd_ctx))
+		hdd_err("enhance green ap is not enabled");
+
 	if (hdd_ctx->config->fIsImpsEnabled)
 		hdd_set_idle_ps_config(hdd_ctx, true);