Selaa lähdekoodia

qcacld-3.0: Provide wma runtime suspend resume apis

wma has to do some extra steps that were part of 802.11 suspend
for runtime suspend.

Change-Id: I91fbdcacd6c557f30e0d4f422324f2db67cb96dc
CRs-Fixed: 935300
Houston Hoffman 9 vuotta sitten
vanhempi
sitoutus
0c83a5b04c

+ 5 - 1
core/mac/src/include/sir_params.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -580,6 +580,10 @@ typedef struct sSirMbMsgP2p {
 #define SIR_HAL_ENABLE_UAPSD_REQ             (SIR_HAL_ITC_MSG_TYPES_BEGIN + 237)
 #define SIR_HAL_DISABLE_UAPSD_REQ            (SIR_HAL_ITC_MSG_TYPES_BEGIN + 238)
 #define SIR_HAL_GATEWAY_PARAM_UPDATE_REQ    (SIR_HAL_ITC_MSG_TYPES_BEGIN + 239)
+
+#define SIR_HAL_RUNTIME_PM_SUSPEND_IND	(SIR_HAL_ITC_MSG_TYPES_BEGIN + 308)
+#define SIR_HAL_RUNTIME_PM_RESUME_IND	(SIR_HAL_ITC_MSG_TYPES_BEGIN + 309)
+
 #define SIR_HAL_SET_EPNO_LIST_REQ          (SIR_HAL_ITC_MSG_TYPES_BEGIN + 313)
 #define SIR_HAL_SET_PASSPOINT_LIST_REQ     (SIR_HAL_ITC_MSG_TYPES_BEGIN + 316)
 #define SIR_HAL_RESET_PASSPOINT_LIST_REQ   (SIR_HAL_ITC_MSG_TYPES_BEGIN + 317)

+ 1 - 0
core/wma/inc/wma.h

@@ -1197,6 +1197,7 @@ typedef struct {
 	cdf_event_t wma_ready_event;
 	cdf_event_t wma_resume_event;
 	cdf_event_t target_suspend;
+	cdf_event_t runtime_suspend;
 	cdf_event_t recovery_event;
 	uint16_t max_station;
 	uint16_t max_bssid;

+ 4 - 2
core/wma/inc/wma_api.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -117,6 +117,8 @@ CDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId);
 CDF_STATUS wma_get_wcnss_software_version(void *p_cds_gctx,
 					  uint8_t *pVersion,
 					  uint32_t versionBufferSize);
+int wma_runtime_suspend(void);
+int wma_runtime_resume(void);
 int wma_bus_suspend(void);
 int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr);
 void wma_target_suspend_acknowledge(void *context);
@@ -124,7 +126,7 @@ int wma_bus_resume(void);
 int wma_resume_target(WMA_HANDLE handle);
 CDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle);
 CDF_STATUS wma_disable_d0wow_in_fw(WMA_HANDLE handle);
-int wma_is_wow_mode_selected(WMA_HANDLE handle);
+bool wma_is_wow_mode_selected(WMA_HANDLE handle);
 CDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle);
 CDF_STATUS wma_enable_d0wow_in_fw(WMA_HANDLE handle);
 bool wma_check_scan_in_progress(WMA_HANDLE handle);

+ 4 - 2
core/wma/inc/wma_internal.h

@@ -981,7 +981,7 @@ static inline int wma_get_wow_bus_suspend(tp_wma_handle wma)
 	return cdf_atomic_read(&wma->is_wow_bus_suspended);
 }
 
-CDF_STATUS wma_resume_req(tp_wma_handle wma);
+CDF_STATUS wma_resume_req(tp_wma_handle wma, enum cdf_suspend_type type);
 
 CDF_STATUS wma_wow_add_pattern(tp_wma_handle wma,
 			struct wow_add_pattern *ptrn);
@@ -993,7 +993,9 @@ 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);
+CDF_STATUS wma_suspend_req(tp_wma_handle wma, enum cdf_suspend_type type);
+void wma_calculate_and_update_conn_state(tp_wma_handle wma);
+void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask);
 void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask);
 
 void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg);

+ 3 - 0
core/wma/inc/wma_types.h

@@ -262,6 +262,9 @@
 #define WMA_WLAN_RESUME_REQ           SIR_HAL_WLAN_RESUME_REQ
 #define WMA_MSG_TYPES_END    SIR_HAL_MSG_TYPES_END
 
+#define WMA_RUNTIME_PM_SUSPEND_IND	SIR_HAL_RUNTIME_PM_SUSPEND_IND
+#define WMA_RUNTIME_PM_RESUME_IND	SIR_HAL_RUNTIME_PM_RESUME_IND
+
 #ifdef WLAN_FEATURE_VOWIFI_11R
 #define WMA_AGGR_QOS_REQ               SIR_HAL_AGGR_QOS_REQ
 #define WMA_AGGR_QOS_RSP               SIR_HAL_AGGR_QOS_RSP

+ 191 - 25
core/wma/src/wma_features.c

@@ -3632,17 +3632,20 @@ error:
 /**
  * wma_resume_req() - clear configured wow patterns in fw
  * @wma: wma handle
+ * @type: type of suspend
  *
  * Return: CDF status
  */
-CDF_STATUS wma_resume_req(tp_wma_handle wma)
+CDF_STATUS wma_resume_req(tp_wma_handle wma, enum cdf_suspend_type type)
 {
-	wma->no_of_resume_ind++;
+	if (type == CDF_SYSTEM_SUSPEND) {
+		wma->no_of_resume_ind++;
 
-	if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
-		return CDF_STATUS_SUCCESS;
+		if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
+			return CDF_STATUS_SUCCESS;
 
-	wma->no_of_resume_ind = 0;
+		wma->no_of_resume_ind = 0;
+	}
 
 	/* Reset the DTIM Parameters */
 	wma_set_resume_dtim(wma);
@@ -3887,6 +3890,23 @@ CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
 	return CDF_STATUS_SUCCESS;
 }
 
+/**
+ * wma_calculate_and_update_conn_state(): calculate each interfaces conn state
+ * @wma: validated wma handle
+ *
+ * Identifies any vdev that is up and not in ap mode as connected.
+ * stores this in the interfaces conn_state varible.
+ */
+void wma_calculate_and_update_conn_state(tp_wma_handle wma)
+{
+	int i;
+	for (i = 0; i < wma->max_bssid; i++) {
+		wma->interfaces[i].conn_state =
+			!!(wma->interfaces[i].vdev_up &&
+					!wma_is_vdev_in_ap_mode(wma, i));
+	}
+}
+
 /**
  * wma_update_conn_state(): synchronize wma & hdd
  * @wma: wma handle
@@ -4131,14 +4151,26 @@ void wma_apply_lphb(tp_wma_handle wma)
 void wma_apply_lphb(tp_wma_handle wma) {}
 #endif /* FEATURE_WLAN_LPHB */
 
+static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
+		enum cdf_suspend_type type)
+{
+	if (type == CDF_SYSTEM_SUSPEND)
+		wma_send_status_to_suspend_ind(wma, true);
+	else if (type == CDF_RUNTIME_SUSPEND)
+		cdf_event_set(&wma->runtime_suspend);
+}
+
 /**
  * wma_suspend_req() -  Handles suspend indication request received from umac.
  * @wma: wma handle
- * @info: suspend params
+ * @type: type of suspend
+ *
+ * The type controlls how we notify the indicator that the indication has
+ * been processed
  *
  * Return: CDF status
  */
-CDF_STATUS wma_suspend_req(tp_wma_handle wma)
+CDF_STATUS wma_suspend_req(tp_wma_handle wma, enum cdf_suspend_type type)
 {
 	if (wma_is_wow_applicable(wma)) {
 		WMA_LOGE("WOW Suspend");
@@ -4152,7 +4184,8 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma)
 
 	/* Set the Suspend DTIM Parameters */
 	wma_set_suspend_dtim(wma);
-	wma_send_status_to_suspend_ind(wma, true);
+
+	wma_notify_suspend_req_procesed(wma, type);
 
 	/* to handle race between hif_pci_suspend and
 	 * unpause/pause tx handler
@@ -4333,7 +4366,7 @@ bool static wma_is_nan_enabled(tp_wma_handle wma)
  *
  * Return: true is wow mode is needed else false
  */
-int wma_is_wow_mode_selected(WMA_HANDLE handle)
+bool wma_is_wow_mode_selected(WMA_HANDLE handle)
 {
 	tp_wma_handle wma = (tp_wma_handle) handle;
 
@@ -6256,13 +6289,69 @@ void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
 }
 
 /**
- * wma_bus_suspend() - handles bus suspend request from hdd
+ * wma_post_runtime_resume_msg() - post the resume request
+ * @handle: validated wma handle
  *
- * Calls the appropriate handler based on configuration and event
+ * request the MC thread unpaus the vdev and set resume dtim
+ *
+ * Return: cdf status of the mq post
+ */
+static CDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
+{
+	cds_msg_t resume_msg;
+
+	resume_msg.bodyptr = NULL;
+	resume_msg.type    = WMA_RUNTIME_PM_RESUME_IND;
+	return cds_mq_post_message(CDF_MODULE_ID_WMA, &resume_msg);
+}
+
+/**
+ * wma_post_runtime_suspend_msg() - post the suspend request
+ * @handle: validated wma handle
+ *
+ * Requests for offloads to be configured for runtime suspend
+ * on the MC thread
+ *
+ * Return CDF_STATUS_E_AGAIN in case of timeout or CDF_STATUS_SUCCESS
+ */
+static CDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
+{
+	cds_msg_t cds_msg;
+	CDF_STATUS cdf_status;
+	tp_wma_handle wma = (tp_wma_handle) handle;
+
+	cdf_event_reset(&wma->runtime_suspend);
+
+	cds_msg.bodyptr = NULL;
+	cds_msg.type    = WMA_RUNTIME_PM_SUSPEND_IND;
+	cdf_status = cds_mq_post_message(CDF_MODULE_ID_WMA, &cds_msg);
+
+	if (cdf_status != CDF_STATUS_SUCCESS)
+		goto failure;
+
+	if (cdf_wait_single_event(&wma->runtime_suspend,
+			WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
+			CDF_STATUS_SUCCESS) {
+		WMA_LOGE("Failed to get runtime suspend event");
+		goto failure;
+	}
+
+	return CDF_STATUS_SUCCESS;
+
+failure:
+	return CDF_STATUS_E_AGAIN;
+}
+
+/**
+ * __wma_bus_suspend(): handles bus suspend for wma
+ * @type: is this suspend part of runtime suspend or system suspend?
+ *
+ * Bails if a scan is in progress.
+ * Calls the appropriate handlers based on configuration and event.
  *
  * Return: 0 for success or error code
  */
-int wma_bus_suspend(void)
+static int __wma_bus_suspend(enum cdf_suspend_type type)
 {
 	WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA);
 	if (NULL == handle) {
@@ -6270,20 +6359,104 @@ int wma_bus_suspend(void)
 		return -EFAULT;
 	}
 
-	WMA_LOGE("%s: wow mode selected %d", __func__,
-	       wma_is_wow_mode_selected(handle));
-
 	if (wma_check_scan_in_progress(handle)) {
 		WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
 		return -EBUSY;
 	}
 
-	if (wma_is_wow_mode_selected(handle))
-		return cdf_status_to_os_return(wma_enable_wow_in_fw(handle));
+	if (type == CDF_RUNTIME_SUSPEND) {
+		CDF_STATUS status = wma_post_runtime_suspend_msg(handle);
+		if (status)
+			return cdf_status_to_os_return(status);
+	}
+
+	if (type == CDF_SYSTEM_SUSPEND)
+		WMA_LOGE("%s: wow mode selected %d", __func__,
+				wma_is_wow_mode_selected(handle));
+
+	if (wma_is_wow_mode_selected(handle)) {
+		CDF_STATUS status = wma_enable_wow_in_fw(handle);
+		return cdf_status_to_os_return(status);
+	}
 
 	return wma_suspend_target(handle, 0);
 }
 
+/**
+ * wma_runtime_suspend() - handles runtime suspend request from hdd
+ *
+ * Calls the appropriate handler based on configuration and event.
+ * Last busy marking should prevent race conditions between processing
+ * of asyncronous fw events and the running of runtime suspend.
+ * (eg. last busy marking should guarantee that any auth requests have
+ * been processed)
+ * Events comming from the host are not protected, but aren't expected
+ * to be an issue.
+ *
+ * Return: 0 for success or error code
+ */
+int wma_runtime_suspend(void)
+{
+	return __wma_bus_suspend(CDF_RUNTIME_SUSPEND);
+}
+
+/**
+ * wma_bus_suspend() - handles bus suspend request from hdd
+ *
+ * Calls the appropriate handler based on configuration and event
+ *
+ * Return: 0 for success or error code
+ */
+int wma_bus_suspend(void)
+{
+
+	return __wma_bus_suspend(CDF_RUNTIME_SUSPEND);
+}
+
+/**
+ * __wma_bus_resume() - bus resume for wma
+ *
+ * does the part of the bus resume common to bus and system suspend
+ *
+ * Return: os error code.
+ */
+int __wma_bus_resume(WMA_HANDLE handle)
+{
+	bool wow_mode = wma_is_wow_mode_selected(handle);
+	CDF_STATUS status;
+
+	WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
+
+	if (!wow_mode)
+		return wma_resume_target(handle);
+
+	status = wma_disable_wow_in_fw(handle);
+	return cdf_status_to_os_return(status);
+}
+
+/**
+ * wma_runtime_resume() - do the runtime resume operation for wma
+ *
+ * Return: os error code.
+ */
+int wma_runtime_resume(void)
+{
+	int ret;
+	CDF_STATUS status;
+	WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA);
+	if (NULL == handle) {
+		WMA_LOGE("%s: wma context is NULL", __func__);
+		return -EFAULT;
+	}
+
+	ret = __wma_bus_resume(handle);
+	if (ret)
+		return ret;
+
+	status = wma_post_runtime_resume_msg(handle);
+	return cdf_status_to_os_return(status);
+}
+
 /**
  * wma_bus_resume() - handles bus resume request from hdd
  * @handle: valid wma handle
@@ -6295,19 +6468,12 @@ int wma_bus_suspend(void)
 int wma_bus_resume(void)
 {
 	WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA);
-	int wow_mode;
 	if (NULL == handle) {
 		WMA_LOGE("%s: wma context is NULL", __func__);
 		return -EFAULT;
 	}
 
-	wow_mode = wma_is_wow_mode_selected(handle);
-	WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
-
-	if (!wow_mode)
-		return wma_resume_target(handle);
-
-	return cdf_status_to_os_return(wma_disable_wow_in_fw(handle));
+	return __wma_bus_resume(handle);
 }
 
 /**

+ 20 - 2
core/wma/src/wma_main.c

@@ -1766,6 +1766,13 @@ CDF_STATUS wma_open(void *cds_context,
 		goto err_event_init;
 	}
 
+	cdf_status = cdf_event_init(&wma_handle->runtime_suspend);
+	if (cdf_status != CDF_STATUS_SUCCESS) {
+		WMA_LOGP("%s: runtime_suspend event initialization failed",
+			 __func__);
+		goto err_event_init;
+	}
+
 	cdf_status = cdf_event_init(&wma_handle->recovery_event);
 	if (cdf_status != CDF_STATUS_SUCCESS) {
 		WMA_LOGP("%s: recovery event initialization failed", __func__);
@@ -3083,6 +3090,7 @@ CDF_STATUS wma_close(void *cds_ctx)
 
 	cdf_event_destroy(&wma_handle->target_suspend);
 	cdf_event_destroy(&wma_handle->wma_resume_event);
+	cdf_event_destroy(&wma_handle->runtime_suspend);
 	cdf_event_destroy(&wma_handle->recovery_event);
 	wma_cleanup_vdev_resp(wma_handle);
 	wma_cleanup_hold_req(wma_handle);
@@ -4874,9 +4882,19 @@ CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg)
 	case WMA_WOWL_EXIT_REQ:
 		wma_wow_exit(wma_handle, (tpSirHalWowlExitParams) msg->bodyptr);
 		break;
+
+	case WMA_RUNTIME_PM_SUSPEND_IND:
+		wma_calculate_and_update_conn_state(wma_handle);
+		wma_suspend_req(wma_handle, CDF_RUNTIME_SUSPEND);
+		break;
+
+	case WMA_RUNTIME_PM_RESUME_IND:
+		wma_resume_req(wma_handle, CDF_RUNTIME_SUSPEND);
+		break;
+
 	case WMA_WLAN_SUSPEND_IND:
 		wma_update_conn_state(wma_handle, msg->bodyval);
-		wma_suspend_req(wma_handle);
+		wma_suspend_req(wma_handle, CDF_SYSTEM_SUSPEND);
 		break;
 	case WMA_8023_MULTICAST_LIST_REQ:
 		wma_process_mcbc_set_filter_req(wma_handle,
@@ -5015,7 +5033,7 @@ CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg)
 		cdf_mem_free(msg->bodyptr);
 		break;
 	case WMA_WLAN_RESUME_REQ:
-		wma_resume_req(wma_handle);
+		wma_resume_req(wma_handle, CDF_SYSTEM_SUSPEND);
 		break;
 
 #ifdef WLAN_FEATURE_STATS_EXT