diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 17854d7e2a22..e374df2d353c 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -2128,6 +2128,12 @@ void wma_process_set_pdev_vht_ie_req(tp_wma_handle wma, void wma_remove_peer(tp_wma_handle wma, u_int8_t *bssid, u_int8_t vdev_id, ol_txrx_peer_handle peer, bool roam_synch_in_progress); + +QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma, + uint32_t vdev_id, + uint32_t bitmap, + bool enable); + #endif struct wma_ini_config *wma_get_ini_handle(tp_wma_handle wma_handle); WLAN_PHY_MODE wma_chan_phy_mode(u8 chan, enum phy_ch_width chan_width, diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index fdf3349504cf..8b92c7826877 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -70,6 +70,7 @@ #include "radar_filters.h" #include "wma_internal.h" #include "ol_txrx.h" +#include "wma_nan_datapath.h" #ifndef ARRAY_LENGTH #define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) @@ -2987,6 +2988,23 @@ int wma_wow_wakeup_host_event(void *handle, uint8_t *event, (uint8_t *)param_buf->wow_packet_buffer, sizeof(WMI_NAN_EVENTID_param_tlvs)); break; + case WOW_REASON_NAN_DATA: + WMA_LOGD(FL("Host woken up for NAN data path event from FW")); + if (param_buf->wow_packet_buffer) { + wow_buf_pkt_len = + *(uint32_t *)param_buf->wow_packet_buffer; + WMA_LOGD(FL("wow_packet_buffer dump")); + qdf_trace_hex_dump(QDF_MODULE_ID_WMA, + QDF_TRACE_LEVEL_DEBUG, + param_buf->wow_packet_buffer, + wow_buf_pkt_len); + wma_ndp_wow_event_callback(handle, + (param_buf->wow_packet_buffer + 4), + wow_buf_pkt_len); + } else { + WMA_LOGE(FL("wow_packet_buffer is empty")); + } + break; default: break; } @@ -3043,7 +3061,7 @@ static inline void wma_set_wow_bus_suspend(tp_wma_handle wma, int val) * * Return: QDF status */ -static QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma, +QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma, uint32_t vdev_id, uint32_t bitmap, bool enable) @@ -3385,6 +3403,13 @@ void wma_register_wow_wakeup_events(WMA_HANDLE handle, event_bitmap = WMA_WOW_SAP_WAKE_UP_EVENTS; WMA_LOGI("SAP specific default wake up event 0x%x vdev id %d", event_bitmap, vdev_id); + } else if (WMI_VDEV_TYPE_NDI == vdev_type) { + /* + * Configure NAN data path specific default wake up events. + * Following routine sends the command to firmware. + */ + wma_ndp_add_wow_wakeup_event(wma, vdev_id); + return; } else { WMA_LOGE("unknown type %d subtype %d", vdev_type, vdev_subtype); return; @@ -3963,6 +3988,9 @@ bool wma_is_p2plo_in_progress(tp_wma_handle wma, int vdev_id) * 3) Is PNO in progress in any one of vdev ? * 4) Is Extscan in progress in any one of vdev ? * 5) Is P2P listen offload in any one of vdev? + * 6) Is any vdev in NAN data mode? BSS is already started at the + * the time of device creation. It is ready to accept data + * requests. * If none of above conditions is true then return false * * Return: true if wma needs to configure wow false otherwise. @@ -3989,6 +4017,11 @@ bool wma_is_wow_applicable(tp_wma_handle wma) WMA_LOGD("P2P LO is in progress, enabling wow"); return true; } + if (WMA_IS_VDEV_IN_NDI_MODE(wma->interfaces, vdev_id)) { + WMA_LOGD("vdev %d is in NAN data mode, enabling wow", + vdev_id); + return true; + } } WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow"); diff --git a/core/wma/src/wma_nan_datapath.c b/core/wma/src/wma_nan_datapath.c index efd1ef2465a0..e77f93ccbb4f 100644 --- a/core/wma/src/wma_nan_datapath.c +++ b/core/wma/src/wma_nan_datapath.c @@ -255,6 +255,153 @@ void wma_ndp_unregister_all_event_handlers(tp_wma_handle wma_handle) WMI_NDP_END_INDICATION_EVENTID); } +/** + * wma_ndp_add_wow_wakeup_event() - Add Wake on Wireless event for NDP + * @wma_handle: WMA context + * @vdev_id: vdev id + * + * Enables the firmware to wake up the host on NAN data path event. + * All NDP events such as NDP_INDICATION, NDP_CONFIRM, etc. use the + * same event. They can be distinguished using their TLV tags. + * + * Return: none + */ +void wma_ndp_add_wow_wakeup_event(tp_wma_handle wma_handle, + uint8_t vdev_id) +{ + uint32_t event_bitmap; + event_bitmap = (1 << WOW_NAN_DATA_EVENT); + WMA_LOGI("NDI specific default wake up event 0x%x vdev id %d", + event_bitmap, vdev_id); + wma_add_wow_wakeup_event(wma_handle, vdev_id, event_bitmap, true); +} + +/** + * wma_ndp_get_eventid_from_tlvtag() - map tlv tag to event id + * @tag: WMI TLV tag + * + * map the tag to known NDP event fixed_param tags and return the + * corresponding NDP event id. + * + * Return: 0 if TLV tag is invalid + * else return corresponding WMI event id + */ +static int wma_ndp_get_eventid_from_tlvtag(uint32_t tag) +{ + uint32_t event_id; + + switch (tag) { + case WMITLV_TAG_STRUC_wmi_ndp_initiator_rsp_event_fixed_param: + event_id = WMI_NDP_INITIATOR_RSP_EVENTID; + break; + + case WMITLV_TAG_STRUC_wmi_ndp_responder_rsp_event_fixed_param: + event_id = WMI_NDP_RESPONDER_RSP_EVENTID; + break; + + case WMITLV_TAG_STRUC_wmi_ndp_end_rsp_event_fixed_param: + event_id = WMI_NDP_END_RSP_EVENTID; + break; + + case WMITLV_TAG_STRUC_wmi_ndp_indication_event_fixed_param: + event_id = WMI_NDP_INDICATION_EVENTID; + break; + + case WMITLV_TAG_STRUC_wmi_ndp_confirm_event_fixed_param: + event_id = WMI_NDP_CONFIRM_EVENTID; + break; + + case WMITLV_TAG_STRUC_wmi_ndp_end_indication_event_fixed_param: + event_id = WMI_NDP_END_INDICATION_EVENTID; + break; + + default: + event_id = 0; + WMA_LOGE(FL("Unknown tag: %d"), tag); + break; + } + + WMA_LOGI(FL("For tag %d WMI event 0x%x"), tag, event_id); + return event_id; +} + +/** + * wma_ndp_wow_event_callback() - NAN data path wow event callback + * @handle: WMA handle + * @event: event buffer + * @len: length of @event buffer + * + * The wow event WOW_REASON_NAN_DATA is followed by the payload of the event + * which generated the wow event. + * Payload is 4 bytes of length followed by event buffer. First 4 bytes + * of event buffer is common tlv header, which is a combination + * of tag (higher 2 bytes) and length (lower 2 bytes). The tag is used to + * identify the event which triggered wow event. + * + * Return: none + */ +void wma_ndp_wow_event_callback(void *handle, void *event, + uint32_t len) +{ + uint32_t id; + int tlv_ok_status = 0; + void *wmi_cmd_struct_ptr = NULL; + uint32_t tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(event)); + + /* Reverse map fixed params tag to EVENT_ID */ + id = wma_ndp_get_eventid_from_tlvtag(tag); + if (!id) { + WMA_LOGE(FL("Invalid Tag: %d"), tag); + return; + } + + tlv_ok_status = wmitlv_check_and_pad_event_tlvs(handle, event, len, + id, + &wmi_cmd_struct_ptr); + if (tlv_ok_status != 0) { + WMA_LOGE(FL("Invalid Tag: %d could not check and pad tlvs"), + tag); + return; + } + + switch (id) { + case WMI_NDP_INITIATOR_RSP_EVENTID: + wma_ndp_initiator_rsp_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + case WMI_NDP_RESPONDER_RSP_EVENTID: + wma_ndp_responder_rsp_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + case WMI_NDP_END_RSP_EVENTID: + wma_ndp_end_response_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + case WMI_NDP_INDICATION_EVENTID: + wma_ndp_indication_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + case WMI_NDP_CONFIRM_EVENTID: + wma_ndp_confirm_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + case WMI_NDP_END_INDICATION_EVENTID: + wma_ndp_end_indication_event_handler(handle, + wmi_cmd_struct_ptr, len); + break; + + default: + WMA_LOGE(FL("Unknown tag: %d"), tag); + break; + } + wmitlv_free_allocated_event_tlvs(id, &wmi_cmd_struct_ptr); +} + /** * wma_add_bss_ndi_mode() - Process BSS creation request while adding NaN * Data interface diff --git a/core/wma/src/wma_nan_datapath.h b/core/wma/src/wma_nan_datapath.h index 413f42024b04..b230a10d49c8 100644 --- a/core/wma/src/wma_nan_datapath.h +++ b/core/wma/src/wma_nan_datapath.h @@ -53,6 +53,9 @@ void wma_delete_all_nan_remote_peers(tp_wma_handle wma, void wma_ndp_register_all_event_handlers(tp_wma_handle wma_handle); void wma_ndp_unregister_all_event_handlers(tp_wma_handle wma_handle); +void wma_ndp_add_wow_wakeup_event(tp_wma_handle wma_handle, + uint8_t vdev_id); +void wma_ndp_wow_event_callback(void *handle, void *event, uint32_t len); #else #define WMA_IS_VDEV_IN_NDI_MODE(intf, vdev_id) (false) static inline void wma_update_hdd_cfg_ndp(tp_wma_handle wma_handle, @@ -73,5 +76,9 @@ static inline void wma_ndp_register_all_event_handlers( tp_wma_handle wma_handle) {} static inline void wma_ndp_unregister_all_event_handlers( tp_wma_handle wma_handle) {} +static inline void wma_ndp_add_wow_wakeup_event(tp_wma_handle wma_handle, + uint8_t vdev_id) {} +static inline void wma_ndp_wow_event_callback(void *handle, void *event, + uint32_t len) {} #endif /* WLAN_FEATURE_NAN_DATAPATH */ #endif /* __WMA_NAN_DATAPATH_H */