From 3cd2b7c56653267554764c3e513b6ef4c6843f4f Mon Sep 17 00:00:00 2001 From: Will Huang Date: Fri, 17 Nov 2017 13:16:56 +0800 Subject: [PATCH] qcacld-3.0: Enable D0WOW for pcie Enable FEATURE_WLAN_DOWOW for pcie. This is for backward compatible with rome fw. Change-Id: Ia2107ff6939666b4a0bd19d57149d17814f2dfb5 CRs-Fixed: 2070426 --- Kbuild | 7 ++++ .../pmo/core/src/wlan_pmo_suspend_resume.c | 1 + .../inc/wlan_pmo_common_public_struct.h | 2 + .../inc/wlan_pmo_obj_mgmt_public_struct.h | 6 +++ .../inc/wlan_pmo_wow_public_struct.h | 16 ++++++++ .../src/wlan_pmo_tgt_suspend_resume.c | 30 +++++++++++++- components/target_if/pmo/inc/target_if_pmo.h | 18 +++++++++ .../target_if/pmo/src/target_if_pmo_main.c | 4 ++ .../pmo/src/target_if_pmo_suspend_resume.c | 27 +++++++++++++ core/hdd/src/wlan_hdd_main.c | 2 + core/wma/inc/wma_api.h | 13 ++++++ core/wma/inc/wma_internal.h | 3 ++ core/wma/src/wma_features.c | 40 +++++++++++++++++++ core/wma/src/wma_main.c | 14 +++++++ 14 files changed, 181 insertions(+), 2 deletions(-) diff --git a/Kbuild b/Kbuild index 93968904d5ba..fc28afbec3b2 100644 --- a/Kbuild +++ b/Kbuild @@ -2197,6 +2197,13 @@ ifeq ($(CONFIG_NAN_CONVERGENCE), y) CDEFINES += -DWLAN_FEATURE_NAN_CONVERGENCE endif +#Flag to enable/disable WLAN D0-WOW +ifeq ($(CONFIG_PCI_MSM), y) +ifeq ($(CONFIG_ROME_IF),pci) +CDEFINES += -DFEATURE_WLAN_D0WOW +endif +endif + ifeq ($(CONFIG_LITHIUM),y) CDEFINES += -DCONFIG_SHADOW_V2 CDEFINES += -DQCA6290_HEADERS_DEF diff --git a/components/pmo/core/src/wlan_pmo_suspend_resume.c b/components/pmo/core/src/wlan_pmo_suspend_resume.c index 48e96d4f8aed..f43a55cc11b3 100644 --- a/components/pmo/core/src/wlan_pmo_suspend_resume.c +++ b/components/pmo/core/src/wlan_pmo_suspend_resume.c @@ -1110,6 +1110,7 @@ void pmo_core_psoc_wakeup_host_event_received(struct wlan_objmgr_psoc *psoc) } psoc_ctx = pmo_psoc_get_priv(psoc); + psoc_ctx->wow.wow_state = pmo_wow_state_none; qdf_event_set(&psoc_ctx->wow.target_resume); out: PMO_EXIT(); diff --git a/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h b/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h index 62e9cf5e92f6..2c2f39ec2329 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h @@ -271,6 +271,7 @@ enum pmo_auto_pwr_detect_failure_mode { * @enable_mc_list: true if psoc supports mc addr list else false * @active_mode_offload: true if psoc supports active mode offload else false * @ap_arpns_support: true if psoc supports arp ns for ap mode + * @d0_wow_supported: true if psoc supports D0 wow command * @max_wow_filters: maximum number of wow filter supported * @ra_ratelimit_enable: true when ra filtering ins eanbled else false * @ra_ratelimit_interval: ra packets interval @@ -298,6 +299,7 @@ struct pmo_psoc_cfg { bool enable_mc_list; bool active_mode_offload; bool ap_arpns_support; + bool d0_wow_supported; uint8_t max_wow_filters; bool ra_ratelimit_enable; uint16_t ra_ratelimit_interval; diff --git a/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h b/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h index 9e6762abb757..9b37e79f58db 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h @@ -102,6 +102,8 @@ int (*pmo_pld_auto_resume_cb)(void); * @psoc_get_runtime_pm_in_progress: fp to get runtime pm is in progress status * @psoc_send_host_wakeup_ind: fp tp send host wake indication to fwr * @psoc_send_target_resume_req: fp to send target resume request + * @psoc_send_d0wow_enable_req: fp to send D0 WOW enable request + * @psoc_send_d0wow_disable_req: fp to send D0 WOW disable request */ struct wlan_pmo_tx_ops { QDF_STATUS (*send_arp_offload_req)(struct wlan_objmgr_vdev *vdev, @@ -196,6 +198,10 @@ struct wlan_pmo_tx_ops { QDF_STATUS (*psoc_send_host_wakeup_ind)(struct wlan_objmgr_psoc *psoc); QDF_STATUS (*psoc_send_target_resume_req)( struct wlan_objmgr_psoc *psoc); + QDF_STATUS (*psoc_send_d0wow_enable_req)( + struct wlan_objmgr_psoc *psoc); + QDF_STATUS (*psoc_send_d0wow_disable_req)( + struct wlan_objmgr_psoc *psoc); }; diff --git a/components/pmo/dispatcher/inc/wlan_pmo_wow_public_struct.h b/components/pmo/dispatcher/inc/wlan_pmo_wow_public_struct.h index aa2c261d1bf5..bfc874975cc0 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_wow_public_struct.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_wow_public_struct.h @@ -173,11 +173,26 @@ enum pmo_wow_action_wakeup_opertion { pmo_action_wakeup_del_set, }; +/** + * enum pmo_wow_state: enumeration of wow state + * @pmo_wow_state_none: not in wow state + * @pmo_wow_state_legacy_d0: in d0 wow state trigger by legacy d0 wow command + * @pmo_wow_state_unified_d0: in d0 wow state trigger by unified wow command + * @pmo_wow_state_unified_d3: in d3 wow state trigger by unified wow command + */ +enum pmo_wow_state { + pmo_wow_state_none = 0, + pmo_wow_state_legacy_d0, + pmo_wow_state_unified_d0, + pmo_wow_state_unified_d3, +}; + /** * struct pmo_wow - store wow patterns * @wow_enable: wow enable/disable * @wow_enable_cmd_sent: is wow enable command sent to fw * @is_wow_bus_suspended: true if bus is suspended + * @wow_state: state of wow * @target_suspend: target suspend event * @target_resume: target resume event * @wow_nack: wow negative ack flag @@ -197,6 +212,7 @@ struct pmo_wow { bool wow_enable; bool wow_enable_cmd_sent; bool is_wow_bus_suspended; + enum pmo_wow_state wow_state; qdf_event_t target_suspend; qdf_event_t target_resume; int wow_nack; diff --git a/components/pmo/dispatcher/src/wlan_pmo_tgt_suspend_resume.c b/components/pmo/dispatcher/src/wlan_pmo_tgt_suspend_resume.c index 0108dfc97ea7..787ec9851f08 100644 --- a/components/pmo/dispatcher/src/wlan_pmo_tgt_suspend_resume.c +++ b/components/pmo/dispatcher/src/wlan_pmo_tgt_suspend_resume.c @@ -133,14 +133,28 @@ void pmo_tgt_update_target_suspend_flag(struct wlan_objmgr_psoc *psoc, QDF_STATUS pmo_tgt_psoc_send_wow_enable_req(struct wlan_objmgr_psoc *psoc, struct pmo_wow_cmd_params *param) { + struct pmo_psoc_priv_obj *psoc_ctx; struct wlan_pmo_tx_ops pmo_tx_ops; + psoc_ctx = pmo_psoc_get_priv(psoc); pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + + if (psoc_ctx->psoc_cfg.d0_wow_supported && !param->can_suspend_link) { + if (!pmo_tx_ops.psoc_send_d0wow_enable_req) { + pmo_err("psoc_send_d0wow_enable_req is null"); + return QDF_STATUS_E_NULL_VALUE; + } + psoc_ctx->wow.wow_state = pmo_wow_state_legacy_d0; + pmo_debug("Sending D0WOW enable command..."); + return pmo_tx_ops.psoc_send_d0wow_enable_req(psoc); + } + if (!pmo_tx_ops.psoc_send_wow_enable_req) { pmo_err("psoc_send_wow_enable_req is null"); return QDF_STATUS_E_NULL_VALUE; } - + psoc_ctx->wow.wow_state = param->can_suspend_link ? + pmo_wow_state_unified_d3 : pmo_wow_state_unified_d0; return pmo_tx_ops.psoc_send_wow_enable_req(psoc, param); } @@ -189,14 +203,26 @@ bool pmo_tgt_psoc_get_runtime_pm_in_progress(struct wlan_objmgr_psoc *psoc) QDF_STATUS pmo_tgt_psoc_send_host_wakeup_ind(struct wlan_objmgr_psoc *psoc) { + struct pmo_psoc_priv_obj *psoc_ctx; struct wlan_pmo_tx_ops pmo_tx_ops; + psoc_ctx = pmo_psoc_get_priv(psoc); pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + + if (psoc_ctx->psoc_cfg.d0_wow_supported && + psoc_ctx->wow.wow_state == pmo_wow_state_legacy_d0) { + if (!pmo_tx_ops.psoc_send_d0wow_disable_req) { + pmo_err("psoc_send_d0wow_disable_req is null"); + return QDF_STATUS_E_NULL_VALUE; + } + pmo_debug("Sending D0WOW disable command..."); + return pmo_tx_ops.psoc_send_d0wow_disable_req(psoc); + } + if (!pmo_tx_ops.psoc_send_host_wakeup_ind) { pmo_err("psoc_send_host_wakeup_ind is null"); return QDF_STATUS_E_NULL_VALUE; } - return pmo_tx_ops.psoc_send_host_wakeup_ind(psoc); } diff --git a/components/target_if/pmo/inc/target_if_pmo.h b/components/target_if/pmo/inc/target_if_pmo.h index 6d8aad59e6b5..d5b772c21549 100644 --- a/components/target_if/pmo/inc/target_if_pmo.h +++ b/components/target_if/pmo/inc/target_if_pmo.h @@ -432,6 +432,24 @@ QDF_STATUS target_if_pmo_psoc_send_host_wakeup_ind( QDF_STATUS target_if_pmo_psoc_send_target_resume_req( struct wlan_objmgr_psoc *psoc); +/** + * target_if_pmo_psoc_send_d0wow_enable_req() - send d0 wow enable request + * @psoc: objmgr psoc + * + * Return: return QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS target_if_pmo_psoc_send_d0wow_enable_req( + struct wlan_objmgr_psoc *psoc); + +/** + * target_if_pmo_psoc_send_d0wow_disable_req() - send d0 wow disable request + * @psoc: objmgr psoc + * + * Return: return QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS target_if_pmo_psoc_send_d0wow_disable_req( + struct wlan_objmgr_psoc *psoc); + /** * target_if_pmo_register_tx_ops() - Register PMO component TX OPS * @tx_ops: PMO if transmit ops diff --git a/components/target_if/pmo/src/target_if_pmo_main.c b/components/target_if/pmo/src/target_if_pmo_main.c index 636120999131..834f88f68829 100644 --- a/components/target_if/pmo/src/target_if_pmo_main.c +++ b/components/target_if/pmo/src/target_if_pmo_main.c @@ -99,6 +99,10 @@ void target_if_pmo_register_tx_ops(struct wlan_pmo_tx_ops *pmo_tx_ops) target_if_pmo_psoc_send_host_wakeup_ind; pmo_tx_ops->psoc_send_target_resume_req = target_if_pmo_psoc_send_target_resume_req; + pmo_tx_ops->psoc_send_d0wow_enable_req = + target_if_pmo_psoc_send_d0wow_enable_req; + pmo_tx_ops->psoc_send_d0wow_disable_req = + target_if_pmo_psoc_send_d0wow_disable_req; pmo_tx_ops->send_set_pkt_filter = target_if_pmo_send_pkt_filter_req; pmo_tx_ops->send_clear_pkt_filter = diff --git a/components/target_if/pmo/src/target_if_pmo_suspend_resume.c b/components/target_if/pmo/src/target_if_pmo_suspend_resume.c index fbbd638d8932..8378df3b4812 100644 --- a/components/target_if/pmo/src/target_if_pmo_suspend_resume.c +++ b/components/target_if/pmo/src/target_if_pmo_suspend_resume.c @@ -183,3 +183,30 @@ QDF_STATUS target_if_pmo_psoc_send_target_resume_req( TGT_WILDCARD_PDEV_ID); } +#ifdef FEATURE_WLAN_D0WOW +QDF_STATUS target_if_pmo_psoc_send_d0wow_enable_req( + struct wlan_objmgr_psoc *psoc) +{ + return wmi_unified_d0wow_enable_send(GET_WMI_HDL_FROM_PSOC(psoc), + TGT_WILDCARD_PDEV_ID); +} + +QDF_STATUS target_if_pmo_psoc_send_d0wow_disable_req( + struct wlan_objmgr_psoc *psoc) +{ + return wmi_unified_d0wow_disable_send(GET_WMI_HDL_FROM_PSOC(psoc), + TGT_WILDCARD_PDEV_ID); +} +#else +QDF_STATUS target_if_pmo_psoc_send_d0wow_enable_req( + struct wlan_objmgr_psoc *psoc) +{ + return QDF_STATUS_E_INVAL; +} + +QDF_STATUS target_if_pmo_psoc_send_d0wow_disable_req( + struct wlan_objmgr_psoc *psoc) +{ + return QDF_STATUS_E_INVAL; +} +#endif diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 2508cd7829ef..9568bac393a2 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -12152,6 +12152,7 @@ static inline void hdd_ra_populate_pmo_config( { } #endif + /** * hdd_update_pmo_config - API to update pmo configuration parameters * @hdd_ctx: HDD context @@ -12190,6 +12191,7 @@ static int hdd_update_pmo_config(struct hdd_context *hdd_ctx) psoc_cfg.active_mode_offload = hdd_ctx->config->active_mode_offload; psoc_cfg.ap_arpns_support = hdd_ctx->ap_arpns_support; + psoc_cfg.d0_wow_supported = wma_d0_wow_is_supported(); psoc_cfg.max_wow_filters = hdd_ctx->config->maxWoWFilters; psoc_cfg.sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM; psoc_cfg.sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM; diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index 2050bd76cdb7..63a490b5b114 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -301,6 +301,19 @@ QDF_STATUS wma_set_qpower_config(uint8_t vdev_id, uint8_t qpower); bool wma_is_service_enabled(WMI_SERVICE service_type); +#ifdef FEATURE_WLAN_D0WOW +static inline bool wma_d0_wow_is_supported(void) +{ + return wma_is_service_enabled(WMI_SERVICE_D0WOW) && + (!wma_is_service_enabled(WMI_SERVICE_UNIFIED_WOW_CAPABILITY)); +} +#else +static inline bool wma_d0_wow_is_supported(void) +{ + return false; +} +#endif + /** * wma_store_pdev() - store pdev * @wma_ctx: wma context diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index e02e4b6b72d4..da8285071dc2 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -972,6 +972,9 @@ QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle, int wma_wow_wakeup_host_event(void *handle, uint8_t *event, uint32_t len); + +int wma_d0_wow_disable_ack_event(void *handle, uint8_t *event, uint32_t len); + int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len); QDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info); diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 2885a9315d95..787f5b85b4ae 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -2803,6 +2803,46 @@ int wma_wow_wakeup_host_event(void *handle, uint8_t *event, uint32_t len) return errno; } +#ifdef FEATURE_WLAN_D0WOW +/** + * wma_d0_wow_disable_ack_event() - wakeup host event handler + * @handle: wma handle + * @event: event data + * @len: buffer length + * + * Handler to catch D0-WOW disable ACK event. This event will have + * reason why the firmware has woken the host. + * This is for backward compatible with cld2.0. + * + * Return: 0 for success or error + */ +int wma_d0_wow_disable_ack_event(void *handle, uint8_t *event, uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + WMI_D0_WOW_DISABLE_ACK_EVENTID_param_tlvs *param_buf; + wmi_d0_wow_disable_ack_event_fixed_param *resp_data; + + param_buf = (WMI_D0_WOW_DISABLE_ACK_EVENTID_param_tlvs *)event; + if (!param_buf) { + WMA_LOGE("Invalid D0-WOW disable ACK event buffer!"); + return -EINVAL; + } + + resp_data = param_buf->fixed_param; + + pmo_ucfg_psoc_wakeup_host_event_received(wma->psoc); + + WMA_LOGD("Received D0-WOW disable ACK"); + + return 0; +} +#else +int wma_d0_wow_disable_ack_event(void *handle, uint8_t *event, uint32_t len) +{ + return 0; +} +#endif + /** * wma_pdev_resume_event_handler() - PDEV resume event handler * @handle: wma handle diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index ffc708dd5d4e..a9c6e83ce3f4 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3534,6 +3534,20 @@ QDF_STATUS wma_start(void) goto end; } + if (wma_d0_wow_is_supported()) { + status = wmi_unified_register_event_handler( + wma_handle->wmi_handle, + WMI_D0_WOW_DISABLE_ACK_EVENTID, + wma_d0_wow_disable_ack_event, + WMA_RX_TASKLET_CTX); + if (status) { + WMA_LOGE("%s: Failed to register d0wow disable ack" + " event handler", __func__); + qdf_status = QDF_STATUS_E_FAILURE; + goto end; + } + } + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_PDEV_RESUME_EVENTID, wma_pdev_resume_event_handler,