From d75a667472e277e16c3150d94e72a0adc44f317b Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Thu, 22 Jun 2017 15:40:53 +0530 Subject: [PATCH] qcacld-3.0: Move PMO from CMN to CLD Move PMO from CMN to CLD. Change-Id: I31380da668ac3305731b8c9906d343a829777591 CRs-fixed: 2071528 --- Kbuild | 43 +- core/components/pmo/core/inc/wlan_pmo_arp.h | 71 + core/components/pmo/core/inc/wlan_pmo_gtk.h | 74 + .../pmo/core/inc/wlan_pmo_hw_filter.h | 46 + core/components/pmo/core/inc/wlan_pmo_lphb.h | 51 + core/components/pmo/core/inc/wlan_pmo_main.h | 357 +++++ .../pmo/core/inc/wlan_pmo_mc_addr_filtering.h | 129 ++ core/components/pmo/core/inc/wlan_pmo_ns.h | 72 + .../components/pmo/core/inc/wlan_pmo_objmgr.h | 207 +++ .../pmo/core/inc/wlan_pmo_pkt_filter.h | 57 + core/components/pmo/core/inc/wlan_pmo_priv.h | 130 ++ .../pmo/core/inc/wlan_pmo_static_config.h | 117 ++ .../pmo/core/inc/wlan_pmo_suspend_resume.h | 437 ++++++ core/components/pmo/core/inc/wlan_pmo_wow.h | 605 ++++++++ core/components/pmo/core/src/wlan_pmo_arp.c | 368 +++++ core/components/pmo/core/src/wlan_pmo_gtk.c | 358 +++++ .../pmo/core/src/wlan_pmo_hw_filter.c | 96 ++ core/components/pmo/core/src/wlan_pmo_lphb.c | 243 ++++ core/components/pmo/core/src/wlan_pmo_main.c | 256 ++++ .../pmo/core/src/wlan_pmo_mc_addr_filtering.c | 616 +++++++++ core/components/pmo/core/src/wlan_pmo_ns.c | 454 ++++++ .../pmo/core/src/wlan_pmo_pkt_filter.c | 96 ++ .../pmo/core/src/wlan_pmo_static_config.c | 380 +++++ .../pmo/core/src/wlan_pmo_suspend_resume.c | 1225 +++++++++++++++++ core/components/pmo/core/src/wlan_pmo_wow.c | 350 +++++ .../inc/wlan_pmo_arp_public_struct.h | 58 + .../inc/wlan_pmo_common_public_struct.h | 298 ++++ .../inc/wlan_pmo_gtk_public_struct.h | 95 ++ .../inc/wlan_pmo_hw_filter_public_struct.h | 54 + .../inc/wlan_pmo_lphb_public_struct.h | 176 +++ ...wlan_pmo_mc_addr_filtering_public_struct.h | 60 + .../inc/wlan_pmo_ns_public_struct.h | 79 ++ .../dispatcher/inc/wlan_pmo_obj_mgmt_api.h | 241 ++++ .../inc/wlan_pmo_obj_mgmt_public_struct.h | 189 +++ .../inc/wlan_pmo_pkt_filter_public_struct.h | 141 ++ .../pmo/dispatcher/inc/wlan_pmo_tgt_api.h | 406 ++++++ .../pmo/dispatcher/inc/wlan_pmo_ucfg_api.h | 565 ++++++++ .../inc/wlan_pmo_wow_public_struct.h | 241 ++++ .../dispatcher/src/wlan_pmo_obj_mgmt_api.c | 761 ++++++++++ .../pmo/dispatcher/src/wlan_pmo_tgt_arp.c | 158 +++ .../pmo/dispatcher/src/wlan_pmo_tgt_gtk.c | 178 +++ .../dispatcher/src/wlan_pmo_tgt_hw_filter.c | 53 + .../pmo/dispatcher/src/wlan_pmo_tgt_lphb.c | 155 +++ .../src/wlan_pmo_tgt_mc_addr_filtering.c | 83 ++ .../pmo/dispatcher/src/wlan_pmo_tgt_ns.c | 159 +++ .../dispatcher/src/wlan_pmo_tgt_pkt_filter.c | 156 +++ .../src/wlan_pmo_tgt_static_config.c | 127 ++ .../src/wlan_pmo_tgt_suspend_resume.c | 215 +++ .../pmo/dispatcher/src/wlan_pmo_tgt_wow.c | 121 ++ .../pmo/dispatcher/src/wlan_pmo_ucfg_api.c | 342 +++++ .../target_if/pmo/inc/target_if_pmo.h | 407 ++++++ .../target_if/pmo/src/target_if_pmo_arp.c | 61 + .../target_if/pmo/src/target_if_pmo_gtk.c | 137 ++ .../pmo/src/target_if_pmo_hw_filter.c | 48 + .../target_if/pmo/src/target_if_pmo_lphb.c | 304 ++++ .../target_if/pmo/src/target_if_pmo_main.c | 100 ++ .../pmo/src/target_if_pmo_mc_addr_filtering.c | 91 ++ .../target_if/pmo/src/target_if_pmo_ns.c | 60 + .../pmo/src/target_if_pmo_pkt_filter.c | 97 ++ .../pmo/src/target_if_pmo_static_config.c | 113 ++ .../pmo/src/target_if_pmo_suspend_resume.c | 185 +++ .../target_if/pmo/src/target_if_pmo_wow.c | 114 ++ core/hdd/src/wlan_hdd_main.c | 26 + core/hdd/src/wlan_hdd_wext.c | 2 +- 64 files changed, 13675 insertions(+), 19 deletions(-) create mode 100644 core/components/pmo/core/inc/wlan_pmo_arp.h create mode 100644 core/components/pmo/core/inc/wlan_pmo_gtk.h create mode 100644 core/components/pmo/core/inc/wlan_pmo_hw_filter.h create mode 100644 core/components/pmo/core/inc/wlan_pmo_lphb.h create mode 100644 core/components/pmo/core/inc/wlan_pmo_main.h create mode 100644 core/components/pmo/core/inc/wlan_pmo_mc_addr_filtering.h create mode 100644 core/components/pmo/core/inc/wlan_pmo_ns.h create mode 100644 core/components/pmo/core/inc/wlan_pmo_objmgr.h create mode 100644 core/components/pmo/core/inc/wlan_pmo_pkt_filter.h create mode 100644 core/components/pmo/core/inc/wlan_pmo_priv.h create mode 100644 core/components/pmo/core/inc/wlan_pmo_static_config.h create mode 100644 core/components/pmo/core/inc/wlan_pmo_suspend_resume.h create mode 100644 core/components/pmo/core/inc/wlan_pmo_wow.h create mode 100644 core/components/pmo/core/src/wlan_pmo_arp.c create mode 100644 core/components/pmo/core/src/wlan_pmo_gtk.c create mode 100644 core/components/pmo/core/src/wlan_pmo_hw_filter.c create mode 100644 core/components/pmo/core/src/wlan_pmo_lphb.c create mode 100644 core/components/pmo/core/src/wlan_pmo_main.c create mode 100644 core/components/pmo/core/src/wlan_pmo_mc_addr_filtering.c create mode 100644 core/components/pmo/core/src/wlan_pmo_ns.c create mode 100644 core/components/pmo/core/src/wlan_pmo_pkt_filter.c create mode 100644 core/components/pmo/core/src/wlan_pmo_static_config.c create mode 100644 core/components/pmo/core/src/wlan_pmo_suspend_resume.c create mode 100644 core/components/pmo/core/src/wlan_pmo_wow.c create mode 100644 core/components/pmo/dispatcher/inc/wlan_pmo_arp_public_struct.h create mode 100644 core/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h create mode 100644 core/components/pmo/dispatcher/inc/wlan_pmo_gtk_public_struct.h create mode 100644 core/components/pmo/dispatcher/inc/wlan_pmo_hw_filter_public_struct.h create mode 100644 core/components/pmo/dispatcher/inc/wlan_pmo_lphb_public_struct.h create mode 100644 core/components/pmo/dispatcher/inc/wlan_pmo_mc_addr_filtering_public_struct.h create mode 100644 core/components/pmo/dispatcher/inc/wlan_pmo_ns_public_struct.h create mode 100644 core/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_api.h create mode 100644 core/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h create mode 100644 core/components/pmo/dispatcher/inc/wlan_pmo_pkt_filter_public_struct.h create mode 100644 core/components/pmo/dispatcher/inc/wlan_pmo_tgt_api.h create mode 100644 core/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h create mode 100644 core/components/pmo/dispatcher/inc/wlan_pmo_wow_public_struct.h create mode 100644 core/components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c create mode 100644 core/components/pmo/dispatcher/src/wlan_pmo_tgt_arp.c create mode 100644 core/components/pmo/dispatcher/src/wlan_pmo_tgt_gtk.c create mode 100644 core/components/pmo/dispatcher/src/wlan_pmo_tgt_hw_filter.c create mode 100644 core/components/pmo/dispatcher/src/wlan_pmo_tgt_lphb.c create mode 100644 core/components/pmo/dispatcher/src/wlan_pmo_tgt_mc_addr_filtering.c create mode 100644 core/components/pmo/dispatcher/src/wlan_pmo_tgt_ns.c create mode 100644 core/components/pmo/dispatcher/src/wlan_pmo_tgt_pkt_filter.c create mode 100644 core/components/pmo/dispatcher/src/wlan_pmo_tgt_static_config.c create mode 100644 core/components/pmo/dispatcher/src/wlan_pmo_tgt_suspend_resume.c create mode 100644 core/components/pmo/dispatcher/src/wlan_pmo_tgt_wow.c create mode 100644 core/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c create mode 100644 core/components/target_if/pmo/inc/target_if_pmo.h create mode 100644 core/components/target_if/pmo/src/target_if_pmo_arp.c create mode 100644 core/components/target_if/pmo/src/target_if_pmo_gtk.c create mode 100644 core/components/target_if/pmo/src/target_if_pmo_hw_filter.c create mode 100644 core/components/target_if/pmo/src/target_if_pmo_lphb.c create mode 100644 core/components/target_if/pmo/src/target_if_pmo_main.c create mode 100644 core/components/target_if/pmo/src/target_if_pmo_mc_addr_filtering.c create mode 100644 core/components/target_if/pmo/src/target_if_pmo_ns.c create mode 100644 core/components/target_if/pmo/src/target_if_pmo_pkt_filter.c create mode 100644 core/components/target_if/pmo/src/target_if_pmo_static_config.c create mode 100644 core/components/target_if/pmo/src/target_if_pmo_suspend_resume.c create mode 100644 core/components/target_if/pmo/src/target_if_pmo_wow.c diff --git a/Kbuild b/Kbuild index 335ba6061f81..fc4f0a715b5a 100644 --- a/Kbuild +++ b/Kbuild @@ -883,11 +883,11 @@ UMAC_MGMT_TXRX_OBJS := $(UMAC_MGMT_TXRX_DIR)/core/src/wlan_mgmt_txrx_main.o \ $(UMAC_MGMT_TXRX_DIR)/dispatcher/src/wlan_mgmt_txrx_tgt_api.o ########## POWER MANAGEMENT OFFLOADS (PMO) ########## -PMO_DIR := $(WLAN_COMMON_ROOT)/pmo -PMO_INC := -I$(WLAN_COMMON_INC)/pmo/core/inc \ - -I$(WLAN_COMMON_INC)/pmo/dispatcher/inc \ - -I$(WLAN_COMMON_INC)/pmo/core/src \ - -I$(WLAN_COMMON_INC)/pmo/dispatcher/src +PMO_DIR := core/components/pmo +PMO_INC := -I$(WLAN_ROOT)/$(PMO_DIR)/core/inc \ + -I$(WLAN_ROOT)/$(PMO_DIR)/core/src \ + -I$(WLAN_ROOT)/$(PMO_DIR)/dispatcher/inc \ + -I$(WLAN_ROOT)/$(PMO_DIR)/dispatcher/src \ PMO_OBJS := $(PMO_DIR)/core/src/wlan_pmo_main.o \ $(PMO_DIR)/core/src/wlan_pmo_arp.o \ @@ -913,6 +913,24 @@ PMO_OBJS := $(PMO_DIR)/core/src/wlan_pmo_main.o \ $(PMO_DIR)/dispatcher/src/wlan_pmo_tgt_hw_filter.o \ $(PMO_DIR)/dispatcher/src/wlan_pmo_tgt_pkt_filter.o +########## CLD TARGET_IF ####### +CLD_TARGET_IF_DIR := core/components/target_if + +CLD_TARGET_IF_INC := -I$(WLAN_ROOT)/$(CLD_TARGET_IF_DIR)/pmo/inc \ + -I$(WLAN_ROOT)/$(CLD_TARGET_IF_DIR)/pmo/src \ + +CLD_TARGET_IF_OBJ := $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_arp.o \ + $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_gtk.o \ + $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_hw_filter.o \ + $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_lphb.o \ + $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_main.o \ + $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_mc_addr_filtering.o \ + $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_ns.o \ + $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_pkt_filter.o \ + $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_static_config.o \ + $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_suspend_resume.o \ + $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_wow.o \ + ############## UMAC P2P ########### P2P_DIR := umac/p2p P2P_CORE_DIR := $(P2P_DIR)/core @@ -973,25 +991,12 @@ TARGET_IF_DIR := $(WLAN_COMMON_ROOT)/target_if TARGET_IF_INC := -I$(WLAN_COMMON_INC)/target_if/core/inc \ -I$(WLAN_COMMON_INC)/target_if/core/src \ -I$(WLAN_COMMON_INC)/target_if/init_deinit/inc \ - -I$(WLAN_COMMON_INC)/target_if/pmo/inc \ - -I$(WLAN_COMMON_INC)/target_if/pmo/src \ -I$(WLAN_COMMON_INC)/target_if/p2p/inc \ -I$(WLAN_COMMON_INC)/target_if/regulatory/inc \ -I$(WLAN_COMMON_INC)/target_if/tdls/inc TARGET_IF_OBJ := $(TARGET_IF_DIR)/core/src/target_if_main.o \ $(TARGET_IF_DIR)/init_deinit/src/service_ready_event_handler.o \ - $(TARGET_IF_DIR)/pmo/src/target_if_pmo_main.o \ - $(TARGET_IF_DIR)/pmo/src/target_if_pmo_arp.o \ - $(TARGET_IF_DIR)/pmo/src/target_if_pmo_ns.o \ - $(TARGET_IF_DIR)/pmo/src/target_if_pmo_gtk.o \ - $(TARGET_IF_DIR)/pmo/src/target_if_pmo_wow.o \ - $(TARGET_IF_DIR)/pmo/src/target_if_pmo_hw_filter.o \ - $(TARGET_IF_DIR)/pmo/src/target_if_pmo_mc_addr_filtering.o \ - $(TARGET_IF_DIR)/pmo/src/target_if_pmo_static_config.o \ - $(TARGET_IF_DIR)/pmo/src/target_if_pmo_lphb.o \ - $(TARGET_IF_DIR)/pmo/src/target_if_pmo_suspend_resume.o \ - $(TARGET_IF_DIR)/pmo/src/target_if_pmo_pkt_filter.o \ $(TARGET_IF_DIR)/p2p/src/target_if_p2p.o \ $(TARGET_IF_DIR)/regulatory/src/target_if_reg.o \ $(TARGET_IF_DIR)/tdls/src/target_if_tdls.o @@ -1415,6 +1420,7 @@ INCS := $(HDD_INC) \ $(CDS_INC) \ $(DFS_INC) \ $(TARGET_IF_INC) \ + $(CLD_TARGET_IF_INC) \ $(OS_IF_INC) \ $(GLOBAL_LMAC_IF_INC) @@ -1507,6 +1513,7 @@ OBJS += $(HIF_OBJS) \ $(HTT_OBJS) \ $(OS_IF_OBJ) \ $(TARGET_IF_OBJ) \ + $(CLD_TARGET_IF_OBJ) \ $(GLOBAL_LMAC_IF_OBJ) ifeq ($(CONFIG_LITHIUM), y) diff --git a/core/components/pmo/core/inc/wlan_pmo_arp.h b/core/components/pmo/core/inc/wlan_pmo_arp.h new file mode 100644 index 000000000000..8d97eec6cddf --- /dev/null +++ b/core/components/pmo/core/inc/wlan_pmo_arp.h @@ -0,0 +1,71 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Declare arp offload feature API's + */ + +#ifndef _WLAN_PMO_ARP_H_ +#define _WLAN_PMO_ARP_H_ + +#include "wlan_pmo_arp_public_struct.h" + +/** + * pmo_core_cache_arp_offload_req() - API to cache arp req in pmo vdev priv ctx + * @arp_req: arp offload request + * + * API To cache ARP offload in pmo vdev priv ctx + * + * Return: QDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_core_cache_arp_offload_req(struct pmo_arp_req *arp_req); + +/** + * pmo_core_flush_arp_offload_req() - API to flush arp req from pmo vdev ctx + * @vdev: objmgr vdev + * + * API To flush saved ARP request from pmo vdev prov ctx + * + * Return: QDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_core_flush_arp_offload_req(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_core_enable_arp_offload_in_fwr() - API to enable arp offload in fwr + * @vdev: objmgr vdev + * @trigger: trigger reason + * + * API to enable arp offload in fwr from vdev priv ctx + * + * Return: QDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_core_enable_arp_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger); + +/** + * pmo_core_disable_arp_offload_in_fwr() - API to disable arp offload in fwr + * @vdev: objmgr vdev + * @trigger: trigger reason + * + * API to disable arp offload in fwr + * + * Return: QQDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_core_disable_arp_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger); + +#endif /* end of _WLAN_PMO_ARP_H_ */ diff --git a/core/components/pmo/core/inc/wlan_pmo_gtk.h b/core/components/pmo/core/inc/wlan_pmo_gtk.h new file mode 100644 index 000000000000..2a9d9f54ae1b --- /dev/null +++ b/core/components/pmo/core/inc/wlan_pmo_gtk.h @@ -0,0 +1,74 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Declare gtk offload feature API's + */ + +#ifndef _WLAN_PMO_GTK_H_ +#define _WLAN_PMO_GTK_H_ + +#include "wlan_pmo_gtk_public_struct.h" + +/** + * pmo_core_cache_gtk_offload_req(): API to cache gtk req in pmo vdev priv obj + * @vdev: objmgr vdev handle + * @gtk_req: pmo gtk req param + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_core_cache_gtk_offload_req(struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_req *gtk_req); + +/** + * pmo_core_flush_gtk_offload_req(): Flush saved gtk req from pmo vdev priv obj + * @vdev: objmgr vdev handle + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_core_flush_gtk_offload_req(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_core_enable_gtk_offload_in_fwr(): enable cached gtk request in fwr + * @vdev: objmgr vdev handle + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_core_enable_gtk_offload_in_fwr(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_core_disable_gtk_offload_in_fwr(): disable cached gtk request in fwr + * @vdev: objmgr vdev handle + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_core_disable_gtk_offload_in_fwr(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_core_get_gtk_rsp(): API to send gtk response request to fwr + * @vdev: objmgr vdev handle + * @gtk_rsp: pmo gtk response request + * + * This api will send gtk response request to fwr + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_core_get_gtk_rsp(struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_rsp_req *gtk_rsp_req); + +#endif /* end of _WLAN_PMO_GTK_H_ */ + diff --git a/core/components/pmo/core/inc/wlan_pmo_hw_filter.h b/core/components/pmo/core/inc/wlan_pmo_hw_filter.h new file mode 100644 index 000000000000..c3cab641eade --- /dev/null +++ b/core/components/pmo/core/inc/wlan_pmo_hw_filter.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: Declare hardware filter offload feature APIs + */ + +#ifndef _WLAN_PMO_HW_FILTER_H_ +#define _WLAN_PMO_HW_FILTER_H_ + +#include "qdf_status.h" +#include "wlan_objmgr_vdev_obj.h" +#include "wlan_pmo_hw_filter_public_struct.h" + +/** + * pmo_core_enable_hw_filter_in_fwr() - enable previously configured hw filter + * @vdev: objmgr vdev to configure + * + * Return: QDF_STATUS + */ +QDF_STATUS pmo_core_enable_hw_filter_in_fwr(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_core_disable_hw_filter_in_fwr() - disable previously configured hw filter + * @vdev: objmgr vdev to configure + * + * Return: QDF_STATUS + */ +QDF_STATUS pmo_core_disable_hw_filter_in_fwr(struct wlan_objmgr_vdev *vdev); + +#endif /* _WLAN_PMO_HW_FILTER_H_*/ diff --git a/core/components/pmo/core/inc/wlan_pmo_lphb.h b/core/components/pmo/core/inc/wlan_pmo_lphb.h new file mode 100644 index 000000000000..20b6952ec5bb --- /dev/null +++ b/core/components/pmo/core/inc/wlan_pmo_lphb.h @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Declare low power heart beat offload feature API's + */ + +#ifndef _WLAN_PMO_LPHB_H_ +#define _WLAN_PMO_LPHB_H_ + +#include "wlan_pmo_lphb_public_struct.h" + +/** + * pmo_core_lphb_config_req() - API to configure lphb request + * @psoc: objmgr psoc handle + * @lphb_req: low power heart beat configuration request + * @lphb_cb_ctx: low power heart beat context + * @callback: osif callback which need to be called when host get lphb event + * + * API to configure lphb request + * + * Return: QDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_core_lphb_config_req(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_req *lphb_req, void *lphb_cb_ctx, + pmo_lphb_callback callback); + +/** + * pmo_core_apply_lphb(): apply cached LPHB settings + * @psoc: objmgr psoc handle + * + * LPHB cache, if any item was enabled, should be + * applied. + */ +void pmo_core_apply_lphb(struct wlan_objmgr_psoc *psoc); + +#endif /* end of _WLAN_PMO_LPHB_H_ */ diff --git a/core/components/pmo/core/inc/wlan_pmo_main.h b/core/components/pmo/core/inc/wlan_pmo_main.h new file mode 100644 index 000000000000..4f095977a96f --- /dev/null +++ b/core/components/pmo/core/inc/wlan_pmo_main.h @@ -0,0 +1,357 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: declare various api which shall be used by + * pmo user configuration and target interface + */ + +#ifndef _WLAN_PMO_MAIN_H_ +#define _WLAN_PMO_MAIN_H_ + +#include "wlan_pmo_common_public_struct.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" +#include "wlan_pmo_priv.h" +#include "wlan_pmo_objmgr.h" + +#define pmo_log(level, args...) QDF_TRACE(QDF_MODULE_ID_PMO, level, ## args) +#define pmo_logfl(level, format, args...) pmo_log(level, FL(format), ## args) + +#define pmo_fatal(format, args...) \ + pmo_logfl(QDF_TRACE_LEVEL_FATAL, format, ## args) +#define pmo_err(format, args...) \ + pmo_logfl(QDF_TRACE_LEVEL_ERROR, format, ## args) +#define pmo_warn(format, args...) \ + pmo_logfl(QDF_TRACE_LEVEL_WARN, format, ## args) +#define pmo_info(format, args...) \ + pmo_logfl(QDF_TRACE_LEVEL_INFO, format, ## args) +#define pmo_debug(format, args...) \ + pmo_logfl(QDF_TRACE_LEVEL_DEBUG, format, ## args) + +#define PMO_ENTER() pmo_debug("enter") +#define PMO_EXIT() pmo_debug("exit") + +#define PMO_VDEV_IN_STA_MODE(mode) \ + ((mode) == QDF_STA_MODE || (mode) == QDF_P2P_CLIENT_MODE ? 1 : 0) + +static inline enum tQDF_ADAPTER_MODE pmo_get_vdev_opmode( + struct wlan_objmgr_vdev *vdev) +{ + enum tQDF_ADAPTER_MODE opmode; + + opmode = wlan_vdev_mlme_get_opmode(vdev); + + return opmode; +} + +/** + * pmo_allocate_ctx() - Api to allocate pmo ctx + * + * Helper function to allocate pmo ctx + * + * Return: Success or failure. + */ +QDF_STATUS pmo_allocate_ctx(void); + +/** + * pmo_free_ctx() - to free pmo context + * + * Helper function to free pmo context + * + * Return: None. + */ +void pmo_free_ctx(void); + +/** + * pmo_get_context() - to get pmo context + * + * Helper function to get pmo context + * + * Return: pmo context. + */ +struct wlan_pmo_ctx *pmo_get_context(void); + +/** + * pmo_get_vdev_bss_peer_mac_addr() - API to get bss peer mac address + * @vdev: objmgr vdev + * @bss_peer_mac_address: bss peer mac address + *. + * Helper function to get bss peer mac address + * + * Return: if success pmo vdev ctx else NULL + */ +QDF_STATUS pmo_get_vdev_bss_peer_mac_addr(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *bss_peer_mac_address); + +/** + * pmo_is_vdev_in_beaconning_mode() - check if vdev is in a beaconning mode + * @vdev_opmode: vdev opmode + * + * Helper function to know whether given vdev + * is in a beaconning mode or not. + * + * Return: True if vdev needs to beacon. + */ +bool pmo_is_vdev_in_beaconning_mode(enum tQDF_ADAPTER_MODE vdev_opmode); + +/** + * pmo_core_is_ap_mode_supports_arp_ns() - To check ap mode supports arp/ns + * @vdev_opmode: vdev opmode + * + * API to check if ap mode supports arp/ns offload + * + * Return: True if ap mode supports arp/ns offload + */ + +bool pmo_core_is_ap_mode_supports_arp_ns(struct wlan_objmgr_psoc *psoc, + enum tQDF_ADAPTER_MODE vdev_opmode); + +/** + * pmo_core_is_vdev_connected() - to check whether peer is associated or not + * @vdev: objmgr vdev + * + * Return: true in case success else false + */ +bool pmo_core_is_vdev_connected(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_core_is_vdev_supports_offload() - Check offload is supported on vdev + * @vdev: objmgr vdev + * + * Return: true in case success else false + */ +bool pmo_core_is_vdev_supports_offload(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_core_get_psoc_config(): API to get the psoc user configurations of pmo + * @psoc: objmgr psoc handle + * @psoc_cfg: fill the current psoc user configurations. + * + * Return pmo psoc configurations + */ +QDF_STATUS pmo_core_get_psoc_config(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_cfg *psoc_cfg); + +/** + * pmo_core_update_psoc_config(): API to update the psoc user configurations + * @psoc: objmgr psoc handle + * @psoc_cfg: pmo psoc configurations + * + * This api shall be used for soc config initialization as well update. + * In case of update caller must first call pmo_get_psoc_cfg to get + * current config and then apply changes on top of current config. + * + * Return QDF_STATUS -in case of success else return error + */ +QDF_STATUS pmo_core_update_psoc_config(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_cfg *psoc_cfg); + + +/** + * pmo_core_get_vdev_op_mode(): API to get the vdev operation mode + * @vdev: objmgr vdev handle + * + * API to get the vdev operation mode + * + * Return QDF_MAX_NO_OF_MODE - in case of error else return vdev opmode + */ +static inline enum tQDF_ADAPTER_MODE pmo_core_get_vdev_op_mode( + struct wlan_objmgr_vdev *vdev) +{ + enum tQDF_ADAPTER_MODE op_mode = QDF_MAX_NO_OF_MODE; + + if (!vdev) + return op_mode; + op_mode = wlan_vdev_mlme_get_opmode(vdev); + + return op_mode; +} + +/** + * pmo_core_psoc_update_dp_handle() - update psoc data path handle + * @psoc: objmgr psoc handle + * @dp_hdl: psoc data path handle + * + * Return: None + */ +static inline +void pmo_core_psoc_update_dp_handle(struct wlan_objmgr_psoc *psoc, + void *dp_hdl) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->dp_hdl = dp_hdl; + qdf_spin_unlock_bh(&psoc_ctx->lock); +} + +/** + * pmo_core_psoc_get_dp_handle() - Get psoc data path handle + * @psoc: objmgr psoc handle + * + * Return: psoc data path handle + */ +static inline +void *pmo_core_psoc_get_dp_handle(struct wlan_objmgr_psoc *psoc) +{ + void *dp_hdl; + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + dp_hdl = psoc_ctx->dp_hdl; + qdf_spin_unlock_bh(&psoc_ctx->lock); + + return dp_hdl; +} + +/** + * pmo_core_vdev_update_dp_handle() - update vdev data path handle + * @vdev: objmgr vdev handle + * @dp_hdl: Vdev data path handle + * + * Return: None + */ +static inline +void pmo_core_vdev_update_dp_handle(struct wlan_objmgr_vdev *vdev, + void *dp_hdl) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->vdev_dp_hdl = dp_hdl; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +} + +/** + * pmo_core_vdev_get_dp_handle() - Get vdev data path handle + * @vdev: objmgr vdev handle + * + * Return: Vdev data path handle + */ +static inline +void *pmo_core_vdev_get_dp_handle(struct wlan_objmgr_vdev *vdev) +{ + void *dp_hdl; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + dp_hdl = vdev_ctx->vdev_dp_hdl; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return dp_hdl; +} + +/** + * pmo_core_psoc_update_htc_handle() - update psoc htc layer handle + * @psoc: objmgr psoc handle + * @htc_hdl: psoc htc layer handle + * + * Return: None + */ +static inline +void pmo_core_psoc_update_htc_handle(struct wlan_objmgr_psoc *psoc, + void *htc_hdl) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->htc_hdl = htc_hdl; + qdf_spin_unlock_bh(&psoc_ctx->lock); +} + +/** + * pmo_core_psoc_get_htc_handle() - Get psoc htc layer handle + * @psoc: objmgr psoc handle + * + * Return: psoc htc layer handle + */ +static inline +void *pmo_core_psoc_get_htc_handle(struct wlan_objmgr_psoc *psoc) +{ + void *htc_hdl; + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + htc_hdl = psoc_ctx->htc_hdl; + qdf_spin_unlock_bh(&psoc_ctx->lock); + + return htc_hdl; +} + +/** + * pmo_core_psoc_set_hif_handle() - update psoc hif layer handle + * @psoc: objmgr psoc handle + * @hif_hdl: hif context handle + * + * Return: None + */ +void pmo_core_psoc_set_hif_handle(struct wlan_objmgr_psoc *psoc, + void *hif_hdl); + +/** + * pmo_core_psoc_get_hif_handle() - Get psoc hif layer handle + * @psoc: objmgr psoc handle + * + * Return: psoc hif layer handle + */ +void *pmo_core_psoc_get_hif_handle(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_core_psoc_set_txrx_handle() - update psoc pdev txrx layer handle + * @psoc: objmgr psoc handle + * @txrx_hdl: pdev txrx context handle + * + * Return: None + */ +void pmo_core_psoc_set_txrx_handle(struct wlan_objmgr_psoc *psoc, + void *txrx_hdl); + +/** + * pmo_core_psoc_get_txrx_handle() - Get psoc pdev txrx handle + * @psoc: objmgr psoc handle + * + * Return: pdev txrx handle + */ +void *pmo_core_psoc_get_txrx_handle(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_is_vdev_up() - API to check whether vdev is UP + * @vdev: objmgr vdev handle + * + * Return:true if vdev is up else false + */ +static inline +bool pmo_is_vdev_up(struct wlan_objmgr_vdev *vdev) +{ + enum wlan_vdev_state state = WLAN_VDEV_S_INIT; + + if (!vdev) { + pmo_err("vdev context is invalid!"); + return false; + } + state = wlan_vdev_mlme_get_state(vdev); + + return state == WLAN_VDEV_S_RUN; +} + +#endif /* end of _WLAN_PMO_MAIN_H_ */ diff --git a/core/components/pmo/core/inc/wlan_pmo_mc_addr_filtering.h b/core/components/pmo/core/inc/wlan_pmo_mc_addr_filtering.h new file mode 100644 index 000000000000..ddedb6403651 --- /dev/null +++ b/core/components/pmo/core/inc/wlan_pmo_mc_addr_filtering.h @@ -0,0 +1,129 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Declare mc addr filtering offload feature API's + */ + +#ifndef _WLAN_PMO_MC_ADDR_FILTERING_H_ +#define _WLAN_PMO_MC_ADDR_FILTERING_H_ + +#include "wlan_pmo_common_public_struct.h" +#include "wlan_pmo_mc_addr_filtering_public_struct.h" + +/** + * pmo_core_set_mc_filter_req() -send mc filter set request + * @vdev: objmgr vdev + * @mc_list: a list of mc addresses to set in fwr + * + * Return: QDF_STATUS_SUCCESS in success else error codes + */ +QDF_STATUS pmo_core_set_mc_filter_req(struct wlan_objmgr_vdev *vdev, + struct pmo_mc_addr_list *mc_list); + +/** + * pmo_clear_mc_filter_req() -send mc filter clear request + * @vdev: objmgr vdev + * @mc_list: a list of mc addresses to clear in fwr + * + * Return: QDF_STATUS_SUCCESS in success else error codes + */ +QDF_STATUS pmo_core_clear_mc_filter_req(struct wlan_objmgr_vdev *vdev, + struct pmo_mc_addr_list *mc_list); + +/** + * pmo_core_cache_mc_addr_list(): API to cache mc addr list in pmo vdev priv obj + * @psoc: objmgr psoc handle + * @vdev_id: vdev id + * @gtk_req: pmo gtk req param + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_core_cache_mc_addr_list( + struct pmo_mc_addr_list_params *mc_list_config); + +/** + * pmo_core_flush_mc_addr_list(): API to flush mc addr list in pmo vdev priv obj + * @psoc: objmgr psoc handle + * @vdev_id: vdev id + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_core_flush_mc_addr_list(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); + +/** + * pmo_core_enable_mc_addr_filtering_in_fwr(): Enable cached mc add list in fwr + * @psoc: objmgr psoc handle + * @vdev_id: vdev id + * @gtk_req: pmo gtk req param + * @action: true for enable els false + * + * API to enable cached mc add list in fwr + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_core_enable_mc_addr_filtering_in_fwr( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum pmo_offload_trigger trigger); + +/** + * pmo_core_disable_mc_addr_filtering_in_fwr(): Disable cached mc addr list + * @psoc: objmgr psoc handle + * @vdev_id: vdev id + * @gtk_req: pmo gtk req param + * @action: true for enable els false + * + * API to disable cached mc add list in fwr + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_core_disable_mc_addr_filtering_in_fwr( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum pmo_offload_trigger trigger); + +/** + * pmo_core_get_mc_addr_list_count() -set mc address count + * @psoc: objmgr psoc + * @vdev_id: vdev id + * + * Return: set mc address count + */ +void pmo_core_set_mc_addr_list_count(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, uint8_t count); + +/** + * pmo_core_get_mc_addr_list_count() -get current mc address count + * @psoc: objmgr psoc + * @vdev_id: vdev id + * + * Return: current mc address count + */ +int pmo_core_get_mc_addr_list_count(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); + +/** + * pmo_core_max_mc_addr_supported() -get max supported mc addresses + * @psoc: objmgr psoc + * + * Return: max supported mc addresses + */ +uint8_t pmo_core_max_mc_addr_supported(struct wlan_objmgr_psoc *psoc); + +#endif /* end of _WLAN_PMO_MC_ADDR_FILTERING_H_ */ diff --git a/core/components/pmo/core/inc/wlan_pmo_ns.h b/core/components/pmo/core/inc/wlan_pmo_ns.h new file mode 100644 index 000000000000..de30ba9b2630 --- /dev/null +++ b/core/components/pmo/core/inc/wlan_pmo_ns.h @@ -0,0 +1,72 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Declare ns offload feature API's + */ + +#ifndef _WLAN_PMO_NS_H_ +#define _WLAN_PMO_NS_H_ + +#include "wlan_pmo_common_public_struct.h" +#include "wlan_pmo_ns_public_struct.h" + +/** + * pmo_core_cache_ns_offload_req() - API to cache ns req in pmo vdev priv ctx + * @ns_req: ns offload request + * + * API to cache ns offload in pmo vdev priv ctx + * + * Return:QDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_core_cache_ns_offload_req(struct pmo_ns_req *ns_req); + +/** + * pmo_core_flush_ns_offload_req() - API to flush ns req from pmo vdev priv ctx + * @vdev: vdev objmgr handle + * + * API to flush ns offload from pmo vdev priv ctx + * + * Return: QDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_core_flush_ns_offload_req(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_core_enable_ns_offload_in_fwr() - API to enable ns offload in fwr + * @vdev: objmgr vdev + * @trigger: trigger reason enable ns offload + * + * API to enable ns offload in fwr from vdev priv ctx + * + * Return: QDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_core_enable_ns_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger); + +/** + * pmo_core_disable_ns_offload_in_fwr() - API to disable ns offload in fwr + * @vdev: objmgr vdev + * @trigger: trigger reason disable ns offload + * + * API to disable arp offload in fwr + * + * Return: QDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_core_disable_ns_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger); + +#endif /* end of _WLAN_PMO_NS_H_ */ diff --git a/core/components/pmo/core/inc/wlan_pmo_objmgr.h b/core/components/pmo/core/inc/wlan_pmo_objmgr.h new file mode 100644 index 000000000000..10b98894cc29 --- /dev/null +++ b/core/components/pmo/core/inc/wlan_pmo_objmgr.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: This file contains various object manager related wrappers and helpers + */ + +#ifndef _WLAN_PMO_OBJMGR_H +#define _WLAN_PMO_OBJMGR_H + +#include "wlan_cmn.h" +#include "wlan_objmgr_cmn.h" +#include "wlan_objmgr_peer_obj.h" +#include "wlan_objmgr_vdev_obj.h" +#include "wlan_objmgr_pdev_obj.h" +#include "wlan_objmgr_psoc_obj.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" + +/* Get/Put Ref */ + +#define pmo_peer_get_ref(peer) wlan_objmgr_peer_try_get_ref(peer, WLAN_PMO_ID) +#define pmo_peer_put_ref(peer) wlan_objmgr_peer_release_ref(peer, WLAN_PMO_ID) + +#define pmo_vdev_get_ref(vdev) wlan_objmgr_vdev_try_get_ref(vdev, WLAN_PMO_ID) +#define pmo_vdev_put_ref(vdev) wlan_objmgr_vdev_release_ref(vdev, WLAN_PMO_ID) + +#define pmo_pdev_get_ref(pdev) wlan_objmgr_pdev_try_get_ref(pdev, WLAN_PMO_ID) +#define pmo_pdev_put_ref(pdev) wlan_objmgr_pdev_release_ref(pdev, WLAN_PMO_ID) + +#define pmo_psoc_get_ref(psoc) wlan_objmgr_psoc_try_get_ref(psoc, WLAN_PMO_ID) +#define pmo_psoc_put_ref(psoc) wlan_objmgr_psoc_release_ref(psoc, WLAN_PMO_ID) + +/* Private Data */ + +#define pmo_vdev_get_priv_nolock(vdev) \ + wlan_objmgr_vdev_get_comp_private_obj(vdev, WLAN_UMAC_COMP_PMO) +#define pmo_psoc_get_priv_nolock(psoc) \ + wlan_objmgr_psoc_get_comp_private_obj(psoc, WLAN_UMAC_COMP_PMO) + +/* Ids */ + +static inline uint8_t +pmo_vdev_get_id(struct wlan_objmgr_vdev *vdev) +{ + uint8_t vdev_id; + + vdev_id = wlan_vdev_get_id(vdev); + + QDF_BUG(vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS); + + return vdev_id; +} + +/* Tree Navigation */ + +/** + * !PLEASE READ! + * + * The following are objmgr naviation helpers for traversing objmgr object + * trees. + * + * Objmgr ensures parents of an objmgr object cannot be freed while a valid + * reference to one of its children is held. Based on this fact, all of these + * navigation helpers make the following assumptions to ensure safe usage: + * + * 1) The caller must hold a valid reference to the input objmgr object! + * E.g. Use pmo_[peer|vdev|pdev|psoc]_get_ref() on the input objmgr object + * before using these APIs + * 2) Given assumption #1, the caller does not need to hold a reference to the + * parents of the input objmgr object + * 3) Given assumption #1, parents of the input objmgr object cannot be null + * 4) Given assumption #1, private contexts of any parent of the input objmgr + * object cannot be null + * + * These characteristics remove the need for most sanity checks when dealing + * with objmgr objects. However, please note that if you ever walk the tree + * from parent to child, references must be acquired all the way down! + * + * Example #1: + * + * psoc = pmo_vdev_get_psoc(vdev); + * if (!psoc) + * // this is dead code + * + * Example #2: + * + * psoc_priv = pmo_psoc_get_priv(psoc); + * if (!psoci_priv) + * // this is dead code + * + * Example #3: + * + * status = pmo_vdev_get_ref(vdev); + * + * ... + * + * psoc = pmo_vdev_get_psoc(vdev); + * + * // the next line is redundant, don't do it! + * status = pmo_psoc_get_ref(psoc); + */ + +/* Tree Navigation: psoc */ + +static inline struct wlan_objmgr_vdev * +pmo_psoc_get_vdev(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + + if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) { + QDF_BUG(0); + return NULL; + } + + wlan_psoc_obj_lock(psoc); + vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_id]; + wlan_psoc_obj_unlock(psoc); + + return vdev; +} + +static inline struct pmo_psoc_priv_obj * +pmo_psoc_get_priv(struct wlan_objmgr_psoc *psoc) +{ + struct pmo_psoc_priv_obj *psoc_priv; + + psoc_priv = pmo_psoc_get_priv_nolock(psoc); + + QDF_BUG(psoc_priv); + + return psoc_priv; +} + +/* Tree Navigation: pdev */ + +static inline struct wlan_objmgr_psoc * +pmo_pdev_get_psoc(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_pdev_get_psoc(pdev); + + QDF_BUG(psoc); + + return psoc; +} + +static inline struct pmo_psoc_priv_obj * +pmo_pdev_get_psoc_priv(struct wlan_objmgr_pdev *pdev) +{ + return pmo_psoc_get_priv(pmo_pdev_get_psoc(pdev)); +} + +/* Tree Navigation: vdev */ + +static inline struct pmo_vdev_priv_obj * +pmo_vdev_get_priv(struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_priv; + + vdev_priv = pmo_vdev_get_priv_nolock(vdev); + + QDF_BUG(vdev_priv); + + return vdev_priv; +} + +static inline struct wlan_objmgr_pdev * +pmo_vdev_get_pdev(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_pdev *pdev; + + pdev = wlan_vdev_get_pdev(vdev); + + QDF_BUG(pdev); + + return pdev; +} + +static inline struct wlan_objmgr_psoc * +pmo_vdev_get_psoc(struct wlan_objmgr_vdev *vdev) +{ + return pmo_pdev_get_psoc(pmo_vdev_get_pdev(vdev)); +} + +static inline struct pmo_psoc_priv_obj * +pmo_vdev_get_psoc_priv(struct wlan_objmgr_vdev *vdev) +{ + return pmo_psoc_get_priv(pmo_pdev_get_psoc(pmo_vdev_get_pdev(vdev))); +} + +#endif /* _WLAN_PMO_OBJMGR_H */ diff --git a/core/components/pmo/core/inc/wlan_pmo_pkt_filter.h b/core/components/pmo/core/inc/wlan_pmo_pkt_filter.h new file mode 100644 index 000000000000..0a900e5fe1f3 --- /dev/null +++ b/core/components/pmo/core/inc/wlan_pmo_pkt_filter.h @@ -0,0 +1,57 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Declare packet filter feature API's + */ + +#ifndef _WLAN_PMO_PKT_FILTER_H_ +#define _WLAN_PMO_PKT_FILTER_ + +#include "wlan_pmo_pkt_filter_public_struct.h" + +struct wlan_objmgr_psoc; + +/** + * pmo_set_pkt_fltr_req() - Set packet filter + * @vdev: objmgr vdev + * @pmo_set_pkt_fltr_req: + * @vdev_id: + * API to set packet filter + * + * Return: QQDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_core_set_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_rcv_pkt_fltr_cfg *pmo_set_pkt_fltr_req, + uint8_t vdev_id); + +/** + * pmo_core_clear_pkt_filter() - Clear packet filter + * @vdev: objmgr vdev + * @pmo_clr_pkt_fltr_req: + * @vdev_id: + * + * API to clear packet filter + * + * Return: QQDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_core_clear_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_rcv_pkt_fltr_clear_param *pmo_clr_pkt_fltr_req, + uint8_t vdev_id); + +#endif /* end of _WLAN_PMO_PKT_FILTER_H_ */ + diff --git a/core/components/pmo/core/inc/wlan_pmo_priv.h b/core/components/pmo/core/inc/wlan_pmo_priv.h new file mode 100644 index 000000000000..8c7614dbc562 --- /dev/null +++ b/core/components/pmo/core/inc/wlan_pmo_priv.h @@ -0,0 +1,130 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ + /** + * DOC: Declare various struct, macros which are used for private to PMO. + * + * Note: This file shall not contain public API's prototype/declarations. + * + */ + +#ifndef _WLAN_PMO_PRIV_STRUCT_H_ +#define _WLAN_PMO_PRIV_STRUCT_H_ + +#include "wlan_pmo_common_public_struct.h" +#include "wlan_pmo_arp_public_struct.h" +#include "wlan_pmo_ns_public_struct.h" +#include "wlan_pmo_gtk_public_struct.h" +#include "wlan_pmo_wow_public_struct.h" +#include "wlan_pmo_mc_addr_filtering_public_struct.h" + +/** + * struct pmo_psoc_priv_obj - psoc related data require for pmo + * @psoc_cfg: place holder for psoc configuration + * @pmo_tx_ops: transmit ops for PMO + * @wow: wow configuration + * @dp_hdl: psoc data path handle + * @htc_hdl: htc layer handle + * @hif_hdl: hif layer handle + * @txrx_hdl: txrx pdev handle + * @pause_bitmap_notifier: registered callback to update pause bitmap value + * @pmo_get_pause_bitmap: registered callback to get pause bitmap value + * @lock: spin lock for pmo psoc + */ +struct pmo_psoc_priv_obj { + struct pmo_psoc_cfg psoc_cfg; + struct wlan_pmo_tx_ops pmo_tx_ops; + struct pmo_wow wow; + void *dp_hdl; + void *htc_hdl; + void *hif_hdl; + void *txrx_hdl; + pmo_notify_pause_bitmap pause_bitmap_notifier; + pmo_get_pause_bitmap get_pause_bitmap; + pmo_is_device_in_low_pwr_mode is_device_in_low_pwr_mode; + qdf_spinlock_t lock; +}; + +/** + * struct wlan_pmo_ctx -offload mgr context + * @psoc_context: psoc context + * @pmo_suspend_handler: suspend handler table for all componenets + * @pmo_suspend_handler_arg: suspend handler argument sfor all componenets + * @pmo_resume_handler: resume handler table for all componenets + * @pmo_resume_handler_arg: resume handler argument for all componenets + * @lock: lock for global pmo ctx + */ +struct wlan_pmo_ctx { + pmo_psoc_suspend_handler + pmo_suspend_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *pmo_suspend_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + pmo_psoc_resume_handler + pmo_resume_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *pmo_resume_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + qdf_spinlock_t lock; +}; + +/** + * struct pmo_vdev_priv_obj -vdev specific user configuration required for pmo + * @pmo_psoc_ctx: pmo psoc ctx + * @vdev_arp_req: place holder for arp request for vdev + * @vdev_ns_req: place holder for ns request for vdev + * @vdev_mc_list_req: place holder for mc addr list for vdev + * @addr_filter_pattern: addr filter pattern for vdev + * @vdev_gtk_params: place holder for gtk request for vdev + * @gtk_err_enable: gtk error is enabled or not + * @vdev_bpf_req: place holder for apf/bpf for vdev + * @vdev_pkt_filter: place holder for vdev packet filter + * @ptrn_match_enable: true when pattern match is enabled else false + * @num_wow_default_patterns: number of wow default patterns for vdev + * @num_wow_user_patterns: number of user wow patterns for vdev + * @nlo_in_progress: true when pno/nlo in progress else false + * @nlo_match_received: true when nlo match recevied from fwr else false + * @extscan_in_progress: true when extscan in progress else false + * @p2plo_in_progress: true when p2plo_in_progress in progress else false + * @dtim_period: dtim period for vdev + * @beacon_interval: vdev beacon interval + * @alt_modulated_dtim_enabled:dynamic modulated dtim enabled + * @dtim_policy: tells vdev beacon dtim policy + * @vdev_dp_hdl: vdev data path handle + * @pmo_vdev_lock: spin lock for pmo vdev priv ctx + */ +struct pmo_vdev_priv_obj { + struct pmo_psoc_priv_obj *pmo_psoc_ctx; + struct pmo_arp_offload_params vdev_arp_req; + struct pmo_ns_offload_params vdev_ns_req; + struct pmo_mc_addr_list vdev_mc_list_req; + uint8_t addr_filter_pattern; + struct pmo_gtk_req vdev_gtk_req; + struct pmo_gtk_rsp_req vdev_gtk_rsp_req; + qdf_atomic_t gtk_err_enable; + bool ptrn_match_enable; + uint8_t num_wow_default_patterns; + uint8_t num_wow_user_patterns; + bool nlo_in_progress; + bool nlo_match_received; + bool extscan_in_progress; + bool p2plo_in_progress; + uint8_t dtim_period; + uint8_t beacon_interval; + bool alt_modulated_dtim_enable; + uint32_t dtim_policy; + void *vdev_dp_hdl; + qdf_spinlock_t pmo_vdev_lock; +}; + +#endif /* end of _WLAN_PMO_PRIV_STRUCT_H_ */ diff --git a/core/components/pmo/core/inc/wlan_pmo_static_config.h b/core/components/pmo/core/inc/wlan_pmo_static_config.h new file mode 100644 index 000000000000..fe4544b79ce4 --- /dev/null +++ b/core/components/pmo/core/inc/wlan_pmo_static_config.h @@ -0,0 +1,117 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Declare static configuration on vdev attach + */ + +#ifndef _WLAN_PMO_STATIC_CONFIG_H_ +#define _WLAN_PMO_STATIC_CONFIG_H_ + +#include "wlan_pmo_common_public_struct.h" +#include "wlan_pmo_wow.h" + +/** + * pmo_register_wow_wakeup_events() - register vdev specific wake events with fw + * @vdev: objmgr vdev + * + * WoW wake up event rule is following: + * 1) STA mode and P2P CLI mode wake up events are same + * 2) SAP mode and P2P GO mode wake up events are same + * 3) IBSS mode wake events are same as STA mode plus WOW_BEACON_EVENT + * + * Return: none + */ +void pmo_register_wow_wakeup_events(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_register_wow_default_patterns() - register default wow patterns with fw + * @vdev_id: vdev id + * + * WoW default wake up pattern rule is: + * - For STA & P2P CLI mode register for same STA specific wow patterns + * - For SAP/P2P GO & IBSS mode register for same SAP specific wow patterns + * + * Return: none + */ +void pmo_register_wow_default_patterns(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_register_action_frame_patterns() - register action frame map to fw + * @vdev: objmgr vdev + * + * This is called to push action frames wow patterns from local + * cache to firmware. + * + * Return: None + */ +void pmo_register_action_frame_patterns( + struct wlan_objmgr_vdev *vdev); + +/** + * pmo_update_target_service(): API to update wmi target service info to PMO. + * @psoc: objmgr psoc + * @wmi_service: wmi service number + * @value: true when wmi service is enabled in firmware otherwise false. + * + * Return void + */ +void pmo_update_target_service(struct wlan_objmgr_psoc *psoc, + WMI_SERVICE service, bool value); + +/** + * pmo_update_ra_limit() - update ra limit based on bpf filter + * enabled or not + * @psoc: objmgr psoc + * @bpf_enabled: true when bpf service is enabled else false + * + * Return: none + */ +void pmo_update_ra_limit(struct wlan_objmgr_psoc *psoc, + bool bpf_enabled); + +/** + * pmo_set_wow_event_bitmap() - Assign bitmask with wow event + * @event: wow event + * @wow_bitmap_size: wow bitmask size + * @bitmask: wow bitmask field + * + * Return: none + */ +void pmo_set_wow_event_bitmap(WOW_WAKE_EVENT_TYPE event, + uint32_t wow_bitmap_size, + uint32_t *bitmask); + +/** + * pmo_set_sta_wow_bitmask() - set predefined STA wow wakeup events + * @bitmask: bitmask field + * @wow_bitmask_size: bitmask field size + * + * Return: none + */ +void pmo_set_sta_wow_bitmask(uint32_t *bitmask, uint32_t wow_bitmask_size); + +/** + * pmo_set_sap_wow_bitmask() - set predefined SAP wow wakeup events + * @bitmask: bitmask field + * @wow_bitmask_size: bitmask field size + * + * Return: none + */ +void pmo_set_sap_wow_bitmask(uint32_t *bitmask, uint32_t wow_bitmask_size); + +#endif /* end of _WLAN_PMO_STATIC_CONFIG_H_ */ diff --git a/core/components/pmo/core/inc/wlan_pmo_suspend_resume.h b/core/components/pmo/core/inc/wlan_pmo_suspend_resume.h new file mode 100644 index 000000000000..516f428ec366 --- /dev/null +++ b/core/components/pmo/core/inc/wlan_pmo_suspend_resume.h @@ -0,0 +1,437 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Declare suspend / resume related API's + */ + +#ifndef _WLAN_PMO_SUSPEND_RESUME_H_ +#define _WLAN_PMO_SUSPEND_RESUME_H_ + +#include "wlan_pmo_common_public_struct.h" +#include "wlan_pmo_wow.h" + +/** + * pmo_core_configure_dynamic_wake_events(): configure dyanmic wake events + * @wma: wma handle + * + * Some wake events need to be enabled dynamically. Control those here. + * + * Return: none + */ +void pmo_core_configure_dynamic_wake_events(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_core_get_wow_bus_suspend(): API to get wow bus is suspended or not + * @psoc: objmgr psoc handle + * + * Return: True if bus suspende else false + */ +static inline +bool pmo_core_get_wow_bus_suspend(struct wlan_objmgr_psoc *psoc) +{ + bool value; + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + value = psoc_ctx->wow.is_wow_bus_suspended; + qdf_spin_unlock_bh(&psoc_ctx->lock); + + return value; +} + +/** + * pmo_core_psoc_user_space_suspend_req() - Core handle user space suspend req + * @psoc: objmgr psoc handle + * @type: type of suspend + * + * Pmo core Handles user space suspend request for psoc + * + * Return: QDF status + */ +QDF_STATUS pmo_core_psoc_user_space_suspend_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type); + +/** + * pmo_core_psoc_user_space_resume_req() - Core handle user space resume req + * @psoc: objmgr psoc handle + * @type: type of suspend from resume required + * + * Pmo core Handles user space resume request for psoc + * + * Return: QDF status + */ +QDF_STATUS pmo_core_psoc_user_space_resume_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type); + +/** + * pmo_core_psoc_bus_suspend_req(): handles bus suspend for psoc + * @psoc: objmgr psoc + * @type: is this suspend part of runtime suspend or system suspend? + * @wow_params: collection of wow enable override parameters + * + * Bails if a scan is in progress. + * Calls the appropriate handlers based on configuration and event. + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS pmo_core_psoc_bus_suspend_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type, + struct pmo_wow_enable_params *wow_params); + +#ifdef FEATURE_RUNTIME_PM +/** + * pmo_core_psoc_bus_runtime_suspend(): handles bus runtime suspend + * @psoc: objmgr psoc + * @pld_cb: callback to do link auto suspend + * + * Suspend the wlan bus without apps suspend. + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS pmo_core_psoc_bus_runtime_suspend(struct wlan_objmgr_psoc *psoc, + pmo_pld_auto_suspend_cb pld_cb); + +/** + * pmo_core_psoc_bus_runtime_resume(): handles bus runtime resume + * @psoc: objmgr psoc + * @pld_cb: callback to do link auto resume + * + * Resume the wlan bus from runtime suspend. + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS pmo_core_psoc_bus_runtime_resume(struct wlan_objmgr_psoc *psoc, + pmo_pld_auto_resume_cb pld_cb); +#endif + +/** + * pmo_core_psoc_suspend_target() -Send suspend target command + * @psoc: objmgr psoc handle + * @disable_target_intr: disable target interrupt + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS pmo_core_psoc_suspend_target(struct wlan_objmgr_psoc *psoc, + int disable_target_intr); + +/** + * pmo_core_psoc_bus_resume() -handle bus resume request for psoc + * @psoc: objmgr psoc handle + * @type: is this suspend part of runtime suspend or system suspend? + * + * Return:QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS pmo_core_psoc_bus_resume_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type); + +/** + * pmo_core_get_vdev_dtim_period() - Get vdev dtim period + * @vdev: objmgr vdev handle + * + * Return: Vdev dtim period + */ +static inline +uint8_t pmo_core_get_vdev_dtim_period(struct wlan_objmgr_vdev *vdev) +{ + uint8_t dtim_period = 0; + + if (!vdev) { + pmo_err("vdev is null"); + QDF_ASSERT(0); + return 0; + } + /* TODO */ + /* dtim_period = wlan_vdev_mlme_get_dtim_period(vdev); */ + + return dtim_period; +} + +/** + * pmo_core_get_vdev_beacon_interval() - Get vdev beacon interval + * @vdev: objmgr vdev handle + * + * Return: Vdev beacon interval + */ +static inline +uint16_t pmo_core_get_vdev_beacon_interval(struct wlan_objmgr_vdev *vdev) +{ + uint16_t beacon_interval = 0; + + if (!vdev) { + pmo_err("vdev is null"); + QDF_ASSERT(0); + return 0; + } + /* TODO */ + /* beacon_interval = wlan_vdev_mlme_get_beacon_interval(vdev); */ + + return beacon_interval; +} + +/** + * pmo_core_update_alt_modulated_dtim_enable() - update alt modulatate dtim + * @vdev: objmgr vdev handle + * @value: true when alt modulated dtim enable else false + * + * Return: None + */ +static inline +void pmo_core_update_alt_modulated_dtim_enable(struct wlan_objmgr_vdev *vdev, + bool value) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->alt_modulated_dtim_enable = value; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +} + +/** + * pmo_core_vdev_set_dtim_policy() - Set vdev beacon dtim policy + * @vdev: objmgr vdev handle + * @value: carry vdev dtim policy + * + * Return: None + */ +static inline +void pmo_core_vdev_set_dtim_policy(struct wlan_objmgr_vdev *vdev, + uint32_t value) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->dtim_policy = value; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +} + +/** + * pmo_core_vdev_get_dtim_policy() - Get vdev beacon dtim policy + * @vdev: objmgr vdev handle + * + * Return: vdev dtim policy + */ +static inline +uint32_t pmo_core_vdev_get_dtim_policy(struct wlan_objmgr_vdev *vdev) +{ + uint32_t value; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + value = vdev_ctx->dtim_policy; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return value; +} + +/** + * pmo_core_update_power_save_mode() - update power save mode + * @vdev: objmgr vdev handle + * @value:describe vdev power save mode + * + * Return: None + */ +static inline +void pmo_core_psoc_update_power_save_mode(struct wlan_objmgr_psoc *psoc, + uint8_t value) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->psoc_cfg.power_save_mode = value; + qdf_spin_unlock_bh(&psoc_ctx->lock); +} + +/** + * pmo_core_psoc_get_power_save_mode() - Get psoc power save mode + * @psoc: objmgr psoc handle + * + * Return: vdev psoc power save mode value + */ +static inline +uint8_t pmo_core_psoc_get_power_save_mode(struct wlan_objmgr_psoc *psoc) +{ + uint8_t value; + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + value = psoc_ctx->psoc_cfg.power_save_mode; + qdf_spin_unlock_bh(&psoc_ctx->lock); + + return value; +} + +/** + * pmo_core_psoc_get_qpower_config() - get qpower configuration + * @psoc: objmgr psoc handle + * + * Power Save Offload configuration: + * 0 -> Power save offload is disabled + * 1 -> Legacy Power save enabled + Deep sleep Disabled + * 2 -> QPower enabled + Deep sleep Disabled + * 3 -> Legacy Power save enabled + Deep sleep Enabled + * 4 -> QPower enabled + Deep sleep Enabled + * 5 -> Duty cycling QPower enabled + * + * Return: enum powersave_qpower_mode with below values + * QPOWER_DISABLED if QPOWER is disabled + * QPOWER_ENABLED if QPOWER is enabled + * QPOWER_DUTY_CYCLING if DUTY CYCLING QPOWER is enabled + */ +static inline +enum pmo_power_save_qpower_mode pmo_core_psoc_get_qpower_config( + struct wlan_objmgr_psoc *psoc) +{ + uint8_t ps_mode = pmo_core_psoc_get_power_save_mode(psoc); + + switch (ps_mode) { + case pmo_ps_qpower_no_deep_sleep: + case pmo_ps_qpower_deep_sleep: + pmo_info("QPOWER is enabled in power save mode %d", ps_mode); + return pmo_qpower_enabled; + case pmo_ps_duty_cycling_qpower: + pmo_info("DUTY cycling QPOWER is enabled in power save mode %d", + ps_mode); + return pmo_qpower_duty_cycling; + default: + pmo_info("QPOWER is disabled in power save mode %d", + ps_mode); + return pmo_qpower_disabled; + } +} + +/** + * pmo_core_vdev_get_pause_bitmap() - Get vdev pause bitmap + * @psoc_ctx: psoc priv ctx + * @vdev_id: vdev id + * + * Return: vdev pause bitmap + */ +static inline +uint16_t pmo_core_vdev_get_pause_bitmap(struct pmo_psoc_priv_obj *psoc_ctx, + uint8_t vdev_id) +{ + uint16_t value = 0; + pmo_get_pause_bitmap handler; + + qdf_spin_lock_bh(&psoc_ctx->lock); + handler = psoc_ctx->get_pause_bitmap; + qdf_spin_unlock_bh(&psoc_ctx->lock); + + if (handler) + value = handler(vdev_id); + + return value; +} + +/** + * wma_is_vdev_in_ap_mode() - check that vdev is in ap mode or not + * @wma: wma handle + * @vdev_id: vdev id + * + * Helper function to know whether given vdev id + * is in AP mode or not. + * + * Return: True/False + */ +static inline +bool pmo_is_vdev_in_ap_mode(struct wlan_objmgr_vdev *vdev) +{ + enum tQDF_ADAPTER_MODE mode; + + mode = pmo_get_vdev_opmode(vdev); + + return (mode == QDF_SAP_MODE || mode == QDF_P2P_GO_MODE) == 1 ? 1 : 0; +} + +#ifdef QCA_IBSS_SUPPORT +/** + * pmo_is_vdev_in_ibss_mode() - check that vdev is in ibss mode or not + * @vdev: objmgr vdev handle + * @vdev_id: vdev id + * + * Helper function to know whether given vdev id + * is in IBSS mode or not. + * + * Return: True/False + */ +static inline +bool pmo_is_vdev_in_ibss_mode(struct wlan_objmgr_vdev *vdev) +{ + enum tQDF_ADAPTER_MODE mode; + + mode = pmo_get_vdev_opmode(vdev); + + return (mode == QDF_IBSS_MODE) ? true : false; +} +#else +static inline bool pmo_is_vdev_in_ibss_mode(struct wlan_objmgr_vdev *vdev) +{ + return false; +} +#endif /* QCA_IBSS_SUPPORT */ + +/** + * pmo_handle_initial_wake_up() - handle initial wake up + * @cb_ctx: callback context + * + * Return: None + */ +void pmo_core_psoc_handle_initial_wake_up(void *cb_ctx); + +/** + * pmo_core_psoc_is_target_wake_up_received() - check for initial wake up + * + * Check if target initial wake up is received and fail PM suspend gracefully + * + * Return: -EAGAIN if initial wake up is received else 0 + */ +int pmo_core_psoc_is_target_wake_up_received(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_core_psoc_clear_target_wake_up() - clear initial wake up + * + * Clear target initial wake up reason + * + * Return: 0 for success and negative error code for failure + */ +int pmo_core_psoc_clear_target_wake_up(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_core_psoc_target_suspend_acknowledge() - update target susspend status + * @context: HTC_INIT_INFO->context + * @wow_nack: true when wow is rejected + * + * Return: none + */ +void pmo_core_psoc_target_suspend_acknowledge(void *context, bool wow_nack); + +/** + * pmo_core_psoc_wakeup_host_event_received() - received host wake up event + * @psoc: objmgr psoc handle + * + * Return: None + */ +void pmo_core_psoc_wakeup_host_event_received(struct wlan_objmgr_psoc *psoc); + +#endif /* end of _WLAN_PMO_SUSPEND_RESUME_H_ */ diff --git a/core/components/pmo/core/inc/wlan_pmo_wow.h b/core/components/pmo/core/inc/wlan_pmo_wow.h new file mode 100644 index 000000000000..47d2eb53a603 --- /dev/null +++ b/core/components/pmo/core/inc/wlan_pmo_wow.h @@ -0,0 +1,605 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/** + * DOC: Declare API's for wow pattern addition and deletion in fwr + */ + +#ifndef _WLAN_PMO_WOW_H_ +#define _WLAN_PMO_WOW_H_ + +#include "wlan_pmo_main.h" +#include "wlan_pmo_wow_public_struct.h" +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_common_public_struct.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" + +/** + * DOC: wlan_pmo_wowl + * + * This module houses all the logic for WOW(wake on wireless) in + * PMO(Power Management and Offload). + * + * It provides the following APIs + * + * - Ability to enable/disable following WoWL modes + * 1) Magic packet (MP) mode + * 2) Pattern Byte Matching (PBM) mode + * - Ability to add/remove patterns for PBM + * + * A Magic Packet is a packet that contains 6 0xFFs followed by 16 + * contiguous copies of the receiving NIC's Ethernet address. There is + * no API to configure Magic Packet Pattern. + * + * Wakeup pattern (used for PBM) is defined as following: + * struct + * { + * U8 PatternSize; // Non-Zero pattern size + * U8 PatternMaskSize; // Non-zero pattern mask size + * U8 PatternMask[PatternMaskSize]; // Pattern mask + * U8 Pattern[PatternSize]; // Pattern + * } hdd_wowl_ptrn_t; + * + * PatternSize and PatternMaskSize indicate size of the variable + * length Pattern and PatternMask. PatternMask indicates which bytes + * of an incoming packet should be compared with corresponding bytes + * in the pattern. + * + * Maximum allowed pattern size is 128 bytes. Maximum allowed + * PatternMaskSize is 16 bytes. + * + * Maximum number of patterns that can be configured is 8 + * + * PMO will add following 2 commonly used patterns for PBM by default: + * 1) ARP Broadcast Pattern + * 2) Unicast Pattern + * + * However note that WoWL will not be enabled by default by PMO. WoWL + * needs to enabled explcitly by exercising the iwpriv command. + * + * PMO will expose an API that accepts patterns as Hex string in the + * following format: + * "PatternSize:PatternMaskSize:PatternMask:Pattern" + * + * Multiple patterns can be specified by deleimiting each pattern with + * the ';' token: + * "PatternSize1:PatternMaskSize1:PatternMask1:Pattern1;PatternSize2:..." + * + * Patterns can be configured dynamically via iwpriv cmd or statically + * via qcom_cfg.ini file + * + * PBM (when enabled) can perform filtering on unicast data or + * broadcast data or both. These configurations are part of factory + * default (cfg.dat) and the default behavior is to perform filtering + * on both unicast and data frames. + * + * MP filtering (when enabled) is performed ALWAYS on both unicast and + * broadcast data frames. + * + * Management frames are not subjected to WoWL filtering and are + * discarded when WoWL is enabled. + * + * Whenever a patern match succeeds, RX path is restored and packets + * (both management and data) will be pushed to the host from that + * point onwards. Therefore, exit from WoWL is implicit and happens + * automatically when the first packet match succeeds. + * + * WoWL works on top of BMPS. So when WoWL is requested, SME will + * attempt to put the device in BMPS mode (if not already in BMPS). If + * attempt to BMPS fails, request for WoWL will be rejected. + */ + +#define PMO_WOW_MAX_EVENT_BM_LEN 4 + +/** + * pmo_get_and_increment_wow_default_ptrn() -Get and increment wow default ptrn + * @vdev_ctx: pmo vdev priv ctx + * + * API to get and increment wow default ptrn + * + * Return: current wow default ptrn count + */ +static inline uint8_t pmo_get_and_increment_wow_default_ptrn( + struct pmo_vdev_priv_obj *vdev_ctx) +{ + uint8_t count; + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + count = vdev_ctx->num_wow_default_patterns++; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return count; +} + +/** + * pmo_increment_wow_default_ptrn() -increment wow default ptrn + * @vdev_ctx: pmo vdev priv ctx + * + * API to increment wow default ptrn + * + * Return: None + */ +static inline void pmo_increment_wow_default_ptrn( + struct pmo_vdev_priv_obj *vdev_ctx) +{ + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->num_wow_default_patterns++; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +} + +/** + * pmo_decrement_wow_default_ptrn() -decrement wow default ptrn + * @vdev_ctx: pmo vdev priv ctx + * + * API to decrement wow default ptrn + * + * Return: None + */ +static inline void pmo_decrement_wow_default_ptrn( + struct pmo_vdev_priv_obj *vdev_ctx) +{ + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->num_wow_default_patterns--; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +} + +/** + * pmo_increment_wow_user_ptrn() -increment wow user ptrn + * @vdev_ctx: pmo vdev priv ctx + * + * API to increment wow user ptrn + * + * Return: None + */ +static inline void pmo_increment_wow_user_ptrn( + struct pmo_vdev_priv_obj *vdev_ctx) +{ + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->num_wow_user_patterns++; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +} + +/** + * pmo_decrement_wow_user_ptrn() -decrement wow user ptrn + * @vdev_ctx: pmo vdev priv ctx + * + * API to decrement wow user ptrn + * + * Return: None + */ +static inline void pmo_decrement_wow_user_ptrn( + struct pmo_vdev_priv_obj *vdev_ctx) +{ + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->num_wow_user_patterns--; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +} + +void pmo_dump_wow_ptrn(struct pmo_wow_add_pattern *ptrn); + +/** + * pmo_core_add_wow_pattern() - Function which will add the WoWL pattern to be + * used when PBM filtering is enabled + * @vdev: pointer to the vdev + * @ptrn: pointer to the pattern string to be added + * + * Return: false if any errors encountered, QDF_STATUS_SUCCESS otherwise + */ +QDF_STATUS pmo_core_add_wow_pattern(struct wlan_objmgr_vdev *vdev, + const char *ptrn); + +/** + * pmo_core_del_wow_pattern() - Function which will delete the WoWL pattern + * @vdev: pointer to the vdev + * @ptrn: pointer to the pattern string to be added + * + * Return: error if any errors encountered, QDF_STATUS_SUCCESS otherwise + */ +QDF_STATUS pmo_core_del_wow_pattern(struct wlan_objmgr_vdev *vdev, + const char *ptrn); + +/** + * pmo_core_wow_enter() - store enable/disable status for pattern + * @wma: wma handle + * @info: wow parameters + * + * Records pattern enable/disable status locally. This choice will + * take effect when the driver enter into suspend state. + * + * Return: QDF status + */ +QDF_STATUS pmo_core_wow_enter(struct wlan_objmgr_vdev *vdev, + struct pmo_wow_enter_params *wow_enter_param); + +/** + * pmo_core_wow_exit() - clear all wma states + * @wma: wma handle + * @info: wow params + * + * Return: QDF status + */ +QDF_STATUS pmo_core_wow_exit(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_core_enable_wakeup_event() - enable wow wakeup events + * @psoc: objmgr psoc + * @vdev_id: vdev id + * @bitmap: Event bitmap + * + * Return: none + */ +void pmo_core_enable_wakeup_event(struct wlan_objmgr_psoc *psoc, + uint32_t vdev_id, uint32_t *bitmap); + +/** + * pmo_core_disable_wakeup_event() - disable wow wakeup events + * @psoc: objmgr psoc + * @vdev_id: vdev id + * @bitmap: Event bitmap + * + * Return: none + */ +void pmo_core_disable_wakeup_event(struct wlan_objmgr_psoc *psoc, + uint32_t vdev_id, uint32_t *bitmap); + +/** + * pmo_is_wow_applicable(): should enable wow + * @psoc: objmgr psoc object + * + * Enable WOW if any one of the condition meets, + * 1) Is any one of vdev in beaconning mode (in AP mode) ? + * 2) Is any one of vdev in connected state (in STA mode) ? + * 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. + * 7) If LPASS feature is enabled + * 8) If NaN feature is enabled + * If none of above conditions is true then return false + * + * Return: true if wma needs to configure wow false otherwise. + */ +bool pmo_core_is_wow_applicable(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_core_update_wow_enable() - update wow enable flag + * @psoc_ctx: Pointer to objmgr psoc handle + * @value: true if wow mode enable else false + * + * Return: None + */ +static inline +void pmo_core_update_wow_enable(struct pmo_psoc_priv_obj *psoc_ctx, + bool value) +{ + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->wow.wow_enable = value; + qdf_spin_unlock_bh(&psoc_ctx->lock); +} + +/** + * pmo_core_is_wow_mode_enabled() - check if wow needs to be enabled in fw + * @psoc_ctx: Pointer to objmgr psoc handle + * + * API to check if wow mode is enabled in fwr as part of apps suspend or not + * + * Return: true is wow mode is enabled else false + */ +static inline +bool pmo_core_is_wow_enabled(struct pmo_psoc_priv_obj *psoc_ctx) +{ + bool value; + + if (!psoc_ctx) { + pmo_err("psoc_ctx is null"); + return false; + } + + qdf_spin_lock_bh(&psoc_ctx->lock); + value = psoc_ctx->wow.wow_enable; + qdf_spin_unlock_bh(&psoc_ctx->lock); + pmo_debug("WoW enable %d", value); + + return value; +} + +/** + * pmo_core_set_wow_nack() - Set wow nack flag + * @psoc_ctx: Pointer to objmgr psoc handle + * @value: true if received wow nack from else false + * + * Return: None + */ +static inline +void pmo_core_set_wow_nack(struct pmo_psoc_priv_obj *psoc_ctx, bool value) +{ + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->wow.wow_nack = value; + qdf_spin_unlock_bh(&psoc_ctx->lock); +} + +/** + * pmo_core_get_wow_nack() - Get wow nack flag + * @psoc_ctx: Pointer to objmgr psoc handle + * + * Return: wow nack flag + */ +static inline +bool pmo_core_get_wow_nack(struct pmo_psoc_priv_obj *psoc_ctx) +{ + bool value; + + qdf_spin_lock_bh(&psoc_ctx->lock); + value = psoc_ctx->wow.wow_nack; + qdf_spin_unlock_bh(&psoc_ctx->lock); + + return value; +} +/** + * pmo_core_update_wow_enable_cmd_sent() - update wow enable cmd sent flag + * @psoc_ctx: Pointer to objmgr psoc handle + * @value: true if wow enable cmd sent else false + * + * Return: None + */ +static inline +void pmo_core_update_wow_enable_cmd_sent(struct pmo_psoc_priv_obj *psoc_ctx, + bool value) +{ + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->wow.wow_enable_cmd_sent = value; + qdf_spin_unlock_bh(&psoc_ctx->lock); +} + +/** + * pmo_core_get_wow_enable_cmd_sent() - Get wow enable cmd sent flag + * @psoc_ctx: Pointer to objmgr psoc handle + * + * Return: return true if wow enable cmd sent else false + */ +static inline +bool pmo_core_get_wow_enable_cmd_sent(struct pmo_psoc_priv_obj *psoc_ctx) +{ + bool value; + + qdf_spin_lock_bh(&psoc_ctx->lock); + value = psoc_ctx->wow.wow_enable_cmd_sent; + qdf_spin_unlock_bh(&psoc_ctx->lock); + + return value; +} + +/** + * pmo_core_update_wow_initial_wake_up() - update wow initial wake up + * @psoc_ctx: Pointer to objmgr psoc handle + * @value: true if wow initial wake up is received else false + * + * Return: None + */ +static inline +void pmo_core_update_wow_initial_wake_up(struct pmo_psoc_priv_obj *psoc_ctx, + bool value) +{ + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->wow.wow_initial_wake_up = value; + qdf_spin_unlock_bh(&psoc_ctx->lock); +} + +/** + * pmo_core_get_wow_initial_wake_up() - Get wow initial wake up + * @psoc_ctx: Pointer to objmgr psoc handle + * + * Return: true if wow initial wake up is received else false + */ +static inline +bool pmo_core_get_wow_initial_wake_up(struct pmo_psoc_priv_obj *psoc_ctx) +{ + bool value; + + qdf_spin_lock_bh(&psoc_ctx->lock); + value = psoc_ctx->wow.wow_initial_wake_up; + qdf_spin_unlock_bh(&psoc_ctx->lock); + + return value; +} + +#ifdef FEATURE_WLAN_EXTSCAN +/** + * pmo_core_is_extscan_in_progress(): check if a extscan is in progress + * @vdev: objmgr vdev handle + * + * Return: TRUE/FALSE + */ +static inline +bool pmo_core_is_extscan_in_progress(struct wlan_objmgr_vdev *vdev) +{ + bool extscan_in_progress; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + extscan_in_progress = vdev_ctx->extscan_in_progress; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return extscan_in_progress; +} + +/** + * pmo_core_update_extscan_in_progress(): update extscan is in progress flags + * @vdev: objmgr vdev handle + * @value:true if extscan is in progress else false + * + * Return: TRUE/FALSE + */ +static inline +void pmo_core_update_extscan_in_progress(struct wlan_objmgr_vdev *vdev, + bool value) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->extscan_in_progress = value; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +} +#else +static inline +bool pmo_core_is_extscan_in_progress(struct wlan_objmgr_vdev *vdev) +{ + return false; +} + +static inline +void pmo_core_update_extscan_in_progress(struct wlan_objmgr_vdev *vdev, + bool value) +{ +} +#endif + +/** + * pmo_core_is_p2plo_in_progress(): check if p2plo is in progress + * @vdev: objmgr vdev handle + * + * Return: TRUE/FALSE + */ +static inline +bool pmo_core_is_p2plo_in_progress(struct wlan_objmgr_vdev *vdev) +{ + bool p2plo_in_progress; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + p2plo_in_progress = vdev_ctx->p2plo_in_progress; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return p2plo_in_progress; +} + +/** + * pmo_core_update_p2plo_in_progress(): update p2plo is in progress flags + * @vdev: objmgr vdev handle + * @value:true if p2plo is in progress else false + * + * Return: TRUE/FALSE + */ +static inline +void pmo_core_update_p2plo_in_progress(struct wlan_objmgr_vdev *vdev, + bool value) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->p2plo_in_progress = value; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +} + +#ifdef WLAN_FEATURE_LPSS +/** + * pmo_is_lpass_enabled() - check if lpass is enabled + * @vdev: objmgr vdev handle + * + * WoW is needed if LPASS or NaN feature is enabled in INI because + * target can't wake up itself if its put in PDEV suspend when LPASS + * or NaN features are supported + * + * Return: true if lpass is enabled else false + */ +static inline +bool pmo_core_is_lpass_enabled(struct wlan_objmgr_vdev *vdev) +{ + bool lpass_enable; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + lpass_enable = vdev_ctx->pmo_psoc_ctx->psoc_cfg.lpass_enable; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return lpass_enable; +} +#else +static inline +bool pmo_core_is_lpass_enabled(struct wlan_objmgr_vdev *vdev) +{ + return false; +} +#endif + +#ifdef WLAN_FEATURE_NAN +/** + * pmo_is_nan_enabled() - check if NaN is enabled + * @vdev: objmgr vdev handle + * + * WoW is needed if LPASS or NaN feature is enabled in INI because + * target can't wake up itself if its put in PDEV suspend when LPASS + * or NaN features are supported + * + * Return: true if NaN is enabled else false + */ +static inline +bool pmo_core_is_nan_enabled(struct wlan_objmgr_vdev *vdev) +{ + bool nan_enable; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + nan_enable = vdev_ctx->pmo_psoc_ctx->psoc_cfg.nan_enable; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return nan_enable; +} +#else +static inline +bool pmo_core_is_nan_enabled(struct wlan_objmgr_vdev *vdev) +{ + return false; +} +#endif + +/** + * pmo_get_event_bitmap_idx() - get indices for extended wow bitmaps + * @event: wow event + * @wow_bitmap_size: WOW bitmap size + * @bit_idx: bit index + * @idx: byte index + * + * Return: none + */ +static inline void pmo_get_event_bitmap_idx(WOW_WAKE_EVENT_TYPE event, + uint32_t wow_bitmap_size, + uint32_t *bit_idx, + uint32_t *idx) +{ + + if (!bit_idx || !idx || wow_bitmap_size == 0) { + pmo_err("bit_idx:%p idx:%p wow_bitmap_size:%u", + bit_idx, idx, wow_bitmap_size); + return; + } + if (event == 0) { + *idx = *bit_idx = 0; + } else { + *idx = event / (wow_bitmap_size * 8); + *bit_idx = event % (wow_bitmap_size * 8); + } +} +#endif /* end of _WLAN_PMO_WOW_H_ */ diff --git a/core/components/pmo/core/src/wlan_pmo_arp.c b/core/components/pmo/core/src/wlan_pmo_arp.c new file mode 100644 index 000000000000..c41941484491 --- /dev/null +++ b/core/components/pmo/core/src/wlan_pmo_arp.c @@ -0,0 +1,368 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements arp offload feature API's + */ + +#include "wlan_pmo_arp.h" +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_main.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" + +static QDF_STATUS pmo_core_cache_arp_in_vdev_priv( + struct pmo_arp_req *arp_req, + struct wlan_objmgr_vdev *vdev) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct pmo_arp_offload_params *request = NULL; + struct pmo_psoc_priv_obj *psoc_ctx; + struct pmo_vdev_priv_obj *vdev_ctx; + int index; + struct qdf_mac_addr peer_bssid; + + PMO_ENTER(); + psoc_ctx = pmo_psoc_get_priv(arp_req->psoc); + + vdev_ctx = pmo_vdev_get_priv(vdev); + + request = qdf_mem_malloc(sizeof(*request)); + if (!request) { + pmo_err("cannot allocate arp request"); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + status = pmo_get_vdev_bss_peer_mac_addr(vdev, + &peer_bssid); + if (status != QDF_STATUS_SUCCESS) + goto out; + + qdf_mem_copy(&request->bssid.bytes, &peer_bssid.bytes, + QDF_MAC_ADDR_SIZE); + pmo_info("vdev self mac addr: %pM bss peer mac addr: %pM", + wlan_vdev_mlme_get_macaddr(vdev), + peer_bssid.bytes); + + request->enable = PMO_OFFLOAD_ENABLE; + /* converting u32 to IPV4 address */ + for (index = 0; index < PMO_IPV4_ADDR_LEN; index++) + request->host_ipv4_addr[index] = + (arp_req->ipv4_addr >> (index * 8)) & 0xFF; + + /* cache arp request */ + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + qdf_mem_copy(&vdev_ctx->vdev_arp_req, request, + sizeof(vdev_ctx->vdev_arp_req)); + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + pmo_info("arp offload ipv4 addr: %d.%d.%d.%d enable: %d", + request->host_ipv4_addr[0], + request->host_ipv4_addr[1], + request->host_ipv4_addr[2], + request->host_ipv4_addr[3], + request->enable); +out: + if (request) + qdf_mem_free(request); + PMO_EXIT(); + + return status; +} + +static QDF_STATUS pmo_core_flush_arp_from_vdev_priv( + struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + PMO_ENTER(); + + vdev_ctx = pmo_vdev_get_priv(vdev); + + /* clear arp request */ + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + qdf_mem_zero(&vdev_ctx->vdev_arp_req, sizeof(vdev_ctx->vdev_arp_req)); + vdev_ctx->vdev_arp_req.enable = PMO_OFFLOAD_DISABLE; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + PMO_EXIT(); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS pmo_core_do_enable_arp_offload(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id, enum pmo_offload_trigger trigger) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct pmo_psoc_priv_obj *psoc_ctx; + struct pmo_vdev_priv_obj *vdev_ctx; + + PMO_ENTER(); + + vdev_ctx = pmo_vdev_get_priv(vdev); + + psoc_ctx = vdev_ctx->pmo_psoc_ctx; + if (!psoc_ctx) { + pmo_err("psoc_ctx is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + switch (trigger) { + case pmo_ipv4_change_notify: + if (!psoc_ctx->psoc_cfg.active_mode_offload) { + pmo_info("active offload is disabled, skip in mode:%d", + trigger); + status = QDF_STATUS_E_INVAL; + goto out; + } + /* enable arp when active offload is true (ipv4 notifier) */ + status = pmo_tgt_enable_arp_offload_req(vdev, vdev_id); + break; + case pmo_apps_suspend: + if (psoc_ctx->psoc_cfg.active_mode_offload) { + pmo_info("active offload is enabled, skip in mode: %d", + trigger); + status = QDF_STATUS_E_INVAL; + goto out; + } + /* enable arp when active offload is false (apps suspend) */ + status = pmo_tgt_enable_arp_offload_req(vdev, vdev_id); + break; + default: + status = QDF_STATUS_E_INVAL; + pmo_err("invalid pmo trigger"); + break; + } +out: + PMO_EXIT(); + + return status; +} + +static QDF_STATUS pmo_core_do_disable_arp_offload(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id, enum pmo_offload_trigger trigger) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct pmo_psoc_priv_obj *psoc_ctx; + struct pmo_vdev_priv_obj *vdev_ctx; + + PMO_ENTER(); + + vdev_ctx = pmo_vdev_get_priv(vdev); + + psoc_ctx = vdev_ctx->pmo_psoc_ctx; + if (!psoc_ctx) { + pmo_err("psoc_ctx is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + switch (trigger) { + case pmo_apps_resume: + if (psoc_ctx->psoc_cfg.active_mode_offload) { + pmo_info("active offload is enabled, skip in mode: %d", + trigger); + status = QDF_STATUS_E_INVAL; + goto out; + } + /* disable arp on apps resume when active offload is disable */ + status = pmo_tgt_disable_arp_offload_req(vdev, vdev_id); + break; + default: + status = QDF_STATUS_E_INVAL; + pmo_err("invalid pmo trigger"); + break; + } +out: + PMO_EXIT(); + + return status; +} + +static QDF_STATUS pmo_core_arp_offload_sanity( + struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + if (!vdev) { + pmo_err("vdev is NULL"); + return QDF_STATUS_E_NULL_VALUE; + } + + vdev_ctx = pmo_vdev_get_priv(vdev); + if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.arp_offload_enable) { + pmo_err("user disabled arp offload using ini"); + return QDF_STATUS_E_INVAL; + } + + if (!pmo_core_is_vdev_supports_offload(vdev)) { + pmo_info("vdev in invalid opmode for arp offload %d", + pmo_get_vdev_opmode(vdev)); + return QDF_STATUS_E_INVAL; + } + + if (!pmo_core_is_vdev_connected(vdev)) + return QDF_STATUS_E_INVAL; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_core_cache_arp_offload_req(struct pmo_arp_req *arp_req) +{ + QDF_STATUS status; + struct wlan_objmgr_vdev *vdev; + + PMO_ENTER(); + if (!arp_req) { + pmo_err("arp_req is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + if (!arp_req->psoc) { + pmo_err("psoc is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + vdev = pmo_psoc_get_vdev(arp_req->psoc, arp_req->vdev_id); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + goto out; + + status = pmo_core_arp_offload_sanity(vdev); + if (status != QDF_STATUS_SUCCESS) + goto dec_ref; + + pmo_info("Cache arp for vdev id: %d psoc: %p vdev: %p", + arp_req->vdev_id, arp_req->psoc, vdev); + + status = pmo_core_cache_arp_in_vdev_priv(arp_req, vdev); +dec_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_flush_arp_offload_req(struct wlan_objmgr_vdev *vdev) +{ + QDF_STATUS status; + uint8_t vdev_id; + + PMO_ENTER(); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (status != QDF_STATUS_SUCCESS) + goto out; + + status = pmo_core_arp_offload_sanity(vdev); + if (status != QDF_STATUS_SUCCESS) + goto def_ref; + + vdev_id = pmo_vdev_get_id(vdev); + pmo_info("Flush arp for vdev id: %d vdev: %p", vdev_id, vdev); + + status = pmo_core_flush_arp_from_vdev_priv(vdev); +def_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_enable_arp_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger) +{ + QDF_STATUS status; + uint8_t vdev_id; + + PMO_ENTER(); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (status != QDF_STATUS_SUCCESS) + goto out; + + status = pmo_core_arp_offload_sanity(vdev); + if (status != QDF_STATUS_SUCCESS) + goto def_ref; + + vdev_id = pmo_vdev_get_id(vdev); + pmo_info("Enable arp offload in fwr vdev id: %d vdev: %p", + vdev_id, vdev); + + status = pmo_core_do_enable_arp_offload(vdev, vdev_id, trigger); +def_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_disable_arp_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger) +{ + QDF_STATUS status; + uint8_t vdev_id; + + PMO_ENTER(); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (status != QDF_STATUS_SUCCESS) + goto out; + + status = pmo_core_arp_offload_sanity(vdev); + if (status != QDF_STATUS_SUCCESS) + goto def_ref; + + vdev_id = pmo_vdev_get_id(vdev); + pmo_info("Disable arp offload in fwr vdev id: %d vdev: %p", + vdev_id, vdev); + + status = pmo_core_do_disable_arp_offload(vdev, vdev_id, trigger); +def_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + diff --git a/core/components/pmo/core/src/wlan_pmo_gtk.c b/core/components/pmo/core/src/wlan_pmo_gtk.c new file mode 100644 index 000000000000..120ff04275d1 --- /dev/null +++ b/core/components/pmo/core/src/wlan_pmo_gtk.c @@ -0,0 +1,358 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements gtk offload feature API's + */ + +#include "wlan_pmo_gtk.h" +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_main.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" + +static QDF_STATUS pmo_core_cache_gtk_req_in_vdev_priv( + struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_req *gtk_req) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + QDF_STATUS status; + struct qdf_mac_addr peer_bssid; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + status = pmo_get_vdev_bss_peer_mac_addr(vdev, &peer_bssid); + if (status != QDF_STATUS_SUCCESS) + return status; + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + qdf_mem_copy(&vdev_ctx->vdev_gtk_req, gtk_req, + sizeof(vdev_ctx->vdev_gtk_req)); + qdf_mem_copy(&vdev_ctx->vdev_gtk_req.bssid, + &peer_bssid, QDF_MAC_ADDR_SIZE); + vdev_ctx->vdev_gtk_req.flags = PMO_GTK_OFFLOAD_ENABLE; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS pmo_core_flush_gtk_req_from_vdev_priv( + struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + qdf_mem_zero(&vdev_ctx->vdev_gtk_req, sizeof(vdev_ctx->vdev_gtk_req)); + vdev_ctx->vdev_gtk_req.flags = PMO_GTK_OFFLOAD_DISABLE; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS pmo_core_do_enable_gtk_offload( + struct wlan_objmgr_vdev *vdev, + struct pmo_vdev_priv_obj *vdev_ctx, + struct pmo_gtk_req *op_gtk_req) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + uint8_t vdev_id; + + if (!pmo_core_is_vdev_supports_offload(vdev)) { + pmo_info("vdev in invalid opmode for gtk offload %d", + pmo_get_vdev_opmode(vdev)); + return QDF_STATUS_E_INVAL; + } + + if (!pmo_core_is_vdev_connected(vdev)) + return QDF_STATUS_E_INVAL; + + vdev_id = pmo_vdev_get_id(vdev); + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + qdf_mem_copy(op_gtk_req, &vdev_ctx->vdev_gtk_req, + sizeof(*op_gtk_req)); + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + if ((op_gtk_req->flags == PMO_GTK_OFFLOAD_ENABLE) && + (qdf_atomic_read(&vdev_ctx->gtk_err_enable) == 1)) { + pmo_info("GTK Offload already enabled, Disabling vdev_id: %d", + vdev_id); + op_gtk_req->flags = PMO_GTK_OFFLOAD_DISABLE; + status = pmo_tgt_send_gtk_offload_req(vdev, op_gtk_req); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("Failed to disable GTK Offload"); + goto out; + } + pmo_debug("Enable GTK Offload again with updated inputs"); + op_gtk_req->flags = PMO_GTK_OFFLOAD_ENABLE; + } + + status = pmo_tgt_send_gtk_offload_req(vdev, op_gtk_req); +out: + + return status; +} + +static QDF_STATUS pmo_core_is_gtk_enabled_in_fwr( + struct wlan_objmgr_vdev *vdev, + struct pmo_vdev_priv_obj *vdev_ctx) +{ + QDF_STATUS status; + struct qdf_mac_addr peer_bssid; + + if (!pmo_core_is_vdev_supports_offload(vdev)) { + pmo_info("vdev in invalid opmode for gtk offload enable %d", + pmo_get_vdev_opmode(vdev)); + return QDF_STATUS_E_INVAL; + } + + if (!pmo_core_is_vdev_connected(vdev)) + return QDF_STATUS_E_INVAL; + + status = pmo_get_vdev_bss_peer_mac_addr(vdev, + &peer_bssid); + if (status != QDF_STATUS_SUCCESS) + return QDF_STATUS_E_INVAL; + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + if (qdf_mem_cmp(&vdev_ctx->vdev_gtk_req.bssid, + &peer_bssid, QDF_MAC_ADDR_SIZE)) { + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + pmo_err("cache request mac:%pM, peer mac:%pM are not same", + vdev_ctx->vdev_gtk_req.bssid.bytes, + peer_bssid.bytes); + return QDF_STATUS_E_INVAL; + } + + if (vdev_ctx->vdev_gtk_req.flags != PMO_GTK_OFFLOAD_ENABLE) { + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + pmo_err("gtk flag is disabled hence no gtk rsp required"); + return QDF_STATUS_E_INVAL; + } + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS pmo_core_do_disable_gtk_offload( + struct wlan_objmgr_vdev *vdev, + struct pmo_vdev_priv_obj *vdev_ctx, + struct pmo_gtk_req *op_gtk_req) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = pmo_core_is_gtk_enabled_in_fwr(vdev, vdev_ctx); + if (status != QDF_STATUS_SUCCESS) + return status; + + op_gtk_req->flags = PMO_GTK_OFFLOAD_DISABLE; + status = pmo_tgt_send_gtk_offload_req(vdev, op_gtk_req); + + return status; +} + +QDF_STATUS pmo_core_cache_gtk_offload_req(struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_req *gtk_req) +{ + QDF_STATUS status; + enum tQDF_ADAPTER_MODE opmode; + uint8_t vdev_id; + + PMO_ENTER(); + if (!gtk_req) { + pmo_err("gtk_req is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (status != QDF_STATUS_SUCCESS) + goto out; + + opmode = pmo_get_vdev_opmode(vdev); + vdev_id = pmo_vdev_get_id(vdev); + pmo_info("vdev opmode: %d vdev_id: %d", opmode, vdev_id); + if (!pmo_core_is_vdev_supports_offload(vdev)) { + pmo_info("vdev in invalid opmode for caching gtk request %d", + opmode); + status = QDF_STATUS_E_INVAL; + goto dec_ref; + } + + status = pmo_core_cache_gtk_req_in_vdev_priv(vdev, gtk_req); +dec_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_flush_gtk_offload_req(struct wlan_objmgr_vdev *vdev) +{ + enum tQDF_ADAPTER_MODE opmode; + uint8_t vdev_id; + QDF_STATUS status; + + PMO_ENTER(); + if (!vdev) { + pmo_err("psoc is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (status != QDF_STATUS_SUCCESS) + goto out; + + opmode = pmo_get_vdev_opmode(vdev); + vdev_id = pmo_vdev_get_id(vdev); + pmo_info("vdev opmode: %d vdev_id: %d", opmode, vdev_id); + if (!pmo_core_is_vdev_supports_offload(vdev)) { + pmo_info("vdev in invalid opmode for flushing gtk request %d", + opmode); + status = QDF_STATUS_E_INVAL; + goto dec_ref; + } + + status = pmo_core_flush_gtk_req_from_vdev_priv(vdev); +dec_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_enable_gtk_offload_in_fwr(struct wlan_objmgr_vdev *vdev) +{ + QDF_STATUS status; + struct pmo_vdev_priv_obj *vdev_ctx; + struct pmo_gtk_req *op_gtk_req = NULL; + + PMO_ENTER(); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (status != QDF_STATUS_SUCCESS) + goto out; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + op_gtk_req = qdf_mem_malloc(sizeof(*op_gtk_req)); + if (!op_gtk_req) { + pmo_err("op_gtk_req is NULL"); + status = QDF_STATUS_E_INVAL; + goto dec_ref; + } + status = pmo_core_do_enable_gtk_offload(vdev, vdev_ctx, op_gtk_req); +dec_ref: + pmo_vdev_put_ref(vdev); +out: + if (op_gtk_req) + qdf_mem_free(op_gtk_req); + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_disable_gtk_offload_in_fwr(struct wlan_objmgr_vdev *vdev) +{ + QDF_STATUS status; + struct pmo_vdev_priv_obj *vdev_ctx; + struct pmo_gtk_req *op_gtk_req = NULL; + + PMO_ENTER(); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (status != QDF_STATUS_SUCCESS) + goto out; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + op_gtk_req = qdf_mem_malloc(sizeof(*op_gtk_req)); + if (!op_gtk_req) { + pmo_err("op_gtk_req is NULL"); + status = QDF_STATUS_E_NOMEM; + goto dec_ref; + } + + status = pmo_core_do_disable_gtk_offload(vdev, vdev_ctx, op_gtk_req); +dec_ref: + pmo_vdev_put_ref(vdev); +out: + if (op_gtk_req) + qdf_mem_free(op_gtk_req); + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_get_gtk_rsp(struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_rsp_req *gtk_rsp_req) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct pmo_vdev_priv_obj *vdev_ctx; + + PMO_ENTER(); + if (!gtk_rsp_req || !vdev) { + pmo_err("%s is null", !vdev ? "vdev":"gtk_rsp_req"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (status != QDF_STATUS_SUCCESS) + goto out; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + status = pmo_core_is_gtk_enabled_in_fwr(vdev, vdev_ctx); + if (status != QDF_STATUS_SUCCESS) + goto dec_ref; + + /* cache gtk rsp request */ + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + qdf_mem_copy(&vdev_ctx->vdev_gtk_rsp_req, gtk_rsp_req, + sizeof(vdev_ctx->vdev_gtk_rsp_req)); + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + /* send cmd to fwr */ + status = pmo_tgt_get_gtk_rsp(vdev); +dec_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + diff --git a/core/components/pmo/core/src/wlan_pmo_hw_filter.c b/core/components/pmo/core/src/wlan_pmo_hw_filter.c new file mode 100644 index 000000000000..ea93d1d4f10e --- /dev/null +++ b/core/components/pmo/core/src/wlan_pmo_hw_filter.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: Implements arp offload feature API's + */ + +#include "qdf_lock.h" +#include "wlan_pmo_hw_filter.h" +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_main.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" + +static QDF_STATUS pmo_core_conf_hw_filter(struct wlan_objmgr_vdev *vdev, + enum pmo_hw_filter_mode mode) +{ + QDF_STATUS status; + struct pmo_hw_filter_params req = { .mode = mode, }; + + PMO_ENTER(); + + if (!pmo_core_is_vdev_connected(vdev)) { + status = QDF_STATUS_E_NOSUPPORT; + goto exit_with_status; + } + + req.vdev_id = pmo_vdev_get_id(vdev); + status = pmo_tgt_conf_hw_filter(pmo_vdev_get_psoc(vdev), &req); + +exit_with_status: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_enable_hw_filter_in_fwr(struct wlan_objmgr_vdev *vdev) +{ + QDF_STATUS status; + struct pmo_psoc_priv_obj *psoc_priv; + enum pmo_hw_filter_mode mode; + + PMO_ENTER(); + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + goto exit_with_status; + + psoc_priv = pmo_vdev_get_psoc_priv(vdev); + qdf_spin_lock_bh(&psoc_priv->lock); + mode = psoc_priv->psoc_cfg.hw_filter_mode; + qdf_spin_unlock_bh(&psoc_priv->lock); + + status = pmo_core_conf_hw_filter(vdev, mode); + + pmo_vdev_put_ref(vdev); + +exit_with_status: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_disable_hw_filter_in_fwr(struct wlan_objmgr_vdev *vdev) +{ + QDF_STATUS status; + + PMO_ENTER(); + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + goto exit_with_status; + + status = pmo_core_conf_hw_filter(vdev, PMO_HW_FILTER_DISABLED); + + pmo_vdev_put_ref(vdev); + +exit_with_status: + PMO_EXIT(); + + return status; +} diff --git a/core/components/pmo/core/src/wlan_pmo_lphb.c b/core/components/pmo/core/src/wlan_pmo_lphb.c new file mode 100644 index 000000000000..31a637217bce --- /dev/null +++ b/core/components/pmo/core/src/wlan_pmo_lphb.c @@ -0,0 +1,243 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements low power heart beat offload feature API's + */ + +#include "wlan_pmo_main.h" +#include "wlan_pmo_lphb.h" +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" + +#ifdef FEATURE_WLAN_LPHB +/** + * pmo_core_send_lphb_enable() - enable command of LPHB configuration requests + * @psoc: objmgr psoc handle + * @psoc_ctx: pmo private psoc ctx + * @lphb_conf_req: lphb request which need s to configure in fwr + * @by_user: whether this call is from user or cached resent + * + * Return: QDF status + */ +static QDF_STATUS pmo_core_send_lphb_enable(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_priv_obj *psoc_ctx, + struct pmo_lphb_req *lphb_conf_req, bool by_user) +{ + QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; + struct pmo_lphb_enable_req *ts_lphb_enable; + int i; + + if (lphb_conf_req == NULL) { + pmo_err("LPHB configuration is NULL"); + return QDF_STATUS_E_FAILURE; + } + + ts_lphb_enable = &(lphb_conf_req->params.lphb_enable_req); + qdf_status = pmo_tgt_send_lphb_enable(psoc, ts_lphb_enable); + if (qdf_status != QDF_STATUS_SUCCESS) + goto out; + + /* No need to cache non user request */ + if (!by_user) { + qdf_status = QDF_STATUS_SUCCESS; + goto out; + } + + /* target already configured, now cache command status */ + if (ts_lphb_enable->enable) { + i = ts_lphb_enable->item - 1; + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->wow.lphb_cache[i].cmd + = pmo_lphb_set_en_param_indid; + psoc_ctx->wow.lphb_cache[i].params.lphb_enable_req.enable = + ts_lphb_enable->enable; + psoc_ctx->wow.lphb_cache[i].params.lphb_enable_req.item = + ts_lphb_enable->item; + psoc_ctx->wow.lphb_cache[i].params.lphb_enable_req.session = + ts_lphb_enable->session; + qdf_spin_unlock_bh(&psoc_ctx->lock); + pmo_info("cached LPHB status in WMA context for item %d", i); + } else { + qdf_spin_lock_bh(&psoc_ctx->lock); + qdf_mem_zero((void *)&psoc_ctx->wow.lphb_cache, + sizeof(psoc_ctx->wow.lphb_cache)); + qdf_spin_unlock_bh(&psoc_ctx->lock); + pmo_info("cleared all cached LPHB status in WMA context"); + } + +out: + return qdf_status; +} + +/** + * pmo_core_send_lphb_tcp_params() - Send tcp params of LPHB requests + * @psoc: objmgr psoc handle + * @lphb_conf_req: lphb request which needs to be configured in fwr + * + * Return: QDF status + */ +static +QDF_STATUS pmo_core_send_lphb_tcp_params(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_req *lphb_conf_req) +{ + return pmo_tgt_send_lphb_tcp_params(psoc, + &lphb_conf_req->params.lphb_tcp_params); + +} + +/** + * pmo_core_send_lphb_tcp_pkt_filter() - Send tcp packet filter command of LPHB + * @psoc: objmgr psoc handle + * @lphb_conf_req: lphb request which needs to be configured in fwr + * + * Return: QDF status + */ +static +QDF_STATUS pmo_core_send_lphb_tcp_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_req *lphb_conf_req) +{ + return pmo_tgt_send_lphb_tcp_pkt_filter(psoc, + &lphb_conf_req->params.lphb_tcp_filter_req); +} + +/** + * pmo_core_send_lphb_udp_params() - Send udp param command of LPHB + * @psoc: objmgr psoc handle + * @lphb_conf_req: lphb request which needs to be configured in fwr + * + * Return: QDF status + */ +static +QDF_STATUS pmo_core_send_lphb_udp_params(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_req *lphb_conf_req) +{ + return pmo_tgt_send_lphb_udp_params(psoc, + &lphb_conf_req->params.lphb_udp_params); +} + +/** + * pmo_core_send_lphb_udp_pkt_filter() - Send udp pkt filter command of LPHB + * @psoc: objmgr psoc handle + * @lphb_conf_req: lphb request which need s to configure in fwr + * + * Return: QDF status + */ +static +QDF_STATUS pmo_core_send_lphb_udp_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_req *lphb_conf_req) +{ + return pmo_tgt_send_lphb_udp_pkt_filter(psoc, + &lphb_conf_req->params.lphb_udp_filter_req); +} + +/** + * pmo_process_lphb_conf_req() - handle LPHB configuration requests + * @psoc: objmgr psoc handle + * @psoc_ctx: pmo private psoc ctx + * @lphb_conf_req: lphb request which needs to be configured in fwr + * + * Return: QDF status + */ +static QDF_STATUS pmo_process_lphb_conf_req(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_priv_obj *psoc_ctx, + struct pmo_lphb_req *lphb_conf_req) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + pmo_info("LPHB configuration cmd id is %d", lphb_conf_req->cmd); + switch (lphb_conf_req->cmd) { + case pmo_lphb_set_en_param_indid: + status = pmo_core_send_lphb_enable(psoc, psoc_ctx, + lphb_conf_req, true); + break; + + case pmo_lphb_set_tcp_pararm_indid: + status = pmo_core_send_lphb_tcp_params(psoc, lphb_conf_req); + break; + + case pmo_lphb_set_tcp_pkt_filter_indid: + status = pmo_core_send_lphb_tcp_pkt_filter(psoc, lphb_conf_req); + break; + + case pmo_lphb_set_udp_pararm_indid: + status = pmo_core_send_lphb_udp_params(psoc, lphb_conf_req); + break; + + case pmo_lphb_set_udp_pkt_filter_indid: + status = pmo_core_send_lphb_udp_pkt_filter(psoc, lphb_conf_req); + break; + + case pmo_lphb_set_network_info_indid: + default: + break; + } + + return status; +} + +void pmo_core_apply_lphb(struct wlan_objmgr_psoc *psoc) +{ + int i; + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + + pmo_debug("checking LPHB cache"); + for (i = 0; i < 2; i++) { + if (psoc_ctx->wow.lphb_cache[i].params.lphb_enable_req.enable) { + pmo_debug("LPHB cache for item %d is marked as enable", + i + 1); + pmo_core_send_lphb_enable(psoc, psoc_ctx, + &(psoc_ctx->wow.lphb_cache[i]), false); + } + } +} + +QDF_STATUS pmo_core_lphb_config_req(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_req *lphb_req, void *lphb_cb_ctx, + pmo_lphb_callback callback) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + + if (lphb_req == NULL) { + pmo_err("LPHB configuration is NULL"); + return QDF_STATUS_E_NULL_VALUE; + } + + psoc_ctx = pmo_psoc_get_priv(psoc); + + if (pmo_lphb_set_en_param_indid == lphb_req->cmd) { + if (!lphb_cb_ctx) { + pmo_err("lphb callback context is null"); + return QDF_STATUS_E_NULL_VALUE; + } + if (!callback) { + pmo_err("lphb callback function is null"); + return QDF_STATUS_E_NULL_VALUE; + } + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->wow.lphb_cb_ctx = lphb_cb_ctx; + psoc_ctx->wow.lphb_cb = callback; + qdf_spin_unlock_bh(&psoc_ctx->lock); + } + + return pmo_process_lphb_conf_req(psoc, psoc_ctx, lphb_req); +} + +#endif /* FEATURE_WLAN_LPHB */ + diff --git a/core/components/pmo/core/src/wlan_pmo_main.c b/core/components/pmo/core/src/wlan_pmo_main.c new file mode 100644 index 000000000000..58fac41e12ef --- /dev/null +++ b/core/components/pmo/core/src/wlan_pmo_main.c @@ -0,0 +1,256 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implement various api / helper function which shall be used + * PMO user and target interface. + */ + +#include "wlan_pmo_main.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" + +static struct wlan_pmo_ctx *gp_pmo_ctx; + +QDF_STATUS pmo_allocate_ctx(void) +{ + /* If it is already created, ignore */ + if (gp_pmo_ctx != NULL) { + pmo_debug("already allocated pmo_ctx"); + return QDF_STATUS_SUCCESS; + } + + /* allocate offload mgr ctx */ + gp_pmo_ctx = (struct wlan_pmo_ctx *)qdf_mem_malloc( + sizeof(*gp_pmo_ctx)); + if (!gp_pmo_ctx) { + pmo_err("unable to allocate pmo_ctx"); + QDF_ASSERT(0); + return QDF_STATUS_E_NOMEM; + } + qdf_spinlock_create(&gp_pmo_ctx->lock); + + return QDF_STATUS_SUCCESS; +} + +void pmo_free_ctx(void) +{ + if (!gp_pmo_ctx) { + pmo_err("pmo ctx is already freed"); + QDF_ASSERT(0); + return; + } + qdf_spinlock_destroy(&gp_pmo_ctx->lock); + qdf_mem_free(gp_pmo_ctx); + gp_pmo_ctx = NULL; +} + +struct wlan_pmo_ctx *pmo_get_context(void) +{ + return gp_pmo_ctx; +} + +bool pmo_is_vdev_in_beaconning_mode(enum tQDF_ADAPTER_MODE vdev_opmode) +{ + switch (vdev_opmode) { + case QDF_SAP_MODE: + case QDF_P2P_GO_MODE: + case QDF_IBSS_MODE: + return true; + default: + return false; + } +} + +QDF_STATUS pmo_get_vdev_bss_peer_mac_addr(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *bss_peer_mac_address) +{ + struct wlan_objmgr_peer *peer; + + if (!vdev) { + pmo_err("vdev is null"); + return QDF_STATUS_E_INVAL; + } + + peer = wlan_vdev_get_bsspeer(vdev); + if (!peer) { + pmo_err("peer is null"); + return QDF_STATUS_E_INVAL; + } + + wlan_peer_obj_lock(peer); + qdf_mem_copy(bss_peer_mac_address->bytes, wlan_peer_get_macaddr(peer), + QDF_MAC_ADDR_SIZE); + wlan_peer_obj_unlock(peer); + + return QDF_STATUS_SUCCESS; +} + +bool pmo_core_is_ap_mode_supports_arp_ns(struct wlan_objmgr_psoc *psoc, + enum tQDF_ADAPTER_MODE vdev_opmode) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + + if ((vdev_opmode == QDF_SAP_MODE || + vdev_opmode == QDF_P2P_GO_MODE) && + !psoc_ctx->psoc_cfg.ap_arpns_support) { + pmo_info("ARP/NS Offload is not supported in SAP/P2PGO mode"); + return false; + } + + return true; +} + +bool pmo_core_is_vdev_connected(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_peer *peer; + enum wlan_peer_state peer_state; + + peer = wlan_vdev_get_bsspeer(vdev); + + if (!peer) { + pmo_err("peer is null"); + return false; + } + peer_state = wlan_peer_mlme_get_state(peer); + + if (peer_state != WLAN_ASSOC_STATE) { + pmo_err("peer is not associated.peer state: %d", + peer_state); + return false; + } + + return true; +} + +bool pmo_core_is_vdev_supports_offload(struct wlan_objmgr_vdev *vdev) +{ + enum tQDF_ADAPTER_MODE opmode; + bool val; + + opmode = pmo_get_vdev_opmode(vdev); + pmo_info("vdev opmode: %d", opmode); + switch (opmode) { + case QDF_STA_MODE: + case QDF_P2P_CLIENT_MODE: + case QDF_NDI_MODE: + val = true; + break; + default: + val = false; + break; + } + + return val; +} + +QDF_STATUS pmo_core_get_psoc_config(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_cfg *psoc_cfg) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + PMO_ENTER(); + if (!psoc || !psoc_cfg) { + pmo_err("%s is null", !psoc ? "psoc":"psoc_cfg"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + psoc_ctx = pmo_psoc_get_priv(psoc); + + qdf_spin_lock(&psoc_ctx->lock); + qdf_mem_copy(psoc_cfg, &psoc_ctx->psoc_cfg, sizeof(*psoc_cfg)); + qdf_spin_unlock(&psoc_ctx->lock); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_update_psoc_config(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_cfg *psoc_cfg) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + PMO_ENTER(); + if (!psoc || !psoc_cfg) { + pmo_err("%s is null", !psoc ? "psoc":"psoc_cfg"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + psoc_ctx = pmo_psoc_get_priv(psoc); + + qdf_spin_lock(&psoc_ctx->lock); + qdf_mem_copy(&psoc_ctx->psoc_cfg, psoc_cfg, sizeof(*psoc_cfg)); + qdf_spin_unlock(&psoc_ctx->lock); +out: + PMO_EXIT(); + + return status; +} + +void pmo_core_psoc_set_hif_handle(struct wlan_objmgr_psoc *psoc, + void *hif_hdl) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->hif_hdl = hif_hdl; + qdf_spin_unlock_bh(&psoc_ctx->lock); +} + +void *pmo_core_psoc_get_hif_handle(struct wlan_objmgr_psoc *psoc) +{ + void *hif_hdl; + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + hif_hdl = psoc_ctx->hif_hdl; + qdf_spin_unlock_bh(&psoc_ctx->lock); + + return hif_hdl; +} + +void pmo_core_psoc_set_txrx_handle(struct wlan_objmgr_psoc *psoc, + void *txrx_hdl) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->txrx_hdl = txrx_hdl; + qdf_spin_unlock_bh(&psoc_ctx->lock); +} + +void *pmo_core_psoc_get_txrx_handle(struct wlan_objmgr_psoc *psoc) +{ + void *txrx_hdl; + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + txrx_hdl = psoc_ctx->txrx_hdl; + qdf_spin_unlock_bh(&psoc_ctx->lock); + + return txrx_hdl; +} diff --git a/core/components/pmo/core/src/wlan_pmo_mc_addr_filtering.c b/core/components/pmo/core/src/wlan_pmo_mc_addr_filtering.c new file mode 100644 index 000000000000..be4bb2dab22d --- /dev/null +++ b/core/components/pmo/core/src/wlan_pmo_mc_addr_filtering.c @@ -0,0 +1,616 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements mc addr filtering offload feature API's + */ + +#include "wlan_pmo_mc_addr_filtering.h" +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_main.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" + + +#define PMO_INVALID_MC_ADDR_COUNT (-1) + +static void pmo_core_fill_mc_list(struct pmo_vdev_priv_obj **vdev_ctx, + struct pmo_mc_addr_list_params *ip) +{ + struct pmo_mc_addr_list *op_list; + int i; + static const uint8_t ipv6_rs[] = { + 0x33, 0x33, 0x00, 0x00, 0x00, 0x02}; + struct pmo_vdev_priv_obj *temp_ctx; + uint8_t addr_fp; + + temp_ctx = *vdev_ctx; + addr_fp = temp_ctx->addr_filter_pattern; + op_list = &temp_ctx->vdev_mc_list_req; + + qdf_spin_lock_bh(&temp_ctx->pmo_vdev_lock); + op_list->mc_cnt = ip->count; + qdf_spin_unlock_bh(&temp_ctx->pmo_vdev_lock); + + for (i = 0; i < ip->count; i++) { + pmo_debug("%pM", ip->mc_addr[i].bytes); + /* + * Skip following addresses: + * 1)IPv6 router solicitation address + * 2)Any other address pattern if its set during + * RXFILTER REMOVE driver command based on + * addr_filter_pattern + */ + if ((!qdf_mem_cmp(ip->mc_addr[i].bytes, ipv6_rs, + QDF_MAC_ADDR_SIZE)) || + (addr_fp && + (!qdf_mem_cmp(ip->mc_addr[i].bytes, &addr_fp, 1)))) { + pmo_debug("MC/BC filtering Skip addr %pM", + ip->mc_addr[i].bytes); + qdf_spin_lock_bh(&temp_ctx->pmo_vdev_lock); + op_list->mc_cnt--; + qdf_spin_unlock_bh(&temp_ctx->pmo_vdev_lock); + continue; + } + qdf_spin_lock_bh(&temp_ctx->pmo_vdev_lock); + qdf_mem_set(&(op_list->mc_addr[i].bytes), 0, + QDF_MAC_ADDR_SIZE); + qdf_mem_copy(&(op_list->mc_addr[i].bytes), + ip->mc_addr[i].bytes, QDF_MAC_ADDR_SIZE); + qdf_spin_unlock_bh(&temp_ctx->pmo_vdev_lock); + pmo_debug("mlist[%pM] = ", op_list->mc_addr[i].bytes); + } +} + +static QDF_STATUS pmo_core_cache_mc_addr_list_in_vdev_priv( + struct pmo_mc_addr_list_params *mc_list_config, + struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + pmo_core_fill_mc_list(&vdev_ctx, mc_list_config); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS pmo_core_flush_mc_addr_list_from_vdev_priv( + struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + qdf_mem_zero(&vdev_ctx->vdev_mc_list_req, + sizeof(vdev_ctx->vdev_mc_list_req)); + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_core_set_mc_filter_req(struct wlan_objmgr_vdev *vdev, + struct pmo_mc_addr_list *mc_list) +{ + uint8_t vdev_id; + int i; + + PMO_ENTER(); + + vdev_id = pmo_vdev_get_id(vdev); + /* + * Configure enhance multicast offload feature for filtering out + * multicast IP data packets transmitted using unicast MAC address + */ + + /* + * TODO + {//(WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + //WMI_SERVICE_ENHANCED_MCAST_FILTER)) { + */ + if (1) { + pmo_info("FW supports enhance multicast offload"); + pmo_tgt_send_enhance_multicast_offload_req(vdev, vdev_id, + false); + } else { + pmo_info("FW does not support enhance multicast offload"); + } + + /* + * set mc_param->action to clear MCList and reset + * to configure the MCList in FW + */ + for (i = 0; i < mc_list->mc_cnt; i++) { + pmo_tgt_set_mc_filter_req(vdev, + mc_list->mc_addr[i]); + } + + PMO_EXIT(); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_core_clear_mc_filter_req(struct wlan_objmgr_vdev *vdev, + struct pmo_mc_addr_list *mc_list) +{ + uint8_t vdev_id; + int i; + + PMO_ENTER(); + + vdev_id = pmo_vdev_get_id(vdev); + + /* + * Configure enhance multicast offload feature for filtering out + * multicast IP data packets transmitted using unicast MAC address + */ + + /* + * TODO + {//(WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + //WMI_SERVICE_ENHANCED_MCAST_FILTER)) { + */ + if (1) { + pmo_info("FW supports enhance multicast offload"); + pmo_tgt_send_enhance_multicast_offload_req(vdev, vdev_id, + true); + } else { + pmo_info("FW does not support enhance multicast offload"); + } + + /* + * set mcbc_param->action to clear MCList and reset + * to configure the MCList in FW + */ + for (i = 0; i < mc_list->mc_cnt; i++) { + pmo_tgt_clear_mc_filter_req(vdev, mc_list->mc_addr[i]); + } + + PMO_EXIT(); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS pmo_core_do_enable_mc_addr_list(struct wlan_objmgr_vdev *vdev, + struct pmo_vdev_priv_obj *vdev_ctx, + struct pmo_mc_addr_list *op_mc_list_req) +{ + QDF_STATUS status; + + PMO_ENTER(); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + if (!vdev_ctx->vdev_mc_list_req.mc_cnt) { + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + pmo_err("mc_cnt is zero so skip to add mc list"); + status = QDF_STATUS_E_INVAL; + goto out; + } + qdf_mem_copy(op_mc_list_req, &vdev_ctx->vdev_mc_list_req, + sizeof(*op_mc_list_req)); + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + status = pmo_core_set_mc_filter_req(vdev, op_mc_list_req); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("cannot apply mc filter request"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->vdev_mc_list_req.is_filter_applied = true; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +out: + PMO_EXIT(); + + return status; +} + +static QDF_STATUS pmo_core_do_disable_mc_addr_list( + struct wlan_objmgr_vdev *vdev, + struct pmo_vdev_priv_obj *vdev_ctx, + struct pmo_mc_addr_list *op_mc_list_req) +{ + QDF_STATUS status; + + PMO_ENTER(); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + /* validate filter is applied before clearing in fwr */ + if (!vdev_ctx->vdev_mc_list_req.is_filter_applied) { + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + pmo_err("mc filter is not applied in fwr"); + status = QDF_STATUS_E_INVAL; + goto out; + } + qdf_mem_copy(op_mc_list_req, &vdev_ctx->vdev_mc_list_req, + sizeof(*op_mc_list_req)); + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + status = pmo_core_clear_mc_filter_req(vdev, op_mc_list_req); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("cannot apply mc filter request"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->vdev_mc_list_req.is_filter_applied = false; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +out: + PMO_EXIT(); + + return status; +} + +uint8_t pmo_core_max_mc_addr_supported(struct wlan_objmgr_psoc *psoc) +{ + return PMO_MAX_MC_ADDR_LIST; +} + +int pmo_core_get_mc_addr_list_count(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) +{ + QDF_STATUS status; + struct wlan_objmgr_vdev *vdev; + struct pmo_vdev_priv_obj *vdev_ctx; + uint8_t mc_cnt; + + vdev = pmo_psoc_get_vdev(psoc, vdev_id); + if (!vdev) { + pmo_err("vdev is NULL"); + return PMO_INVALID_MC_ADDR_COUNT; + } + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) { + pmo_warn("failed to get vdev reference"); + return PMO_INVALID_MC_ADDR_COUNT; + } + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + mc_cnt = vdev_ctx->vdev_mc_list_req.mc_cnt; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + pmo_vdev_put_ref(vdev); + + return mc_cnt; +} + +void pmo_core_set_mc_addr_list_count(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, uint8_t count) +{ + QDF_STATUS status; + struct pmo_vdev_priv_obj *vdev_ctx; + struct wlan_objmgr_vdev *vdev; + + vdev = pmo_psoc_get_vdev(psoc, vdev_id); + if (!vdev) { + pmo_err("vdev is NULL"); + return; + } + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) { + pmo_warn("failed to get vdev reference"); + return; + } + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->vdev_mc_list_req.mc_cnt = count; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + pmo_vdev_put_ref(vdev); +} + +static QDF_STATUS pmo_core_mc_addr_flitering_sanity( + struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + if (!vdev) { + pmo_err("vdev is NULL"); + return QDF_STATUS_E_NULL_VALUE; + } + + vdev_ctx = pmo_vdev_get_priv(vdev); + + /* Check if INI is enabled or not, otherwise just return */ + if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.enable_mc_list) { + pmo_info("user disabled mc_addr_list using INI"); + return QDF_STATUS_E_INVAL; + } + + if (!pmo_core_is_vdev_supports_offload(vdev)) { + pmo_info("vdev in invalid opmode for mc addr filtering %d", + pmo_get_vdev_opmode(vdev)); + return QDF_STATUS_E_INVAL; + } + + if (!pmo_core_is_vdev_connected(vdev)) + return QDF_STATUS_E_INVAL; + + return QDF_STATUS_SUCCESS; +} +QDF_STATUS pmo_core_cache_mc_addr_list( + struct pmo_mc_addr_list_params *mc_list_config) +{ + struct wlan_objmgr_vdev *vdev; + QDF_STATUS status; + + PMO_ENTER(); + + if (!mc_list_config->psoc) { + pmo_err("psoc is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + vdev = pmo_psoc_get_vdev(mc_list_config->psoc, mc_list_config->vdev_id); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) { + pmo_warn("failed to get vdev reference"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_core_mc_addr_flitering_sanity(vdev); + if (status != QDF_STATUS_SUCCESS) + goto dec_ref; + + pmo_info("Cache mc addr list for vdev id: %d psoc: %p vdev: %p", + mc_list_config->vdev_id, mc_list_config->psoc, vdev); + + status = pmo_core_cache_mc_addr_list_in_vdev_priv(mc_list_config, vdev); +dec_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_flush_mc_addr_list(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + PMO_ENTER(); + if (!psoc) { + pmo_err("psoc is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + vdev = pmo_psoc_get_vdev(psoc, vdev_id); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) { + pmo_warn("failed to get vdev reference"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_core_mc_addr_flitering_sanity(vdev); + if (status != QDF_STATUS_SUCCESS) + goto dec_ref; + + pmo_info("Flush mc addr list for vdev id: %d psoc: %p vdev: %p", + vdev_id, psoc, vdev); + + status = pmo_core_flush_mc_addr_list_from_vdev_priv(vdev); + +dec_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + +static QDF_STATUS pmo_core_handle_enable_mc_list_trigger( + struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + QDF_STATUS status; + struct pmo_mc_addr_list *op_mc_list_req = NULL; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + op_mc_list_req = qdf_mem_malloc(sizeof(*op_mc_list_req)); + if (!op_mc_list_req) { + pmo_err("op_mc_list_req is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + switch (trigger) { + case pmo_mc_list_change_notify: + if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) { + pmo_info("active offload is disabled, skip in mode: %d", + trigger); + status = QDF_STATUS_E_INVAL; + goto out; + } + status = pmo_core_do_enable_mc_addr_list(vdev, vdev_ctx, + op_mc_list_req); + break; + case pmo_apps_suspend: + if (vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) { + pmo_info("active offload is enabled, skip in mode: %d", + trigger); + status = QDF_STATUS_E_INVAL; + goto out; + } + status = pmo_core_do_enable_mc_addr_list(vdev, vdev_ctx, + op_mc_list_req); + break; + default: + status = QDF_STATUS_E_INVAL; + pmo_err("invalid pmo trigger for enable mc list"); + break; + } +out: + if (op_mc_list_req) + qdf_mem_free(op_mc_list_req); + + return status; +} + +QDF_STATUS pmo_core_enable_mc_addr_filtering_in_fwr( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum pmo_offload_trigger trigger) +{ + QDF_STATUS status; + struct wlan_objmgr_vdev *vdev; + + PMO_ENTER(); + if (!psoc) { + pmo_err("psoc is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + vdev = pmo_psoc_get_vdev(psoc, vdev_id); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + goto out; + + status = pmo_core_mc_addr_flitering_sanity(vdev); + if (status != QDF_STATUS_SUCCESS) + goto dec_ref; + + pmo_info("enable mclist trigger: %d", trigger); + status = pmo_core_handle_enable_mc_list_trigger(vdev, trigger); +dec_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + +static QDF_STATUS pmo_core_handle_disable_mc_list_trigger( + struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + QDF_STATUS status; + struct pmo_mc_addr_list *op_mc_list_req = NULL; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + op_mc_list_req = qdf_mem_malloc(sizeof(*op_mc_list_req)); + if (!op_mc_list_req) { + pmo_err("op_mc_list_req is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + switch (trigger) { + case pmo_peer_disconnect: + case pmo_mc_list_change_notify: + if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) { + pmo_info("active offload is disabled, skip in mode: %d", + trigger); + status = QDF_STATUS_E_INVAL; + goto out; + } + status = pmo_core_do_disable_mc_addr_list(vdev, vdev_ctx, + op_mc_list_req); + break; + case pmo_apps_resume: + if (vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) { + pmo_info("active offload is enabled, skip in mode: %d", + trigger); + status = QDF_STATUS_E_INVAL; + goto out; + } + status = pmo_core_do_disable_mc_addr_list(vdev, vdev_ctx, + op_mc_list_req); + break; + default: + status = QDF_STATUS_E_INVAL; + pmo_err("invalid pmo trigger for disable mc list"); + break; + } +out: + if (op_mc_list_req) + qdf_mem_free(op_mc_list_req); + + return status; +} + +QDF_STATUS pmo_core_disable_mc_addr_filtering_in_fwr( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum pmo_offload_trigger trigger) +{ + QDF_STATUS status; + struct wlan_objmgr_vdev *vdev; + + PMO_ENTER(); + if (!psoc) { + pmo_err("psoc is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + vdev = pmo_psoc_get_vdev(psoc, vdev_id); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + goto out; + + status = pmo_core_mc_addr_flitering_sanity(vdev); + if (status != QDF_STATUS_SUCCESS) + goto dec_ref; + + pmo_info("disable mclist trigger: %d", trigger); + status = pmo_core_handle_disable_mc_list_trigger(vdev, trigger); +dec_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + diff --git a/core/components/pmo/core/src/wlan_pmo_ns.c b/core/components/pmo/core/src/wlan_pmo_ns.c new file mode 100644 index 000000000000..b34374e0b644 --- /dev/null +++ b/core/components/pmo/core/src/wlan_pmo_ns.c @@ -0,0 +1,454 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements ns offload feature API's + */ + +#include "wlan_pmo_ns.h" +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_main.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" + +static void pmo_core_fill_ns_addr(struct pmo_ns_offload_params *request, + struct pmo_ns_req *ns_req) +{ + int i; + + for (i = 0; i < ns_req->count; i++) { + /* + * Filling up the request structure + * Filling the selfIPv6Addr with solicited address + * A Solicited-Node multicast address is created by + * taking the last 24 bits of a unicast or anycast + * address and appending them to the prefix + * + * FF02:0000:0000:0000:0000:0001:FFXX:XXXX + * + * here XX is the unicast/anycast bits + */ + request->self_ipv6_addr[i][0] = 0xFF; + request->self_ipv6_addr[i][1] = 0x02; + request->self_ipv6_addr[i][11] = 0x01; + request->self_ipv6_addr[i][12] = 0xFF; + request->self_ipv6_addr[i][13] = + ns_req->ipv6_addr[i][13]; + request->self_ipv6_addr[i][14] = + ns_req->ipv6_addr[i][14]; + request->self_ipv6_addr[i][15] = + ns_req->ipv6_addr[i][15]; + request->slot_idx = i; + qdf_mem_copy(&request->target_ipv6_addr[i], + &ns_req->ipv6_addr[i][0], PMO_MAC_IPV6_ADDR_LEN); + + request->target_ipv6_addr_valid[i] = + PMO_IPV6_ADDR_VALID; + request->target_ipv6_addr_ac_type[i] = + ns_req->ipv6_addr_type[i]; + + pmo_info("NSoffload solicitIp: %pI6 targetIp: %pI6 Index: %d", + &request->self_ipv6_addr[i], + &request->target_ipv6_addr[i], i); + } +} + +static QDF_STATUS pmo_core_cache_ns_in_vdev_priv( + struct pmo_ns_req *ns_req, + struct wlan_objmgr_vdev *vdev) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct pmo_vdev_priv_obj *vdev_ctx; + struct pmo_ns_offload_params request; + struct wlan_objmgr_peer *peer; + + PMO_ENTER(); + + vdev_ctx = pmo_vdev_get_priv(vdev); + + qdf_mem_zero(&request, sizeof(request)); + pmo_core_fill_ns_addr(&request, ns_req); + + request.enable = PMO_OFFLOAD_ENABLE; + qdf_mem_copy(&request.self_macaddr.bytes, + wlan_vdev_mlme_get_macaddr(vdev), + QDF_MAC_ADDR_SIZE); + + /* set number of ns offload address count */ + request.num_ns_offload_count = ns_req->count; + + peer = wlan_vdev_get_bsspeer(vdev); + if (!peer) { + pmo_err("peer is null"); + status = QDF_STATUS_E_INVAL; + goto out; + } + pmo_info("vdev self mac addr: %pM bss peer mac addr: %pM", + wlan_vdev_mlme_get_macaddr(vdev), + wlan_peer_get_macaddr(peer)); + /* get peer and peer mac accdress aka ap mac address */ + qdf_mem_copy(&request.bssid, + wlan_peer_get_macaddr(peer), + QDF_MAC_ADDR_SIZE); + /* cache ns request */ + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + qdf_mem_copy(&vdev_ctx->vdev_ns_req, &request, + sizeof(vdev_ctx->vdev_ns_req)); + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); +out: + PMO_EXIT(); + + return status; +} + +static QDF_STATUS pmo_core_flush_ns_from_vdev_priv( + struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + PMO_ENTER(); + + vdev_ctx = pmo_vdev_get_priv(vdev); + + /* clear ns request */ + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + qdf_mem_zero(&vdev_ctx->vdev_ns_req, sizeof(vdev_ctx->vdev_ns_req)); + vdev_ctx->vdev_ns_req.enable = PMO_OFFLOAD_DISABLE; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + PMO_EXIT(); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS pmo_core_do_enable_ns_offload(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id, enum pmo_offload_trigger trigger) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct pmo_psoc_priv_obj *psoc_ctx; + struct pmo_vdev_priv_obj *vdev_ctx; + + PMO_ENTER(); + + vdev_ctx = pmo_vdev_get_priv(vdev); + + psoc_ctx = vdev_ctx->pmo_psoc_ctx; + if (!psoc_ctx) { + pmo_err("psoc_ctx is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + switch (trigger) { + case pmo_ipv6_change_notify: + case pmo_ns_offload_dynamic_update: + if (!psoc_ctx->psoc_cfg.active_mode_offload) { + pmo_info("active offload is disabled, skip in mode:%d", + trigger); + status = QDF_STATUS_E_INVAL; + goto out; + } + /* enable arp when active offload is true (ipv6 notifier) */ + status = pmo_tgt_enable_ns_offload_req(vdev, vdev_id); + break; + case pmo_apps_suspend: + if (psoc_ctx->psoc_cfg.active_mode_offload) { + pmo_info("active offload is enabled, skip in mode: %d", + trigger); + status = QDF_STATUS_E_INVAL; + goto out; + } + /* enable arp when active offload is false (apps suspend) */ + status = pmo_tgt_enable_ns_offload_req(vdev, vdev_id); + break; + default: + status = QDF_STATUS_E_INVAL; + pmo_err("invalid pmo trigger"); + break; + } +out: + PMO_EXIT(); + + return status; +} + +static QDF_STATUS pmo_core_do_disable_ns_offload(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id, enum pmo_offload_trigger trigger) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct pmo_psoc_priv_obj *psoc_ctx; + + PMO_ENTER(); + + psoc_ctx = pmo_vdev_get_psoc_priv(vdev); + + switch (trigger) { + case pmo_ipv6_change_notify: + case pmo_ns_offload_dynamic_update: + if (!psoc_ctx->psoc_cfg.active_mode_offload) { + pmo_info("active offload is disabled, skip in mode:%d", + trigger); + status = QDF_STATUS_E_INVAL; + goto out; + } + /* config ns when active offload is enable */ + status = pmo_tgt_disable_ns_offload_req(vdev, vdev_id); + break; + case pmo_apps_resume: + if (psoc_ctx->psoc_cfg.active_mode_offload) { + pmo_info("active offload is enabled, skip in mode: %d", + trigger); + status = QDF_STATUS_E_INVAL; + goto out; + } + /* config arp/ns when active offload is disable */ + status = pmo_tgt_disable_ns_offload_req(vdev, vdev_id); + break; + default: + status = QDF_STATUS_E_INVAL; + pmo_err("invalid pmo trigger"); + break; + } +out: + PMO_EXIT(); + + return status; +} + + +static QDF_STATUS pmo_core_ns_offload_sanity(struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.ns_offload_enable_static) { + pmo_info("ns offload statically disable"); + return QDF_STATUS_E_INVAL; + } + + if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.ns_offload_enable_dynamic) { + pmo_info("ns offload dynamically disable"); + return QDF_STATUS_E_INVAL; + } + + if (!pmo_core_is_vdev_supports_offload(vdev)) { + pmo_info("vdev in invalid opmode for ns offload %d", + pmo_get_vdev_opmode(vdev)); + return QDF_STATUS_E_INVAL; + } + + if (pmo_core_is_vdev_connected(vdev) == false) + return QDF_STATUS_E_INVAL; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_core_cache_ns_offload_req( + struct pmo_ns_req *ns_req) +{ + QDF_STATUS status; + struct wlan_objmgr_vdev *vdev; + + PMO_ENTER(); + if (!ns_req) { + pmo_err("ns is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + if (!ns_req->psoc) { + pmo_err("psoc is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + vdev = pmo_psoc_get_vdev(ns_req->psoc, ns_req->vdev_id); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + goto out; + + status = pmo_core_ns_offload_sanity(vdev); + if (status != QDF_STATUS_SUCCESS) + goto dec_ref; + + if (ns_req->count == 0) { + pmo_info("skip ns offload caching as ns count is 0"); + status = QDF_STATUS_E_INVAL; + goto dec_ref; + } + + status = pmo_core_cache_ns_in_vdev_priv(ns_req, vdev); +dec_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_flush_ns_offload_req(struct wlan_objmgr_vdev *vdev) +{ + QDF_STATUS status; + uint8_t vdev_id; + + PMO_ENTER(); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (status != QDF_STATUS_SUCCESS) + goto out; + + status = pmo_core_ns_offload_sanity(vdev); + if (status != QDF_STATUS_SUCCESS) + goto dec_ref; + + vdev_id = pmo_vdev_get_id(vdev); + pmo_info("Flush ns offload on vdev id: %d vdev: %p", vdev_id, vdev); + + status = pmo_core_flush_ns_from_vdev_priv(vdev); +dec_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_enable_ns_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger) +{ + QDF_STATUS status; + struct pmo_vdev_priv_obj *vdev_ctx; + uint8_t vdev_id; + + PMO_ENTER(); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (status != QDF_STATUS_SUCCESS) + goto out; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + status = pmo_core_ns_offload_sanity(vdev); + if (status != QDF_STATUS_SUCCESS) + goto dec_ref; + + if (trigger == pmo_ns_offload_dynamic_update) { + /* + * user disable ns offload using ioctl/vendor cmd dynamically. + */ + vdev_ctx->pmo_psoc_ctx->psoc_cfg.ns_offload_enable_dynamic = + true; + goto skip_ns_dynamic_check; + } + + if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.ns_offload_enable_dynamic) { + pmo_info("ns offload dynamically disable"); + status = QDF_STATUS_E_INVAL; + goto dec_ref; + } + +skip_ns_dynamic_check: + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + if (vdev_ctx->vdev_ns_req.num_ns_offload_count == 0) { + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + pmo_info("skip ns offload enable as ns count is 0"); + status = QDF_STATUS_E_INVAL; + goto out; + } + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + vdev_id = pmo_vdev_get_id(vdev); + pmo_info("Enable ns offload in fwr vdev id: %d vdev: %p trigger: %d", + vdev_id, vdev, trigger); + status = pmo_core_do_enable_ns_offload(vdev, vdev_id, trigger); +dec_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_disable_ns_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger) +{ + QDF_STATUS status; + uint8_t vdev_id; + struct pmo_vdev_priv_obj *vdev_ctx; + + PMO_ENTER(); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (status != QDF_STATUS_SUCCESS) + goto out; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + status = pmo_core_ns_offload_sanity(vdev); + if (status != QDF_STATUS_SUCCESS) + goto dec_ref; + + if (trigger == pmo_ns_offload_dynamic_update) { + /* + * user disable ns offload using ioctl/vendor cmd dynamically. + */ + vdev_ctx->pmo_psoc_ctx->psoc_cfg.ns_offload_enable_dynamic = + false; + goto skip_ns_dynamic_check; + } + + if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.ns_offload_enable_dynamic) { + pmo_info("ns offload dynamically disable"); + status = QDF_STATUS_E_INVAL; + goto dec_ref; + } + +skip_ns_dynamic_check: + vdev_id = pmo_vdev_get_id(vdev); + pmo_info("disable ns offload in fwr vdev id: %d vdev: %p trigger: %d", + vdev_id, vdev, trigger); + + status = pmo_core_do_disable_ns_offload(vdev, vdev_id, trigger); +dec_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + diff --git a/core/components/pmo/core/src/wlan_pmo_pkt_filter.c b/core/components/pmo/core/src/wlan_pmo_pkt_filter.c new file mode 100644 index 000000000000..a59e25dfa80b --- /dev/null +++ b/core/components/pmo/core/src/wlan_pmo_pkt_filter.c @@ -0,0 +1,96 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements Packet filter feature API's + */ + +#include "wlan_pmo_pkt_filter.h" +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_main.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" + +QDF_STATUS pmo_core_set_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_rcv_pkt_fltr_cfg *pmo_set_pkt_fltr_req, + uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + QDF_STATUS status; + + PMO_ENTER(); + + if (!psoc) { + pmo_err("psoc is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_PMO_ID); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_tgt_set_pkt_filter(vdev, pmo_set_pkt_fltr_req, vdev_id); + if (status != QDF_STATUS_SUCCESS) + goto dec_ref; + +dec_ref: + wlan_objmgr_vdev_release_ref(vdev, WLAN_PMO_ID); +out: + PMO_EXIT(); + + return status; + +} + +QDF_STATUS pmo_core_clear_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_rcv_pkt_fltr_clear_param *pmo_clr_pkt_fltr_param, + uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + QDF_STATUS status; + + PMO_ENTER(); + + if (!psoc) { + pmo_err("psoc is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_PMO_ID); + if (!vdev) { + pmo_err("vdev is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_tgt_clear_pkt_filter(vdev, pmo_clr_pkt_fltr_param, + vdev_id); + if (status != QDF_STATUS_SUCCESS) + goto dec_ref; + +dec_ref: + wlan_objmgr_vdev_release_ref(vdev, WLAN_PMO_ID); +out: + PMO_EXIT(); + + return status; + +} diff --git a/core/components/pmo/core/src/wlan_pmo_static_config.c b/core/components/pmo/core/src/wlan_pmo_static_config.c new file mode 100644 index 000000000000..b0653f35f618 --- /dev/null +++ b/core/components/pmo/core/src/wlan_pmo_static_config.c @@ -0,0 +1,380 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements static configuration on vdev attach + */ + +#include "wlan_pmo_static_config.h" +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_main.h" +#include "wlan_pmo_wow.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" + +static const uint8_t arp_ptrn[] = {0x08, 0x06}; +static const uint8_t arp_mask[] = {0xff, 0xff}; +static const uint8_t ns_ptrn[] = {0x86, 0xDD}; +static const uint8_t discvr_ptrn[] = {0xe0, 0x00, 0x00, 0xf8}; +static const uint8_t discvr_mask[] = {0xf0, 0x00, 0x00, 0xf8}; + +void pmo_register_wow_wakeup_events(struct wlan_objmgr_vdev *vdev) +{ + uint32_t event_bitmap[PMO_WOW_MAX_EVENT_BM_LEN] = {0}; + uint8_t vdev_id; + enum tQDF_ADAPTER_MODE vdev_opmode; + const char *iface_type; + + vdev_opmode = pmo_get_vdev_opmode(vdev); + vdev_id = pmo_vdev_get_id(vdev); + pmo_info("vdev_opmode %d vdev_id %d", vdev_opmode, vdev_id); + + switch (vdev_opmode) { + case QDF_P2P_CLIENT_MODE: + case QDF_P2P_DEVICE_MODE: + case QDF_OCB_MODE: + case QDF_STA_MODE: + case QDF_MONITOR_MODE: + iface_type = "STA"; + pmo_set_sta_wow_bitmask(event_bitmap, PMO_WOW_MAX_EVENT_BM_LEN); + break; + + case QDF_IBSS_MODE: + iface_type = "IBSS"; + pmo_set_sta_wow_bitmask(event_bitmap, PMO_WOW_MAX_EVENT_BM_LEN); + pmo_set_wow_event_bitmap(WOW_BEACON_EVENT, + PMO_WOW_MAX_EVENT_BM_LEN, + event_bitmap); + break; + + case QDF_P2P_GO_MODE: + case QDF_SAP_MODE: + iface_type = "SAP"; + pmo_set_sap_wow_bitmask(event_bitmap, PMO_WOW_MAX_EVENT_BM_LEN); + break; + + case QDF_NDI_MODE: +#ifdef WLAN_FEATURE_NAN_DATAPATH + iface_type = "NAN"; + pmo_set_wow_event_bitmap(WOW_NAN_DATA_EVENT, + PMO_WOW_MAX_EVENT_BM_LEN, + event_bitmap); +#endif + break; + + default: + pmo_err("Skipping wake event configuration for vdev_opmode %d", + vdev_opmode); + return; + } + + pmo_info("Selected %s wake event mask 0x%x%x%x%x, vdev %d", + iface_type, event_bitmap[0], event_bitmap[1], + event_bitmap[2], event_bitmap[3], vdev_id); + + pmo_tgt_enable_wow_wakeup_event(vdev, event_bitmap); +} + +/** + * pmo_configure_wow_ap() - set WOW patterns in ap mode + * @vdev: objmgr vdev handle + * + * Configures default WOW pattern for the given vdev_id which is in AP mode. + * + * Return: QDF status + */ +static QDF_STATUS pmo_configure_wow_ap(struct wlan_objmgr_vdev *vdev) +{ + QDF_STATUS ret; + uint8_t arp_offset = 20; + uint8_t mac_mask[PMO_80211_ADDR_LEN]; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + /* + * Setup unicast pkt pattern + * WoW pattern id should be unique for each vdev + * WoW pattern id can be same on 2 different VDEVs + */ + qdf_mem_set(&mac_mask, PMO_80211_ADDR_LEN, 0xFF); + ret = pmo_tgt_send_wow_patterns_to_fw(vdev, + pmo_get_and_increment_wow_default_ptrn(vdev_ctx), + wlan_vdev_mlme_get_macaddr(vdev), + PMO_80211_ADDR_LEN, 0, mac_mask, + PMO_80211_ADDR_LEN, false); + if (ret != QDF_STATUS_SUCCESS) { + pmo_err("Failed to add WOW unicast pattern ret %d", ret); + return ret; + } + + /* + * Setup all ARP pkt pattern. This is dummy pattern hence the length + * is zero. Pattern ID should be unique per vdev. + */ + ret = pmo_tgt_send_wow_patterns_to_fw(vdev, + pmo_get_and_increment_wow_default_ptrn(vdev_ctx), + arp_ptrn, 0, arp_offset, arp_mask, 0, false); + if (ret != QDF_STATUS_SUCCESS) + pmo_err("Failed to add WOW ARP pattern ret %d", ret); + + return ret; +} + +/** + * pmo_configure_mc_ssdp() - API to configure SSDP address as MC list + *@vdev: objmgr vdev handle. + * + * SSDP address 239.255.255.250 is converted to Multicast Mac address + * and configure it to FW. Firmware will apply this pattern on the incoming + * packets to filter them out during chatter/wow mode. + * + * Return: Success/Failure + */ +static QDF_STATUS pmo_configure_mc_ssdp( + struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_psoc *psoc; + const uint8_t ssdp_addr[QDF_MAC_ADDR_SIZE] = { + 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xfa }; + struct qdf_mac_addr multicast_addr; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + psoc = pmo_vdev_get_psoc(vdev); + + qdf_mem_copy(&multicast_addr.bytes, &ssdp_addr, QDF_MAC_ADDR_SIZE); + status = pmo_tgt_set_mc_filter_req(vdev, + multicast_addr); + if (status != QDF_STATUS_SUCCESS) + pmo_err("unable to set ssdp as mc addr list filter"); + + return status; +} + +/** + * pmo_configure_wow_ssdp() - API to configure WoW SSDP + *@vdev: objmgr vdev handle + * + * API to configure SSDP pattern as WoW pattern + * + * Return: Success/Failure + */ +static QDF_STATUS pmo_configure_wow_ssdp( + struct wlan_objmgr_vdev *vdev) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + uint8_t discvr_offset = 30; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + /* + * WoW pattern ID should be unique for each vdev + * Different WoW patterns can use same pattern ID + */ + status = pmo_tgt_send_wow_patterns_to_fw(vdev, + pmo_get_and_increment_wow_default_ptrn(vdev_ctx), + discvr_ptrn, sizeof(discvr_ptrn), discvr_offset, + discvr_mask, sizeof(discvr_ptrn), false); + + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to add WOW mDNS/SSDP/LLMNR pattern"); + + return status; +} + +/** + * pmo_configure_ssdp() - API to Configure SSDP pattern to FW + *@vdev: objmgr vdev handle + * + * Setup multicast pattern for mDNS 224.0.0.251, SSDP 239.255.255.250 and LLMNR + * 224.0.0.252 + * + * Return: Success/Failure. + */ +static QDF_STATUS pmo_configure_ssdp(struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.ssdp) { + pmo_err("mDNS, SSDP, LLMNR patterns are disabled from ini"); + return QDF_STATUS_SUCCESS; + } + + pmo_debug("enable_mc_list:%d", + vdev_ctx->pmo_psoc_ctx->psoc_cfg.enable_mc_list); + + if (vdev_ctx->pmo_psoc_ctx->psoc_cfg.enable_mc_list) + return pmo_configure_mc_ssdp(vdev); + + return pmo_configure_wow_ssdp(vdev); +} + +/** + * pmo_configure_wow_sta() - set WOW patterns in sta mode + * @vdev: objmgr vdev handle + * + * Configures default WOW pattern for the given vdev_id which is in sta mode. + * + * Return: QDF status + */ +static QDF_STATUS pmo_configure_wow_sta(struct wlan_objmgr_vdev *vdev) +{ + uint8_t arp_offset = 12; + uint8_t mac_mask[PMO_80211_ADDR_LEN]; + QDF_STATUS ret = QDF_STATUS_SUCCESS; + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + qdf_mem_set(&mac_mask, PMO_80211_ADDR_LEN, 0xFF); + /* + * Set up unicast wow pattern + * WoW pattern ID should be unique for each vdev + * Different WoW patterns can use same pattern ID + */ + ret = pmo_tgt_send_wow_patterns_to_fw(vdev, + pmo_get_and_increment_wow_default_ptrn(vdev_ctx), + wlan_vdev_mlme_get_macaddr(vdev), + PMO_80211_ADDR_LEN, 0, mac_mask, + PMO_80211_ADDR_LEN, false); + if (ret != QDF_STATUS_SUCCESS) { + pmo_err("Failed to add WOW unicast pattern ret %d", ret); + return ret; + } + + ret = pmo_configure_ssdp(vdev); + if (ret != QDF_STATUS_SUCCESS) + pmo_err("Failed to configure SSDP patterns to FW"); + + /* + * when arp offload or ns offloaded is disabled + * from ini file, configure broad cast arp pattern + * to fw, so that host can wake up + */ + if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.arp_offload_enable) { + /* Setup all ARP pkt pattern */ + pmo_info("ARP offload is disabled in INI enable WoW for ARP"); + ret = pmo_tgt_send_wow_patterns_to_fw(vdev, + pmo_get_and_increment_wow_default_ptrn( + vdev_ctx), + arp_ptrn, sizeof(arp_ptrn), arp_offset, + arp_mask, sizeof(arp_mask), false); + if (ret != QDF_STATUS_SUCCESS) { + pmo_err("Failed to add WOW ARP pattern"); + return ret; + } + } + /* for NS or NDP offload packets */ + if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.ns_offload_enable_static) { + /* Setup all NS pkt pattern */ + pmo_info("NS offload is disabled in INI enable WoW for NS"); + ret = pmo_tgt_send_wow_patterns_to_fw(vdev, + pmo_get_and_increment_wow_default_ptrn( + vdev_ctx), + ns_ptrn, sizeof(arp_ptrn), arp_offset, + arp_mask, sizeof(arp_mask), false); + if (ret != QDF_STATUS_SUCCESS) { + pmo_err("Failed to add WOW NS pattern"); + return ret; + } + } + + return ret; +} + +void pmo_register_wow_default_patterns(struct wlan_objmgr_vdev *vdev) +{ + enum tQDF_ADAPTER_MODE vdev_opmode = QDF_MAX_NO_OF_MODE; + struct pmo_vdev_priv_obj *vdev_ctx; + uint8_t vdev_id; + struct pmo_psoc_priv_obj *psoc_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + vdev_id = pmo_vdev_get_id(vdev); + if (vdev_id > WLAN_UMAC_PSOC_MAX_VDEVS) { + pmo_err("Invalid vdev id %d", vdev_id); + return; + } + + vdev_opmode = pmo_get_vdev_opmode(vdev); + if (vdev_opmode == QDF_MAX_NO_OF_MODE) { + pmo_err("Invalid vdev opmode %d", vdev_id); + return; + } + + if (!vdev_ctx->ptrn_match_enable) { + pmo_err("ptrn_match is disable for vdev %d", vdev_id); + return; + } + + if (pmo_is_vdev_in_beaconning_mode(vdev_opmode)) { + /* Configure SAP/GO/IBSS mode default wow patterns */ + pmo_info("Config SAP default wow patterns vdev_id %d", + vdev_id); + pmo_configure_wow_ap(vdev); + } else { + /* Configure STA/P2P CLI mode default wow patterns */ + pmo_info("Config STA default wow patterns vdev_id %d", + vdev_id); + pmo_configure_wow_sta(vdev); + psoc_ctx = vdev_ctx->pmo_psoc_ctx; + if (psoc_ctx && psoc_ctx->psoc_cfg.ra_ratelimit_enable) { + pmo_info("Config STA RA wow pattern vdev_id %d", + vdev_id); + pmo_tgt_send_ra_filter_req(vdev); + } + } + +} + +void pmo_register_action_frame_patterns(struct wlan_objmgr_vdev *vdev) +{ + + struct pmo_action_wakeup_set_params cmd = {0}; + int i = 0; + QDF_STATUS status; + + cmd.vdev_id = pmo_vdev_get_id(vdev); + cmd.operation = pmo_action_wakeup_set; + + cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP0; + cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP1; + cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP2; + cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP3; + cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP4; + cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP5; + cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP6; + cmd.action_category_map[i++] = ALLOWED_ACTION_FRAMES_BITMAP7; + + for (i = 0; i < PMO_SUPPORTED_ACTION_CATE_ELE_LIST; i++) { + if (i < ALLOWED_ACTION_FRAME_MAP_WORDS) + pmo_debug("%s: %d action Wakeup pattern 0x%x in fw", + __func__, i, cmd.action_category_map[i]); + else + cmd.action_category_map[i] = 0; + } + + /* config action frame patterns */ + status = pmo_tgt_send_action_frame_pattern_req(vdev, &cmd); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to config wow action frame map, ret %d", + status); +} + diff --git a/core/components/pmo/core/src/wlan_pmo_suspend_resume.c b/core/components/pmo/core/src/wlan_pmo_suspend_resume.c new file mode 100644 index 000000000000..65e3a20e81c7 --- /dev/null +++ b/core/components/pmo/core/src/wlan_pmo_suspend_resume.c @@ -0,0 +1,1225 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Define API's for suspend / resume handling + */ + +#include "wlan_pmo_wow.h" +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_main.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" +#include "wlan_pmo_lphb.h" +#include "wlan_pmo_suspend_resume.h" +#include "cdp_txrx_ops.h" +#include "cdp_txrx_misc.h" +#include "cdp_txrx_flow_ctrl_legacy.h" +#include "hif.h" +#include "htc_api.h" +#include "wlan_pmo_obj_mgmt_api.h" +#include +#include "cds_api.h" +#include "wlan_pmo_static_config.h" + +/** + * pmo_core_calculate_listen_interval() - Calculate vdev listen interval + * @vdev: objmgr vdev handle + * @vdev_ctx: pmo vdev priv ctx + * @listen_interval: listen interval which is computed for vdev + * + * Return: QDF_STATUS + */ +static QDF_STATUS pmo_core_calculate_listen_interval( + struct wlan_objmgr_vdev *vdev, + struct pmo_vdev_priv_obj *vdev_ctx, + uint32_t *listen_interval) +{ + uint32_t max_mod_dtim; + uint32_t beacon_interval_mod; + struct pmo_psoc_cfg *psoc_cfg = &vdev_ctx->pmo_psoc_ctx->psoc_cfg; + + if (psoc_cfg->sta_dynamic_dtim) { + *listen_interval = psoc_cfg->sta_dynamic_dtim; + } else if ((psoc_cfg->sta_mod_dtim) && + (psoc_cfg->sta_max_li_mod_dtim)) { + /* + * When the system is in suspend + * (maximum beacon will be at 1s == 10) + * If maxModulatedDTIM ((MAX_LI_VAL = 10) / AP_DTIM) + * equal or larger than MDTIM + * (configured in WCNSS_qcom_cfg.ini) + * Set LI to MDTIM * AP_DTIM + * If Dtim = 2 and Mdtim = 2 then LI is 4 + * Else + * Set LI to maxModulatedDTIM * AP_DTIM + */ + beacon_interval_mod = + pmo_core_get_vdev_beacon_interval(vdev) / 100; + if (beacon_interval_mod == 0) + beacon_interval_mod = 1; + + max_mod_dtim = psoc_cfg->sta_max_li_mod_dtim / + (pmo_core_get_vdev_dtim_period(vdev) + * beacon_interval_mod); + + if (max_mod_dtim <= 0) + max_mod_dtim = 1; + + if (max_mod_dtim >= psoc_cfg->sta_mod_dtim) { + *listen_interval = + (psoc_cfg->sta_mod_dtim * + pmo_core_get_vdev_dtim_period(vdev)); + } else { + *listen_interval = + (max_mod_dtim * + pmo_core_get_vdev_dtim_period(vdev)); + } + } else { + return QDF_STATUS_E_FAULT; + } + return QDF_STATUS_SUCCESS; +} + +/** + * pmo_core_set_vdev_suspend_dtim() - set suspend dtim parameters in fw + * @psoc: objmgr psoc handle + * @vdev: objmgr vdev handle + * @vdev_ctx: pmo vdev priv ctx + * + * Return: none + */ +static void pmo_core_set_vdev_suspend_dtim(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev, + struct pmo_vdev_priv_obj *vdev_ctx) +{ + uint32_t listen_interval; + QDF_STATUS ret; + uint8_t vdev_id; + enum pmo_power_save_qpower_mode qpower_config; + enum tQDF_ADAPTER_MODE opmode = pmo_core_get_vdev_op_mode(vdev); + + qpower_config = pmo_core_psoc_get_qpower_config(psoc); + vdev_id = pmo_vdev_get_id(vdev); + if (PMO_VDEV_IN_STA_MODE(opmode) && + pmo_core_get_vdev_dtim_period(vdev) != 0) { + /* calculate listen interval */ + ret = pmo_core_calculate_listen_interval(vdev, vdev_ctx, + &listen_interval); + if (ret != QDF_STATUS_SUCCESS) { + /* even it fails continue fwr will take default LI */ + pmo_info("Fail to calculate listen interval"); + } + + ret = pmo_tgt_vdev_update_param_req(vdev, + pmo_vdev_param_listen_interval, + listen_interval); + if (QDF_IS_STATUS_ERROR(ret)) { + /* even it fails continue fwr will take default LI */ + pmo_info("Failed to Set Listen Interval vdevId %d", + vdev_id); + } + pmo_debug("Set Listen Interval vdevId %d Listen Intv %d", + vdev_id, listen_interval); + + if (qpower_config) { + pmo_debug("disable Qpower in suspend mode!"); + ret = pmo_tgt_send_vdev_sta_ps_param(vdev, + pmo_sta_ps_enable_qpower, 0); + if (QDF_IS_STATUS_ERROR(ret)) + pmo_info("Failed to disable Qpower in suspend mode!"); + } + + ret = pmo_tgt_vdev_update_param_req(vdev, + pmo_vdev_param_dtim_policy, + pmo_normal_dtim); + if (QDF_IS_STATUS_ERROR(ret)) + pmo_info("Failed to Set to Normal DTIM vdevId %d", + vdev_id); + + /* Set it to Normal DTIM */ + pmo_core_vdev_set_dtim_policy(vdev, pmo_normal_dtim); + pmo_debug("Set DTIM Policy to Normal Dtim vdevId %d", vdev_id); + } +} + +/** + * pmo_core_set_suspend_dtim() - set suspend dtim + * @psoc: objmgr psoc handle + * + * Return: none + */ +static void pmo_core_set_suspend_dtim(struct wlan_objmgr_psoc *psoc) +{ + uint8_t vdev_id; + struct wlan_objmgr_vdev *vdev; + struct pmo_vdev_priv_obj *vdev_ctx; + bool alt_mdtim_enabled; + QDF_STATUS status; + + /* Iterate through VDEV list */ + for (vdev_id = 0; vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS; vdev_id++) { + vdev = pmo_psoc_get_vdev(psoc, vdev_id); + if (!vdev) + continue; + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + continue; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + alt_mdtim_enabled = vdev_ctx->alt_modulated_dtim_enable; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + if (!alt_mdtim_enabled) + pmo_core_set_vdev_suspend_dtim(psoc, vdev, vdev_ctx); + + pmo_vdev_put_ref(vdev); + } +} + +/** + * pmo_core_update_wow_bus_suspend() - set wow bus suspend flag + * @psoc: objmgr psoc handle + * @psoc_ctx: pmo psoc priv ctx + * @val: true for enable else false + * Return: none + */ +static inline +void pmo_core_update_wow_bus_suspend(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_priv_obj *psoc_ctx, int val) +{ + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->wow.is_wow_bus_suspended = val; + qdf_spin_unlock_bh(&psoc_ctx->lock); + pmo_tgt_psoc_update_wow_bus_suspend_state(psoc, val); +} + +/* Define for conciseness */ +#define BM_LEN PMO_WOW_MAX_EVENT_BM_LEN +#define EV_NLO WOW_NLO_SCAN_COMPLETE_EVENT +#define EV_PWR WOW_CHIP_POWER_FAILURE_DETECT_EVENT + +void pmo_core_configure_dynamic_wake_events(struct wlan_objmgr_psoc *psoc) +{ + int vdev_id; + uint32_t adapter_type; + uint32_t enable_mask[BM_LEN]; + uint32_t disable_mask[BM_LEN]; + struct wlan_objmgr_vdev *vdev; + struct pmo_psoc_priv_obj *psoc_ctx; + bool enable_configured; + bool disable_configured; + + /* Iterate through VDEV list */ + for (vdev_id = 0; vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS; vdev_id++) { + + enable_configured = false; + disable_configured = false; + + qdf_mem_set(enable_mask, sizeof(uint32_t) * BM_LEN, 0); + qdf_mem_set(disable_mask, sizeof(uint32_t) * BM_LEN, 0); + + vdev = pmo_psoc_get_vdev(psoc, vdev_id); + if (!vdev) + continue; + + if (ucfg_scan_get_pno_in_progress(vdev)) { + if (ucfg_scan_get_pno_match(vdev)) { + pmo_set_wow_event_bitmap(EV_NLO, + BM_LEN, + enable_mask); + enable_configured = true; + } else { + pmo_set_wow_event_bitmap(EV_NLO, + BM_LEN, + disable_mask); + disable_configured = true; + } + } + + adapter_type = pmo_get_vdev_opmode(vdev); + + psoc_ctx = pmo_psoc_get_priv(psoc); + + if (psoc_ctx->psoc_cfg.auto_power_save_fail_mode && + (adapter_type == QDF_STA_MODE || + adapter_type == QDF_P2P_CLIENT_MODE) + ) { + if (psoc_ctx->is_device_in_low_pwr_mode && + psoc_ctx->is_device_in_low_pwr_mode(vdev_id)) + pmo_set_wow_event_bitmap(EV_PWR, + BM_LEN, + enable_mask); + pmo_core_enable_wakeup_event(psoc, vdev_id, + enable_mask); + enable_configured = true; + } + if (enable_configured) + pmo_core_enable_wakeup_event(psoc, vdev_id, + enable_mask); + + if (disable_configured) + pmo_core_disable_wakeup_event(psoc, vdev_id, + disable_mask); + } + +} + +/** + * pmo_core_psoc_configure_suspend(): configure suspend req events + * @psoc: objmgr psoc + * + * Responsibility of the caller to take the psoc reference. + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +static QDF_STATUS pmo_core_psoc_configure_suspend(struct wlan_objmgr_psoc *psoc) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + + PMO_ENTER(); + + psoc_ctx = pmo_psoc_get_priv(psoc); + + if (pmo_core_is_wow_applicable(psoc)) { + pmo_info("WOW Suspend"); + pmo_core_apply_lphb(psoc); + + pmo_core_configure_dynamic_wake_events(psoc); + pmo_core_update_wow_enable(psoc_ctx, true); + pmo_core_update_wow_enable_cmd_sent(psoc_ctx, false); + } + + pmo_core_set_suspend_dtim(psoc); + + /* + * To handle race between hif_pci_suspend and unpause/pause tx handler. + * This happens when host sending WMI_WOW_ENABLE_CMDID to FW and receive + * WMI_TX_PAUSE_EVENT with ACTON_UNPAUSE almost at same time. + */ + pmo_core_update_wow_bus_suspend(psoc, psoc_ctx, true); + + PMO_EXIT(); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_core_psoc_user_space_suspend_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type) +{ + QDF_STATUS status; + + PMO_ENTER(); + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("pmo cannot get the reference out of psoc"); + goto out; + } + + /* Suspend all components before sending target suspend command */ + status = pmo_suspend_all_components(psoc, type); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("Failed to suspend all component"); + goto dec_psoc_ref; + } + + status = pmo_core_psoc_configure_suspend(psoc); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to configure suspend"); + +dec_psoc_ref: + pmo_psoc_put_ref(psoc); +out: + PMO_EXIT(); + + return status; +} + +/** + * pmo_core_set_vdev_resume_dtim() - set resume dtim parameters in fw + * @psoc: objmgr psoc handle + * @vdev: objmgr vdev handle + * @vdev_ctx: pmo vdev priv ctx + * + * Return: none + */ +static void pmo_core_set_vdev_resume_dtim(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev, + struct pmo_vdev_priv_obj *vdev_ctx) +{ + enum pmo_power_save_qpower_mode qpower_config; + QDF_STATUS ret; + uint8_t vdev_id; + enum tQDF_ADAPTER_MODE opmode = pmo_core_get_vdev_op_mode(vdev); + uint32_t cfg_data_val = 0; + + qpower_config = pmo_core_psoc_get_qpower_config(psoc); + vdev_id = pmo_vdev_get_id(vdev); + if ((PMO_VDEV_IN_STA_MODE(opmode)) && + (pmo_core_vdev_get_dtim_policy(vdev) == pmo_normal_dtim)) { +/* + if (!mac) { + WMA_LOGE(FL("Failed to get mac context")); + return; + } + if ((wlan_cfg_get_int(mac, WNI_CFG_LISTEN_INTERVAL, + &cfg_data_val) != eSIR_SUCCESS)) { + pmo_err("Failed to get value for listen interval"); + cfg_data_val = POWERSAVE_DEFAULT_LISTEN_INTERVAL; + } +*/ + cfg_data_val = 1; + ret = pmo_tgt_vdev_update_param_req(vdev, + pmo_vdev_param_listen_interval, cfg_data_val); + if (QDF_IS_STATUS_ERROR(ret)) { + /* Even it fails continue Fw will take default LI */ + pmo_err("Failed to Set Listen Interval vdevId %d", + vdev_id); + } + pmo_debug("Set Listen Interval vdevId %d Listen Intv %d", + vdev_id, cfg_data_val); + + ret = pmo_tgt_vdev_update_param_req(vdev, + pmo_vdev_param_dtim_policy, + pmo_stick_dtim); + if (QDF_IS_STATUS_ERROR(ret)) { + /* Set it back to Stick DTIM */ + pmo_err("Failed to Set to Stick DTIM vdevId %d", + vdev_id); + } + pmo_core_vdev_set_dtim_policy(vdev, pmo_stick_dtim); + pmo_debug("Set DTIM Policy to Stick Dtim vdevId %d", vdev_id); + + if (qpower_config) { + pmo_debug("enable Qpower in resume mode!"); + ret = pmo_tgt_send_vdev_sta_ps_param(vdev, + pmo_sta_ps_enable_qpower, qpower_config); + if (QDF_IS_STATUS_ERROR(ret)) + pmo_err("Failed to enable Qpower in resume"); + } + } +} + +/** + * pmo_core_set_resume_dtim() - set resume time dtim + * @psoc: objmgr psoc handle + * + * Return: none + */ +static void pmo_core_set_resume_dtim(struct wlan_objmgr_psoc *psoc) +{ + uint8_t vdev_id; + struct wlan_objmgr_vdev *vdev; + struct pmo_vdev_priv_obj *vdev_ctx; + bool alt_mdtim_enabled; + QDF_STATUS status; + + /* Iterate through VDEV list */ + for (vdev_id = 0; vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS; vdev_id++) { + vdev = pmo_psoc_get_vdev(psoc, vdev_id); + if (!vdev) + continue; + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + continue; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + alt_mdtim_enabled = vdev_ctx->alt_modulated_dtim_enable; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + if (!alt_mdtim_enabled) + pmo_core_set_vdev_resume_dtim(psoc, vdev, vdev_ctx); + + pmo_vdev_put_ref(vdev); + } +} + +/** + * pmo_unpause_vdev - unpause all vdev + * @psoc: objmgr psoc handle + * + * unpause all vdev aftter resume/coming out of wow mode + * + * Return: none + */ +static void pmo_unpause_all_vdev(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_priv_obj *psoc_ctx) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc_objmgr *objmgr; + struct wlan_objmgr_vdev *vdev; + + /* Iterate through VDEV list */ + for (vdev_id = 0; vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS; vdev_id++) { + wlan_psoc_obj_lock(psoc); + objmgr = &psoc->soc_objmgr; + if (!objmgr->wlan_vdev_list[vdev_id]) { + wlan_psoc_obj_unlock(psoc); + continue; + } + vdev = objmgr->wlan_vdev_list[vdev_id]; + wlan_psoc_obj_unlock(psoc); + if (vdev) { +#if defined(QCA_LL_LEGACY_TX_FLOW_CONTROL) || defined(QCA_LL_TX_FLOW_CONTROL_V2) + /* + * When host resume, by default, + * unpause all active vdev + */ + if (pmo_core_vdev_get_pause_bitmap(psoc_ctx, vdev_id)) { + cdp_fc_vdev_unpause( + pmo_core_psoc_get_dp_handle(psoc), + pmo_core_vdev_get_dp_handle(vdev), + 0xffffffff); + if (psoc_ctx->pause_bitmap_notifier) + psoc_ctx->pause_bitmap_notifier(vdev_id, + 0); + } +#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ + } + } +} + +/** + * pmo_core_psoc_configure_resume(): configure events after bus resume + * @psoc: objmgr psoc + * + * Responsibility of the caller to take the psoc reference. + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +static QDF_STATUS pmo_core_psoc_configure_resume(struct wlan_objmgr_psoc *psoc) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + + PMO_ENTER(); + + psoc_ctx = pmo_psoc_get_priv(psoc); + + pmo_core_set_resume_dtim(psoc); + pmo_core_update_wow_bus_suspend(psoc, psoc_ctx, false); + pmo_unpause_all_vdev(psoc, psoc_ctx); + + PMO_EXIT(); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_core_psoc_user_space_resume_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + PMO_ENTER(); + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("pmo cannot get the reference out of psoc"); + goto out; + } + + /* Resume all components */ + status = pmo_resume_all_components(psoc, type); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("Failed to resume all the components"); + goto dec_psoc_ref; + } + + status = pmo_core_psoc_configure_resume(psoc); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to configure resume"); + +dec_psoc_ref: + pmo_psoc_put_ref(psoc); +out: + PMO_EXIT(); + + return status; +} + +/** + * pmo_core_enable_wow_in_fw() - enable wow in fw + * @psoc: objmgr psoc handle + * @psoc_ctx: pmo psoc private ctx + * @wow_params: collection of wow enable override parameters + * + * Return: QDF status + */ +static +QDF_STATUS pmo_core_enable_wow_in_fw(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_priv_obj *psoc_ctx, + struct pmo_wow_enable_params *wow_params) +{ + int host_credits, wmi_pending_cmds; + struct pmo_wow_cmd_params param = {0}; + QDF_STATUS status; + + PMO_ENTER(); + qdf_event_reset(&psoc_ctx->wow.target_suspend); + pmo_core_set_wow_nack(psoc_ctx, false); + host_credits = pmo_tgt_psoc_get_host_credits(psoc); + wmi_pending_cmds = pmo_tgt_psoc_get_pending_cmnds(psoc); + pmo_debug("Credits:%d; Pending_Cmds: %d", + host_credits, wmi_pending_cmds); + + param.enable = true; + if (wow_params->is_unit_test) + param.flags = WMI_WOW_FLAG_UNIT_TEST_ENABLE; + + switch (wow_params->interface_pause) { + default: + pmo_err("Invalid interface pause setting: %d", + wow_params->interface_pause); + /* intentional fall-through to default */ + case PMO_WOW_INTERFACE_PAUSE_DEFAULT: + param.can_suspend_link = + htc_can_suspend_link( + pmo_core_psoc_get_htc_handle(psoc)); + break; + case PMO_WOW_INTERFACE_PAUSE_ENABLE: + param.can_suspend_link = true; + break; + case PMO_WOW_INTERFACE_PAUSE_DISABLE: + param.can_suspend_link = false; + break; + } + + switch (wow_params->resume_trigger) { + default: + pmo_err("Invalid resume trigger setting: %d", + wow_params->resume_trigger); + /* intentional fall-through to default */ + case PMO_WOW_RESUME_TRIGGER_DEFAULT: + case PMO_WOW_RESUME_TRIGGER_GPIO: + /* + * GPIO is currently implicit. This means you can't actually + * force GPIO if a platform's default wake trigger is HTC wakeup + */ + break; + case PMO_WOW_RESUME_TRIGGER_HTC_WAKEUP: + param.flags |= WMI_WOW_FLAG_DO_HTC_WAKEUP; + break; + } + + status = pmo_tgt_psoc_send_wow_enable_req(psoc, ¶m); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("Failed to enable wow in fw"); + goto out; + } + + pmo_tgt_update_target_suspend_flag(psoc, true); + + if (qdf_wait_single_event(&psoc_ctx->wow.target_suspend, + PMO_TGT_SUSPEND_COMPLETE_TIMEOUT) + != QDF_STATUS_SUCCESS) { + pmo_err("Failed to receive WoW Enable Ack from FW"); + pmo_err("Credits:%d; Pending_Cmds: %d", + pmo_tgt_psoc_get_host_credits(psoc), + pmo_tgt_psoc_get_pending_cmnds(psoc)); + pmo_tgt_update_target_suspend_flag(psoc, false); + status = QDF_STATUS_E_FAILURE; + QDF_BUG(0); + goto out; + } + + if (pmo_core_get_wow_nack(psoc_ctx)) { + pmo_err("FW not ready to WOW"); + pmo_tgt_update_target_suspend_flag(psoc, false); + status = QDF_STATUS_E_AGAIN; + goto out; + } + + host_credits = pmo_tgt_psoc_get_host_credits(psoc); + wmi_pending_cmds = pmo_tgt_psoc_get_pending_cmnds(psoc); + + if (host_credits < PMO_WOW_REQUIRED_CREDITS) { + pmo_err("No Credits after HTC ACK:%d, pending_cmds:%d," + "cannot resume back", host_credits, wmi_pending_cmds); + htc_dump_counter_info(pmo_core_psoc_get_htc_handle(psoc)); +/* + if (!cds_is_driver_recovering()) + QDF_BUG(0); + else + pmo_err("SSR in progress, ignore no credit issue"); +*/ + } + pmo_debug("WOW enabled successfully in fw: credits:%d pending_cmds: %d", + host_credits, wmi_pending_cmds); + + pmo_core_update_wow_enable_cmd_sent(psoc_ctx, true); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_psoc_suspend_target(struct wlan_objmgr_psoc *psoc, + int disable_target_intr) +{ + QDF_STATUS status; + struct pmo_suspend_params param; + struct pmo_psoc_priv_obj *psoc_ctx; + + PMO_ENTER(); + + psoc_ctx = pmo_psoc_get_priv(psoc); + + qdf_event_reset(&psoc_ctx->wow.target_suspend); + param.disable_target_intr = disable_target_intr; + status = pmo_tgt_psoc_send_supend_req(psoc, ¶m); + if (status != QDF_STATUS_SUCCESS) + goto out; + + pmo_tgt_update_target_suspend_flag(psoc, true); + + if (qdf_wait_single_event(&psoc_ctx->wow.target_suspend, + PMO_TGT_SUSPEND_COMPLETE_TIMEOUT) + != QDF_STATUS_SUCCESS) { + status = QDF_STATUS_E_TIMEOUT; + pmo_err("Failed to get ACK from firmware for pdev suspend"); + pmo_tgt_update_target_suspend_flag(psoc, false); + /* wma_suspend_target_timeout(pmac->sme.enableSelfRecovery); */ + } +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_psoc_bus_suspend_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type, + struct pmo_wow_enable_params *wow_params) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + QDF_STATUS status; + bool wow_mode_selected = false; + + PMO_ENTER(); + if (!psoc) { + pmo_err("psoc is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + if (!wow_params) { + pmo_err("wow_params is NULL"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("pmo cannot get the reference out of psoc"); + goto out; + } + + psoc_ctx = pmo_psoc_get_priv(psoc); + +/* TODO - scan manager need to provide the below public api + if (wma_check_scan_in_progress(handle)) { + pmo_err("Scan in progress. Aborting suspend"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } +*/ + + wow_mode_selected = pmo_core_is_wow_enabled(psoc_ctx); + pmo_info("wow mode selected %d", wow_mode_selected); + + if (wow_mode_selected) + status = pmo_core_enable_wow_in_fw(psoc, psoc_ctx, wow_params); + else + status = pmo_core_psoc_suspend_target(psoc, 0); + + pmo_psoc_put_ref(psoc); +out: + PMO_EXIT(); + + return status; +} + +#ifdef FEATURE_RUNTIME_PM +QDF_STATUS pmo_core_psoc_bus_runtime_suspend(struct wlan_objmgr_psoc *psoc, + pmo_pld_auto_suspend_cb pld_cb) +{ + void *hif_ctx; + void *dp_soc; + void *txrx_pdev; + void *htc_ctx; + QDF_STATUS status; + struct pmo_wow_enable_params wow_params = {0}; + + PMO_ENTER(); + + if (!psoc) { + pmo_err("psoc is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("pmo cannot get the reference out of psoc"); + goto out; + } + + hif_ctx = pmo_core_psoc_get_hif_handle(psoc); + dp_soc = pmo_core_psoc_get_dp_handle(psoc); + txrx_pdev = pmo_core_psoc_get_txrx_handle(psoc); + htc_ctx = pmo_core_psoc_get_htc_handle(psoc); + if (!hif_ctx || !dp_soc || !txrx_pdev || !htc_ctx) { + pmo_err("Invalid hif: %p, dp: %p, txrx: %p, htc: %p", + hif_ctx, dp_soc, txrx_pdev, htc_ctx); + status = QDF_STATUS_E_INVAL; + goto dec_psoc_ref; + } + + wow_params.interface_pause = PMO_WOW_INTERFACE_PAUSE_ENABLE; + wow_params.resume_trigger = PMO_WOW_RESUME_TRIGGER_GPIO; + + if (hif_pre_runtime_suspend(hif_ctx)) + goto runtime_failure; + + status = cdp_runtime_suspend(dp_soc, txrx_pdev); + if (status != QDF_STATUS_SUCCESS) + goto runtime_failure; + + if (htc_runtime_suspend(htc_ctx)) + goto cdp_runtime_resume; + + status = pmo_tgt_psoc_set_runtime_pm_inprogress(psoc, true); + if (status != QDF_STATUS_SUCCESS) + goto resume_htc; + + status = pmo_core_psoc_configure_suspend(psoc); + if (status != QDF_STATUS_SUCCESS) + goto resume_htc; + + status = pmo_core_psoc_bus_suspend_req(psoc, QDF_RUNTIME_SUSPEND, + &wow_params); + if (status != QDF_STATUS_SUCCESS) + goto pmo_resume_configure; + + if (hif_runtime_suspend(hif_ctx)) + goto pmo_bus_resume; + + if (pld_cb && pld_cb()) + goto resume_hif; + + hif_process_runtime_suspend_success(hif_ctx); + + goto dec_psoc_ref; + +resume_hif: + QDF_BUG(!hif_runtime_resume(hif_ctx)); + +pmo_bus_resume: + QDF_BUG(QDF_STATUS_SUCCESS == + pmo_core_psoc_bus_resume_req(psoc, QDF_RUNTIME_SUSPEND)); + +pmo_resume_configure: + QDF_BUG(QDF_STATUS_SUCCESS == + pmo_core_psoc_configure_resume(psoc)); + +resume_htc: + QDF_BUG(QDF_STATUS_SUCCESS == + pmo_tgt_psoc_set_runtime_pm_inprogress(psoc, false)); + + QDF_BUG(!htc_runtime_resume(htc_ctx)); + +cdp_runtime_resume: + QDF_BUG(QDF_STATUS_SUCCESS == + cdp_runtime_resume(dp_soc, txrx_pdev)); + +runtime_failure: + hif_process_runtime_suspend_failure(hif_ctx); + +dec_psoc_ref: + pmo_psoc_put_ref(psoc); + +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_psoc_bus_runtime_resume(struct wlan_objmgr_psoc *psoc, + pmo_pld_auto_resume_cb pld_cb) +{ + void *hif_ctx; + void *dp_soc; + void *txrx_pdev; + void *htc_ctx; + QDF_STATUS status; + + PMO_ENTER(); + + if (!psoc) { + pmo_err("psoc is NULL"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("pmo cannot get the reference out of psoc"); + goto out; + } + + hif_ctx = pmo_core_psoc_get_hif_handle(psoc); + dp_soc = pmo_core_psoc_get_dp_handle(psoc); + txrx_pdev = pmo_core_psoc_get_txrx_handle(psoc); + htc_ctx = pmo_core_psoc_get_htc_handle(psoc); + if (!hif_ctx || !dp_soc || !txrx_pdev || !htc_ctx) { + pmo_err("Invalid hif: %p, dp: %p, txrx: %p, htc: %p", + hif_ctx, dp_soc, txrx_pdev, htc_ctx); + status = QDF_STATUS_E_INVAL; + goto dec_psoc_ref; + } + + hif_pre_runtime_resume(hif_ctx); + + if (pld_cb) + QDF_BUG(!pld_cb()); + + QDF_BUG(!hif_runtime_resume(hif_ctx)); + + status = pmo_core_psoc_bus_resume_req(psoc, QDF_RUNTIME_SUSPEND); + QDF_BUG(status == QDF_STATUS_SUCCESS); + + status = pmo_core_psoc_configure_resume(psoc); + QDF_BUG(status == QDF_STATUS_SUCCESS); + + status = pmo_tgt_psoc_set_runtime_pm_inprogress(psoc, false); + QDF_BUG(status == QDF_STATUS_SUCCESS); + + QDF_BUG(!htc_runtime_resume(htc_ctx)); + + status = cdp_runtime_resume(dp_soc, txrx_pdev); + QDF_BUG(status == QDF_STATUS_SUCCESS); + + hif_process_runtime_resume_success(hif_ctx); + +dec_psoc_ref: + pmo_psoc_put_ref(psoc); + +out: + PMO_EXIT(); + + return status; +} +#endif + +/** + * pmo_core_psoc_send_host_wakeup_ind_to_fw() - send wakeup ind to fw + * @psoc: objmgr psoc handle + * @psoc_ctx: pmo psoc private context + * + * Sends host wakeup indication to FW. On receiving this indication, + * FW will come out of WOW. + * + * Return: QDF status + */ +static +QDF_STATUS pmo_core_psoc_send_host_wakeup_ind_to_fw( + struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_priv_obj *psoc_ctx) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + PMO_ENTER(); + qdf_event_reset(&psoc_ctx->wow.target_resume); + + status = pmo_tgt_psoc_send_host_wakeup_ind(psoc); + if (status) { + status = QDF_STATUS_E_FAILURE; + goto out; + } + pmo_debug("Host wakeup indication sent to fw"); + + status = qdf_wait_single_event(&psoc_ctx->wow.target_resume, + PMO_RESUME_TIMEOUT); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("Timeout waiting for resume event from FW"); + pmo_err("Pending commands %d credits %d", + pmo_tgt_psoc_get_pending_cmnds(psoc), + pmo_tgt_psoc_get_host_credits(psoc)); + QDF_BUG(0); + } else { + pmo_debug("Host wakeup received"); + } + + if (status == QDF_STATUS_SUCCESS) + pmo_tgt_update_target_suspend_flag(psoc, false); +out: + PMO_EXIT(); + + return status; +} + +/** + * pmo_core_psoc_disable_wow_in_fw() - Disable wow in bus resume context. + * @psoc: objmgr psoc handle + * @psoc_ctx: pmo psoc private context + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +static +QDF_STATUS pmo_core_psoc_disable_wow_in_fw(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_priv_obj *psoc_ctx) +{ + QDF_STATUS ret; + + PMO_ENTER(); + ret = pmo_core_psoc_send_host_wakeup_ind_to_fw(psoc, psoc_ctx); + if (ret != QDF_STATUS_SUCCESS) + goto out; + + pmo_core_update_wow_enable(psoc_ctx, false); + pmo_core_update_wow_enable_cmd_sent(psoc_ctx, false); + + /* To allow the tx pause/unpause events */ + pmo_core_update_wow_bus_suspend(psoc, psoc_ctx, false); + /* Unpause the vdev as we are resuming */ + pmo_unpause_all_vdev(psoc, psoc_ctx); +out: + PMO_EXIT(); + + return ret; +} + +/** + * pmo_core_psoc_resume_target() - resume target + * @psoc: objmgr psoc handle + * @psoc_ctx: pmo psoc private context + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +static +QDF_STATUS pmo_core_psoc_resume_target(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_priv_obj *psoc_ctx) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + PMO_ENTER(); + qdf_event_reset(&psoc_ctx->wow.target_resume); + + status = pmo_tgt_psoc_send_target_resume_req(psoc); + if (status != QDF_STATUS_SUCCESS) { + status = QDF_STATUS_E_FAILURE; + goto out; + } + + status = qdf_wait_single_event(&psoc_ctx->wow.target_resume, + PMO_RESUME_TIMEOUT); + if (status != QDF_STATUS_SUCCESS) { + pmo_fatal("Timeout waiting for resume event from FW"); + pmo_fatal("Pending commands %d credits %d", + pmo_tgt_psoc_get_pending_cmnds(psoc), + pmo_tgt_psoc_get_host_credits(psoc)); + QDF_BUG(0); + } else { + pmo_debug("Host wakeup received"); + } + + if (status == QDF_STATUS_SUCCESS) + pmo_tgt_update_target_suspend_flag(psoc, false); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_core_psoc_bus_resume_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + bool wow_mode; + QDF_STATUS status; + + PMO_ENTER(); + if (!psoc) { + pmo_err("psoc is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("pmo cannot get the reference out of psoc"); + goto out; + } + + psoc_ctx = pmo_psoc_get_priv(psoc); + wow_mode = pmo_core_is_wow_enabled(psoc_ctx); + pmo_info("wow mode %d", wow_mode); + + pmo_core_update_wow_initial_wake_up(psoc_ctx, false); + + if (wow_mode) + status = pmo_core_psoc_disable_wow_in_fw(psoc, psoc_ctx); + else + status = pmo_core_psoc_resume_target(psoc, psoc_ctx); + + pmo_psoc_put_ref(psoc); + +out: + PMO_EXIT(); + + return status; +} + +void pmo_core_psoc_target_suspend_acknowledge(void *context, bool wow_nack) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)context; + QDF_STATUS status; + + PMO_ENTER(); + if (!psoc) { + pmo_err("psoc is null"); + goto out; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("Failed to get psoc reference"); + goto out; + } + + psoc_ctx = pmo_psoc_get_priv(psoc); + + pmo_core_set_wow_nack(psoc_ctx, wow_nack); + qdf_event_set(&psoc_ctx->wow.target_suspend); + if (wow_nack && !pmo_tgt_psoc_get_runtime_pm_in_progress(psoc)) { + qdf_wake_lock_timeout_acquire(&psoc_ctx->wow.wow_wake_lock, + PMO_WAKE_LOCK_TIMEOUT); + } + + pmo_psoc_put_ref(psoc); +out: + PMO_EXIT(); +} + +void pmo_core_psoc_wakeup_host_event_received(struct wlan_objmgr_psoc *psoc) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + + PMO_ENTER(); + if (!psoc) { + pmo_err("psoc is null"); + goto out; + } + + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_event_set(&psoc_ctx->wow.target_resume); +out: + PMO_EXIT(); +} + +int pmo_core_psoc_is_target_wake_up_received(struct wlan_objmgr_psoc *psoc) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + int ret = 0; + QDF_STATUS status; + + if (!psoc) { + pmo_err("psoc is NULL"); + ret = -EAGAIN; + goto out; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("Failed to get psoc reference"); + ret = -EAGAIN; + goto out; + } + + psoc_ctx = pmo_psoc_get_priv(psoc); + if (pmo_core_get_wow_initial_wake_up(psoc_ctx)) { + pmo_err("Target initial wake up received try again"); + ret = -EAGAIN; + } + + pmo_psoc_put_ref(psoc); +out: + PMO_EXIT(); + + return ret; +} + + +int pmo_core_psoc_clear_target_wake_up(struct wlan_objmgr_psoc *psoc) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + int ret = 0; + QDF_STATUS status; + + if (!psoc) { + pmo_err("psoc is NULL"); + ret = -EAGAIN; + goto out; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("Failed to get psoc reference"); + ret = -EAGAIN; + goto out; + } + + psoc_ctx = pmo_psoc_get_priv(psoc); + pmo_core_update_wow_initial_wake_up(psoc_ctx, false); + + pmo_psoc_put_ref(psoc); +out: + PMO_EXIT(); + + return ret; +} + +void pmo_core_psoc_handle_initial_wake_up(void *cb_ctx) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)cb_ctx; + QDF_STATUS status; + + PMO_ENTER(); + if (!psoc) { + pmo_err("cb ctx/psoc is null"); + goto out; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("Failed to get psoc reference"); + goto out; + } + + psoc_ctx = pmo_psoc_get_priv(psoc); + pmo_core_update_wow_initial_wake_up(psoc_ctx, true); + + pmo_psoc_put_ref(psoc); + +out: + PMO_EXIT(); +} + diff --git a/core/components/pmo/core/src/wlan_pmo_wow.c b/core/components/pmo/core/src/wlan_pmo_wow.c new file mode 100644 index 000000000000..e32e32f96ebe --- /dev/null +++ b/core/components/pmo/core/src/wlan_pmo_wow.c @@ -0,0 +1,350 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Define API's for wow pattern addition and deletion in fwr + */ + +#include "wlan_pmo_wow.h" +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_main.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" +#include +#include "wlan_pmo_static_config.h" +#include "wlan_reg_services_api.h" + +static inline int pmo_find_wow_ptrn_len(const char *ptrn) +{ + int len = 0; + + while (*ptrn != '\0' && *ptrn != PMO_WOW_INTER_PTRN_TOKENIZER) { + len++; + ptrn++; + } + + return len; +} + +QDF_STATUS pmo_core_add_wow_pattern(struct wlan_objmgr_vdev *vdev, + const char *ptrn) +{ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_core_del_wow_pattern(struct wlan_objmgr_vdev *vdev, + const char *ptrn) +{ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_core_wow_enter(struct wlan_objmgr_vdev *vdev, + struct pmo_wow_enter_params *wow_enter_param) +{ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_core_wow_exit(struct wlan_objmgr_vdev *vdev) +{ + return QDF_STATUS_SUCCESS; +} + +void pmo_core_enable_wakeup_event(struct wlan_objmgr_psoc *psoc, + uint32_t vdev_id, uint32_t *bitmap) +{ + QDF_STATUS status; + struct wlan_objmgr_vdev *vdev; + + PMO_ENTER(); + if (!psoc) { + pmo_err("psoc is null"); + goto out; + } + + vdev = pmo_psoc_get_vdev(psoc, vdev_id); + if (!vdev) { + pmo_err("vdev is NULL"); + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + goto out; + + pmo_info("enable wakeup event vdev_id %d wake up event 0x%x%x%x%x", + vdev_id, bitmap[0], bitmap[1], bitmap[2], bitmap[3]); + pmo_tgt_enable_wow_wakeup_event(vdev, bitmap); + + pmo_vdev_put_ref(vdev); + +out: + PMO_EXIT(); +} + +void pmo_core_disable_wakeup_event(struct wlan_objmgr_psoc *psoc, + uint32_t vdev_id, uint32_t *bitmap) +{ + QDF_STATUS status; + struct wlan_objmgr_vdev *vdev; + + PMO_ENTER(); + if (!psoc) { + pmo_err("psoc is null"); + goto out; + } + + vdev = pmo_psoc_get_vdev(psoc, vdev_id); + if (!vdev) { + pmo_err("vdev is NULL"); + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + goto out; + + pmo_info("Disable wakeup event vdev_id %d wake up event 0x%x%x%x%x", + vdev_id, bitmap[0], bitmap[1], bitmap[2], bitmap[3]); + pmo_tgt_disable_wow_wakeup_event(vdev, bitmap); + + pmo_vdev_put_ref(vdev); + +out: + PMO_EXIT(); +} + +/** + * pmo_is_beaconing_vdev_up(): check if a beaconning vdev is up + * @psoc: objmgr psoc handle + * + * Return TRUE if beaconning vdev is up + */ +static +bool pmo_is_beaconing_vdev_up(struct wlan_objmgr_psoc *psoc) +{ + int vdev_id; + struct wlan_objmgr_vdev *vdev; + enum tQDF_ADAPTER_MODE vdev_opmode; + bool is_beaconing; + QDF_STATUS status; + + /* Iterate through VDEV list */ + for (vdev_id = 0; vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS; vdev_id++) { + vdev = pmo_psoc_get_vdev(psoc, vdev_id); + if (!vdev) + continue; + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + continue; + + vdev_opmode = pmo_get_vdev_opmode(vdev); + is_beaconing = pmo_is_vdev_in_beaconning_mode(vdev_opmode) && + pmo_is_vdev_up(vdev); + + pmo_vdev_put_ref(vdev); + + if (is_beaconing) + return true; + } + + return false; +} + +/** + * pmo_support_wow_for_beaconing: wow query for beaconning + * @psoc: objmgr psoc handle + * + * Need to configure wow to enable beaconning offload when + * a beaconing vdev is up and beaonning offload is configured. + * + * Return: true if we need to enable wow for beaconning offload + */ +static +bool pmo_support_wow_for_beaconing(struct wlan_objmgr_psoc *psoc) +{ + /* + * if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + * WMI_SERVICE_BEACON_OFFLOAD)) + */ + return pmo_is_beaconing_vdev_up(psoc); +} + +bool pmo_core_is_wow_applicable(struct wlan_objmgr_psoc *psoc) +{ + int vdev_id; + struct wlan_objmgr_vdev *vdev; + bool is_wow_applicable; + QDF_STATUS status; + + if (!psoc) { + pmo_err("psoc is null"); + return false; + } + + if (pmo_support_wow_for_beaconing(psoc)) { + pmo_debug("one of vdev is in beaconning mode, enabling wow"); + return true; + } + + if (wlan_reg_is_11d_scan_inprogress(psoc)) { + pmo_debug("11d scan is in progress, enabling wow"); + return true; + } + + /* Iterate through VDEV list */ + for (vdev_id = 0; vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS; vdev_id++) { + vdev = pmo_psoc_get_vdev(psoc, vdev_id); + if (!vdev) + continue; + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + continue; + + if (pmo_core_is_vdev_connected(vdev)) { + pmo_debug("STA is connected, enabling wow"); + is_wow_applicable = true; + } else if (ucfg_scan_get_pno_in_progress(vdev)) { + pmo_debug("NLO is in progress, enabling wow"); + is_wow_applicable = true; + } else if (pmo_core_is_extscan_in_progress(vdev)) { + pmo_debug("EXT is in progress, enabling wow"); + is_wow_applicable = true; + } else if (pmo_core_is_p2plo_in_progress(vdev)) { + pmo_debug("P2P LO is in progress, enabling wow"); + is_wow_applicable = true; + } else if (pmo_core_is_lpass_enabled(vdev)) { + pmo_debug("LPASS is enabled, enabling WoW"); + is_wow_applicable = true; + } else if (pmo_core_is_nan_enabled(vdev)) { + pmo_debug("NAN is enabled, enabling WoW"); + is_wow_applicable = true; + } else if (pmo_core_get_vdev_op_mode(vdev) == QDF_NDI_MODE) { + pmo_debug("vdev %d is in NAN data mode, enabling wow", + vdev_id); + is_wow_applicable = true; + } + + pmo_vdev_put_ref(vdev); + + if (is_wow_applicable) + return true; + } + + pmo_debug("All vdev are in disconnected state\n" + "and pno/extscan is not in progress, skipping wow"); + + return false; +} + +void pmo_set_wow_event_bitmap(WOW_WAKE_EVENT_TYPE event, + uint32_t wow_bitmap_size, + uint32_t *bitmask) +{ + uint32_t bit_idx = 0, idx = 0; + + if (!bitmask || wow_bitmap_size < PMO_WOW_MAX_EVENT_BM_LEN) { + pmo_err("wow bitmask length shorter than %d", + PMO_WOW_MAX_EVENT_BM_LEN); + return; + } + pmo_get_event_bitmap_idx(event, wow_bitmap_size, &bit_idx, &idx); + bitmask[idx] |= 1 << bit_idx; + + pmo_debug("%s: bitmask updated %x%x%x%x", + __func__, bitmask[0], bitmask[1], bitmask[2], bitmask[3]); +} + +void pmo_set_sta_wow_bitmask(uint32_t *bitmask, uint32_t wow_bitmap_size) +{ + + pmo_set_wow_event_bitmap(WOW_CSA_IE_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_CLIENT_KICKOUT_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_PATTERN_MATCH_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_MAGIC_PKT_RECVD_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_DEAUTH_RECVD_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_DISASSOC_RECVD_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_BMISS_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_GTK_ERR_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_BETTER_AP_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_HTT_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_RA_MATCH_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_NLO_DETECTED_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_EXTSCAN_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_OEM_RESPONSE_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_TDLS_CONN_TRACKER_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_11D_SCAN_EVENT, + wow_bitmap_size, + bitmask); + +} + +void pmo_set_sap_wow_bitmask(uint32_t *bitmask, uint32_t wow_bitmap_size) +{ + + pmo_set_wow_event_bitmap(WOW_PROBE_REQ_WPS_IE_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_PATTERN_MATCH_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_AUTH_REQ_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_ASSOC_REQ_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_DEAUTH_RECVD_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_DISASSOC_RECVD_EVENT, + wow_bitmap_size, + bitmask); + pmo_set_wow_event_bitmap(WOW_HTT_EVENT, + wow_bitmap_size, + bitmask); +} diff --git a/core/components/pmo/dispatcher/inc/wlan_pmo_arp_public_struct.h b/core/components/pmo/dispatcher/inc/wlan_pmo_arp_public_struct.h new file mode 100644 index 000000000000..533b80998632 --- /dev/null +++ b/core/components/pmo/dispatcher/inc/wlan_pmo_arp_public_struct.h @@ -0,0 +1,58 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ + /** + * DOC: Declare various struct, macros which shall be used in + * pmo arp offload feature. + * + * Note: This file shall not contain public API's prototype/declarations. + * + */ + +#ifndef _WLAN_PMO_ARP_PUBLIC_STRUCT_H_ +#define _WLAN_PMO_ARP_PUBLIC_STRUCT_H_ + +#include "wlan_pmo_common_public_struct.h" + +/** + * struct pmo_arp_req - pmo arp request + * @psoc: objmgr psoc + * @vdev_id: vdev id on which arp offload needed + * @ipv4_addr: ipv4 address for the interface + * @trigger: context from where arp offload triggered + */ +struct pmo_arp_req { + struct wlan_objmgr_psoc *psoc; + uint8_t vdev_id; + uint32_t ipv4_addr; + enum pmo_offload_trigger trigger; +}; + +/** + * struct pmo_arp_req - pmo arp offload param for target interface + * @enable: true when arp offload is enabled else false + * @host_ipv4_addr: host interface ipv4 address + * @bssid: peer ap address + */ +struct pmo_arp_offload_params { + uint8_t enable; + uint8_t host_ipv4_addr[PMO_IPV4_ADDR_LEN]; + struct qdf_mac_addr bssid; +}; + +#endif /* end of _WLAN_PMO_ARP_PUBLIC_STRUCT_H_ */ + diff --git a/core/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h b/core/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h new file mode 100644 index 000000000000..31b9edbd9369 --- /dev/null +++ b/core/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h @@ -0,0 +1,298 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Declare various struct, macros which are common for + * various pmo related features. + * + * Note: This file shall not contain public API's prototype/declartions. + * + */ + +#ifndef _WLAN_PMO_COMMONP_PUBLIC_STRUCT_H_ +#define _WLAN_PMO_COMMONP_PUBLIC_STRUCT_H_ + +#include "wlan_cmn.h" +#include "wlan_objmgr_cmn.h" +#include "wlan_objmgr_global_obj.h" +#include "wlan_objmgr_psoc_obj.h" +#include "wlan_objmgr_pdev_obj.h" +#include "wlan_objmgr_vdev_obj.h" +#include "wlan_objmgr_peer_obj.h" +#include "wmi_unified.h" +#include "qdf_status.h" +#include "qdf_lock.h" +#include "qdf_event.h" +#include "wlan_pmo_hw_filter_public_struct.h" + +#define PMO_IPV4_ADDR_LEN 4 + +#define PMO_IPV4_ARP_REPLY_OFFLOAD 0 +#define PMO_IPV6_NEIGHBOR_DISCOVERY_OFFLOAD 1 +#define PMO_IPV6_NS_OFFLOAD 2 +#define PMO_OFFLOAD_DISABLE 0 +#define PMO_OFFLOAD_ENABLE 1 + +#define PMO_MAC_NS_OFFLOAD_SIZE 1 +#define PMO_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA 16 +#define PMO_MAC_IPV6_ADDR_LEN 16 +#define PMO_IPV6_ADDR_VALID 1 +#define PMO_IPV6_ADDR_UC_TYPE 0 +#define PMO_IPV6_ADDR_AC_TYPE 1 + +#define PMO_80211_ADDR_LEN 6 /* size of 802.11 address */ + +#define PMO_WOW_REQUIRED_CREDITS 1 + +/** + * enum pmo_offload_type: tell offload type + * @pmo_arp_offload: arp offload + * @pmo_ns_offload: ns offload + * @pmo_gtk_offload: gtk offload + */ +enum pmo_offload_type { + pmo_arp_offload = 0, + pmo_ns_offload, + pmo_gtk_offload, +}; + +/** + * enum pmo_vdev_param_id: tell vdev param id + * @pmo_vdev_param_listen_interval: vdev listen interval param id + * @pmo_vdev_param_dtim_policy: vdev param dtim policy + * @pmo_vdev_max_param: Max vdev param id + */ +enum pmo_vdev_param_id { + pmo_vdev_param_listen_interval = 0, + pmo_vdev_param_dtim_policy, + pmo_vdev_max_param +}; + +/** + * enum pmo_beacon_dtim_policy: tell vdev beacon policy + * @pmo_ignore_dtim: fwr need to igonre dtime policy + * @pmo_normal_dtim: fwr need to use normal dtime policy + * @pmo_stick_dtim: fwr need to use stick dtime policy + * @auto_dtim: fwr need to auto dtime policy + */ +enum pmo_beacon_dtim_policy { + pmo_ignore_dtim = 0x01, + pmo_normal_dtim = 0x02, + pmo_stick_dtim = 0x03, + pmo_auto_dtim = 0x04, +}; + +/** + * @pmo_sta_ps_param_rx_wake_policy: Controls how frames are retrievd from AP + * while STA is sleeping. + * @pmo_sta_ps_param_tx_wake_threshold: STA will go active after this many TX + * @pmo_sta_ps_param_pspoll_count:No of PS-Poll to send before STA wakes up + * @pmo_sta_ps_param_inactivity_time: TX/RX inactivity time in msec before + going to sleep. + * @pmo_sta_ps_param_uapsd: Set uapsd configuration. + * @pmo_sta_ps_param_qpower_pspoll_count: No of PS-Poll to send before + STA wakes up in QPower Mode. + * @pmo_sta_ps_enable_qpower: Enable QPower + * @pmo_sta_ps_param_qpower_max_tx_before_wake: Number of TX frames before the + entering the Active state + */ +enum pmo_sta_powersave_param { + pmo_sta_ps_param_rx_wake_policy = 0, + pmo_sta_ps_param_tx_wake_threshold = 1, + pmo_sta_ps_param_pspoll_count = 2, + pmo_sta_ps_param_inactivity_time = 3, + pmo_sta_ps_param_uapsd = 4, + pmo_sta_ps_param_qpower_pspoll_count = 5, + pmo_sta_ps_enable_qpower = 6, + pmo_sta_ps_param_qpower_max_tx_before_wake = 7, +}; + +/** + * enum powersave_qpower_mode: QPOWER modes + * @pmo_qpower_disabled: Qpower is disabled + * @pmo_qpower_enabled: Qpower is enabled + * @pmo_qpower_duty_cycling: Qpower is enabled with duty cycling + */ +enum pmo_power_save_qpower_mode { + pmo_qpower_disabled = 0, + pmo_qpower_enabled = 1, + pmo_qpower_duty_cycling = 2 +}; + +/** + * enum powersave_qpower_mode: powersave_mode + * @pmo_ps_not_supported: Power save is not supported + * @pmo_ps_legacy_no_deep_sleep: Legacy pwr save enabled and deep sleep disabled + * @pmo_ps_qpower_no_deep_sleep: QPOWER enabled and deep sleep disabled + * @pmo_ps_legacy_deep_sleep: Legacy power save enabled and deep sleep enabled + * @pmo_ps_qpower_deep_sleep: QPOWER enabled and deep sleep enabled + * @pmo_ps_duty_cycling_qpower: QPOWER enabled in duty cycling mode + */ +enum pmo_powersave_mode { + pmo_ps_not_supported = 0, + pmo_ps_legacy_no_deep_sleep = 1, + pmo_ps_qpower_no_deep_sleep = 2, + pmo_ps_legacy_deep_sleep = 3, + pmo_ps_qpower_deep_sleep = 4, + pmo_ps_duty_cycling_qpower = 5 +}; + +/** + * enum wow_resume_trigger - resume trigger override setting values + * @PMO_WOW_RESUME_TRIGGER_DEFAULT: fw to use platform default resume trigger + * @PMO_WOW_RESUME_TRIGGER_HTC_WAKEUP: force fw to use HTC Wakeup to resume + * @PMO_WOW_RESUME_TRIGGER_GPIO: force fw to use GPIO to resume + * @PMO_WOW_RESUME_TRIGGER_COUNT: number of resume trigger options + */ +enum pmo_wow_resume_trigger { + /* always first */ + PMO_WOW_RESUME_TRIGGER_DEFAULT = 0, + PMO_WOW_RESUME_TRIGGER_HTC_WAKEUP, + PMO_WOW_RESUME_TRIGGER_GPIO, + /* always last */ + PMO_WOW_RESUME_TRIGGER_COUNT +}; + +/** + * enum wow_interface_pause - interface pause override setting values + * @PMO_WOW_INTERFACE_PAUSE_DEFAULT: use platform default iface pause setting + * @PMO_WOW_INTERFACE_PAUSE_ENABLE: force interface pause setting to enabled + * @PMO_WOW_INTERFACE_PAUSE_DISABLE: force interface pause setting to disabled + * @PMO_WOW_INTERFACE_PAUSE_COUNT: number of interface pause options + */ +enum pmo_wow_interface_pause { + /* always first */ + PMO_WOW_INTERFACE_PAUSE_DEFAULT = 0, + PMO_WOW_INTERFACE_PAUSE_ENABLE, + PMO_WOW_INTERFACE_PAUSE_DISABLE, + /* always last */ + PMO_WOW_INTERFACE_PAUSE_COUNT +}; + +#define PMO_TGT_SUSPEND_COMPLETE_TIMEOUT 6000 +#define PMO_WAKE_LOCK_TIMEOUT 1000 +#define PMO_RESUME_TIMEOUT 25000 + +/** + * struct wow_enable_params - A collection of wow enable override parameters + * @is_unit_test: true to notify fw this is a unit-test suspend + * @interface_pause: used to override the interface pause indication sent to fw + * @resume_trigger: used to force fw to use a particular resume method + */ +struct pmo_wow_enable_params { + bool is_unit_test; + enum pmo_wow_interface_pause interface_pause; + enum pmo_wow_resume_trigger resume_trigger; +}; + +/** + * typedef for psoc suspend handler + */ +typedef QDF_STATUS(*pmo_psoc_suspend_handler) + (struct wlan_objmgr_psoc *psoc, void *arg); +/** + * typedef for psoc resume handler + */ +typedef QDF_STATUS(*pmo_psoc_resume_handler) + (struct wlan_objmgr_psoc *psoc, void *arg); + +/** + * enum pmo_offload_trigger: trigger information + * @pmo_apps_suspend: trigger is apps suspend + * @pmo_apps_resume: trigger is apps resume + * @pmo_runtime_suspend: trigger is runtime suspend + * @pmo_runtime_resume: trigger is runtime resume + * @pmo_ipv4_change_notify: trigger is ipv4 change handler + * @pmo_ipv6_change_notify: trigger is ipv6 change handler + * @pmo_ns_offload_dynamic_update: enable/disable ns offload on the fly + * @pmo_peer_disconnect: trigger is peer disconnect + * @pmo_mcbc_setting_dynamic_update: mcbc value update on the fly + * + * @pmo_offload_trigger_max: Max trigger value + */ +enum pmo_offload_trigger { + pmo_apps_suspend = 0, + pmo_apps_resume, + pmo_runtime_suspend, + pmo_runtime_resume, + pmo_ipv4_change_notify, + pmo_ipv6_change_notify, + pmo_mc_list_change_notify, + pmo_ns_offload_dynamic_update, + pmo_peer_disconnect, + pmo_mcbc_setting_dynamic_update, + + pmo_offload_trigger_max, +}; + +/** + * struct pmo_psoc_cfg - user configuration required for pmo + * @ptrn_match_enable_all_vdev: true when pattern match is enable for all vdev + * @bpf_enable: true if psoc supports bpf else false + * @arp_offload_enable: true if arp offload is supported for psoc else false + * @hw_filter_mode: which mode the hardware filter should use during DTIM + * @ns_offload_enable_static: true if psoc supports ns offload in ini else false + * @ns_offload_enable_dynamic: to enable / disable the ns offload using + * ioctl or vendor command. + * @ssdp: true if psoc supports if ssdp configuration in wow 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 + * @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 + * @magic_ptrn_enable: true when magic pattern is enabled else false + * @deauth_enable: true when wake up on deauth is enabled else false + * @disassoc_enable: true when wake up on disassoc is enabled else false + * @bmiss_enable: true when wake up on bmiss is enabled else false + * @nan_enable: true when nan is enabled else false + * @lpass_enable: true when lpass is enabled else false + * @sta_dynamic_dtim: station dynamic DTIM value + * @sta_mod_dtim: station modulated DTIM value + * @sta_max_li_mod_dtim: station max listen interval DTIM value + * @power_save_mode: power save mode for psoc + * @auto_power_save_fail_mode: auto detect power save failure + */ +struct pmo_psoc_cfg { + bool ptrn_match_enable_all_vdev; + bool bpf_enable; + bool arp_offload_enable; + enum pmo_hw_filter_mode hw_filter_mode; + bool ns_offload_enable_static; + bool ns_offload_enable_dynamic; + bool ssdp; + bool enable_mc_list; + bool active_mode_offload; + bool ap_arpns_support; + uint8_t max_wow_filters; + bool ra_ratelimit_enable; + uint16_t ra_ratelimit_interval; + bool magic_ptrn_enable; + bool deauth_enable; + bool disassoc_enable; + bool bmiss_enable; + bool nan_enable; + bool lpass_enable; + uint8_t sta_dynamic_dtim; + uint8_t sta_mod_dtim; + uint8_t sta_max_li_mod_dtim; + uint8_t power_save_mode; + bool auto_power_save_fail_mode; +}; + +#endif /* end of _WLAN_PMO_COMMONP_STRUCT_H_ */ + diff --git a/core/components/pmo/dispatcher/inc/wlan_pmo_gtk_public_struct.h b/core/components/pmo/dispatcher/inc/wlan_pmo_gtk_public_struct.h new file mode 100644 index 000000000000..8c27cc0ab276 --- /dev/null +++ b/core/components/pmo/dispatcher/inc/wlan_pmo_gtk_public_struct.h @@ -0,0 +1,95 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ + /** + * DOC: Declare various struct, macros which shall be used in + * pmo gtk related feature. + * + * Note: This file shall not contain public API's prototype/declarations. + * + */ + +#ifndef _WLAN_PMO_GTK_PUBLIC_STRUCT_H +#define _WLAN_PMO_GTK_PUBLIC_STRUCT_H + +#include "wlan_pmo_common_public_struct.h" + +#define PMO_GTK_OFFLOAD_ENABLE 0 +#define PMO_GTK_OFFLOAD_DISABLE 1 +#define PMO_KEK_LEN 16 +#define PMO_KCK_LEN 16 +#define PMO_REPLAY_COUNTER_LEN 8 +#define PMO_MAC_MAX_KEY_LENGTH 32 +#define PMO_IGTK_PN_SIZE 6 + +/** + * struct pmo_gtk_req - pmo gtk request + * @flags: optional flags + * @kck: Key confirmation key + * @kek: key encryption key + * @replay_counter: replay_counter + * @bssid: bssid + */ +struct pmo_gtk_req { + uint32_t flags; + uint8_t kck[PMO_KCK_LEN]; + uint8_t kek[PMO_KEK_LEN]; + uint64_t replay_counter; + struct qdf_mac_addr bssid; +}; + +/** + * struct pmo_gtk_rsp_params - pmo gtk response + * @psoc: objmgr psoc + * @vdev_id: vdev id on which arp offload needed + * @status_flag: status flags + * @refresh_cnt: number of successful GTK refresh exchanges since SET operation + * @igtk_key_index: igtk key index + * @igtk_key_length: igtk key length + * @igtk_key_rsc: igtk key index + * @igtk_key: igtk key length + */ +struct pmo_gtk_rsp_params { + uint8_t vdev_id; + uint32_t status_flag; + uint32_t refresh_cnt; + uint64_t replay_counter; + uint8_t igtk_key_index; + uint8_t igtk_key_length; + uint8_t igtk_key_rsc[PMO_IGTK_PN_SIZE]; + uint8_t igtk_key[PMO_MAC_MAX_KEY_LENGTH]; + struct qdf_mac_addr bssid; +}; + +/** + * typedef for gtk response callback + */ +typedef void (*pmo_gtk_rsp_callback)(void *callback_context, + struct pmo_gtk_rsp_params *gtk_rsp); + +/** + * struct pmo_gtk_rsp_req -gtk respsonse request + * @callback: client callback for providing gtk resposne when fwr send event + * @callback_context: client callback response + */ +struct pmo_gtk_rsp_req { + pmo_gtk_rsp_callback callback; + void *callback_context; +}; + +#endif /* end of _WLAN_PMO_GTK_PUBLIC_STRUCT_H */ + diff --git a/core/components/pmo/dispatcher/inc/wlan_pmo_hw_filter_public_struct.h b/core/components/pmo/dispatcher/inc/wlan_pmo_hw_filter_public_struct.h new file mode 100644 index 000000000000..106cef75c7ef --- /dev/null +++ b/core/components/pmo/dispatcher/inc/wlan_pmo_hw_filter_public_struct.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: This file shall contain all public parameter (struct/macro/enum) + * definitions to support hardware filtering configuration. No APIs, or + * implememtations of APIs, shall be contained within. + */ + +#ifndef _WLAN_PMO_HW_FILTER_PUBLIC_STRUCT_H +#define _WLAN_PMO_HW_FILTER_PUBLIC_STRUCT_H + +/** + * pmo_hw_filter_mode - bitmap for enabled hardware filters + * @HW_FILTER_DISABLED: hardware filter is completely disabled + * @HW_FILTER_NON_ARP_BC: drop all broadcast frames, except ARP + * @HW_FILTER_NON_ICMPV6_MC: drop all multicast frames, except ICMPv6 + * + * The hardware filter is only effective in DTIM mode. Use this configuration + * to blanket drop broadcast/multicast packets at the hardware level, without + * waking up the firmware. + */ +enum pmo_hw_filter_mode { + PMO_HW_FILTER_DISABLED = 0, + PMO_HW_FILTER_NON_ARP_BC = 1, + PMO_HW_FILTER_NON_ICMPV6_MC = 2, +}; + +/** + * struct pmo_hw_filter_params - hardware filter configuration parameters + * @vdev_id: Id of the virtual device to configure + * @mode: the hardware filter mode to configure + */ +struct pmo_hw_filter_params { + uint8_t vdev_id; + enum pmo_hw_filter_mode mode; +}; + +#endif /* _WLAN_PMO_HW_FILTER_PUBLIC_STRUCT_H */ diff --git a/core/components/pmo/dispatcher/inc/wlan_pmo_lphb_public_struct.h b/core/components/pmo/dispatcher/inc/wlan_pmo_lphb_public_struct.h new file mode 100644 index 000000000000..7778f91f3004 --- /dev/null +++ b/core/components/pmo/dispatcher/inc/wlan_pmo_lphb_public_struct.h @@ -0,0 +1,176 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ + /** + * DOC: Declare various struct, macros which shall be used in + * pmo lphb offload feature. + * + * Note: This file shall not contain public API's prototype/declarations. + * + */ + +#ifndef _WLAN_PMO_LPHB_PUBLIC_STRUCT_H_ +#define _WLAN_PMO_LPHB_PUBLIC_STRUCT_H_ + +#include "wlan_pmo_common_public_struct.h" + +#ifdef FEATURE_WLAN_LPHB +#define PMO_SIR_LPHB_FILTER_LEN 64 + +/** + * enum lphb_ind_type -Low power heart beat indication type + * @pmo_lphb_set_en_param_indid: lphb enable indication + * @pmo_lphb_set_tcp_pararm_indid: lphb tcp param indication + * @pmo_lphb_set_tcp_pkt_filter_indid: lphb tcp packet filter indication + * @pmo_lphb_set_udp_pararm_indid: lphb udp param indication + * @pmo_lphb_set_udp_pkt_filter_indid: lphb udp packet filter indication + * @pmo_lphb_set_network_info_indid: lphb network information indication + */ +enum lphb_ind_type { + pmo_lphb_set_en_param_indid, + pmo_lphb_set_tcp_pararm_indid, + pmo_lphb_set_tcp_pkt_filter_indid, + pmo_lphb_set_udp_pararm_indid, + pmo_lphb_set_udp_pkt_filter_indid, + pmo_lphb_set_network_info_indid, +}; + +/** + * struct pmo_lphb_enable_req -Low power heart beat enable request + * @enable: lphb enable request + * @item: request item + * @session: lphb session + */ +struct pmo_lphb_enable_req { + uint8_t enable; + uint8_t item; + uint8_t session; +}; + +/** + * struct pmo_lphb_tcp_params - Low power heart beat tcp params + * @srv_ip: source ip address + * @dev_ip: destination ip address + * @src_port: source port + * @dst_port: destination port + * @timeout: tcp timeout value + * @session: session on which lphb needs to be configured + * @gateway_mac: gateway mac address + * @time_period_sec: time period in seconds + * @tcp_sn: tcp sequence number + */ +struct pmo_lphb_tcp_params { + uint32_t srv_ip; + uint32_t dev_ip; + uint16_t src_port; + uint16_t dst_port; + uint16_t timeout; + uint8_t session; + struct qdf_mac_addr gateway_mac; + uint16_t time_period_sec; + uint32_t tcp_sn; +}; + +/** + * struct pmo_lphb_tcp_filter_req - Low power heart beat tcp filter request + * @length: length of filter + * @offset: offset of filter + * @session: session on which lphb needs to be configured + * @filter: filter buffer + */ +struct pmo_lphb_tcp_filter_req { + uint16_t length; + uint8_t offset; + uint8_t session; + uint8_t filter[PMO_SIR_LPHB_FILTER_LEN]; +}; + +/** + * struct pmo_lphb_udp_params - Low power heart beat udp params + * @srv_ip: source ip address + * @dev_ip: destination ip address + * @src_port: source port + * @dst_port: destination port + * @timeout: tcp timeout value + * @session: session on which lphb needs to be configured + * @gateway_mac: gateway mac address + * @time_period_sec: time period in seconds + */ +struct pmo_lphb_udp_params { + uint32_t srv_ip; + uint32_t dev_ip; + uint16_t src_port; + uint16_t dst_port; + uint16_t interval; + uint16_t timeout; + uint8_t session; + struct qdf_mac_addr gateway_mac; +}; + +/** + * struct pmo_lphb_udp_filter_req - Low power heart beat udp filter request + * @length: length of filter + * @offset: offset of filter + * @session: session on which lphb needs to be configured + * @filter: filter buffer + */ +struct pmo_lphb_udp_filter_req { + uint16_t length; + uint8_t offset; + uint8_t session; + uint8_t filter[PMO_SIR_LPHB_FILTER_LEN]; +}; + +/** + * struct pmo_lphb_req - Low power heart beat request + * @cmd: lphb command type + * @dummy: whether dummy or not + * @params: based on command lphb request buffer + */ +struct pmo_lphb_req { + uint16_t cmd; + uint16_t dummy; + union { + struct pmo_lphb_enable_req lphb_enable_req; + struct pmo_lphb_tcp_params lphb_tcp_params; + struct pmo_lphb_tcp_filter_req lphb_tcp_filter_req; + struct pmo_lphb_udp_params lphb_udp_params; + struct pmo_lphb_udp_filter_req lphb_udp_filter_req; + } params; +}; + +/** + * struct pmo_lphb_rsp - Low power heart beat response + * @session_idx: session id + * @protocol_type: tell protocol type + * @event_reason: carry reason of lphb event + */ +struct pmo_lphb_rsp { + uint8_t session_idx; + uint8_t protocol_type; /*TCP or UDP */ + uint8_t event_reason; +}; +#endif /* FEATURE_WLAN_LPHB */ + +/* + * Define typedef for lphb callback when fwr send response + */ +typedef +void (*pmo_lphb_callback)(void *cb_ctx, struct pmo_lphb_rsp *ind_param); + +#endif /* end of _WLAN_PMO_LPHB_PUBLIC_STRUCT_H_ */ + diff --git a/core/components/pmo/dispatcher/inc/wlan_pmo_mc_addr_filtering_public_struct.h b/core/components/pmo/dispatcher/inc/wlan_pmo_mc_addr_filtering_public_struct.h new file mode 100644 index 000000000000..8607c171319c --- /dev/null +++ b/core/components/pmo/dispatcher/inc/wlan_pmo_mc_addr_filtering_public_struct.h @@ -0,0 +1,60 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ + /** + * DOC: Declare various struct, macros which shall be used in + * pmo mc address filterign related features. + * + * Note: This file shall not contain public API's prototype/declarations. + * + */ + + +#ifndef _WLAN_PMO_MC_ADDR_FILTERING_STRUCT_H_ +#define _WLAN_PMO_MC_ADDR_FILTERING_STRUCT_H_ + +#include "wlan_pmo_common_public_struct.h" + +#define PMO_MAX_MC_ADDR_LIST 32 + +/** + * struct pmo_mc_addr_list_params -pmo mc address list request params + * @psoc: objmgr psoc + * @vdev_id: vdev id on which arp offload needed + * @count: multicast address count + * @mc_addr: multicast address array + */ +struct pmo_mc_addr_list_params { + struct wlan_objmgr_psoc *psoc; + uint8_t vdev_id; + uint8_t count; + struct qdf_mac_addr mc_addr[PMO_MAX_MC_ADDR_LIST]; +}; + +/** + * struct pmo_mc_addr_list -pmo mc address list params for vdev + * @is_filter_applied: is mc list filter applied on vdev + * @mc_cnt: mc address count + * @mc_addr:mc address list + */ +struct pmo_mc_addr_list { + uint8_t is_filter_applied; + uint8_t mc_cnt; + struct qdf_mac_addr mc_addr[PMO_MAX_MC_ADDR_LIST]; +}; + +#endif /* end of _WLAN_PMO_MC_ADDR_FILTERING_STRUCT_H_ */ diff --git a/core/components/pmo/dispatcher/inc/wlan_pmo_ns_public_struct.h b/core/components/pmo/dispatcher/inc/wlan_pmo_ns_public_struct.h new file mode 100644 index 000000000000..27a0c0499fed --- /dev/null +++ b/core/components/pmo/dispatcher/inc/wlan_pmo_ns_public_struct.h @@ -0,0 +1,79 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ + /** + * DOC: Declare various struct, macros which shall be used in + * pmo ns offload feature. + * + * Note: This file shall not contain public API's prototype/declarations. + * + */ + + +#ifndef _WLAN_PMO_NS_PUBLIC_STRUCT_H_ +#define _WLAN_PMO_NS_PUBLIC_STRUCT_H_ + +#include "wlan_pmo_common_public_struct.h" + +/** + * struct pmo_ns_offload_params - pmo ns offload parameters + * @enable: true when ns offload enable + * @num_ns_offload_count: total ns entries + * @src_ipv6_addr: in request source ipv 6 address + * @self_ipv6_addr: self ipv6 address + * @target_ipv6_addr: target ipv6 address + * @self_macaddr: self mac address + * @src_ipv6_addr_valid: true if source ipv6 address is valid else false + * @target_ipv6_addr_valid: target ipv6 address are valid or not + * @target_ipv6_addr_ac_type: target ipv6 address type (unicast or anycast) + * @slot_idx: slot index + */ +struct pmo_ns_offload_params { + uint8_t enable; + uint32_t num_ns_offload_count; + uint8_t src_ipv6_addr[PMO_MAC_IPV6_ADDR_LEN]; + uint8_t self_ipv6_addr[PMO_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] + [PMO_MAC_IPV6_ADDR_LEN]; + uint8_t target_ipv6_addr[PMO_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] + [PMO_MAC_IPV6_ADDR_LEN]; + struct qdf_mac_addr self_macaddr; + uint8_t src_ipv6_addr_valid; + uint8_t target_ipv6_addr_valid[PMO_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA]; + uint8_t target_ipv6_addr_ac_type[PMO_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA]; + uint8_t slot_idx; + struct qdf_mac_addr bssid; +}; + +/** + * struct pmo_ns_req - pmo ns request + * @psoc: objmgr psoc + * @vdev_id: vdev id on which arp offload needed + * @trigger: context from where arp offload triggered + * @count: ns entries count + * @ipv6_addr: ipv6 address array + * @ipv6_addr_type: ipv6 address type (unicast/anycast) array + */ +struct pmo_ns_req { + struct wlan_objmgr_psoc *psoc; + uint8_t vdev_id; + enum pmo_offload_trigger trigger; + uint32_t count; + uint8_t ipv6_addr[PMO_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] + [PMO_MAC_IPV6_ADDR_LEN]; + uint8_t ipv6_addr_type[PMO_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA]; +}; +#endif /* end of _WLAN_PMO_NS_PUBLIC_STRUCT_H_ */ diff --git a/core/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_api.h b/core/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_api.h new file mode 100644 index 000000000000..42ee0b95ddcf --- /dev/null +++ b/core/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_api.h @@ -0,0 +1,241 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: declare utility API related to the pmo component + * called by other components + */ + +#ifndef _WLAN_PMO_OBJ_MGMT_API_H_ +#define _WLAN_PMO_OBJ_MGMT_API_H_ + +#include "wlan_pmo_common_public_struct.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" + +/** + * pmo_init() - initialize pmo_ctx context. + * + * This function initializes the power manager offloads (a.k.a pmo) context. + * + * Return: QDF_STATUS_SUCCESS - in case of success else return error + */ +QDF_STATUS pmo_init(void); + +/** + * pmo_deinit() - De initialize pmo_ctx context. + * + * This function De initializes power manager offloads (a.k.a pmo) contex. + * + * Return: QDF_STATUS_SUCCESS - in case of success else return error + */ +QDF_STATUS pmo_deinit(void); + +/** + * pmo_psoc_object_created_notification(): pmo psoc create handler + * @psoc: psoc which is going to created by objmgr + * @arg: argument for vdev create handler + * + * PMO, register this api with objmgr to detect psoc is created in fwr + * + * Return QDF_STATUS status in case of success else return error + */ +QDF_STATUS pmo_psoc_object_created_notification( + struct wlan_objmgr_psoc *psoc, void *arg); + +/** + * pmo_psoc_object_destroyed_notification(): pmo psoc delete handler + * @psco: psoc which is going to delete by objmgr + * @arg: argument for vdev delete handler + * + * PMO, register this api with objmgr to detect psoc is deleted in fwr + * + * Return QDF_STATUS status in case of success else return error + */ +QDF_STATUS pmo_psoc_object_destroyed_notification( + struct wlan_objmgr_psoc *psoc, void *arg); + +/** + * pmo_vdev_object_created_notification(): pmo vdev create handler + * @vdev: vdev which is going to created by objmgr + * @arg: argument for vdev create handler + * + * PMO, register this api with objmgr to detect vdev is created in fwr + * + * Return QDF_STATUS status in case of success else return error + */ +QDF_STATUS pmo_vdev_object_created_notification( + struct wlan_objmgr_vdev *vdev, void *arg); + +/** + * pmo_vdev_ready() - handles vdev ready in firmware event + * @vdev: vdev which is ready in firmware + * + * Objmgr vdev_create event does not guarantee vdev creation in firmware. + * Any logic that would normally go in the vdev_create event, but needs to + * communicate with firmware, needs to go here instead. + * + * Return QDF_STATUS + */ +QDF_STATUS pmo_vdev_ready(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_vdev_object_destroyed_notification(): pmo vdev delete handler + * @vdev: vdev which is going to delete by objmgr + * @arg: argument for vdev delete handler + * + * PMO, register this api with objmgr to detect vdev is deleted in fwr + * + * Return QDF_STATUS status in case of success else return error + */ +QDF_STATUS pmo_vdev_object_destroyed_notification( + struct wlan_objmgr_vdev *vdev, void *arg); + +/** + * pmo_register_suspend_handler(): register suspend handler for components + * @id: component id + * @handler: resume handler for the mention component + * @arg: argument to pass while calling resume handler + * + * Return QDF_STATUS status -in case of success else return error + */ +QDF_STATUS pmo_register_suspend_handler( + enum wlan_umac_comp_id id, + pmo_psoc_suspend_handler handler, + void *arg); + +/** + * pmo_unregister_suspend_handler():unregister suspend handler for components + * @id: component id + * @handler: resume handler for the mention component + * + * Return QDF_STATUS status -in case of success else return error + */ +QDF_STATUS pmo_unregister_suspend_handler( + enum wlan_umac_comp_id id, + pmo_psoc_suspend_handler handler); + +/** + * pmo_register_resume_handler(): API to register resume handler for components + * @id: component id + * @handler: resume handler for the mention component + * @arg: argument to pass while calling resume handler + * + * Return QDF_STATUS status - in case of success else return error + */ +QDF_STATUS pmo_register_resume_handler( + enum wlan_umac_comp_id id, + pmo_psoc_resume_handler handler, + void *arg); + +/** + * pmo_unregister_resume_handler(): unregister resume handler for components + * @id: component id + * @handler: resume handler for the mention component + * + * Return QDF_STATUS status - in case of success else return error + */ +QDF_STATUS pmo_unregister_resume_handler( + enum wlan_umac_comp_id id, + pmo_psoc_resume_handler handler); + +/** + * pmo_suspend_all_components(): API to suspend all component + * @psoc:objmgr psoc + * @suspend_type: Tell suspend type (apps suspend / runtime suspend) + * + * Return QDF_STATUS status - in case of success else return error + */ +QDF_STATUS pmo_suspend_all_components(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type suspend_type); + +/** + * pmo_resume_all_components(): API to resume all component + * @psoc:objmgr psoc + * @suspend_type: Tell suspend type from which resume is required + * + * Return QDF_STATUS status - in case of success else return error + */ +QDF_STATUS pmo_resume_all_components(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type suspend_type); + +/** + * pmo_register_pause_bitmap_notifier(): API to register pause bitmap notifier + * @psoc: objmgr psoc handle + * @handler: pause bitmap updated notifier + * + * Return QDF_STATUS status - in case of success else return error + */ +QDF_STATUS pmo_register_pause_bitmap_notifier( + struct wlan_objmgr_psoc *psoc, + pmo_notify_pause_bitmap handler); + +/** + * pmo_unregister_pause_bitmap_notifier(): API to unregister pause bitmap notifier + * @psoc: objmgr psoc handle + * @handler: pause bitmap updated notifier + * + * Return QDF_STATUS status - in case of success else return error + */ +QDF_STATUS pmo_unregister_pause_bitmap_notifier( + struct wlan_objmgr_psoc *psoc, + pmo_notify_pause_bitmap handler); + +/** + * pmo_register_get_pause_bitmap(): API to get register pause bitmap notifier + * @psoc: objmgr psoc handle + * @handler: pause bitmap updated notifier + * + * Return QDF_STATUS status - in case of success else return error + */ +QDF_STATUS pmo_register_get_pause_bitmap(struct wlan_objmgr_psoc *psoc, + pmo_get_pause_bitmap handler); + +/** + * pmo_unregister_get_pause_bitmap(): API to unregister get pause bitmap callback + * @psoc: objmgr psoc handle + * @handler: pause bitmap updated notifier + * + * Return QDF_STATUS status - in case of success else return error + */ +QDF_STATUS pmo_unregister_get_pause_bitmap(struct wlan_objmgr_psoc *psoc, + pmo_get_pause_bitmap handler); + + +/** + * pmo_register_is_device_in_low_pwr_mode(): API to get register device power + * save check notifier. + * @psoc: objmgr psoc handle + * @handler: device power save check notifier + * + * Return QDF_STATUS status - in case of success else return error + */ +QDF_STATUS pmo_register_is_device_in_low_pwr_mode(struct wlan_objmgr_psoc *psoc, + pmo_is_device_in_low_pwr_mode handler); + +/** + * pmo_unregister_is_device_in_low_pwr_mode(): API to unregister device power + * save check notifier. + * @psoc: objmgr psoc handle + * @handler: device power save check notifier + * + * Return QDF_STATUS status - in case of success else return error + */ +QDF_STATUS pmo_unregister_is_device_in_low_pwr_mode( + struct wlan_objmgr_psoc *psoc, + pmo_is_device_in_low_pwr_mode handler); + +#endif /* end of _WLAN_PMO_OBJ_MGMT_API_H_ */ diff --git a/core/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h b/core/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h new file mode 100644 index 000000000000..4be33ff9dfcd --- /dev/null +++ b/core/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h @@ -0,0 +1,189 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ + /** + * DOC: Declare various struct, macros which are used for object mgmt in pmo. + * + * Note: This file shall not contain public API's prototype/declarations. + * + */ + + +#ifndef _WLAN_PMO_OBJ_MGMT_PUBLIC_STRUCT_H_ +#define _WLAN_PMO_OBJ_MGMT_PUBLIC_STRUCT_H_ + +#include "wlan_pmo_common_public_struct.h" +#include "wlan_pmo_arp_public_struct.h" +#include "wlan_pmo_ns_public_struct.h" +#include "wlan_pmo_gtk_public_struct.h" +#include "wlan_pmo_wow_public_struct.h" +#include "wlan_pmo_mc_addr_filtering_public_struct.h" +#include "wlan_pmo_hw_filter_public_struct.h" +#include "wlan_pmo_pkt_filter_public_struct.h" +#include "wlan_pmo_lphb_public_struct.h" + +/** + * typedef for vdev notifying the vdev pause bitmap new value to mlme + */ +typedef void (*pmo_notify_pause_bitmap)( + uint8_t vdev_id, uint16_t value); + +/** + * typedef for getting vdev pause bitmap + */ +typedef uint16_t(*pmo_get_pause_bitmap)(uint8_t vdev_id); + +/** + * typedef to know is deviec is in power save mode + */ +typedef bool (*pmo_is_device_in_low_pwr_mode)(uint8_t vdev_id); + +/* + * typedef for pld auto suspend callback during runtime suspend + */ +typedef +int (*pmo_pld_auto_suspend_cb)(void); + +/* + * typedef for pld auto resume callback during runtime resume + */ +typedef +int (*pmo_pld_auto_resume_cb)(void); + +/** + * struct wlan_pmo_tx_ops - structure of tx function + * pointers for pmo component + * @send_arp_offload_req: fp to send arp offload request + * @send_ns_offload_req: fp to send ns offload request + * @send_non_arp_bcast_filter_req: for enable/disable broadcast filter + * @send_set_pkt_filter: send set packet filter + * @send_clear_pkt_filter: send clear packet filter + * @send_enable_wakeup_event_req: fp to send enable wow wakeup events req + * @send_disable_wakeup_event_req: fp to send disable wow wakeup events req + * @send_add_wow_pattern: fp to send wow pattern request + * @send_enhance_mc_offload_req: fp to send enhanced multicast offload request + * @send_set_mc_filter_req: fp to send set mc filter request + * @send_clear_mc_filter_req: fp to send clear mc filter request + * @send_ra_filter_req: fp to send ra filter request + * @send_gtk_offload_req: fp to send gtk offload request command + * @send_get_gtk_rsp_cmd: fp to send get gtk response request cmd to firmware + * @send_action_frame_pattern_req: fp to send wow action frame patterns request + * @send_lphb_enable: fp to send lphb enable request command + * @send_lphb_tcp_params: fp to send lphb tcp params request command + * @send_lphb_tcp_filter_req: fp to send lphb tcp packet filter request command + * @send_lphb_upd_params: fp to send lphb udp params request command + * @send_lphb_udp_filter_req: fp to send lphb udp packet filter request command + * @send_vdev_param_update_req: fp to send vdev param request + * @send_vdev_set_sta_ps_param: fp to send sta vdev ps power set req + * @psoc_update_wow_bus_suspend: fp to update bus suspend req flag at wmi + * @psoc_get_host_credits: fp to get the host credits + * @psoc_get_pending_cmnds: fp to get the host pending wmi commands + * @update_target_suspend_flag: fp to update target suspend flag at wmi + * @psoc_send_wow_enable_req: fp to send wow enable request + * @psoc_send_supend_req: fp to send target suspend request + * @psoc_set_runtime_pm_in_progress: fp to set runtime pm is in progress status + * @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 + */ +struct wlan_pmo_tx_ops { + QDF_STATUS (*send_arp_offload_req)(struct wlan_objmgr_vdev *vdev, + struct pmo_arp_offload_params *arp_offload_req, + struct pmo_ns_offload_params *ns_offload_req); + QDF_STATUS (*send_conf_hw_filter_req)( + struct wlan_objmgr_psoc *psoc, + struct pmo_hw_filter_params *req); + QDF_STATUS (*send_ns_offload_req)(struct wlan_objmgr_vdev *vdev, + struct pmo_arp_offload_params *arp_offload_req, + struct pmo_ns_offload_params *ns_offload_req); + QDF_STATUS(*send_set_pkt_filter)(struct wlan_objmgr_vdev *vdev, + struct pmo_rcv_pkt_fltr_cfg *pmo_set_pkt_fltr_req); + QDF_STATUS(*send_clear_pkt_filter)(struct wlan_objmgr_vdev *vdev, + struct pmo_rcv_pkt_fltr_clear_param + *pmo_clr_pkt_fltr_param); + QDF_STATUS (*send_enable_wow_wakeup_event_req)( + struct wlan_objmgr_vdev *vdev, + uint32_t *bitmap); + QDF_STATUS (*send_disable_wow_wakeup_event_req)( + struct wlan_objmgr_vdev *vdev, + uint32_t *bitmap); + QDF_STATUS (*send_add_wow_pattern)( + struct wlan_objmgr_vdev *vdev, + uint8_t ptrn_id, const uint8_t *ptrn, uint8_t ptrn_len, + uint8_t ptrn_offset, const uint8_t *mask, + uint8_t mask_len, bool user); + QDF_STATUS (*send_enhance_mc_offload_req)( + struct wlan_objmgr_vdev *vdev, bool enable); + QDF_STATUS (*send_set_mc_filter_req)( + struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr multicast_addr); + QDF_STATUS (*send_clear_mc_filter_req)( + struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr multicast_addr); + QDF_STATUS (*send_ra_filter_req)( + struct wlan_objmgr_vdev *vdev, + uint8_t default_pattern, uint16_t rate_limit_interval); + QDF_STATUS (*send_gtk_offload_req)( + struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_req *gtk_offload_req); + QDF_STATUS (*send_get_gtk_rsp_cmd)(struct wlan_objmgr_vdev *vdev); + QDF_STATUS (*send_action_frame_pattern_req)( + struct wlan_objmgr_vdev *vdev, + struct pmo_action_wakeup_set_params *ip_cmd); + QDF_STATUS (*send_lphb_enable)( + struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_enable_req *ts_lphb_enable); + QDF_STATUS (*send_lphb_tcp_params)( + struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_tcp_params *ts_lphb_tcp_param); + QDF_STATUS (*send_lphb_tcp_filter_req)( + struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_tcp_filter_req *ts_lphb_tcp_filter); + QDF_STATUS (*send_lphb_upd_params)( + struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_udp_params *ts_lphb_udp_param); + QDF_STATUS (*send_lphb_udp_filter_req)( + struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_udp_filter_req *ts_lphb_udp_filter); + QDF_STATUS (*send_vdev_param_update_req)( + struct wlan_objmgr_vdev *vdev, + uint32_t param_id, uint32_t param_value); + QDF_STATUS (*send_vdev_sta_ps_param_req)( + struct wlan_objmgr_vdev *vdev, + uint32_t ps_mode, uint32_t value); + void (*psoc_update_wow_bus_suspend)( + struct wlan_objmgr_psoc *psoc, uint8_t value); + int (*psoc_get_host_credits)( + struct wlan_objmgr_psoc *psoc); + int (*psoc_get_pending_cmnds)( + struct wlan_objmgr_psoc *psoc); + void (*update_target_suspend_flag)( + struct wlan_objmgr_psoc *psoc, uint8_t value); + QDF_STATUS (*psoc_send_wow_enable_req)(struct wlan_objmgr_psoc *psoc, + struct pmo_wow_cmd_params *param); + QDF_STATUS (*psoc_send_supend_req)(struct wlan_objmgr_psoc *psoc, + struct pmo_suspend_params *param); + void (*psoc_set_runtime_pm_in_progress)(struct wlan_objmgr_psoc *psoc, + bool value); + bool (*psoc_get_runtime_pm_in_progress)(struct wlan_objmgr_psoc *psoc); + QDF_STATUS (*psoc_send_host_wakeup_ind)(struct wlan_objmgr_psoc *psoc); + QDF_STATUS (*psoc_send_target_resume_req)( + struct wlan_objmgr_psoc *psoc); + +}; + +#endif /* end of _WLAN_PMO_OBJ_MGMT_PUBLIC_STRUCT_H_ */ diff --git a/core/components/pmo/dispatcher/inc/wlan_pmo_pkt_filter_public_struct.h b/core/components/pmo/dispatcher/inc/wlan_pmo_pkt_filter_public_struct.h new file mode 100644 index 000000000000..d067fe1486d7 --- /dev/null +++ b/core/components/pmo/dispatcher/inc/wlan_pmo_pkt_filter_public_struct.h @@ -0,0 +1,141 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ + /** + * DOC: Declare various struct, macros which shall be used in + * pmo packet filter feature. + * + * Note: This file shall not contain public API's prototype/declarations. + * + */ + +#ifndef _WLAN_PMO_PKT_FILTER_PUBLIC_STRUCT_H_ +#define _WLAN_PMO_PKT_FILTER_PUBLIC_STRUCT_H_ + +#include "qdf_types.h" + +#define PMO_MAX_FILTER_TEST_DATA_LEN 8 +#define PMO_MAX_NUM_TESTS_PER_FILTER 10 + +/** + * enum pmo_rcv_pkt_fltr_type: Receive Filter Parameters + * @PMO_RCV_FILTER_TYPE_INVALID: invalied filter type + * @PMO_RCV_FILTER_TYPE_FILTER_PKT: packet filter + * @PMO_RCV_FILTER_TYPE_BUFFER_PKT: buffer packet + * @PMO_RCV_FILTER_TYPE_MAX_ENUM_SIZE: max filter + */ +enum pmo_rcv_pkt_fltr_type { + PMO_RCV_FILTER_TYPE_INVALID, + PMO_RCV_FILTER_TYPE_FILTER_PKT, + PMO_RCV_FILTER_TYPE_BUFFER_PKT, + PMO_RCV_FILTER_TYPE_MAX_ENUM_SIZE +}; + +/** + * enum pmo_rcv_pkt_fltr_flag_type: Receive Filter flags + * @PMO_FILTER_CMP_TYPE_INVALID: invalied flag + * @PMO_FILTER_CMP_TYPE_EQUAL: equal + * @PMO_FILTER_CMP_TYPE_MASK_EQUAL: mask + * @PMO_FILTER_CMP_TYPE_NOT_EQUAL: not equal + * @PMO_FILTER_CMP_TYPE_MASK_NOT_EQUAL: mask not equal + * @PMO_FILTER_CMP_TYPE_MAX: max size of flag + */ +enum pmo_rcv_pkt_fltr_flag_type { + PMO_FILTER_CMP_TYPE_INVALID, + PMO_FILTER_CMP_TYPE_EQUAL, + PMO_FILTER_CMP_TYPE_MASK_EQUAL, + PMO_FILTER_CMP_TYPE_NOT_EQUAL, + PMO_FILTER_CMP_TYPE_MASK_NOT_EQUAL, + PMO_FILTER_CMP_TYPE_MAX +}; + +/** + * enum pmo_rcv_pkt_fltr_protocol_params: Receive Filter protocal parameters + * @PMO_FILTER_HDR_TYPE_INVALID: invalied type + * @PMO_FILTER_HDR_TYPE_MAC: mac protocol + * @PMO_FILTER_HDR_TYPE_ARP: arp protocol + * @PMO_FILTER_HDR_TYPE_IPV4: ipv4 protocol + * @PMO_FILTER_HDR_TYPE_IPV6: ipv6 protocol + * @PMO_FILTER_HDR_TYPE_UDP: udp protocol + * @PMO_FILTER_HDR_TYPE_MAX: max of type of protocol + */ +enum pmo_rcv_pkt_fltr_protocol_params { + PMO_FILTER_HDR_TYPE_INVALID, + PMO_FILTER_HDR_TYPE_MAC, + PMO_FILTER_HDR_TYPE_ARP, + PMO_FILTER_HDR_TYPE_IPV4, + PMO_FILTER_HDR_TYPE_IPV6, + PMO_FILTER_HDR_TYPE_UDP, + PMO_FILTER_HDR_TYPE_MAX +}; + +/** + * struct pmo_rcv_pkt_fltr_field_params - pmo packet filter field parameters + * @protocol_layer: Protocol layer + * @compare_flag: Comparison flag + * @data_length: Length of the data to compare + * @data_offset: from start of the respective frame header + * @reserved: Reserved field + * @compare_data: Data to compare + * @data_mask: Mask to be applied on the received packet data before compare + */ +struct pmo_rcv_pkt_fltr_field_params { + enum pmo_rcv_pkt_fltr_protocol_params protocol_layer; + enum pmo_rcv_pkt_fltr_flag_type compare_flag; + uint16_t data_length; + uint8_t data_offset; + uint8_t reserved; + uint8_t compare_data[PMO_MAX_FILTER_TEST_DATA_LEN]; + uint8_t data_mask[PMO_MAX_FILTER_TEST_DATA_LEN]; +}; + +/** + * struct pmo_rcv_pkt_fltr_cfg - pmo packet filter config + * @filter_id: filter id + * @filter_type: filter type + * @num_params: number of parameters + * @coalesce_time: time + * @self_macaddr: mac address + * @bssid: Bssid of the connected AP + * @params_data: data + */ +struct pmo_rcv_pkt_fltr_cfg { + uint8_t filter_id; + enum pmo_rcv_pkt_fltr_type filter_type; + uint32_t num_params; + uint32_t coalesce_time; + struct qdf_mac_addr self_macaddr; + struct qdf_mac_addr bssid; + struct pmo_rcv_pkt_fltr_field_params + params_data[PMO_MAX_NUM_TESTS_PER_FILTER]; +}; + +/** + * struct pmo_rcv_pkt_fltr_cfg - pmo receive Filter Clear Parameters + * @status: only valid for response message + * @filter_id: + * @self_macaddr: + * @bssid: peer ap address + */ +struct pmo_rcv_pkt_fltr_clear_param { + uint32_t status; + uint8_t filter_id; + struct qdf_mac_addr self_macaddr; + struct qdf_mac_addr bssid; +}; + +#endif /* end of _WLAN_PMO_PKT_FILTER_PUBLIC_STRUCT_H_ */ diff --git a/core/components/pmo/dispatcher/inc/wlan_pmo_tgt_api.h b/core/components/pmo/dispatcher/inc/wlan_pmo_tgt_api.h new file mode 100644 index 000000000000..e702da8690c3 --- /dev/null +++ b/core/components/pmo/dispatcher/inc/wlan_pmo_tgt_api.h @@ -0,0 +1,406 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Declare public API for pmo to interact with target/WMI + */ + +#ifndef _WLAN_PMO_TGT_API_H_ +#define _WLAN_PMO_TGT_API_H_ + +#include "wlan_pmo_common_public_struct.h" +#include "wlan_pmo_arp_public_struct.h" +#include "wlan_pmo_ns_public_struct.h" +#include "wlan_pmo_gtk_public_struct.h" +#include "wlan_pmo_wow_public_struct.h" +#include "wlan_pmo_mc_addr_filtering_public_struct.h" +#include "wlan_pmo_hw_filter_public_struct.h" +#include "wlan_pmo_pkt_filter_public_struct.h" + +#define GET_PMO_TX_OPS_FROM_PSOC(psoc) \ + (pmo_psoc_get_priv(psoc)->pmo_tx_ops) + +/** + * pmo_tgt_conf_hw_filter() - configure hardware filter mode in firmware + * @psoc: the psoc to use to communicate with firmware + * @req: the configuration request + * + * Return: QDF_STATUS + */ +QDF_STATUS pmo_tgt_conf_hw_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_hw_filter_params *req); + +/** + * pmo_tgt_set_pkt_filter() - Set packet filter + * @vdev: objmgr vdev + * @pmo_set_pkt_fltr_req: + * @vdev_id: vdev id + * + * API to set packet filter + * + * Return: QDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_tgt_set_pkt_filter(struct wlan_objmgr_vdev *vdev, + struct pmo_rcv_pkt_fltr_cfg *pmo_set_pkt_fltr_req, + uint8_t vdev_id); + +/** + * pmo_tgt_clear_pkt_filter() - Clear packet filter + * @vdev: objmgr vdev + * @pmo_clr_pkt_fltr_param: + * @vdev_id: vdev id + * + * API to clear packet filter + * + * Return: QDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_tgt_clear_pkt_filter(struct wlan_objmgr_vdev *vdev, + struct pmo_rcv_pkt_fltr_clear_param *pmo_clr_pkt_fltr_param, + uint8_t vdev_id); + +/** + * pmo_tgt_enable_arp_offload_req() - Enable arp offload req to target + * @vdev: objmgr vdev + * @vdev_id: vdev id + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_enable_arp_offload_req(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id); + +/** + * pmo_tgt_disable_arp_offload_req() - Disable arp offload req to target + * @vdev: objmgr vdev + * @vdev_id: vdev id + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_disable_arp_offload_req(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id); + +/** + * pmo_tgt_enable_ns_offload_req() - Send ns offload req to targe + * @vdev: objmgr vdev + * @vdev_id: vdev id + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_enable_ns_offload_req(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id); + +/** + * pmo_tgt_disable_ns_offload_req() - Disable arp offload req to target + * @vdev: objmgr vdev + * @vdev_id: vdev id + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_disable_ns_offload_req(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id); + +/** + * pmo_tgt_enable_wow_wakeup_event() - Send Enable wow wakeup events req to fwr + * @vdev: objmgr vdev handle + * @bitmap: Event bitmap + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_enable_wow_wakeup_event(struct wlan_objmgr_vdev *vdev, + uint32_t *bitmap); + +/** + * pmo_tgt_disable_wow_wakeup_event() - Send Disable wow wakeup events to fwr + * @vdev: objmgr vdev handle + * @bitmap: Event bitmap + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_disable_wow_wakeup_event(struct wlan_objmgr_vdev *vdev, + uint32_t *bitmap); + +/** + * pmo_tgt_send_wow_patterns_to_fw() - Sends WOW patterns to FW. + * @vdev: objmgr vdev + * @ptrn_id: pattern id + * @ptrn: pattern + * @ptrn_len: pattern length + * @ptrn_offset: pattern offset + * @mask: mask + * @mask_len: mask length + * @user: true for user configured pattern and false for default pattern + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_send_wow_patterns_to_fw(struct wlan_objmgr_vdev *vdev, + uint8_t ptrn_id, const uint8_t *ptrn, uint8_t ptrn_len, + uint8_t ptrn_offset, const uint8_t *mask, + uint8_t mask_len, bool user); + +/** + * pmo_tgt_set_mc_filter_req() - Set mcast filter command to fw + * @vdev: objmgr vdev + * @multicastAddr: mcast address + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS pmo_tgt_set_mc_filter_req(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr multicast_addr); + +/** + * pmo_tgt_clear_mc_filter_req() - Clear mcast filter command to fw + * @vdev: objmgr vdev + * @multicastAddr: mcast address + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS pmo_tgt_clear_mc_filter_req(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr multicast_addr); + +/** + * pmo_tgt_send_enhance_multicast_offload_req() - send enhance mc offload req + * @wma_handle: wma handle + * @vdev_id: vdev id + * @action: enable or disable enhance multicast offload + * + * Return: QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS pmo_tgt_send_enhance_multicast_offload_req( + struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id, + uint8_t action); + +/** + * pmo_tgt_send_ra_filter_req() - send ra filter request to target + * @vdev: objmgr vdev handle + * + * Return: QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS pmo_tgt_send_ra_filter_req(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_tgt_send_action_frame_pattern_req - send wow action frame patterns req + * @vdev: objmgr vdev handle + * @cmd: action frame pattern cmd + * + * Return: QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS pmo_tgt_send_action_frame_pattern_req( + struct wlan_objmgr_vdev *vdev, + struct pmo_action_wakeup_set_params *cmd); + +/** + * pmo_tgt_send_gtk_offload_req() - send GTK offload command to fw + * @vdev: objmgr vdev + * @gtk_req: pmo gtk req + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_send_gtk_offload_req(struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_req *gtk_req); + +/** + * pmo_tgt_get_gtk_rsp() - send get gtk rsp command to fw + * @vdev: objmgr vdev + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_get_gtk_rsp(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_tgt_gtk_rsp_evt() - receive gtk rsp event from fwr + * @psoc: objmgr psoc + * @gtk_rsp_param: gtk response parameters + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_gtk_rsp_evt(struct wlan_objmgr_psoc *psoc, + struct pmo_gtk_rsp_params *rsp_param); + +/** + * pmo_tgt_send_lphb_enable() - enable command of LPHB configuration requests + * @psoc: objmgr psoc handle + * @ts_lphb_enable: lphb enable request which needs to configure in fwr + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_send_lphb_enable(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_enable_req *ts_lphb_enable); + +/** + * pmo_tgt_send_lphb_tcp_params() - set tcp params of LPHB configuration req + * @psoc: objmgr psoc handle + * @ts_lphb_tcp_param: lphb tcp params which needs to configure in fwr + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_send_lphb_tcp_params(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_tcp_params *ts_lphb_tcp_param); + +/** + * pmo_tgt_send_lphb_tcp_pkt_filter() - send tcp packet filter command of LPHB + * @psoc: objmgr psoc handle + * @ts_lphb_tcp_filter: lphb tcp filter request which needs to configure in fwr + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_send_lphb_tcp_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_tcp_filter_req *ts_lphb_tcp_filter); + +/** + * pmo_tgt_send_lphb_udp_params() - Send udp param command of LPHB + * @psoc: objmgr psoc handle + * @ts_lphb_udp_param: lphb udp params which needs to configure in fwr + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_send_lphb_udp_params(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_udp_params *ts_lphb_udp_param); + +/** + * pmo_tgt_send_lphb_udp_pkt_filter() - Send udp pkt filter command of LPHB + * @psoc: objmgr psoc handle + * @ts_lphb_udp_filter: lphb udp filter request which needs to configure in fwr + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_send_lphb_udp_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_udp_filter_req *ts_lphb_udp_filter); + + +/** + * pmo_tgt_lphb_rsp_evt() - receive lphb rsp event from fwr + * @psoc: objmgr psoc + * @rsp_param: lphb response parameters + * + * Return: QDF_STATUS + */ +QDF_STATUS pmo_tgt_lphb_rsp_evt(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_rsp *rsp_param); + +/** + * pmo_tgt_vdev_update_param_req() - Update vdev param value to fwr + * @vdev: objmgr vdev + * @param_id: tell vdev param id which needs to be updated in fwr + * @param_value: vdev parameter value + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_vdev_update_param_req(struct wlan_objmgr_vdev *vdev, + enum pmo_vdev_param_id param_id, uint32_t param_value); + +/** + * pmo_tgt_send_vdev_sta_ps_param() - Send vdev sta power save param to fwr + * @vdev: objmgr vdev + * @ps_param: sta mode ps power save params type + * @param_value: power save parameter value + * + * Return: QDF status + */ +QDF_STATUS pmo_tgt_send_vdev_sta_ps_param(struct wlan_objmgr_vdev *vdev, + enum pmo_sta_powersave_param ps_param, uint32_t param_value); + +/** + * pmo_tgt_update_wow_bus_suspend_state() - update wow bus suspend state flag + * @psoc: objmgr psoc + * @val: true for setting wow suspend flag to set else false + * + * Return: None + */ +void pmo_tgt_psoc_update_wow_bus_suspend_state(struct wlan_objmgr_psoc *psoc, + uint8_t val); + +/** + * pmo_tgt_get_host_credits() - Get host credits + * @psoc: objmgr psoc + * + * Return: Pending WMI commands on success else EAGAIN on error + */ +int pmo_tgt_psoc_get_host_credits(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_tgt_get_pending_cmnds() - Get pending commands + * @psoc: objmgr psoc + * + * Return: Pending WMI commands on success else EAGAIN on error + */ +int pmo_tgt_psoc_get_pending_cmnds(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_tgt_update_target_suspend_flag() - Set WMI target Suspend flag + * @psoc: objmgr psoc + * @val: true on suspend false for resume + * + * Return: Pending WMI commands on success else EAGAIN on error + */ +void pmo_tgt_update_target_suspend_flag(struct wlan_objmgr_psoc *psoc, + uint8_t val); + +/** + * pmo_tgt_psoc_send_wow_enable_req() -Send wow enable request + * @psoc: objmgr psoc + * @param: WOW enable request buffer + * + * Return: QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS pmo_tgt_psoc_send_wow_enable_req(struct wlan_objmgr_psoc *psoc, + struct pmo_wow_cmd_params *param); + +/** + * pmo_tgt_psoc_send_supend_req() -Send target suspend request to fwr + * @psoc: objmgr psoc + * @param: suspend request buffer + * + * Return: QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS pmo_tgt_psoc_send_supend_req(struct wlan_objmgr_psoc *psoc, + struct pmo_suspend_params *param); + +/** + * pmo_tgt_psoc_set_runtime_pm_inprogress() -set runtime status + * @psoc: objmgr psoc + * @value: set runtime pm in progress true or false + * + * Return: none + */ +QDF_STATUS pmo_tgt_psoc_set_runtime_pm_inprogress(struct wlan_objmgr_psoc *psoc, + bool value); + +/** + * pmo_tgt_psoc_get_runtime_pm_in_progress() -get runtime status + * @psoc: objmgr psoc + * + * Return: true if runtime pm is in progress else false + */ +bool pmo_tgt_psoc_get_runtime_pm_in_progress(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_tgt_psoc_send_host_wakeup_ind() -Send host wake up indication to fwr + * @psoc: objmgr psoc + * + * Return: QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS pmo_tgt_psoc_send_host_wakeup_ind(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_tgt_psoc_send_target_resume_req() -Send target resume request + * @psoc: objmgr psoc + * + * Return: QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS pmo_tgt_psoc_send_target_resume_req(struct wlan_objmgr_psoc *psoc); + +#endif /* end of _WLAN_PMO_TGT_API_H_ */ diff --git a/core/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h b/core/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h new file mode 100644 index 000000000000..beb2adea6d8f --- /dev/null +++ b/core/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h @@ -0,0 +1,565 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Declare public API related to the pmo called by north bound HDD/OSIF + */ + +#ifndef _WLAN_PMO_UCFG_API_H_ +#define _WLAN_PMO_UCFG_API_H_ + +#include "wlan_pmo_arp_public_struct.h" +#include "wlan_pmo_ns_public_struct.h" +#include "wlan_pmo_gtk_public_struct.h" +#include "wlan_pmo_mc_addr_filtering_public_struct.h" +#include "wlan_pmo_wow_public_struct.h" +#include "wlan_pmo_common_public_struct.h" +#include "wlan_pmo_obj_mgmt_api.h" +#include "wlan_pmo_pkt_filter_public_struct.h" +#include "wlan_pmo_hw_filter_public_struct.h" + +/** + * pmo_ucfg_is_ap_mode_supports_arp_ns() - Check ap mode support arp&ns offload + * @psoc: objmgr psoc + * @vdev_opmode: vdev opmode + * + * Return: true in case support else false + */ +bool pmo_ucfg_is_ap_mode_supports_arp_ns(struct wlan_objmgr_psoc *psoc, + enum tQDF_ADAPTER_MODE vdev_opmode); + +/** + * pmo_ucfg_is_vdev_connected() - to check whether peer is associated or not + * @vdev: objmgr vdev + * + * Return: true in case success else false + */ +bool pmo_ucfg_is_vdev_connected(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_ucfg_is_vdev_supports_offload() - check offload is supported on vdev + * @vdev: objmgr vdev + * + * Return: true in case success else false + */ +bool pmo_ucfg_is_vdev_supports_offload(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_ucfg_get_psoc_config(): API to get the psoc user configurations of pmo + * @psoc: objmgr psoc handle + * @psoc_cfg: fill the current psoc user configurations. + * + * Return pmo psoc configurations + */ +QDF_STATUS pmo_ucfg_get_psoc_config(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_cfg *psoc_cfg); + +/** + * pmo_ucfg_update_psoc_config(): API to update the psoc user configurations + * @psoc: objmgr psoc handle + * @psoc_cfg: pmo psoc configurations + * + * This api shall be used for soc config initialization as well update. + * In case of update caller must first call pmo_get_psoc_cfg to get + * current config and then apply changes on top of current config. + * + * Return QDF_STATUS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_update_psoc_config(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_cfg *psoc_cfg); + +/** + * pmo_ucfg_enable_wakeup_event() - enable wow wakeup events + * @psoc: objmgr psoc + * @vdev_id: vdev id + * @bitmap: Event bitmap + * + * Return: none + */ +void pmo_ucfg_enable_wakeup_event(struct wlan_objmgr_psoc *psoc, + uint32_t vdev_id, uint32_t *bitmap); + +/** + * pmo_ucfg_disable_wakeup_event() - disable wow wakeup events + * @psoc: objmgr psoc + * @vdev_id: vdev id + * @bitmap: Event bitmap + * + * Return: none + */ +void pmo_ucfg_disable_wakeup_event(struct wlan_objmgr_psoc *psoc, + uint32_t vdev_id, uint32_t bitmap); + +/** + * pmo_ucfg_cache_arp_offload_req(): API to cache arp req in pmo vdev priv ctx + * @arp_req: pmo arp req param + * + * Return QDF_STATUS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_cache_arp_offload_req(struct pmo_arp_req *arp_req); + +/** + * pmo_ucfg_flush_arp_offload_req(): API to flush arp req from pmo vdev priv ctx + * @vdev: objmgr vdev param + * + * Return QDF_STATUS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_flush_arp_offload_req(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_ucfg_enable_arp_offload_in_fwr(): API to enable arp req in fwr + * @vdev: objmgr vdev param + * @trigger: triger reason for enable arp offload + * + * API to enable cache arp req in fwr from pmo vdev priv ctx + * + * Return QDF_STATUS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_enable_arp_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger); + +/** + * pmo_ucfg_disable_arp_offload_in_fwr(): API to disable arp req in fwr + * @vdev: objmgr vdev param + * @trigger: triger reason for disable arp offload + * API to disable cache arp req in fwr + * + * Return QDF_STATUS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_disable_arp_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger); + +/** + * pmo_ucfg_cache_ns_offload_req(): API to cache ns req in pmo vdev priv ctx + * @ns_req: pmo ns req param + * + * Return QDF_STATUS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_cache_ns_offload_req(struct pmo_ns_req *ns_req); + +/** + * pmo_ucfg_flush_ns_offload_req(): API to flush ns req from pmo vdev priv ctx + * @vdev: vdev ojbmgr handle + * + * Return QDF_STATUS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_flush_ns_offload_req(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_ucfg_enable_ns_offload_in_fwr(): API to enable ns req in fwr + * @arp_req: pmo arp req param + * @trigger: trigger reason to enable ns offload + * + * API to enable cache ns req in fwr from pmo vdev priv ctx + * + * Return QDF_STATUS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_enable_ns_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger); + +/** + * pmo_ucfg_disable_ns_offload_in_fwr(): API to disable ns req in fwr + * @arp_req: pmo arp req param + * @trigger: trigger reason to disable ns offload + * + * API to disable ns req in fwr + * + * Return QDF_STATUS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_disable_ns_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger); + +/** + * pmo_ucfg_enable_hw_filter_in_fwr() - enable previously configured hw filter + * @vdev: objmgr vdev to configure + * + * Return: QDF_STATUS + */ +QDF_STATUS pmo_ucfg_enable_hw_filter_in_fwr(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_ucfg_disable_hw_filter_in_fwr() - disable previously configured hw filter + * @vdev: objmgr vdev to configure + * + * Return: QDF_STATUS + */ +QDF_STATUS pmo_ucfg_disable_hw_filter_in_fwr(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_ucfg_max_mc_addr_supported() - to get max support mc address + * @psoc: objmgr psoc + * + * Return: max mc addr supported count for all vdev in corresponding psoc + */ +uint8_t pmo_ucfg_max_mc_addr_supported(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_ucfg_cache_mc_addr_list(): API to cache mc addr list in pmo vdev priv obj + * @psoc: objmgr psoc handle + * @vdev_id: vdev id + * @gtk_req: pmo gtk req param + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_cache_mc_addr_list( + struct pmo_mc_addr_list_params *mc_list_config); + +/** + * pmo_ucfg_flush_mc_addr_list(): API to flush mc addr list in pmo vdev priv obj + * @psoc: objmgr psoc handle + * @vdev_id: vdev id + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_flush_mc_addr_list(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); + +/** + * pmo_ucfg_enable_mc_addr_filtering_in_fwr(): Enable cached mc add list in fwr + * @psoc: objmgr psoc handle + * @vdev_id: vdev id + * @gtk_req: pmo gtk req param + * @action: true for enable els false + * + * API to enable cached mc add list in fwr + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_enable_mc_addr_filtering_in_fwr( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum pmo_offload_trigger trigger); + +/** + * pmo_ucfg_disable_mc_addr_filtering_in_fwr(): Disable cached mc addr list + * @psoc: objmgr psoc handle + * @vdev_id: vdev id + * @gtk_req: pmo gtk req param + * @action: true for enable els false + * + * API to disable cached mc add list in fwr + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_disable_mc_addr_filtering_in_fwr( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum pmo_offload_trigger trigger); + +/** + * pmo_ucfg_cache_gtk_offload_req(): API to cache gtk req in pmo vdev priv obj + * @vdev: objmgr vdev handle + * @gtk_req: pmo gtk req param + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_cache_gtk_offload_req(struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_req *gtk_req); + +/** + * pmo_ucfg_flush_gtk_offload_req(): Flush saved gtk req from pmo vdev priv obj + * @vdev: objmgr vdev handle + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_flush_gtk_offload_req(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_ucfg_enable_gtk_offload_in_fwr(): enable cached gtk request in fwr + * @vdev: objmgr vdev handle + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_enable_gtk_offload_in_fwr(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_ucfg_disable_gtk_offload_in_fwr(): disable cached gtk request in fwr + * @vdev: objmgr vdev handle + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_disable_gtk_offload_in_fwr(struct wlan_objmgr_vdev *vdev); + +/** + * pmo_ucfg_set_pkt_filter() - Set packet filter + * @psoc: objmgr psoc handle + * @pmo_set_pkt_fltr_req: + * @vdev_id: vdev id + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_set_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_rcv_pkt_fltr_cfg *pmo_set_pkt_fltr_req, + uint8_t vdev_id); + +/** + * pmo_ucfg_clear_pkt_filter() - Clear packet filter + * @psoc: objmgr psoc handle + * @pmo_clr_pkt_fltr_req: + * @vdev_id: vdev id + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_clear_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_rcv_pkt_fltr_clear_param *pmo_clr_pkt_fltr_param, + uint8_t vdev_id); + +/** + * pmo_ucfg_get_gtk_rsp(): API to send gtk response request to fwr + * @vdev: objmgr vdev handle + * @gtk_rsp: pmo gtk response request + * + * This api will send gtk response request to fwr + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_ucfg_get_gtk_rsp(struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_rsp_req *gtk_rsp_req); + +/** + * pmo_ucfg_update_extscan_in_progress(): update extscan is in progress flags + * @vdev: objmgr vdev handle + * @value:true if extscan is in progress else false + * + * Return: TRUE/FALSE + */ +void pmo_ucfg_update_extscan_in_progress(struct wlan_objmgr_vdev *vdev, + bool value); + +/** + * pmo_ucfg_update_p2plo_in_progress(): update p2plo is in progress flags + * @vdev: objmgr vdev handle + * @value:true if p2plo is in progress else false + * + * Return: TRUE/FALSE + */ +void pmo_ucfg_update_p2plo_in_progress(struct wlan_objmgr_vdev *vdev, + bool value); + +/** + * pmo_ucfg_lphb_config_req() - Handles lphb config request for psoc + * @psoc: objmgr psoc handle + * @lphb_req: low power heart beat request + * @lphb_cb_ctx: Context which needs to pass to soif when lphb callback called + * @callback: upon receiving of lphb indication from fwr call lphb callback + * + * Return: QDF status + */ +QDF_STATUS pmo_ucfg_lphb_config_req(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_req *lphb_req, void *lphb_cb_ctx, + pmo_lphb_callback callback); + +/** + * pmo_ucfg_update_alt_modulated_dtim_enable() - update alt modulatate dtim + * @vdev: objmgr vdev handle + * @value: true for alt_modulated_dtim enable else false + * + * Return: QDF status + */ +void pmo_ucfg_update_alt_modulated_dtim_enable(struct wlan_objmgr_vdev *vdev, + bool value); + +/** + * pmo_ucfg_psoc_update_power_save_mode() - update power save mode + * @vdev: objmgr vdev handle + * @value:vdev power save mode + * + * Return: None + */ +void pmo_ucfg_psoc_update_power_save_mode(struct wlan_objmgr_psoc *psoc, + uint8_t value); + +/** + * pmo_ucfg_psoc_update_dp_handle() - update psoc data path handle + * @psoc: objmgr psoc handle + * @dp_hdl: psoc data path handle + * + * Return: None + */ +void pmo_ucfg_psoc_update_dp_handle(struct wlan_objmgr_psoc *psoc, + void *dp_hdl); + +/** + * pmo_ucfg_vdev_update_dp_handle() - update vdev data path handle + * @vdev: objmgr vdev handle + * @dp_hdl: vdev data path handle + * + * Return: None + */ +void pmo_ucfg_vdev_update_dp_handle(struct wlan_objmgr_vdev *vdev, + void *dp_hdl); + +/** + * pmo_ucfg_psoc_update_htc_handle() - update psoc htc layer handle + * @psoc: objmgr psoc handle + * @htc_handle: psoc host-to-tagret layer (htc) handle + * + * Return: None + */ +void pmo_ucfg_psoc_update_htc_handle(struct wlan_objmgr_psoc *psoc, + void *htc_handle); + +/** + * pmo_ucfg_psoc_set_hif_handle() - Set psoc hif layer handle + * @psoc: objmgr psoc handle + * @hif_handle: hif context handle + * + * Return: None + */ +void pmo_ucfg_psoc_set_hif_handle(struct wlan_objmgr_psoc *psoc, + void *hif_handle); + +/** + * pmo_ucfg_psoc_set_txrx_handle() - Set psoc pdev txrx layer handle + * @psoc: objmgr psoc handle + * @txrx_handle: pdev txrx context handle + * + * Return: None + */ +void pmo_ucfg_psoc_set_txrx_handle(struct wlan_objmgr_psoc *psoc, + void *txrx_handle); + +/** + * pmo_ucfg_psoc_user_space_suspend_req() - Handles user space suspend req + * @psoc: objmgr psoc handle + * @type: type of suspend + * + * Handles user space suspend indication for psoc + * + * Return: QDF status + */ +QDF_STATUS pmo_ucfg_psoc_user_space_suspend_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type); + +/** + * pmo_ucfg_psoc_user_space_resume_req() - Handles user space resume req + * @psoc: objmgr psoc handle + * @type: type of suspend from which resume needed + * + * Handles user space resume indication for psoc + * + * Return: QDF status + */ +QDF_STATUS pmo_ucfg_psoc_user_space_resume_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type); + +/** + * pmo_ucfg_psoc_bus_suspend_req(): handles bus suspend for psoc + * @psoc: objmgr psoc + * @type: is this suspend part of runtime suspend or system suspend? + * @wow_params: collection of wow enable override parameters + * + * Bails if a scan is in progress. + * Calls the appropriate handlers based on configuration and event. + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS pmo_ucfg_psoc_bus_suspend_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type, + struct pmo_wow_enable_params *wow_params); + +#ifdef FEATURE_RUNTIME_PM +/** + * pmo_ucfg_psoc_bus_runtime_suspend(): handles bus runtime suspend for psoc + * @psoc: objmgr psoc + * @pld_cb: callback to call link auto suspend + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS pmo_ucfg_psoc_bus_runtime_suspend(struct wlan_objmgr_psoc *psoc, + pmo_pld_auto_suspend_cb pld_cb); + +/** + * pmo_ucfg_psoc_bus_runtime_resume(): handles bus runtime resume for psoc + * @psoc: objmgr psoc + * @pld_cb: callback to call link auto resume + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS pmo_ucfg_psoc_bus_runtime_resume(struct wlan_objmgr_psoc *psoc, + pmo_pld_auto_resume_cb pld_cb); +#endif + +/** + * pmo_ucfg_psoc_suspend_target() -Send suspend target command + * @psoc: objmgr psoc handle + * @disable_target_intr: disable target interrupt + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS pmo_ucfg_psoc_suspend_target(struct wlan_objmgr_psoc *psoc, + int disable_target_intr); + +/** + * pmo_ucfg_psoc_bus_resume() -handle bus resume request for psoc + * @psoc: objmgr psoc handle + * @type: is this suspend part of runtime suspend or system suspend? + * + * Return:QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS pmo_ucfg_psoc_bus_resume_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type); + +/** + * pmo_ucfg_get_wow_bus_suspend(): API to check if wow bus is suspended or not + * @psoc: objmgr psoc handle + * + * Return: True if bus suspende else false + */ +bool pmo_ucfg_get_wow_bus_suspend(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_ucfg_psoc_handle_initial_wake_up() - update initial wake up + * @cb_ctx: objmgr psoc handle as void * due to htc layer is not aware psoc + * + * Return: None + */ +void pmo_ucfg_psoc_handle_initial_wake_up(void *cb_ctx); + +/** + * pmo_ucfg_psoc_is_target_wake_up_received() - Get initial wake up status + * @psoc: objmgr psoc handle + * + * Return: 0 on success else error code + */ +int pmo_ucfg_psoc_is_target_wake_up_received(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_ucfg_psoc_is_target_wake_up_received() - Clear initial wake up status + * @psoc: objmgr psoc handle + * + * Return: 0 on success else error code + */ +int pmo_ucfg_psoc_clear_target_wake_up(struct wlan_objmgr_psoc *psoc); + +/** + * pmo_ucfg_psoc_target_suspend_acknowledge() - Clear initial wake up status + * @psoc: objmgr psoc handle + * + * Return: None + */ +void pmo_ucfg_psoc_target_suspend_acknowledge(void *context, bool wow_nack); + +/** + * pmo_ucfg_psoc_wakeup_host_event_received() - got host wake up evennt from fwr + * @psoc: objmgr psoc handle + * + * Return: None + */ +void pmo_ucfg_psoc_wakeup_host_event_received(struct wlan_objmgr_psoc *psoc); + +#endif /* end of _WLAN_PMO_UCFG_API_H_ */ diff --git a/core/components/pmo/dispatcher/inc/wlan_pmo_wow_public_struct.h b/core/components/pmo/dispatcher/inc/wlan_pmo_wow_public_struct.h new file mode 100644 index 000000000000..46d7048b5db8 --- /dev/null +++ b/core/components/pmo/dispatcher/inc/wlan_pmo_wow_public_struct.h @@ -0,0 +1,241 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ + /** + * DOC: Declare various struct, macros which shall be used in + * pmo wow related features. + * + * Note: This file shall not contain public API's prototype/declarations. + * + */ + +#ifndef _WLAN_PMO_WOW_PUBLIC_STRUCT_H_ +#include "wlan_pmo_lphb_public_struct.h" + +#define _WLAN_PMO_WOW_PUBLIC_STRUCT_H_ + +#define PMO_WOWL_PTRN_MAX_SIZE 146 +#define PMO_WOWL_PTRN_MASK_MAX_SIZE 19 +#define PMO_WOWL_MAX_PTRNS_ALLOWED CFG_MAX_WOW_FILTERS_MAX +#define PMO_WOWL_BCAST_PATTERN_MAX_SIZE 146 + +#define PMO_WOW_INTER_PTRN_TOKENIZER ';' +#define PMO_WOW_INTRA_PTRN_TOKENIZER ':' + + +/* Action frame categories */ + +#define PMO_MAC_ACTION_SPECTRUM_MGMT 0 +#define PMO_MAC_ACTION_QOS_MGMT 1 +#define PMO_MAC_ACTION_DLP 2 +#define PMO_MAC_ACTION_BLKACK 3 +#define PMO_MAC_ACTION_PUBLIC_USAGE 4 +#define PMO_MAC_ACTION_RRM 5 +#define PMO_MAC_ACTION_FAST_BSS_TRNST 6 +#define PMO_MAC_ACTION_HT 7 +#define PMO_MAC_ACTION_SA_QUERY 8 +#define PMO_MAC_ACTION_PROT_DUAL_PUB 9 +#define PMO_MAC_ACTION_WNM 10 +#define PMO_MAC_ACTION_UNPROT_WNM 11 +#define PMO_MAC_ACTION_TDLS 12 +#define PMO_MAC_ACITON_MESH 13 +#define PMO_MAC_ACTION_MHF 14 +#define PMO_MAC_SELF_PROTECTED 15 +#define PMO_MAC_ACTION_WME 17 +#define PMO_MAC_ACTION_FST 18 +#define PMO_MAC_ACTION_VHT 21 +#define PMO_MAC_ACTION_MAX 256 + +/* + * ALLOWED_ACTION_FRAMES_BITMAP + * + * Bitmask is based on the below. The frames with 0's + * set to their corresponding bit can be dropped in FW. + * + * -----------------------------+-----+-------+ + * Type | Bit | Allow | + * -----------------------------+-----+-------+ + * PMO_ACTION_SPECTRUM_MGMT 0 1 + * PMO_ACTION_QOS_MGMT 1 1 + * PMO_ACTION_DLP 2 0 + * PMO_ACTION_BLKACK 3 0 + * PMO_ACTION_PUBLIC_USAGE 4 1 + * PMO_ACTION_RRM 5 1 + * PMO_ACTION_FAST_BSS_TRNST 6 0 + * PMO_ACTION_HT 7 0 + * PMO_ACTION_SA_QUERY 8 1 + * PMO_ACTION_PROT_DUAL_PUB 9 1 + * PMO_ACTION_WNM 10 1 + * PMO_ACTION_UNPROT_WNM 11 0 + * PMO_ACTION_TDLS 12 0 + * PMO_ACITON_MESH 13 0 + * PMO_ACTION_MHF 14 0 + * PMO_SELF_PROTECTED 15 0 + * PMO_ACTION_WME 17 1 + * PMO_ACTION_FST 18 1 + * PMO_ACTION_VHT 21 1 + * ----------------------------+------+-------+ + */ +#define ALLOWED_ACTION_FRAMES_BITMAP0 \ + ((1 << PMO_MAC_ACTION_SPECTRUM_MGMT) | \ + (1 << PMO_MAC_ACTION_QOS_MGMT) | \ + (1 << PMO_MAC_ACTION_PUBLIC_USAGE) | \ + (1 << PMO_MAC_ACTION_RRM) | \ + (1 << PMO_MAC_ACTION_SA_QUERY) | \ + (1 << PMO_MAC_ACTION_PROT_DUAL_PUB) | \ + (1 << PMO_MAC_ACTION_WNM) | \ + (1 << PMO_MAC_ACTION_WME) | \ + (1 << PMO_MAC_ACTION_FST) | \ + (1 << PMO_MAC_ACTION_VHT)) + +#define ALLOWED_ACTION_FRAMES_BITMAP1 0x0 +#define ALLOWED_ACTION_FRAMES_BITMAP2 0x0 +#define ALLOWED_ACTION_FRAMES_BITMAP3 0x0 +#define ALLOWED_ACTION_FRAMES_BITMAP4 0x0 +#define ALLOWED_ACTION_FRAMES_BITMAP5 0x0 +#define ALLOWED_ACTION_FRAMES_BITMAP6 0x0 +#define ALLOWED_ACTION_FRAMES_BITMAP7 0x0 + +#define ALLOWED_ACTION_FRAME_MAP_WORDS (PMO_MAC_ACTION_MAX / 32) + + +#define PMO_SUPPORTED_ACTION_CATE 256 +#define PMO_SUPPORTED_ACTION_CATE_ELE_LIST (PMO_SUPPORTED_ACTION_CATE/32) + +/** + * struct pmo_action_wakeup_set_params - action wakeup set params + * @vdev_id: virtual device id + * @operation: 0 reset to fw default, 1 set the bits, + * 2 add the setting bits, 3 delete the setting bits + * @action_category_map: bit mapping. + */ +struct pmo_action_wakeup_set_params { + uint32_t vdev_id; + uint32_t operation; + uint32_t action_category_map[PMO_SUPPORTED_ACTION_CATE_ELE_LIST]; +}; + +/** + * enum pmo_wow_action_wakeup_opertion: describe action wakeup operation + * @pmo_action_wakeup_reset: reset + * @pmo_action_wakeup_set: set + * @pmo_action_wakeup_add_set: add and set + * @pmo_action_wakeup_del_set: delete and set + */ +enum pmo_wow_action_wakeup_opertion { + pmo_action_wakeup_reset = 0, + pmo_action_wakeup_set, + pmo_action_wakeup_add_set, + pmo_action_wakeup_del_set, +}; + +/** + * 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 + * @target_suspend: target suspend event + * @target_resume: target resume event + * @wow_nack: wow negative ack flag + * @wow_initial_wake_up: target initial wake up is received + * @wow_wake_lock: wow wake lock + * @lphb_cache: lphb cache + * @lphb_cb_ctx: callback context for lphb, kept as void* as + * osif structures are opaque to pmo. + * @pmo_lphb_callback: registered os if calllback function + * + * This structure stores wow patterns and + * wow related parameters in host. + */ +struct pmo_wow { + bool wow_enable; + bool wow_enable_cmd_sent; + bool is_wow_bus_suspended; + qdf_event_t target_suspend; + qdf_event_t target_resume; + int wow_nack; + bool wow_initial_wake_up; + qdf_wake_lock_t wow_wake_lock; + /* + * currently supports only vdev 0. + * cache has two entries: one for TCP and one for UDP. + */ + struct pmo_lphb_req lphb_cache[2]; + void *lphb_cb_ctx; + pmo_lphb_callback lphb_cb; +}; + +/* WOW related structures */ +/** + * struct pmo_wow_add_pattern - wow pattern add structure + * @pattern_id: pattern id + * @pattern_byte_offset: pattern byte offset from beginning of the 802.11 + * packet to start of the wake-up pattern + * @pattern_size: pattern size + * @pattern: pattern byte stream + * @pattern_mask_size: pattern mask size + * @pattern_mask: pattern mask + * @session_id: session id + */ +struct pmo_wow_add_pattern { + uint8_t pattern_id; + uint8_t pattern_byte_offset; + uint8_t pattern_size; + uint8_t pattern[PMO_WOWL_BCAST_PATTERN_MAX_SIZE]; + uint8_t pattern_mask_size; + uint8_t pattern_mask[PMO_WOWL_BCAST_PATTERN_MAX_SIZE]; + uint8_t session_id; +}; + +/** + * struct pmo_wow_add_pattern - wow pattern add structure + * @magic_pkt_enable: enables or disables magic packet filtering + * @wow_deauth_rcv: This configuration is valid only when magicPktEnable=1, + * It requests hardware to wake up when it receives the + * Deauthentication Frame. + * @pattern_filtering_enable: Enables/disables packet pattern filtering + * @wow_bss_conn_loss: wake up host when bss connection lost + */ +struct pmo_wow_enter_params { + uint8_t magic_pkt_enable; + uint8_t wow_deauth_rcv; + uint8_t pattern_filtering_enable; + uint8_t wow_bss_conn_loss; +}; + +/** + * struct pmo_wow_cmd_params - wow cmd parameter + * @enable: wow enable or disable flag + * @can_suspend_link: flag to indicate if link can be suspended + * @pause_iface_config: interface config + */ +struct pmo_wow_cmd_params { + bool enable; + bool can_suspend_link; + uint8_t pause_iface_config; + uint32_t flags; +}; + +/** + * struct pmo_suspend_params - suspend cmd parameter + * @disable_target_intr: disable target interrupt + */ +struct pmo_suspend_params { + uint8_t disable_target_intr; +}; + +#endif /* end of _WLAN_PMO_WOW_PUBLIC_STRUCT_H_ */ diff --git a/core/components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c b/core/components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c new file mode 100644 index 000000000000..0041fa2e9a4f --- /dev/null +++ b/core/components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c @@ -0,0 +1,761 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: define utility API related to the pmo component + * called by other components + */ + +#include "wlan_pmo_obj_mgmt_api.h" +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_static_config.h" +#include "wlan_pmo_main.h" +#include "target_if_pmo.h" + +QDF_STATUS pmo_init(void) +{ + QDF_STATUS status; + struct wlan_pmo_ctx *pmo_ctx; + + PMO_ENTER(); + if (pmo_allocate_ctx() != QDF_STATUS_SUCCESS) { + pmo_err("unable to allocate psoc ctx"); + status = QDF_STATUS_E_FAULT; + goto out; + } + + pmo_ctx = pmo_get_context(); + if (!pmo_ctx) { + pmo_err("unable to get pmo ctx"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = wlan_objmgr_register_psoc_create_handler( + WLAN_UMAC_COMP_PMO, + pmo_psoc_object_created_notification, + (void *)pmo_ctx); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("unable to register psoc create handle"); + goto out; + } + + status = wlan_objmgr_register_psoc_destroy_handler( + WLAN_UMAC_COMP_PMO, + pmo_psoc_object_destroyed_notification, + (void *)pmo_ctx); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("unable to register psoc create handle"); + goto out; + } + + status = wlan_objmgr_register_vdev_create_handler( + WLAN_UMAC_COMP_PMO, + pmo_vdev_object_created_notification, + (void *)pmo_ctx); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("unable to register vdev create handle"); + goto out; + } + + status = wlan_objmgr_register_vdev_destroy_handler( + WLAN_UMAC_COMP_PMO, + pmo_vdev_object_destroyed_notification, + (void *)pmo_ctx); + if (status != QDF_STATUS_SUCCESS) + pmo_err("unable to register vdev create handle"); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_deinit(void) +{ + QDF_STATUS status; + struct wlan_pmo_ctx *pmo_ctx; + + PMO_ENTER(); + pmo_ctx = pmo_get_context(); + if (!pmo_ctx) { + pmo_err("unable to get pmo ctx"); + status = QDF_STATUS_E_FAILURE; + goto out; + } + + status = wlan_objmgr_unregister_psoc_create_handler( + WLAN_UMAC_COMP_PMO, + pmo_psoc_object_created_notification, + (void *)pmo_ctx); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("unable to unregister psoc create handle"); + goto out; + } + + status = wlan_objmgr_unregister_psoc_destroy_handler( + WLAN_UMAC_COMP_PMO, + pmo_psoc_object_destroyed_notification, + (void *)pmo_ctx); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("unable to unregister psoc create handle"); + goto out; + } + + status = wlan_objmgr_unregister_vdev_create_handler( + WLAN_UMAC_COMP_PMO, + pmo_vdev_object_created_notification, + (void *)pmo_ctx); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("unable to unregister vdev create handle"); + goto out; + } + + status = wlan_objmgr_unregister_vdev_destroy_handler( + WLAN_UMAC_COMP_PMO, + pmo_vdev_object_destroyed_notification, + (void *)pmo_ctx); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("unable to unregister vdev create handle"); + goto out; + } + +out: + pmo_free_ctx(); + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_psoc_object_created_notification( + struct wlan_objmgr_psoc *psoc, void *arg) +{ + struct pmo_psoc_priv_obj *psoc_ctx = NULL; + QDF_STATUS status; + struct wlan_pmo_ctx *pmo_ctx; + + PMO_ENTER(); + pmo_ctx = pmo_get_context(); + if (!pmo_ctx) { + QDF_ASSERT(0); + pmo_err("unable to get pmo ctx"); + status = QDF_STATUS_E_FAILURE; + goto out; + } + + psoc_ctx = qdf_mem_malloc(sizeof(*psoc_ctx)); + if (psoc_ctx == NULL) { + pmo_err("Failed to allocate pmo_psoc"); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + status = wlan_objmgr_psoc_component_obj_attach(psoc, + WLAN_UMAC_COMP_PMO, + psoc_ctx, + QDF_STATUS_SUCCESS); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("Failed to attach psoc_ctx with psoc"); + qdf_mem_free(psoc_ctx); + status = QDF_STATUS_E_FAILURE; + goto out; + } + qdf_spinlock_create(&psoc_ctx->lock); + qdf_wake_lock_create(&psoc_ctx->wow.wow_wake_lock, "pmo_wow_wl"); + status = qdf_event_create(&psoc_ctx->wow.target_suspend); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("target suspend event initialization failed"); + status = QDF_STATUS_E_FAILURE; + goto out; + } + status = qdf_event_create(&psoc_ctx->wow.target_resume); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("target resume event initialization failed"); + status = QDF_STATUS_E_FAILURE; + goto out; + } + /* Register PMO tx ops*/ + target_if_pmo_register_tx_ops(&psoc_ctx->pmo_tx_ops); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_psoc_object_destroyed_notification( + struct wlan_objmgr_psoc *psoc, void *arg) +{ + struct pmo_psoc_priv_obj *psoc_ctx = NULL; + QDF_STATUS status; + + PMO_ENTER(); + + psoc_ctx = pmo_psoc_get_priv(psoc); + + status = wlan_objmgr_psoc_component_obj_detach(psoc, + WLAN_UMAC_COMP_PMO, + psoc_ctx); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("Failed to detach psoc_ctx from psoc"); + status = QDF_STATUS_E_FAILURE; + goto out; + } + + qdf_spinlock_destroy(&psoc_ctx->lock); + qdf_event_destroy(&psoc_ctx->wow.target_suspend); + qdf_event_destroy(&psoc_ctx->wow.target_resume); + qdf_wake_lock_destroy(&psoc_ctx->wow.wow_wake_lock); + qdf_mem_zero(psoc_ctx, sizeof(*psoc_ctx)); + qdf_mem_free(psoc_ctx); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_vdev_object_created_notification( + struct wlan_objmgr_vdev *vdev, void *arg) +{ + struct pmo_psoc_priv_obj *psoc_ctx = NULL; + struct wlan_objmgr_psoc *psoc; + struct pmo_vdev_priv_obj *vdev_ctx; + QDF_STATUS status; + + PMO_ENTER(); + + psoc = pmo_vdev_get_psoc(vdev); + + psoc_ctx = pmo_psoc_get_priv(psoc); + + vdev_ctx = qdf_mem_malloc(sizeof(*vdev_ctx)); + if (vdev_ctx == NULL) { + pmo_err("Failed to allocate vdev_ctx"); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + status = wlan_objmgr_vdev_component_obj_attach(vdev, + WLAN_UMAC_COMP_PMO, + (void *)vdev_ctx, QDF_STATUS_SUCCESS); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("Failed to attach vdev_ctx with vdev"); + qdf_mem_free(vdev_ctx); + goto out; + } + + qdf_spinlock_create(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->ptrn_match_enable = + psoc_ctx->psoc_cfg.ptrn_match_enable_all_vdev; + vdev_ctx->pmo_psoc_ctx = psoc_ctx; + qdf_atomic_init(&vdev_ctx->gtk_err_enable); + +out: + PMO_EXIT(); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_vdev_ready(struct wlan_objmgr_vdev *vdev) +{ + QDF_STATUS status; + + PMO_ENTER(); + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + return status; + + /* Register static configuration with firmware */ + pmo_register_wow_wakeup_events(vdev); + pmo_register_action_frame_patterns(vdev); + + /* Register default wow patterns with firmware */ + pmo_register_wow_default_patterns(vdev); + + pmo_vdev_put_ref(vdev); + + PMO_EXIT(); + + /* + * The above APIs should return a status but don't. + * Just return success for now. + */ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_vdev_object_destroyed_notification( + struct wlan_objmgr_vdev *vdev, void *arg) +{ + struct pmo_vdev_priv_obj *vdev_ctx = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + PMO_ENTER(); + + vdev_ctx = pmo_vdev_get_priv(vdev); + + status = wlan_objmgr_vdev_component_obj_detach(vdev, + WLAN_UMAC_COMP_PMO, + (void *)vdev_ctx); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to detach vdev_ctx with vdev"); + + qdf_spinlock_destroy(&vdev_ctx->pmo_vdev_lock); + qdf_mem_free(vdev_ctx); + + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_register_suspend_handler( + enum wlan_umac_comp_id id, + pmo_psoc_suspend_handler handler, + void *arg) +{ + struct wlan_pmo_ctx *pmo_ctx; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + PMO_ENTER(); + pmo_ctx = pmo_get_context(); + if (!pmo_ctx) { + QDF_ASSERT(0); + pmo_err("unable to get pmo ctx"); + status = QDF_STATUS_E_FAILURE; + goto out; + } + + if (id > WLAN_UMAC_MAX_COMPONENTS || id < 0) { + pmo_err("component id: %d is %s then valid components id", + id, id < 0 ? "Less" : "More"); + status = QDF_STATUS_E_FAILURE; + goto out; + } + + qdf_spin_lock_bh(&pmo_ctx->lock); + pmo_ctx->pmo_suspend_handler[id] = handler; + pmo_ctx->pmo_suspend_handler_arg[id] = arg; + qdf_spin_unlock_bh(&pmo_ctx->lock); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_unregister_suspend_handler( + enum wlan_umac_comp_id id, + pmo_psoc_suspend_handler handler) +{ + struct wlan_pmo_ctx *pmo_ctx; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + PMO_ENTER(); + pmo_ctx = pmo_get_context(); + if (!pmo_ctx) { + QDF_ASSERT(0); + pmo_err("unable to get pmo ctx"); + status = QDF_STATUS_E_FAILURE; + goto out; + } + + if (id > WLAN_UMAC_MAX_COMPONENTS || id < 0) { + pmo_err("component id: %d is %s then valid components id", + id, id < 0 ? "Less" : "More"); + status = QDF_STATUS_E_FAILURE; + goto out; + } + + qdf_spin_lock_bh(&pmo_ctx->lock); + if (pmo_ctx->pmo_suspend_handler[id] == handler) { + pmo_ctx->pmo_suspend_handler[id] = NULL; + pmo_ctx->pmo_suspend_handler_arg[id] = NULL; + qdf_spin_unlock_bh(&pmo_ctx->lock); + } else { + qdf_spin_unlock_bh(&pmo_ctx->lock); + pmo_err("can't find suspend handler for component id: %d ", id); + status = QDF_STATUS_E_FAILURE; + } +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_register_resume_handler( + enum wlan_umac_comp_id id, + pmo_psoc_resume_handler handler, + void *arg) +{ + struct wlan_pmo_ctx *pmo_ctx; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + PMO_ENTER(); + pmo_ctx = pmo_get_context(); + if (!pmo_ctx) { + pmo_err("unable to get pmo ctx"); + status = QDF_STATUS_E_FAILURE; + goto out; + } + + if (id > WLAN_UMAC_MAX_COMPONENTS || id < 0) { + pmo_err("component id: %d is %s then valid components id", + id, id < 0 ? "Less" : "More"); + status = QDF_STATUS_E_FAILURE; + goto out; + } + + qdf_spin_lock_bh(&pmo_ctx->lock); + pmo_ctx->pmo_resume_handler[id] = handler; + pmo_ctx->pmo_resume_handler_arg[id] = arg; + qdf_spin_unlock_bh(&pmo_ctx->lock); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_unregister_resume_handler( + enum wlan_umac_comp_id id, + pmo_psoc_resume_handler handler) +{ + struct wlan_pmo_ctx *pmo_ctx; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + PMO_ENTER(); + pmo_ctx = pmo_get_context(); + if (!pmo_ctx) { + pmo_err("unable to get pmo ctx"); + status = QDF_STATUS_E_FAILURE; + goto out; + } + + if (id > WLAN_UMAC_MAX_COMPONENTS || id < 0) { + pmo_err("component id: %d is %s then valid components id", + id, id < 0 ? "Less" : "More"); + status = QDF_STATUS_E_FAILURE; + goto out; + } + + qdf_spin_lock_bh(&pmo_ctx->lock); + if (pmo_ctx->pmo_resume_handler[id] == handler) { + pmo_ctx->pmo_resume_handler[id] = NULL; + pmo_ctx->pmo_resume_handler_arg[id] = NULL; + qdf_spin_unlock_bh(&pmo_ctx->lock); + } else { + qdf_spin_unlock_bh(&pmo_ctx->lock); + pmo_err("can't find resume handler for component id: %d ", id); + status = QDF_STATUS_E_FAILURE; + } +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_suspend_all_components(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type suspend_type) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + QDF_STATUS resume_status; + struct wlan_pmo_ctx *pmo_ctx; + uint8_t i; + pmo_psoc_suspend_handler handler; + void *arg; + + PMO_ENTER(); + + pmo_ctx = pmo_get_context(); + if (!pmo_ctx) { + pmo_err("unable to get pmo ctx"); + QDF_ASSERT(0); + status = QDF_STATUS_E_FAILURE; + goto exit_with_status; + } + + /* call each component's suspend handler */ + for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { + qdf_spin_lock_bh(&pmo_ctx->lock); + handler = pmo_ctx->pmo_suspend_handler[i]; + arg = pmo_ctx->pmo_suspend_handler_arg[i]; + qdf_spin_unlock_bh(&pmo_ctx->lock); + + if (!handler) + continue; + + status = handler(psoc, arg); + if (QDF_IS_STATUS_ERROR(status)) { + pmo_err("component %d failed to suspend; status: %d", + i, status); + QDF_ASSERT(0); + goto suspend_recovery; + } + } + + goto exit_with_status; + +suspend_recovery: + /* resume, starting with the last successfully suspended component */ + for (i -= 1; i >= 0; i--) { + qdf_spin_lock_bh(&pmo_ctx->lock); + handler = pmo_ctx->pmo_resume_handler[i]; + arg = pmo_ctx->pmo_resume_handler_arg[i]; + qdf_spin_unlock_bh(&pmo_ctx->lock); + + if (!handler) + continue; + + resume_status = handler(psoc, arg); + if (QDF_IS_STATUS_ERROR(resume_status)) { + pmo_fatal("Non-recoverable failure occurred!"); + pmo_fatal("component %d failed to resume; status: %d", + i, resume_status); + QDF_BUG(0); + } + } + +exit_with_status: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_resume_all_components(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type suspend_type) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct wlan_pmo_ctx *pmo_ctx; + uint8_t i; + pmo_psoc_suspend_handler handler; + void *arg; + + PMO_ENTER(); + + pmo_ctx = pmo_get_context(); + if (!pmo_ctx) { + pmo_err("unable to get pmo ctx"); + QDF_ASSERT(0); + status = QDF_STATUS_E_FAILURE; + goto exit_with_status; + } + + /* call each component's resume handler */ + for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { + qdf_spin_lock_bh(&pmo_ctx->lock); + handler = pmo_ctx->pmo_resume_handler[i]; + arg = pmo_ctx->pmo_resume_handler_arg[i]; + qdf_spin_unlock_bh(&pmo_ctx->lock); + + if (!handler) + continue; + + status = handler(psoc, arg); + if (QDF_IS_STATUS_ERROR(status)) { + pmo_fatal("Non-recoverable failure occurred!"); + pmo_fatal("component %d failed to resume; status: %d", + i, status); + QDF_BUG(0); + } + } + +exit_with_status: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_register_pause_bitmap_notifier(struct wlan_objmgr_psoc *psoc, + pmo_notify_pause_bitmap handler) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + QDF_STATUS status; + + if (!psoc) { + pmo_err("psoc is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!handler) { + pmo_err("pmo_notify_vdev_pause_bitmap is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("pmo cannot get the reference out of psoc"); + return status; + } + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->pause_bitmap_notifier = handler; + qdf_spin_unlock_bh(&psoc_ctx->lock); + pmo_psoc_put_ref(psoc); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_unregister_pause_bitmap_notifier(struct wlan_objmgr_psoc *psoc, + pmo_notify_pause_bitmap handler) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + QDF_STATUS status; + + if (!psoc) { + pmo_err("psoc is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!handler) { + pmo_err("pmo_notify_vdev_pause_bitmap is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("pmo cannot get the reference out of psoc"); + return status; + } + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + if (psoc_ctx->pause_bitmap_notifier == handler) + psoc_ctx->pause_bitmap_notifier = NULL; + qdf_spin_unlock_bh(&psoc_ctx->lock); + pmo_psoc_put_ref(psoc); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_register_get_pause_bitmap(struct wlan_objmgr_psoc *psoc, + pmo_get_pause_bitmap handler) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + QDF_STATUS status; + + if (!psoc) { + pmo_err("psoc is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!handler) { + pmo_err("pmo_get_pause_bitmap is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("pmo cannot get the reference out of psoc"); + return status; + } + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->get_pause_bitmap = handler; + qdf_spin_unlock_bh(&psoc_ctx->lock); + pmo_psoc_put_ref(psoc); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_unregister_get_pause_bitmap(struct wlan_objmgr_psoc *psoc, + pmo_get_pause_bitmap handler) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + QDF_STATUS status; + + if (!psoc) { + pmo_err("psoc is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!handler) { + pmo_err("pmo_get_pause_bitmap is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("pmo cannot get the reference out of psoc"); + return status; + } + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + if (psoc_ctx->get_pause_bitmap == handler) + psoc_ctx->get_pause_bitmap = NULL; + qdf_spin_unlock_bh(&psoc_ctx->lock); + pmo_psoc_put_ref(psoc); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_register_is_device_in_low_pwr_mode(struct wlan_objmgr_psoc *psoc, + pmo_is_device_in_low_pwr_mode handler) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + QDF_STATUS status; + + if (!psoc) { + pmo_err("psoc is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!handler) { + pmo_err("pmo_get_pause_bitmap is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("pmo cannot get the reference out of psoc"); + return status; + } + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->is_device_in_low_pwr_mode = handler; + qdf_spin_unlock_bh(&psoc_ctx->lock); + pmo_psoc_put_ref(psoc); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS pmo_unregister_is_device_in_low_pwr_mode( + struct wlan_objmgr_psoc *psoc, + pmo_is_device_in_low_pwr_mode handler) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + QDF_STATUS status; + + if (!psoc) { + pmo_err("psoc is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!handler) { + pmo_err("pmo_get_pause_bitmap is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + status = pmo_psoc_get_ref(psoc); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("pmo cannot get the reference out of psoc"); + return status; + } + psoc_ctx = pmo_psoc_get_priv(psoc); + qdf_spin_lock_bh(&psoc_ctx->lock); + psoc_ctx->is_device_in_low_pwr_mode = NULL; + qdf_spin_unlock_bh(&psoc_ctx->lock); + pmo_psoc_put_ref(psoc); + + return QDF_STATUS_SUCCESS; +} + + diff --git a/core/components/pmo/dispatcher/src/wlan_pmo_tgt_arp.c b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_arp.c new file mode 100644 index 000000000000..eafcbeda1ab6 --- /dev/null +++ b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_arp.c @@ -0,0 +1,158 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements public API for pmo to interact with target/WMI + */ + +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_arp_public_struct.h" +#include "wlan_pmo_ns_public_struct.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" +#include "wlan_pmo_main.h" + +QDF_STATUS pmo_tgt_enable_arp_offload_req(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id) +{ + struct pmo_arp_offload_params *arp_offload_req = NULL; + struct pmo_ns_offload_params *ns_offload_req = NULL; + struct pmo_vdev_priv_obj *vdev_ctx; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + + vdev_ctx = pmo_vdev_get_priv(vdev); + + psoc = pmo_vdev_get_psoc(vdev); + + arp_offload_req = qdf_mem_malloc(sizeof(*arp_offload_req)); + if (!arp_offload_req) { + pmo_err("unable to allocate arp_offload_req"); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + ns_offload_req = qdf_mem_malloc(sizeof(*ns_offload_req)); + if (!ns_offload_req) { + pmo_err("unable to allocate ns_offload_req"); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + qdf_mem_copy(arp_offload_req, &vdev_ctx->vdev_arp_req, + sizeof(*arp_offload_req)); + qdf_mem_copy(ns_offload_req, &vdev_ctx->vdev_ns_req, + sizeof(*ns_offload_req)); + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + pmo_debug("ARP Offload vdev_id: %d enable: %d", + vdev_id, + arp_offload_req->enable); + pmo_debug("NS Offload vdev_id: %d enable: %d ns_count: %u", + vdev_id, + ns_offload_req->enable, + ns_offload_req->num_ns_offload_count); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_arp_offload_req) { + pmo_err("send_arp_offload_req is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + status = pmo_tx_ops.send_arp_offload_req( + vdev, arp_offload_req, ns_offload_req); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to send ARP offload"); +out: + if (arp_offload_req) + qdf_mem_free(arp_offload_req); + if (ns_offload_req) + qdf_mem_free(ns_offload_req); + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_disable_arp_offload_req(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id) +{ + struct pmo_arp_offload_params *arp_offload_req = NULL; + struct pmo_ns_offload_params *ns_offload_req = NULL; + struct pmo_vdev_priv_obj *vdev_ctx; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + + vdev_ctx = pmo_vdev_get_priv(vdev); + + psoc = pmo_vdev_get_psoc(vdev); + + arp_offload_req = qdf_mem_malloc(sizeof(*arp_offload_req)); + if (!arp_offload_req) { + pmo_err("unable to allocate arp_offload_req"); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + ns_offload_req = qdf_mem_malloc(sizeof(*ns_offload_req)); + if (!ns_offload_req) { + pmo_err("unable to allocate ns_offload_req"); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + qdf_mem_copy(arp_offload_req, &vdev_ctx->vdev_arp_req, + sizeof(*arp_offload_req)); + qdf_mem_copy(ns_offload_req, &vdev_ctx->vdev_ns_req, + sizeof(*ns_offload_req)); + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + pmo_debug("ARP Offload vdev_id: %d enable: %d", + vdev_id, + arp_offload_req->enable); + pmo_debug("NS Offload vdev_id: %d enable: %d ns_count: %u", + vdev_id, + ns_offload_req->enable, + ns_offload_req->num_ns_offload_count); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_arp_offload_req) { + pmo_err("send_arp_offload_req is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + status = pmo_tx_ops.send_arp_offload_req( + vdev, arp_offload_req, ns_offload_req); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to send ARP offload"); + +out: + if (arp_offload_req) + qdf_mem_free(arp_offload_req); + if (ns_offload_req) + qdf_mem_free(ns_offload_req); + PMO_EXIT(); + + return status; +} + diff --git a/core/components/pmo/dispatcher/src/wlan_pmo_tgt_gtk.c b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_gtk.c new file mode 100644 index 000000000000..8f3827814002 --- /dev/null +++ b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_gtk.c @@ -0,0 +1,178 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements public API for PMO GTK offload feature to interact + * with target/wmi. + */ + +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_gtk_public_struct.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" +#include "wlan_pmo_main.h" + +QDF_STATUS pmo_tgt_send_gtk_offload_req(struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_req *gtk_req) +{ + struct pmo_gtk_req *op_gtk_req = NULL; + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct pmo_vdev_priv_obj *vdev_ctx; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + pmo_err("Failed to find psoc from from vdev:%p", + vdev); + status = QDF_STATUS_E_INVAL; + goto out; + } + + vdev_ctx = pmo_vdev_get_priv(vdev); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_gtk_offload_req) { + pmo_err("send_gtk_offload_req is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + op_gtk_req = qdf_mem_malloc(sizeof(*op_gtk_req)); + if (!op_gtk_req) { + pmo_err("cannot allocate op_gtk_req "); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + if (gtk_req->flags == PMO_GTK_OFFLOAD_ENABLE) { + qdf_atomic_set(&vdev_ctx->gtk_err_enable, true); + qdf_mem_copy(op_gtk_req->kck, gtk_req->kck, + PMO_KCK_LEN); + qdf_mem_copy(op_gtk_req->kek, gtk_req->kek, + PMO_KEK_LEN); + qdf_mem_copy(&op_gtk_req->replay_counter, + >k_req->replay_counter, PMO_REPLAY_COUNTER_LEN); + } else { + qdf_atomic_set(&vdev_ctx->gtk_err_enable, false); + } + + pmo_info("replay counter %llu", op_gtk_req->replay_counter); + op_gtk_req->flags = gtk_req->flags; + status = pmo_tx_ops.send_gtk_offload_req(vdev, op_gtk_req); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to send gtk offload req event"); +out: + if (op_gtk_req) + qdf_mem_free(op_gtk_req); + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_get_gtk_rsp(struct wlan_objmgr_vdev *vdev) +{ + + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + pmo_err("Failed to find psoc from from vdev:%p", + vdev); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_get_gtk_rsp_cmd) { + pmo_err("send_get_gtk_rsp_cmd is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + status = pmo_tx_ops.send_get_gtk_rsp_cmd(vdev); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to send_get_gtk_rsp_cmd event"); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_gtk_rsp_evt(struct wlan_objmgr_psoc *psoc, + struct pmo_gtk_rsp_params *rsp_param) +{ + QDF_STATUS status; + struct wlan_objmgr_vdev *vdev; + struct pmo_vdev_priv_obj *vdev_ctx; + + PMO_ENTER(); + if (!rsp_param) { + pmo_err("gtk rsp param is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + vdev = pmo_psoc_get_vdev(psoc, rsp_param->vdev_id); + if (!vdev) { + pmo_err("vdev is null vdev_id:%d psoc:%p", + rsp_param->vdev_id, psoc); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(status)) + goto out; + + vdev_ctx = pmo_vdev_get_priv(vdev); + + status = pmo_get_vdev_bss_peer_mac_addr(vdev, &rsp_param->bssid); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("cannot find peer mac address"); + goto dec_ref; + } + + /* update cached replay counter */ + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_ctx->vdev_gtk_req.replay_counter = rsp_param->replay_counter; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + if (vdev_ctx->vdev_gtk_rsp_req.callback) { + pmo_info("callback:%p context:%p psoc:%p vdev_id:%d", + vdev_ctx->vdev_gtk_rsp_req.callback, + vdev_ctx->vdev_gtk_rsp_req.callback_context, + psoc, rsp_param->vdev_id); + vdev_ctx->vdev_gtk_rsp_req.callback( + vdev_ctx->vdev_gtk_rsp_req.callback_context, + rsp_param); + } else { + pmo_err("gtk rsp callback is null for vdev_id:%d psoc %p", + rsp_param->vdev_id, + psoc); + } + +dec_ref: + pmo_vdev_put_ref(vdev); +out: + PMO_EXIT(); + + return status; +} + diff --git a/core/components/pmo/dispatcher/src/wlan_pmo_tgt_hw_filter.c b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_hw_filter.c new file mode 100644 index 000000000000..1d29826aa26e --- /dev/null +++ b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_hw_filter.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: Implements public API for pmo to interact with target/WMI + */ + +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_hw_filter_public_struct.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" +#include "wlan_pmo_main.h" + +QDF_STATUS pmo_tgt_conf_hw_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_hw_filter_params *req) +{ + QDF_STATUS status; + struct wlan_pmo_tx_ops ops; + + PMO_ENTER(); + + pmo_debug("Configure hw filter; vdev_id:%u, mode:%d", + req->vdev_id, req->mode); + + ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!ops.send_conf_hw_filter_req) { + pmo_err("send_conf_hw_filter_req is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto exit_with_status; + } + + status = ops.send_conf_hw_filter_req(psoc, req); + +exit_with_status: + PMO_EXIT(); + + return status; +} + diff --git a/core/components/pmo/dispatcher/src/wlan_pmo_tgt_lphb.c b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_lphb.c new file mode 100644 index 000000000000..5dce758a5afe --- /dev/null +++ b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_lphb.c @@ -0,0 +1,155 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements public API for pmo low power hear beat feature + * to interact with target/WMI. + */ + +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_lphb_public_struct.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" +#include "wlan_pmo_main.h" + +QDF_STATUS pmo_tgt_send_lphb_enable(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_enable_req *ts_lphb_enable) +{ + QDF_STATUS status; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_lphb_enable) { + pmo_err("send_lphb_enable is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + status = pmo_tx_ops.send_lphb_enable(psoc, ts_lphb_enable); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to send lphb enable"); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_send_lphb_tcp_params(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_tcp_params *ts_lphb_tcp_param) +{ + QDF_STATUS status; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_lphb_tcp_params) { + pmo_err("send_lphb_tcp_params is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + status = pmo_tx_ops.send_lphb_tcp_params(psoc, ts_lphb_tcp_param); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to send lphb tcp params"); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_send_lphb_tcp_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_tcp_filter_req *ts_lphb_tcp_filter) +{ + QDF_STATUS status; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_lphb_tcp_filter_req) { + pmo_err("send_lphb_tcp_filter_req is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + status = pmo_tx_ops.send_lphb_tcp_filter_req(psoc, ts_lphb_tcp_filter); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to send lphb tcp filter req"); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_send_lphb_udp_params(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_udp_params *ts_lphb_udp_param) +{ + QDF_STATUS status; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_lphb_upd_params) { + pmo_err("send_lphb_upd_params is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + status = pmo_tx_ops.send_lphb_upd_params(psoc, ts_lphb_udp_param); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to send lphb udp param"); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_send_lphb_udp_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_udp_filter_req *ts_lphb_udp_filter) +{ + QDF_STATUS status; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_lphb_udp_filter_req) { + pmo_err("send_lphb_udp_filter_req is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + status = pmo_tx_ops.send_lphb_udp_filter_req(psoc, ts_lphb_udp_filter); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to send lphb udp filter req"); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_lphb_rsp_evt(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_rsp *rsp_param) +{ + struct pmo_psoc_priv_obj *psoc_ctx; + + psoc_ctx = pmo_psoc_get_priv(psoc); + if (psoc_ctx->wow.lphb_cb && psoc_ctx->wow.lphb_cb_ctx) { + pmo_info("callback:%p context:%p psoc:%p", + psoc_ctx->wow.lphb_cb, psoc_ctx->wow.lphb_cb_ctx, psoc); + psoc_ctx->wow.lphb_cb(psoc_ctx->wow.lphb_cb_ctx, rsp_param); + } else { + pmo_err("lphb rsp callback/context is null for psoc %p", + psoc); + } + + return QDF_STATUS_SUCCESS; +} + diff --git a/core/components/pmo/dispatcher/src/wlan_pmo_tgt_mc_addr_filtering.c b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_mc_addr_filtering.c new file mode 100644 index 000000000000..9cc05636c147 --- /dev/null +++ b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_mc_addr_filtering.c @@ -0,0 +1,83 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements public API for pmo to interact with target/WMI + */ + +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_mc_addr_filtering_public_struct.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" +#include "wlan_pmo_main.h" + +QDF_STATUS pmo_tgt_set_mc_filter_req(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr multicast_addr) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + + psoc = pmo_vdev_get_psoc(vdev); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_set_mc_filter_req) { + pmo_err("send_add_clear_mcbc_filter_request is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_tx_ops.send_set_mc_filter_req( + vdev, multicast_addr); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to add/clear mc filter"); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_clear_mc_filter_req(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr multicast_addr) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + + psoc = pmo_vdev_get_psoc(vdev); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_clear_mc_filter_req) { + pmo_err("send_add_clear_mcbc_filter_request is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_tx_ops.send_clear_mc_filter_req( + vdev, multicast_addr); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to add/clear mc filter"); +out: + PMO_EXIT(); + + return status; +} + + diff --git a/core/components/pmo/dispatcher/src/wlan_pmo_tgt_ns.c b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_ns.c new file mode 100644 index 000000000000..9757cad01228 --- /dev/null +++ b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_ns.c @@ -0,0 +1,159 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements public API for PMO NS offload feature to interact + * with target/wmi. + */ + +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_arp_public_struct.h" +#include "wlan_pmo_ns_public_struct.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" +#include "wlan_pmo_main.h" + +QDF_STATUS pmo_tgt_enable_ns_offload_req(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id) +{ + struct pmo_arp_offload_params *arp_offload_req = NULL; + struct pmo_ns_offload_params *ns_offload_req = NULL; + struct pmo_vdev_priv_obj *vdev_ctx; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + vdev_ctx = pmo_vdev_get_priv(vdev); + + psoc = pmo_vdev_get_psoc(vdev); + + arp_offload_req = qdf_mem_malloc(sizeof(*arp_offload_req)); + if (!arp_offload_req) { + pmo_err("unable to allocate arp_offload_req"); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + ns_offload_req = qdf_mem_malloc(sizeof(*ns_offload_req)); + if (!ns_offload_req) { + pmo_err("unable to allocate ns_offload_req"); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + qdf_mem_copy(arp_offload_req, &vdev_ctx->vdev_arp_req, + sizeof(*arp_offload_req)); + qdf_mem_copy(ns_offload_req, &vdev_ctx->vdev_ns_req, + sizeof(*ns_offload_req)); + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + pmo_debug("ARP Offload vdev_id: %d enable: %d", + vdev_id, + arp_offload_req->enable); + pmo_debug("NS Offload vdev_id: %d enable: %d ns_count: %u", + vdev_id, + ns_offload_req->enable, + ns_offload_req->num_ns_offload_count); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_ns_offload_req) { + pmo_err("send_ns_offload_req is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + status = pmo_tx_ops.send_ns_offload_req( + vdev, arp_offload_req, ns_offload_req); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to send NS offload"); + +out: + if (arp_offload_req) + qdf_mem_free(arp_offload_req); + if (ns_offload_req) + qdf_mem_free(ns_offload_req); + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_disable_ns_offload_req(struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id) +{ + struct pmo_arp_offload_params *arp_offload_req = NULL; + struct pmo_ns_offload_params *ns_offload_req = NULL; + struct pmo_vdev_priv_obj *vdev_ctx; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + + vdev_ctx = pmo_vdev_get_priv(vdev); + + psoc = pmo_vdev_get_psoc(vdev); + + arp_offload_req = qdf_mem_malloc(sizeof(*arp_offload_req)); + if (!arp_offload_req) { + pmo_err("unable to allocate arp_offload_req"); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + ns_offload_req = qdf_mem_malloc(sizeof(*ns_offload_req)); + if (!ns_offload_req) { + pmo_err("unable to allocate ns_offload_req"); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + qdf_mem_copy(arp_offload_req, &vdev_ctx->vdev_arp_req, + sizeof(*arp_offload_req)); + qdf_mem_copy(ns_offload_req, &vdev_ctx->vdev_ns_req, + sizeof(*ns_offload_req)); + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + pmo_debug("ARP Offload vdev_id: %d enable: %d", + vdev_id, + arp_offload_req->enable); + pmo_debug("NS Offload vdev_id: %d enable: %d ns_count: %u", + vdev_id, + ns_offload_req->enable, + ns_offload_req->num_ns_offload_count); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_ns_offload_req) { + pmo_err("send_ns_offload_req is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + status = pmo_tx_ops.send_ns_offload_req( + vdev, arp_offload_req, ns_offload_req); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to send NS offload"); + +out: + if (arp_offload_req) + qdf_mem_free(arp_offload_req); + if (ns_offload_req) + qdf_mem_free(ns_offload_req); + PMO_EXIT(); + + return status; +} + diff --git a/core/components/pmo/dispatcher/src/wlan_pmo_tgt_pkt_filter.c b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_pkt_filter.c new file mode 100644 index 000000000000..6b46ede88d9e --- /dev/null +++ b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_pkt_filter.c @@ -0,0 +1,156 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements public API for pmo to interact with target/WMI + */ + +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_pkt_filter_public_struct.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" +#include "wlan_pmo_main.h" + +QDF_STATUS pmo_tgt_set_pkt_filter(struct wlan_objmgr_vdev *vdev, + struct pmo_rcv_pkt_fltr_cfg *pmo_set_pkt_fltr_req, + uint8_t vdev_id) +{ + QDF_STATUS status; + struct pmo_rcv_pkt_fltr_cfg *request_buf = NULL; + struct wlan_objmgr_psoc *psoc; + struct wlan_pmo_tx_ops pmo_tx_ops; + struct qdf_mac_addr peer_bssid; + + PMO_ENTER(); + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + pmo_err("psoc unavailable for vdev %p", vdev); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + pmo_info("filter_type=%d, filter_id = %d", + pmo_set_pkt_fltr_req->filter_type, + pmo_set_pkt_fltr_req->filter_id); + + request_buf = qdf_mem_malloc(sizeof(*request_buf)); + + if (request_buf == NULL) { + pmo_err("Not able to allocate memory for Receive Filter Set Filter request"); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + status = pmo_get_vdev_bss_peer_mac_addr(vdev, + &peer_bssid); + if (status != QDF_STATUS_SUCCESS) { + status = QDF_STATUS_E_INVAL; + goto out; + } + + qdf_mem_copy(request_buf, pmo_set_pkt_fltr_req, sizeof(*request_buf)); + + qdf_mem_copy(&request_buf->self_macaddr.bytes, + wlan_vdev_mlme_get_macaddr(vdev), + QDF_MAC_ADDR_SIZE); + + qdf_copy_macaddr(&pmo_set_pkt_fltr_req->bssid, + &peer_bssid); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_set_pkt_filter) { + pmo_err("send_set_pkt_filter is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_tx_ops.send_set_pkt_filter(vdev, request_buf); + if (status != QDF_STATUS_SUCCESS) + goto out; + +out: + if (request_buf) + qdf_mem_free(request_buf); + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_clear_pkt_filter(struct wlan_objmgr_vdev *vdev, + struct pmo_rcv_pkt_fltr_clear_param *pmo_clr_pkt_fltr_param, + uint8_t vdev_id) +{ + QDF_STATUS status; + struct pmo_rcv_pkt_fltr_clear_param *request_buf = NULL; + struct wlan_objmgr_psoc *psoc; + struct wlan_pmo_tx_ops pmo_tx_ops; + struct qdf_mac_addr peer_bssid; + + PMO_ENTER(); + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + pmo_err("psoc unavailable for vdev %p", vdev); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + pmo_info("filter_id = %d", pmo_clr_pkt_fltr_param->filter_id); + + request_buf = qdf_mem_malloc(sizeof(*request_buf)); + + if (request_buf == NULL) { + pmo_err("Not able to allocate memory for Receive Filter Set Filter request"); + status = QDF_STATUS_E_NOMEM; + goto out; + } + + status = pmo_get_vdev_bss_peer_mac_addr(vdev, + &peer_bssid); + if (status != QDF_STATUS_SUCCESS) { + status = QDF_STATUS_E_INVAL; + goto out; + } + + qdf_mem_copy(request_buf, pmo_clr_pkt_fltr_param, sizeof(*request_buf)); + + qdf_mem_copy(&request_buf->self_macaddr.bytes, + wlan_vdev_mlme_get_macaddr(vdev), + QDF_MAC_ADDR_SIZE); + + qdf_copy_macaddr(&pmo_clr_pkt_fltr_param->bssid, + &peer_bssid); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_clear_pkt_filter) { + pmo_err("send_clear_pkt_filter is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_tx_ops.send_clear_pkt_filter(vdev, request_buf); + if (status != QDF_STATUS_SUCCESS) + goto out; + +out: + if (request_buf) + qdf_mem_free(request_buf); + PMO_EXIT(); + + return status; +} + diff --git a/core/components/pmo/dispatcher/src/wlan_pmo_tgt_static_config.c b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_static_config.c new file mode 100644 index 000000000000..bd322f9eedcc --- /dev/null +++ b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_static_config.c @@ -0,0 +1,127 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements public API for pmo to interact with target/WMI + */ + +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_wow.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" +#include "wlan_pmo_main.h" + +QDF_STATUS pmo_tgt_send_enhance_multicast_offload_req( + struct wlan_objmgr_vdev *vdev, + uint8_t vdev_id, + uint8_t action) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + psoc = pmo_vdev_get_psoc(vdev); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_enhance_mc_offload_req) { + pmo_err("send_enhance_multicast_offload is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_tx_ops.send_enhance_mc_offload_req(vdev, action); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to config enhance multicast offload"); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_send_ra_filter_req(struct wlan_objmgr_vdev *vdev) +{ + + QDF_STATUS status; + uint8_t default_pattern; + uint16_t ra_interval; + struct pmo_vdev_priv_obj *vdev_ctx; + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + + psoc = pmo_vdev_get_psoc(vdev); + + vdev_ctx = pmo_vdev_get_priv(vdev); + + vdev_id = pmo_vdev_get_id(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + ra_interval = vdev_ctx->pmo_psoc_ctx->psoc_cfg.ra_ratelimit_interval; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + pmo_debug("send RA rate limit [%d] to fw vdev = %d", + ra_interval, vdev_id); + + default_pattern = pmo_get_and_increment_wow_default_ptrn(vdev_ctx); + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_ra_filter_req) { + pmo_err("send_ra_filter_cmd is null"); + status = QDF_STATUS_E_INVAL; + goto out; + } + + status = pmo_tx_ops.send_ra_filter_req( + vdev, default_pattern, ra_interval); + if (status != QDF_STATUS_SUCCESS) { + pmo_err("Failed to send RA rate limit to fw"); + pmo_decrement_wow_default_ptrn(vdev_ctx); + } +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_send_action_frame_pattern_req( + struct wlan_objmgr_vdev *vdev, + struct pmo_action_wakeup_set_params *cmd) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + + psoc = pmo_vdev_get_psoc(vdev); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_action_frame_pattern_req) { + pmo_err("send_add_action_frame_pattern_cmd is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_tx_ops.send_action_frame_pattern_req(vdev, cmd); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to add filter"); +out: + PMO_EXIT(); + + return status; +} + diff --git a/core/components/pmo/dispatcher/src/wlan_pmo_tgt_suspend_resume.c b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_suspend_resume.c new file mode 100644 index 000000000000..13e89c570d5d --- /dev/null +++ b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_suspend_resume.c @@ -0,0 +1,215 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements public API for pmo to interact with target/WMI + */ + +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_wow.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" +#include "wlan_pmo_main.h" + +QDF_STATUS pmo_tgt_vdev_update_param_req(struct wlan_objmgr_vdev *vdev, + enum pmo_vdev_param_id param_id, uint32_t param_value) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + + psoc = pmo_vdev_get_psoc(vdev); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_vdev_param_update_req) { + pmo_err("send_vdev_param_update_req is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_tx_ops.send_vdev_param_update_req(vdev, param_id, + param_value); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_send_vdev_sta_ps_param(struct wlan_objmgr_vdev *vdev, + enum pmo_sta_powersave_param ps_param, uint32_t param_value) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + + psoc = pmo_vdev_get_psoc(vdev); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_vdev_sta_ps_param_req) { + pmo_err("send_vdev_param_set_req is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + status = pmo_tx_ops.send_vdev_sta_ps_param_req(vdev, ps_param, + param_value); +out: + PMO_EXIT(); + + return status; +} + +void pmo_tgt_psoc_update_wow_bus_suspend_state(struct wlan_objmgr_psoc *psoc, + uint8_t val) +{ + struct wlan_pmo_tx_ops pmo_tx_ops; + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.psoc_update_wow_bus_suspend) { + pmo_err("psoc_update_wow_bus_suspend is null"); + return; + } + pmo_tx_ops.psoc_update_wow_bus_suspend(psoc, val); +} + +int pmo_tgt_psoc_get_host_credits(struct wlan_objmgr_psoc *psoc) +{ + + struct wlan_pmo_tx_ops pmo_tx_ops; + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.psoc_get_host_credits) { + pmo_err("psoc_get_host_credits is null"); + return 0; + } + + return pmo_tx_ops.psoc_get_host_credits(psoc); +} + +int pmo_tgt_psoc_get_pending_cmnds(struct wlan_objmgr_psoc *psoc) +{ + + struct wlan_pmo_tx_ops pmo_tx_ops; + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.psoc_get_pending_cmnds) { + pmo_err("psoc_get_pending_cmnds is null"); + return -EAGAIN; + } + + return pmo_tx_ops.psoc_get_pending_cmnds(psoc); +} + +void pmo_tgt_update_target_suspend_flag(struct wlan_objmgr_psoc *psoc, + uint8_t val) +{ + struct wlan_pmo_tx_ops pmo_tx_ops; + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.update_target_suspend_flag) { + pmo_err("update_target_suspend_flag is null"); + return; + } + pmo_tx_ops.update_target_suspend_flag(psoc, val); +} + +QDF_STATUS pmo_tgt_psoc_send_wow_enable_req(struct wlan_objmgr_psoc *psoc, + struct pmo_wow_cmd_params *param) +{ + struct wlan_pmo_tx_ops pmo_tx_ops; + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(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; + } + + return pmo_tx_ops.psoc_send_wow_enable_req(psoc, param); +} + +QDF_STATUS pmo_tgt_psoc_send_supend_req(struct wlan_objmgr_psoc *psoc, + struct pmo_suspend_params *param) +{ + struct wlan_pmo_tx_ops pmo_tx_ops; + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.psoc_send_supend_req) { + pmo_err("psoc_send_supend_req is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + return pmo_tx_ops.psoc_send_supend_req(psoc, param); +} + +QDF_STATUS pmo_tgt_psoc_set_runtime_pm_inprogress(struct wlan_objmgr_psoc *psoc, + bool value) +{ + struct wlan_pmo_tx_ops pmo_tx_ops; + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.psoc_set_runtime_pm_in_progress) { + pmo_err("pmo ops is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + pmo_tx_ops.psoc_set_runtime_pm_in_progress(psoc, value); + + return QDF_STATUS_SUCCESS; +} + +bool pmo_tgt_psoc_get_runtime_pm_in_progress(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_pmo_tx_ops pmo_tx_ops; + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.psoc_get_runtime_pm_in_progress) { + pmo_err("psoc_get_runtime_pm_in_progress is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + return pmo_tx_ops.psoc_get_runtime_pm_in_progress(psoc); +} + +QDF_STATUS pmo_tgt_psoc_send_host_wakeup_ind(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_pmo_tx_ops pmo_tx_ops; + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(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); +} + +QDF_STATUS pmo_tgt_psoc_send_target_resume_req(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_pmo_tx_ops pmo_tx_ops; + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.psoc_send_target_resume_req) { + pmo_err("send_target_resume_req is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + return pmo_tx_ops.psoc_send_target_resume_req(psoc); +} + diff --git a/core/components/pmo/dispatcher/src/wlan_pmo_tgt_wow.c b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_wow.c new file mode 100644 index 000000000000..c3e982603622 --- /dev/null +++ b/core/components/pmo/dispatcher/src/wlan_pmo_tgt_wow.c @@ -0,0 +1,121 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: Implements public API for pmo to interact with target/WMI + */ + +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_wow.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" +#include "wlan_pmo_main.h" + +QDF_STATUS pmo_tgt_enable_wow_wakeup_event( + struct wlan_objmgr_vdev *vdev, + uint32_t *bitmap) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + + psoc = pmo_vdev_get_psoc(vdev); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_enable_wow_wakeup_event_req) { + pmo_err("send_enable_wow_wakeup_event_req is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + status = pmo_tx_ops.send_enable_wow_wakeup_event_req(vdev, bitmap); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to enable wow wakeup event"); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_disable_wow_wakeup_event( + struct wlan_objmgr_vdev *vdev, + uint32_t *bitmap) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + + psoc = pmo_vdev_get_psoc(vdev); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_disable_wow_wakeup_event_req) { + pmo_err("send_disable_wow_wakeup_event_req is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + status = pmo_tx_ops.send_disable_wow_wakeup_event_req(vdev, bitmap); + if (status != QDF_STATUS_SUCCESS) + pmo_err("Failed to disable wow wakeup event"); +out: + PMO_EXIT(); + + return status; +} + +QDF_STATUS pmo_tgt_send_wow_patterns_to_fw( + struct wlan_objmgr_vdev *vdev, uint8_t ptrn_id, + const uint8_t *ptrn, uint8_t ptrn_len, + uint8_t ptrn_offset, const uint8_t *mask, + uint8_t mask_len, bool user) +{ + QDF_STATUS status; + struct pmo_vdev_priv_obj *vdev_ctx; + struct wlan_objmgr_psoc *psoc; + struct wlan_pmo_tx_ops pmo_tx_ops; + + PMO_ENTER(); + psoc = pmo_vdev_get_psoc(vdev); + + vdev_ctx = pmo_vdev_get_priv(vdev); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_add_wow_pattern) { + pmo_err("send_add_wow_pattern is null"); + status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + status = pmo_tx_ops.send_add_wow_pattern( + vdev, ptrn_id, ptrn, + ptrn_len, ptrn_offset, mask, + mask_len, user); + if (status != QDF_STATUS_SUCCESS) { + if (!user) + pmo_decrement_wow_default_ptrn(vdev_ctx); + pmo_err("Failed to sen wow pattern event"); + goto out; + } + + if (user) + pmo_increment_wow_user_ptrn(vdev_ctx); +out: + PMO_EXIT(); + + return status; +} + diff --git a/core/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c b/core/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c new file mode 100644 index 000000000000..c1a19cb055d4 --- /dev/null +++ b/core/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c @@ -0,0 +1,342 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** + * DOC: public API related to the pmo called by north bound HDD/OSIF + */ + +#include "wlan_pmo_ucfg_api.h" +#include "wlan_pmo_arp.h" +#include "wlan_pmo_ns.h" +#include "wlan_pmo_gtk.h" +#include "wlan_pmo_wow.h" +#include "wlan_pmo_mc_addr_filtering.h" +#include "wlan_pmo_main.h" +#include "wlan_pmo_lphb.h" +#include "wlan_pmo_suspend_resume.h" +#include "wlan_pmo_pkt_filter.h" +#include "wlan_pmo_hw_filter.h" + +QDF_STATUS pmo_ucfg_get_psoc_config(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_cfg *psoc_cfg) +{ + return pmo_core_get_psoc_config(psoc, psoc_cfg); +} + +QDF_STATUS pmo_ucfg_update_psoc_config(struct wlan_objmgr_psoc *psoc, + struct pmo_psoc_cfg *psoc_cfg) +{ + return pmo_core_update_psoc_config(psoc, psoc_cfg); +} + +bool pmo_ucfg_is_ap_mode_supports_arp_ns(struct wlan_objmgr_psoc *psoc, + enum tQDF_ADAPTER_MODE vdev_opmode) +{ + return pmo_core_is_ap_mode_supports_arp_ns(psoc, vdev_opmode); +} + +bool pmo_ucfg_is_vdev_connected(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_is_vdev_connected(vdev); +} + +bool pmo_ucfg_is_vdev_supports_offload(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_is_vdev_supports_offload(vdev); +} + +void pmo_ucfg_enable_wakeup_event(struct wlan_objmgr_psoc *psoc, + uint32_t vdev_id, uint32_t *bitmap) +{ + pmo_core_enable_wakeup_event(psoc, vdev_id, bitmap); +} + +void pmo_ucfg_disable_wakeup_event(struct wlan_objmgr_psoc *psoc, + uint32_t vdev_id, uint32_t bitmap) +{ + pmo_core_disable_wakeup_event(psoc, vdev_id, &bitmap); +} + +QDF_STATUS pmo_ucfg_cache_arp_offload_req(struct pmo_arp_req *arp_req) +{ + return pmo_core_cache_arp_offload_req(arp_req); +} + +QDF_STATUS pmo_ucfg_flush_arp_offload_req(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_flush_arp_offload_req(vdev); +} + +QDF_STATUS pmo_ucfg_enable_arp_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger) +{ + return pmo_core_enable_arp_offload_in_fwr(vdev, trigger); +} + +QDF_STATUS pmo_ucfg_disable_arp_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger) +{ + return pmo_core_disable_arp_offload_in_fwr(vdev, trigger); +} + +QDF_STATUS pmo_ucfg_cache_ns_offload_req(struct pmo_ns_req *ns_req) +{ + return pmo_core_cache_ns_offload_req(ns_req); +} + +QDF_STATUS pmo_ucfg_flush_ns_offload_req(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_flush_ns_offload_req(vdev); +} + +QDF_STATUS pmo_ucfg_enable_ns_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger) +{ + return pmo_core_enable_ns_offload_in_fwr(vdev, trigger); +} + +QDF_STATUS pmo_ucfg_disable_ns_offload_in_fwr(struct wlan_objmgr_vdev *vdev, + enum pmo_offload_trigger trigger) +{ + return pmo_core_disable_ns_offload_in_fwr(vdev, trigger); +} + +QDF_STATUS pmo_ucfg_cache_mc_addr_list( + struct pmo_mc_addr_list_params *mc_list_config) +{ + return pmo_core_cache_mc_addr_list(mc_list_config); +} + +QDF_STATUS pmo_ucfg_flush_mc_addr_list(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) +{ + return pmo_core_flush_mc_addr_list(psoc, vdev_id); +} + +QDF_STATUS pmo_ucfg_enable_mc_addr_filtering_in_fwr( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum pmo_offload_trigger trigger) +{ + return pmo_core_enable_mc_addr_filtering_in_fwr(psoc, + vdev_id, trigger); +} + +QDF_STATUS pmo_ucfg_disable_mc_addr_filtering_in_fwr( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum pmo_offload_trigger trigger) +{ + return pmo_core_disable_mc_addr_filtering_in_fwr(psoc, + vdev_id, trigger); +} + +uint8_t pmo_ucfg_max_mc_addr_supported(struct wlan_objmgr_psoc *psoc) +{ + return pmo_core_max_mc_addr_supported(psoc); +} + +QDF_STATUS pmo_ucfg_cache_gtk_offload_req(struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_req *gtk_req) +{ + return pmo_core_cache_gtk_offload_req(vdev, gtk_req); +} + +QDF_STATUS pmo_ucfg_flush_gtk_offload_req(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_flush_gtk_offload_req(vdev); +} + +QDF_STATUS pmo_ucfg_enable_gtk_offload_in_fwr(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_enable_gtk_offload_in_fwr(vdev); +} + +QDF_STATUS pmo_ucfg_disable_gtk_offload_in_fwr(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_disable_gtk_offload_in_fwr(vdev); +} + +QDF_STATUS pmo_ucfg_set_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_rcv_pkt_fltr_cfg *pmo_set_pkt_fltr_req, + uint8_t vdev_id) +{ + return pmo_core_set_pkt_filter(psoc, pmo_set_pkt_fltr_req, vdev_id); +} + +QDF_STATUS pmo_ucfg_clear_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_rcv_pkt_fltr_clear_param *pmo_clr_pkt_fltr_param, + uint8_t vdev_id) +{ + return pmo_core_clear_pkt_filter(psoc, + pmo_clr_pkt_fltr_param, vdev_id); +} + +QDF_STATUS pmo_ucfg_get_gtk_rsp(struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_rsp_req *gtk_rsp_req) +{ + return pmo_core_get_gtk_rsp(vdev, gtk_rsp_req); +} + +void pmo_ucfg_update_extscan_in_progress(struct wlan_objmgr_vdev *vdev, + bool value) +{ + pmo_core_update_extscan_in_progress(vdev, value); +} + +void pmo_ucfg_update_p2plo_in_progress(struct wlan_objmgr_vdev *vdev, + bool value) +{ + pmo_core_update_p2plo_in_progress(vdev, value); +} + +QDF_STATUS pmo_ucfg_lphb_config_req(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_req *lphb_req, void *lphb_cb_ctx, + pmo_lphb_callback callback) +{ + return pmo_core_lphb_config_req(psoc, lphb_req, lphb_cb_ctx, callback); +} + +void pmo_ucfg_update_alt_modulated_dtim_enable(struct wlan_objmgr_vdev *vdev, + bool value) +{ + pmo_core_update_alt_modulated_dtim_enable(vdev, value); +} + +void pmo_ucfg_psoc_update_power_save_mode(struct wlan_objmgr_psoc *psoc, + uint8_t value) +{ + pmo_core_psoc_update_power_save_mode(psoc, value); +} + +void pmo_ucfg_psoc_update_dp_handle(struct wlan_objmgr_psoc *psoc, + void *dp_handle) +{ + pmo_core_psoc_update_dp_handle(psoc, dp_handle); +} + +void pmo_ucfg_vdev_update_dp_handle(struct wlan_objmgr_vdev *vdev, + void *dp_handle) +{ + pmo_core_vdev_update_dp_handle(vdev, dp_handle); +} + +void pmo_ucfg_psoc_update_htc_handle(struct wlan_objmgr_psoc *psoc, + void *htc_handle) +{ + pmo_core_psoc_update_htc_handle(psoc, htc_handle); +} + +void pmo_ucfg_psoc_set_hif_handle(struct wlan_objmgr_psoc *psoc, + void *hif_handle) +{ + pmo_core_psoc_set_hif_handle(psoc, hif_handle); +} + +void pmo_ucfg_psoc_set_txrx_handle(struct wlan_objmgr_psoc *psoc, + void *txrx_handle) +{ + pmo_core_psoc_set_txrx_handle(psoc, txrx_handle); +} + +void pmo_ucfg_psoc_handle_initial_wake_up(void *cb_ctx) +{ + return pmo_core_psoc_handle_initial_wake_up(cb_ctx); +} + +QDF_STATUS pmo_ucfg_psoc_user_space_suspend_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type) +{ + return pmo_core_psoc_user_space_suspend_req(psoc, type); +} + + +QDF_STATUS pmo_ucfg_psoc_user_space_resume_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type) +{ + return pmo_core_psoc_user_space_resume_req(psoc, type); +} + +QDF_STATUS pmo_ucfg_psoc_bus_suspend_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type, + struct pmo_wow_enable_params *wow_params) +{ + return pmo_core_psoc_bus_suspend_req(psoc, type, wow_params); +} + +#ifdef FEATURE_RUNTIME_PM +QDF_STATUS pmo_ucfg_psoc_bus_runtime_suspend(struct wlan_objmgr_psoc *psoc, + pmo_pld_auto_suspend_cb pld_cb) +{ + return pmo_core_psoc_bus_runtime_suspend(psoc, pld_cb); +} + +QDF_STATUS pmo_ucfg_psoc_bus_runtime_resume(struct wlan_objmgr_psoc *psoc, + pmo_pld_auto_suspend_cb pld_cb) +{ + return pmo_core_psoc_bus_runtime_resume(psoc, pld_cb); +} +#endif + +QDF_STATUS pmo_ucfg_psoc_suspend_target(struct wlan_objmgr_psoc *psoc, + int disable_target_intr) +{ + return pmo_core_psoc_suspend_target(psoc, disable_target_intr); +} + +QDF_STATUS pmo_ucfg_psoc_bus_resume_req(struct wlan_objmgr_psoc *psoc, + enum qdf_suspend_type type) +{ + return pmo_core_psoc_bus_resume_req(psoc, type); +} + +bool pmo_ucfg_get_wow_bus_suspend(struct wlan_objmgr_psoc *psoc) +{ + return pmo_core_get_wow_bus_suspend(psoc); +} + +int pmo_ucfg_psoc_is_target_wake_up_received(struct wlan_objmgr_psoc *psoc) +{ + return pmo_core_psoc_is_target_wake_up_received(psoc); +} + +int pmo_ucfg_psoc_clear_target_wake_up(struct wlan_objmgr_psoc *psoc) +{ + return pmo_core_psoc_clear_target_wake_up(psoc); +} + +void pmo_ucfg_psoc_target_suspend_acknowledge(void *context, bool wow_nack) +{ + pmo_core_psoc_target_suspend_acknowledge(context, wow_nack); +} + +void pmo_ucfg_psoc_wakeup_host_event_received(struct wlan_objmgr_psoc *psoc) +{ + pmo_core_psoc_wakeup_host_event_received(psoc); +} + +QDF_STATUS pmo_ucfg_enable_hw_filter_in_fwr(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_enable_hw_filter_in_fwr(vdev); +} + +QDF_STATUS pmo_ucfg_disable_hw_filter_in_fwr(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_disable_hw_filter_in_fwr(vdev); +} + + diff --git a/core/components/target_if/pmo/inc/target_if_pmo.h b/core/components/target_if/pmo/inc/target_if_pmo.h new file mode 100644 index 000000000000..cb3bea6f5a14 --- /dev/null +++ b/core/components/target_if/pmo/inc/target_if_pmo.h @@ -0,0 +1,407 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted, provided that the +* above copyright notice and this permission notice appear in all +* copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +*/ +/** +* DOC: Declare various api/struct which shall be used +* by pmo component for wmi cmd (tx path) and +* event (rx) handling. +*/ + +#ifndef _TARGET_IF_PMO_H_ +#define _TARGET_IF_PMO_H_ + +#include "target_if.h" +#include "wlan_pmo_tgt_api.h" +#include "wlan_pmo_obj_mgmt_public_struct.h" + +/** + * target_if_pmo_enable_wow_wakeup_event() - Enable wow wakeup events. + * @vdev:objmgr vdev handle + * @bitmap: Event bitmap + * @enable: enable/disable + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_enable_wow_wakeup_event(struct wlan_objmgr_vdev *vdev, + uint32_t *bitmap); + +/** + * target_if_pmo_disable_wow_wakeup_event() - Disable wow wakeup events. + * @vdev:objmgr vdev handle + * @bitmap: Event bitmap + * @enable: enable/disable + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_disable_wow_wakeup_event( + struct wlan_objmgr_vdev *vdev, uint32_t *bitmap); + +/** + * target_if_pmo_send_wow_patterns_to_fw() - Sends WOW patterns to FW. + * @vdev: objmgr vdev handle + * @ptrn_id: pattern id + * @ptrn: pattern + * @ptrn_len: pattern length + * @ptrn_offset: pattern offset + * @mask: mask + * @mask_len: mask length + * @user: true for user configured pattern and false for default pattern + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_send_wow_patterns_to_fw(struct wlan_objmgr_vdev *vdev, + uint8_t ptrn_id, + const uint8_t *ptrn, uint8_t ptrn_len, + uint8_t ptrn_offset, const uint8_t *mask, + uint8_t mask_len, bool user); + +/** + * target_if_pmo_send_enhance_mc_offload_req() - send enhance mc offload req + * @vdev: objmgr vdev + * @action: enable or disable enhance multicast offload + * + * Return: QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS target_if_pmo_send_enhance_mc_offload_req( + struct wlan_objmgr_vdev *vdev, + bool enable); + +/** + * target_if_pmo_set_mc_filter_req() - set mcast filter command to fw + * @vdev: objmgr vdev handle + * @multicastAddr: mcast address + * + * Return: 0 for success or error code + */ +QDF_STATUS target_if_pmo_set_mc_filter_req(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr multicast_addr); + +/** + * target_if_pmo_clear_mc_filter_req() - clear mcast filter command to fw + * @vdev: objmgr vdev handle + * @multicastAddr: mcast address + * + * Return: 0 for success or error code + */ +QDF_STATUS target_if_pmo_clear_mc_filter_req(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr multicast_addr); + +/** + * target_if_pmo_send_ra_filter_req() - set RA filter pattern in fw + * @vdev: objmgr vdev handle + * @default_pattern: default pattern id + * @rate_limit_interval: ra rate limit interval + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_send_ra_filter_req(struct wlan_objmgr_vdev *vdev, + uint8_t default_pattern, uint16_t rate_limit_interval); + +/** + * target_if_pmo_send_action_frame_patterns() - register action frame map to fw + * @handle: Pointer to wma handle + * @vdev_id: VDEV ID + * + * This is called to push action frames wow patterns from local + * cache to firmware. + * + * Return: QDF_STATUS + */ +QDF_STATUS target_if_pmo_send_action_frame_patterns( + struct wlan_objmgr_vdev *vdev, + struct pmo_action_wakeup_set_params *ip_cmd); + +/** + * target_if_pmo_conf_hw_filter() - configure hardware filter in DTIM mode + * @psoc: the psoc containing the vdev to configure + * @req: the request parameters + * + * Return: QDF_STATUS + */ +QDF_STATUS target_if_pmo_conf_hw_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_hw_filter_params *req); + +/** + * target_if_pmo_send_pkt_filter_req() - enable packet filter + * @vdev: objmgr vdev + * @rcv_filter_param: filter params + * + * This function enable packet filter + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS target_if_pmo_send_pkt_filter_req(struct wlan_objmgr_vdev *vdev, + struct pmo_rcv_pkt_fltr_cfg *rcv_filter_param); + +/** + * target_if_pmo_clear_pkt_filter_req() - disable packet filter + * @vdev: objmgr vdev + * @rcv_clear_param: filter params + * + * This function disable packet filter + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS target_if_pmo_clear_pkt_filter_req(struct wlan_objmgr_vdev *vdev, + struct pmo_rcv_pkt_fltr_clear_param *rcv_clear_param); + +/** + * target_if_pmo_send_arp_offload_req() - sends arp request to fwr + * @vdev: objmgr vdev + * @arp_offload_req: arp offload req + * @ns_offload_req: ns offload request + * + * This functions sends arp request to fwr. + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS target_if_pmo_send_arp_offload_req( + struct wlan_objmgr_vdev *vdev, + struct pmo_arp_offload_params *arp_offload_req, + struct pmo_ns_offload_params *ns_offload_req); + +/** + * target_if_pmo_send_ns_offload_req() - sends ns request to fwr + * @vdev: objmgr vdev + * @arp_offload_req: arp offload req + * @ns_offload_req: ns offload request + * + * This functions sends ns request to fwr. + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS target_if_pmo_send_ns_offload_req( + struct wlan_objmgr_vdev *vdev, + struct pmo_arp_offload_params *arp_offload_req, + struct pmo_ns_offload_params *ns_offload_req); + +/** + * target_if_pmo_send_gtk_offload_req() - send gtk offload request in fwr + * @vdev: objmgr vdev handle + * @gtk_offload_req: gtk offload request + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_send_gtk_offload_req(struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_req *gtk_offload_req); + +/** + * target_if_pmo_send_gtk_response_req() - send gtk response request in fwr + * @vdev: objmgr vdev handle + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_send_gtk_response_req(struct wlan_objmgr_vdev *vdev); + +/** + * target_if_pmo_gtk_offload_status_event() - GTK offload status event handler + * @scn_handle: scn handle + * @event: event buffer + * @len: buffer length + * + * Return: 0 for success or error code + */ +int target_if_pmo_gtk_offload_status_event(void *scn_handle, + uint8_t *event, uint32_t len); + +/** + * target_if_pmo_send_lphb_enable() - enable command of LPHB config req + * @psoc: objmgr psoc handle + * @ts_lphb_enable: lphb enable request which needs to configure in fwr + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_send_lphb_enable(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_enable_req *ts_lphb_enable); + +/** + * target_if_pmo_send_lphb_tcp_params() - set lphb tcp params config request + * @psoc: objmgr psoc handle + * @ts_lphb_tcp_param: lphb tcp params which needs to configure in fwr + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_send_lphb_tcp_params(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_tcp_params *ts_lphb_tcp_param); + +/** + * target_if_pmo_send_lphb_tcp_pkt_filter() - send lphb tcp packet filter req + * @psoc: objmgr psoc handle + * @ts_lphb_tcp_filter: lphb tcp filter request which needs to configure in fwr + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_send_lphb_tcp_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_tcp_filter_req *ts_lphb_tcp_filter); + +/** + * target_if_pmo_send_lphb_udp_params() - Send udp param command of LPHB + * @psoc: objmgr psoc handle + * @ts_lphb_udp_param: lphb udp params which needs to configure in fwr + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_send_lphb_udp_params(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_udp_params *ts_lphb_udp_param); + +/** + * target_if_pmo_send_lphb_udp_pkt_filter() - Send lphb udp pkt filter cmd req + * @psoc: objmgr psoc handle + * @ts_lphb_udp_filter: lphb udp filter request which needs to configure in fwr + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_send_lphb_udp_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_udp_filter_req *ts_lphb_udp_filter); + +/** + * target_if_pmo_lphb_evt_handler() - send LPHB indication to os if /HDD + * @psoc: objmgr psoc handle + * @event: lphb event buffer + * + * Return: QDF_STATUS_SUCCESS for success else error code + */ +QDF_STATUS target_if_pmo_lphb_evt_handler(struct wlan_objmgr_psoc *psoc, + uint8_t *event); + +/** + * target_if_pmo_send_vdev_update_param_req() - Send vdev param value to fwr + * @vdev: objmgr vdev + * @param_id: tell vdev param id which needs to be updated in fwr + * @param_value: vdev parameter value + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_send_vdev_update_param_req( + struct wlan_objmgr_vdev *vdev, + uint32_t param_id, uint32_t param_value); + +/** + * target_if_pmo_send_vdev_ps_param_req() - Send vdev ps param value to fwr + * @vdev: objmgr vdev + * @param_id: tell vdev param id which needs to be updated in fwr + * @param_value: vdev parameter value + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_send_vdev_ps_param_req( + struct wlan_objmgr_vdev *vdev, + uint32_t param_id, + uint32_t param_value); + +/** + * target_if_pmo_psoc_update_bus_suspend() - update wmi bus suspend flag + * @psoc: objmgr psoc + * @value: bus suspend value + * + * Return: None + */ +void target_if_pmo_psoc_update_bus_suspend(struct wlan_objmgr_psoc *psoc, + uint8_t value); + +/** + * target_if_pmo_psoc_get_host_credits() - get available host credits + * @psoc: objmgr psoc + * + * Return: return host credits + */ +int target_if_pmo_psoc_get_host_credits(struct wlan_objmgr_psoc *psoc); + +/** + * target_if_pmo_psoc_get_pending_cmnds() - get wmi pending commands + * @psoc: objmgr psoc + * + * Return: return wmi pending commands + */ +int target_if_pmo_psoc_get_pending_cmnds(struct wlan_objmgr_psoc *psoc); + +/** + * target_if_pmo_update_target_suspend_flag() - set wmi target suspend flag + * @psoc: objmgr psoc + * @value: value + * + * Return: return wmi pending commands + */ +void target_if_pmo_update_target_suspend_flag(struct wlan_objmgr_psoc *psoc, + uint8_t value); + +/** + * target_if_pmo_psoc_send_wow_enable_req() -send wow enable request + * @psoc: objmgr psoc + * @param: wow command params + * + * Return: return QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS target_if_pmo_psoc_send_wow_enable_req(struct wlan_objmgr_psoc *psoc, + struct pmo_wow_cmd_params *param); + +/** + * target_if_pmo_psoc_send_suspend_req() - fp to send suspend request + * @psoc: objmgr psoc + * @param: target suspend params + * + * Return: return QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS target_if_pmo_psoc_send_suspend_req(struct wlan_objmgr_psoc *psoc, + struct pmo_suspend_params *param); + +/** + * target_if_pmo_set_runtime_pm_in_progress() - set runtime pm status + * @psoc: objmgr psoc + * @value: set runtime pm status + * + * Return: none + */ +void target_if_pmo_set_runtime_pm_in_progress(struct wlan_objmgr_psoc *psoc, + bool value); + +/** + * target_if_pmo_get_runtime_pm_in_progress() - fp to get runtime pm status + * @psoc: objmgr psoc + * + * Return: true if runtime pm in progress else false + */ +bool target_if_pmo_get_runtime_pm_in_progress(struct wlan_objmgr_psoc *psoc); + +/** + * target_if_pmo_psoc_send_host_wakeup_ind() - send host wake ind to fwr + * @psoc: objmgr psoc + * + * Return: return QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS target_if_pmo_psoc_send_host_wakeup_ind( + struct wlan_objmgr_psoc *psoc); + +/** + * target_if_pmo_psoc_send_target_resume_req() -send target resume request + * @psoc: objmgr psoc + * + * Return: return QDF_STATUS_SUCCESS on success else error code + */ +QDF_STATUS target_if_pmo_psoc_send_target_resume_req( + struct wlan_objmgr_psoc *psoc); + +/** + * target_if_pmo_register_tx_ops() - Register PMO component TX OPS + * @tx_ops: PMO if transmit ops + * + * Return: None + */ +void target_if_pmo_register_tx_ops(struct wlan_pmo_tx_ops *tx_ops); + +#endif + diff --git a/core/components/target_if/pmo/src/target_if_pmo_arp.c b/core/components/target_if/pmo/src/target_if_pmo_arp.c new file mode 100644 index 000000000000..b28b08a55f01 --- /dev/null +++ b/core/components/target_if/pmo/src/target_if_pmo_arp.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/** + * DOC: target_if_pmo_arp.c + * + * Target interface file for pmo component to + * send arp offload related cmd and process event. + */ + +#include "target_if.h" +#include "target_if_pmo.h" +#include "wmi_unified_api.h" + +QDF_STATUS target_if_pmo_send_arp_offload_req( + struct wlan_objmgr_vdev *vdev, + struct pmo_arp_offload_params *arp_offload_req, + struct pmo_ns_offload_params *ns_offload_req) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_enable_arp_ns_offload_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + arp_offload_req, + ns_offload_req, + vdev_id); + if (status != QDF_STATUS_SUCCESS) + target_if_err("Failed to enable ARP NDP/NSffload"); + + return status; +} + + diff --git a/core/components/target_if/pmo/src/target_if_pmo_gtk.c b/core/components/target_if/pmo/src/target_if_pmo_gtk.c new file mode 100644 index 000000000000..5f67b9fa03a5 --- /dev/null +++ b/core/components/target_if/pmo/src/target_if_pmo_gtk.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/** + * DOC: target_if_pmo_gtk.c + * + * Target interface file for pmo component to + * send gtk offload related cmd and process event. + */ + +#include "target_if.h" +#include "target_if_pmo.h" +#include "wmi_unified_api.h" + +QDF_STATUS target_if_pmo_send_gtk_offload_req(struct wlan_objmgr_vdev *vdev, + struct pmo_gtk_req *gtk_req) +{ + uint8_t vdev_id; + QDF_STATUS status; + uint32_t gtk_offload_opcode; + struct wlan_objmgr_psoc *psoc; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + if (gtk_req->flags == PMO_GTK_OFFLOAD_ENABLE) + gtk_offload_opcode = GTK_OFFLOAD_ENABLE_OPCODE; + else + gtk_offload_opcode = GTK_OFFLOAD_DISABLE_OPCODE; + + status = wmi_unified_send_gtk_offload_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + vdev_id, + gtk_req, + gtk_req->flags, + gtk_offload_opcode); + if (status) + target_if_err("Failed to send gtk offload cmd to fw"); + + return status; +} + +QDF_STATUS target_if_pmo_send_gtk_response_req(struct wlan_objmgr_vdev *vdev) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status = QDF_STATUS_SUCCESS; + uint32_t offload_req_opcode; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + /* Request for GTK offload status */ + offload_req_opcode = GTK_OFFLOAD_REQUEST_STATUS_OPCODE; + + /* send the wmi command */ + status = wmi_unified_process_gtk_offload_getinfo_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + vdev_id, offload_req_opcode); + + return status; +} + +int target_if_pmo_gtk_offload_status_event(void *scn_handle, + uint8_t *event, uint32_t len) +{ + struct pmo_gtk_rsp_params *gtk_rsp_param; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS ret; + + TARGET_IF_ENTER(); + psoc = target_if_get_psoc_from_scn_hdl(scn_handle); + if (!psoc) { + target_if_err("psoc ptr is NULL"); + ret = -EINVAL; + goto out; + } + + gtk_rsp_param = qdf_mem_malloc(sizeof(*gtk_rsp_param)); + if (!gtk_rsp_param) { + target_if_err("memory allocation failed"); + ret = -ENOMEM; + goto out; + } + + if (wmi_extract_gtk_rsp_event(GET_WMI_HDL_FROM_PSOC(psoc), + event, gtk_rsp_param, len) != QDF_STATUS_SUCCESS) { + target_if_err("Extraction of gtk rsp event failed"); + qdf_mem_free(gtk_rsp_param); + ret = -EINVAL; + goto out; + } + + ret = pmo_tgt_gtk_rsp_evt(psoc, (void *)gtk_rsp_param); + if (ret != QDF_STATUS_SUCCESS) { + target_if_err("Failed to rx_gtk_rsp_event"); + ret = -EINVAL; + } + qdf_mem_free(gtk_rsp_param); +out: + TARGET_IF_EXIT(); + + return ret; +} + diff --git a/core/components/target_if/pmo/src/target_if_pmo_hw_filter.c b/core/components/target_if/pmo/src/target_if_pmo_hw_filter.c new file mode 100644 index 000000000000..8070a6459a7e --- /dev/null +++ b/core/components/target_if/pmo/src/target_if_pmo_hw_filter.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/** + * DOC: target_if_pmo_non_arp_bcast_fltr.c + * + * Target interface file for pmo component to + * send non arp hw bcast filtering related cmd and process event. + */ + +#include "target_if.h" +#include "target_if_pmo.h" +#include "wmi_unified_api.h" +#include "wlan_pmo_hw_filter_public_struct.h" + +QDF_STATUS target_if_pmo_conf_hw_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_hw_filter_params *req) +{ + QDF_STATUS status; + + if (!psoc) { + target_if_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_conf_hw_filter_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + req); + + if (QDF_IS_STATUS_ERROR(status)) + target_if_err("Failed to configure HW Filter"); + + return status; +} diff --git a/core/components/target_if/pmo/src/target_if_pmo_lphb.c b/core/components/target_if/pmo/src/target_if_pmo_lphb.c new file mode 100644 index 000000000000..8c630b803ab0 --- /dev/null +++ b/core/components/target_if/pmo/src/target_if_pmo_lphb.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/** + * DOC: target_if_pmo_lphb.c + * + * Target interface file for pmo component to + * send lphb offload related cmd and process event. + */ +#ifdef FEATURE_WLAN_LPHB + +#include "target_if.h" +#include "target_if_pmo.h" +#include "wmi_unified_pmo_api.h" + +QDF_STATUS target_if_pmo_send_lphb_enable(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_enable_req *ts_lphb_enable) +{ + QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; + int status = 0; + wmi_hb_set_enable_cmd_fixed_param hb_enable_fp; + + if (ts_lphb_enable == NULL) { + target_if_err("LPHB Enable configuration is NULL"); + return QDF_STATUS_E_FAILURE; + } + + target_if_info("PMO_HB_SET_ENABLE enable=%d, item=%d, session=%d", + ts_lphb_enable->enable, + ts_lphb_enable->item, ts_lphb_enable->session); + + if ((ts_lphb_enable->item != 1) && (ts_lphb_enable->item != 2)) { + target_if_err("LPHB configuration wrong item %d", + ts_lphb_enable->item); + return QDF_STATUS_E_FAILURE; + } + + /* fill in values */ + hb_enable_fp.vdev_id = ts_lphb_enable->session; + hb_enable_fp.enable = ts_lphb_enable->enable; + hb_enable_fp.item = ts_lphb_enable->item; + hb_enable_fp.session = ts_lphb_enable->session; + + status = wmi_unified_lphb_config_hbenable_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + &hb_enable_fp); + if (status != EOK) { + qdf_status = QDF_STATUS_E_FAILURE; + goto error; + } + return QDF_STATUS_SUCCESS; +error: + + return qdf_status; +} + +QDF_STATUS target_if_pmo_send_lphb_tcp_params(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_tcp_params *ts_lphb_tcp_param) +{ + QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; + int status = 0; + wmi_hb_set_tcp_params_cmd_fixed_param hb_tcp_params_fp = {0}; + + if (ts_lphb_tcp_param == NULL) { + target_if_err("TCP params LPHB configuration is NULL"); + return QDF_STATUS_E_FAILURE; + } + + target_if_info("PMO --> WMI_HB_SET_TCP_PARAMS srv_ip=%08x, " + "dev_ip=%08x, src_port=%d, dst_port=%d, timeout=%d, " + "session=%d, gateway_mac= %pM, time_period_sec=%d," + "tcp_sn=%d", ts_lphb_tcp_param->srv_ip, + ts_lphb_tcp_param->dev_ip, ts_lphb_tcp_param->src_port, + ts_lphb_tcp_param->dst_port, ts_lphb_tcp_param->timeout, + ts_lphb_tcp_param->session, + ts_lphb_tcp_param->gateway_mac.bytes, + ts_lphb_tcp_param->time_period_sec, ts_lphb_tcp_param->tcp_sn); + + /* fill in values */ + hb_tcp_params_fp.vdev_id = ts_lphb_tcp_param->session; + hb_tcp_params_fp.srv_ip = ts_lphb_tcp_param->srv_ip; + hb_tcp_params_fp.dev_ip = ts_lphb_tcp_param->dev_ip; + hb_tcp_params_fp.seq = ts_lphb_tcp_param->tcp_sn; + hb_tcp_params_fp.src_port = ts_lphb_tcp_param->src_port; + hb_tcp_params_fp.dst_port = ts_lphb_tcp_param->dst_port; + hb_tcp_params_fp.interval = ts_lphb_tcp_param->time_period_sec; + hb_tcp_params_fp.timeout = ts_lphb_tcp_param->timeout; + hb_tcp_params_fp.session = ts_lphb_tcp_param->session; + WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_tcp_param->gateway_mac.bytes, + &hb_tcp_params_fp.gateway_mac); + + status = wmi_unified_lphb_config_tcp_params_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + &hb_tcp_params_fp); + if (status != EOK) { + qdf_status = QDF_STATUS_E_FAILURE; + goto error; + } + + return QDF_STATUS_SUCCESS; +error: + return qdf_status; +} + +QDF_STATUS target_if_pmo_send_lphb_tcp_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_tcp_filter_req *ts_lphb_tcp_filter) +{ + QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; + int status = 0; + wmi_hb_set_tcp_pkt_filter_cmd_fixed_param hb_tcp_filter_fp = {0}; + + if (ts_lphb_tcp_filter == NULL) { + target_if_err("TCP PKT FILTER LPHB configuration is NULL"); + return QDF_STATUS_E_FAILURE; + } + + target_if_info("SET_TCP_PKT_FILTER length=%d, offset=%d, session=%d, " + "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", + ts_lphb_tcp_filter->length, ts_lphb_tcp_filter->offset, + ts_lphb_tcp_filter->session, ts_lphb_tcp_filter->filter[0], + ts_lphb_tcp_filter->filter[1], ts_lphb_tcp_filter->filter[2], + ts_lphb_tcp_filter->filter[3], ts_lphb_tcp_filter->filter[4], + ts_lphb_tcp_filter->filter[5]); + + /* fill in values */ + hb_tcp_filter_fp.vdev_id = ts_lphb_tcp_filter->session; + hb_tcp_filter_fp.length = ts_lphb_tcp_filter->length; + hb_tcp_filter_fp.offset = ts_lphb_tcp_filter->offset; + hb_tcp_filter_fp.session = ts_lphb_tcp_filter->session; + memcpy((void *)&hb_tcp_filter_fp.filter, + (void *)&ts_lphb_tcp_filter->filter, + WMI_WLAN_HB_MAX_FILTER_SIZE); + + status = wmi_unified_lphb_config_tcp_pkt_filter_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + &hb_tcp_filter_fp); + if (status != EOK) { + qdf_status = QDF_STATUS_E_FAILURE; + goto error; + } + + return QDF_STATUS_SUCCESS; +error: + return qdf_status; +} + +QDF_STATUS target_if_pmo_send_lphb_udp_params(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_udp_params *ts_lphb_udp_param) +{ + QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; + int status = 0; + wmi_hb_set_udp_params_cmd_fixed_param hb_udp_params_fp = {0}; + + if (ts_lphb_udp_param == NULL) { + target_if_err("UDP param for LPHB configuration is NULL"); + return QDF_STATUS_E_FAILURE; + } + + target_if_info("HB_SET_UDP_PARAMS srv_ip=%d, dev_ip=%d, src_port=%d, " + "dst_port=%d, interval=%d, timeout=%d, session=%d, " + "gateway_mac= %pM", + ts_lphb_udp_param->srv_ip, ts_lphb_udp_param->dev_ip, + ts_lphb_udp_param->src_port, ts_lphb_udp_param->dst_port, + ts_lphb_udp_param->interval, ts_lphb_udp_param->timeout, + ts_lphb_udp_param->session, + ts_lphb_udp_param->gateway_mac.bytes); + + /* fill in values */ + hb_udp_params_fp.vdev_id = ts_lphb_udp_param->session; + hb_udp_params_fp.srv_ip = ts_lphb_udp_param->srv_ip; + hb_udp_params_fp.dev_ip = ts_lphb_udp_param->dev_ip; + hb_udp_params_fp.src_port = ts_lphb_udp_param->src_port; + hb_udp_params_fp.dst_port = ts_lphb_udp_param->dst_port; + hb_udp_params_fp.interval = ts_lphb_udp_param->interval; + hb_udp_params_fp.timeout = ts_lphb_udp_param->timeout; + hb_udp_params_fp.session = ts_lphb_udp_param->session; + WMI_CHAR_ARRAY_TO_MAC_ADDR(ts_lphb_udp_param->gateway_mac.bytes, + &hb_udp_params_fp.gateway_mac); + + status = wmi_unified_lphb_config_udp_params_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + &hb_udp_params_fp); + if (status != EOK) { + qdf_status = QDF_STATUS_E_FAILURE; + goto error; + } + + return QDF_STATUS_SUCCESS; +error: + return qdf_status; +} + +/** + * target_if_pmo_lphb_send_udp_pkt_filter() - Send LPHB udp pkt filter req + * @psoc: objmgr psoc handle + * @ts_lphb_udp_filter: lphb udp filter request which needs to configure in fwr + * + * Return: QDF status + */ +QDF_STATUS target_if_pmo_send_lphb_udp_pkt_filter(struct wlan_objmgr_psoc *psoc, + struct pmo_lphb_udp_filter_req *ts_lphb_udp_filter) +{ + QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; + int status = 0; + wmi_hb_set_udp_pkt_filter_cmd_fixed_param hb_udp_filter_fp = {0}; + + if (ts_lphb_udp_filter == NULL) { + target_if_err("LPHB UDP packet filter configuration is NULL"); + return QDF_STATUS_E_FAILURE; + } + + target_if_info("SET_UDP_PKT_FILTER length=%d, offset=%d, session=%d, " + "filter=%2x:%2x:%2x:%2x:%2x:%2x ...", + ts_lphb_udp_filter->length, ts_lphb_udp_filter->offset, + ts_lphb_udp_filter->session, ts_lphb_udp_filter->filter[0], + ts_lphb_udp_filter->filter[1], ts_lphb_udp_filter->filter[2], + ts_lphb_udp_filter->filter[3], ts_lphb_udp_filter->filter[4], + ts_lphb_udp_filter->filter[5]); + + /* fill in values */ + hb_udp_filter_fp.vdev_id = ts_lphb_udp_filter->session; + hb_udp_filter_fp.length = ts_lphb_udp_filter->length; + hb_udp_filter_fp.offset = ts_lphb_udp_filter->offset; + hb_udp_filter_fp.session = ts_lphb_udp_filter->session; + qdf_mem_copy((void *)&hb_udp_filter_fp.filter, + (void *)&ts_lphb_udp_filter->filter, + WMI_WLAN_HB_MAX_FILTER_SIZE); + + status = wmi_unified_lphb_config_udp_pkt_filter_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + &hb_udp_filter_fp); + if (status != EOK) { + qdf_status = QDF_STATUS_E_FAILURE; + goto error; + } + + return QDF_STATUS_SUCCESS; +error: + return qdf_status; +} + +QDF_STATUS target_if_pmo_lphb_evt_handler(struct wlan_objmgr_psoc *psoc, + uint8_t *event) +{ + wmi_hb_ind_event_fixed_param *hb_fp; + struct pmo_lphb_rsp *slphb_indication = NULL; + QDF_STATUS qdf_status; + + TARGET_IF_ENTER(); + if (!psoc) { + target_if_err("psoc ptr is NULL"); + qdf_status = QDF_STATUS_E_NULL_VALUE; + goto out; + } + + hb_fp = (wmi_hb_ind_event_fixed_param *) event; + if (!hb_fp) { + target_if_err("Invalid wmi_hb_ind_event_fixed_param buffer"); + qdf_status = QDF_STATUS_E_INVAL; + goto out; + } + + target_if_debug("lphb indication received with\n" + "vdev_id=%d, session=%d, reason=%d", + hb_fp->vdev_id, hb_fp->session, hb_fp->reason); + + slphb_indication = (struct pmo_lphb_rsp *)qdf_mem_malloc( + sizeof(struct pmo_lphb_rsp)); + + if (!slphb_indication) { + target_if_err("Invalid LPHB indication buffer"); + qdf_status = QDF_STATUS_E_NOMEM; + goto out; + } + + slphb_indication->session_idx = hb_fp->session; + slphb_indication->protocol_type = hb_fp->reason; + slphb_indication->event_reason = hb_fp->reason; + + qdf_status = pmo_tgt_lphb_rsp_evt(psoc, slphb_indication); + if (qdf_status != QDF_STATUS_SUCCESS) + target_if_err("Failed to lphb_rsp_event"); +out: + if (slphb_indication) + qdf_mem_free(slphb_indication); + + return qdf_status; +} +#endif + diff --git a/core/components/target_if/pmo/src/target_if_pmo_main.c b/core/components/target_if/pmo/src/target_if_pmo_main.c new file mode 100644 index 000000000000..6e63d045e831 --- /dev/null +++ b/core/components/target_if/pmo/src/target_if_pmo_main.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/** + * DOC: Target interface file for pmo component to + * Implement api's which shall be used by pmo component + * in target if internally. + */ + +#include "target_if_pmo.h" +#include "wlan_pmo_common_public_struct.h" + +void target_if_pmo_register_tx_ops(struct wlan_pmo_tx_ops *pmo_tx_ops) +{ + if (!pmo_tx_ops) { + target_if_err("pmo_tx_ops is null"); + return; + } + + pmo_tx_ops->send_arp_offload_req = + target_if_pmo_send_arp_offload_req; + pmo_tx_ops->send_conf_hw_filter_req = + target_if_pmo_conf_hw_filter; + pmo_tx_ops->send_ns_offload_req = + target_if_pmo_send_ns_offload_req; + pmo_tx_ops->send_enable_wow_wakeup_event_req = + target_if_pmo_enable_wow_wakeup_event; + pmo_tx_ops->send_disable_wow_wakeup_event_req = + target_if_pmo_disable_wow_wakeup_event; + pmo_tx_ops->send_add_wow_pattern = + target_if_pmo_send_wow_patterns_to_fw; + pmo_tx_ops->send_enhance_mc_offload_req = + target_if_pmo_send_enhance_mc_offload_req; + pmo_tx_ops->send_set_mc_filter_req = + target_if_pmo_set_mc_filter_req; + pmo_tx_ops->send_clear_mc_filter_req = + target_if_pmo_clear_mc_filter_req; + pmo_tx_ops->send_ra_filter_req = + target_if_pmo_send_ra_filter_req; + pmo_tx_ops->send_gtk_offload_req = + target_if_pmo_send_gtk_offload_req; + pmo_tx_ops->send_get_gtk_rsp_cmd = + target_if_pmo_send_gtk_response_req; + pmo_tx_ops->send_action_frame_pattern_req = + target_if_pmo_send_action_frame_patterns; + pmo_tx_ops->send_lphb_enable = + target_if_pmo_send_lphb_enable; + pmo_tx_ops->send_lphb_tcp_params = + target_if_pmo_send_lphb_tcp_params; + pmo_tx_ops->send_lphb_tcp_filter_req = + target_if_pmo_send_lphb_tcp_pkt_filter; + pmo_tx_ops->send_lphb_upd_params = + target_if_pmo_send_lphb_udp_params; + pmo_tx_ops->send_lphb_udp_filter_req = + target_if_pmo_send_lphb_udp_pkt_filter; + pmo_tx_ops->send_vdev_param_update_req = + target_if_pmo_send_vdev_update_param_req; + pmo_tx_ops->send_vdev_sta_ps_param_req = + target_if_pmo_send_vdev_ps_param_req; + pmo_tx_ops->psoc_update_wow_bus_suspend = + target_if_pmo_psoc_update_bus_suspend; + pmo_tx_ops->psoc_get_host_credits = + target_if_pmo_psoc_get_host_credits; + pmo_tx_ops->psoc_get_pending_cmnds = + target_if_pmo_psoc_get_pending_cmnds; + pmo_tx_ops->update_target_suspend_flag = + target_if_pmo_update_target_suspend_flag; + pmo_tx_ops->psoc_send_wow_enable_req = + target_if_pmo_psoc_send_wow_enable_req; + pmo_tx_ops->psoc_send_supend_req = + target_if_pmo_psoc_send_suspend_req; + pmo_tx_ops->psoc_set_runtime_pm_in_progress = + target_if_pmo_set_runtime_pm_in_progress; + pmo_tx_ops->psoc_get_runtime_pm_in_progress = + target_if_pmo_get_runtime_pm_in_progress; + pmo_tx_ops->psoc_send_host_wakeup_ind = + 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->send_set_pkt_filter = + target_if_pmo_send_pkt_filter_req; + pmo_tx_ops->send_clear_pkt_filter = + target_if_pmo_clear_pkt_filter_req; + +} + diff --git a/core/components/target_if/pmo/src/target_if_pmo_mc_addr_filtering.c b/core/components/target_if/pmo/src/target_if_pmo_mc_addr_filtering.c new file mode 100644 index 000000000000..bd3b29b8aeea --- /dev/null +++ b/core/components/target_if/pmo/src/target_if_pmo_mc_addr_filtering.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/** + * DOC: target_if_pmo_mc_addr_filtering.c + * + * Target interface file for pmo component to + * send mc address filtering offload related cmd and process event. + */ + + +#include "target_if.h" +#include "target_if_pmo.h" +#include "wmi_unified_api.h" + +QDF_STATUS target_if_pmo_set_mc_filter_req( + struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr multicast_addr) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_add_clear_mcbc_filter_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + vdev_id, + multicast_addr, false); + if (status) + target_if_err("Failed to send add/clear mcbc filter cmd"); + + return status; +} + +QDF_STATUS target_if_pmo_clear_mc_filter_req( + struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr multicast_addr) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_add_clear_mcbc_filter_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + vdev_id, + multicast_addr, true); + if (status) + target_if_err("Failed to send add/clear mcbc filter cmd"); + + return status; + +} + + diff --git a/core/components/target_if/pmo/src/target_if_pmo_ns.c b/core/components/target_if/pmo/src/target_if_pmo_ns.c new file mode 100644 index 000000000000..6b2946b88fc8 --- /dev/null +++ b/core/components/target_if/pmo/src/target_if_pmo_ns.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/** + * DOC: target_if_pmo_ns.c + * + * Target interface file for pmo component to + * send ns offload related cmd and process event. + */ + +#include "target_if.h" +#include "target_if_pmo.h" +#include "wmi_unified_api.h" + +QDF_STATUS target_if_pmo_send_ns_offload_req( + struct wlan_objmgr_vdev *vdev, + struct pmo_arp_offload_params *arp_offload_req, + struct pmo_ns_offload_params *ns_offload_req) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_enable_arp_ns_offload_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + arp_offload_req, + ns_offload_req, + vdev_id); + if (status != QDF_STATUS_SUCCESS) + target_if_err("Failed to enable ARP NDP/NSffload"); + + return status; +} + diff --git a/core/components/target_if/pmo/src/target_if_pmo_pkt_filter.c b/core/components/target_if/pmo/src/target_if_pmo_pkt_filter.c new file mode 100644 index 000000000000..7907c7a0a0f9 --- /dev/null +++ b/core/components/target_if/pmo/src/target_if_pmo_pkt_filter.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/** + * DOC: target_if_pmo_pkt_filter.c + * + * Target interface file for pmo component to + * send packet filter related cmd and process event. + */ + +#include "target_if.h" +#include "target_if_pmo.h" +#include "wmi_unified_pmo_api.h" +#include "wlan_pmo_pkt_filter_public_struct.h" + +QDF_STATUS target_if_pmo_send_pkt_filter_req(struct wlan_objmgr_vdev *vdev, + struct pmo_rcv_pkt_fltr_cfg *rcv_filter_param) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + /* send the command along with data */ + status = wmi_unified_config_packet_filter_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), vdev_id, + rcv_filter_param, + rcv_filter_param->filter_id, true); + if (status) { + target_if_err("Failed to send pkt_filter cmd"); + return QDF_STATUS_E_INVAL; + } + + /* Enable packet filter */ + status = wmi_unified_enable_disable_packet_filter_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + vdev_id, true); + if (status) + target_if_err("Failed to send packet filter wmi cmd to fw"); + + return status; +} + +QDF_STATUS target_if_pmo_clear_pkt_filter_req(struct wlan_objmgr_vdev *vdev, + struct pmo_rcv_pkt_fltr_clear_param *rcv_clear_param) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + /* send the command along with data */ + status = wmi_unified_config_packet_filter_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), vdev_id, + NULL, rcv_clear_param->filter_id, false); + + if (status) + target_if_err("Failed to clear filter cmd"); + + return status; +} diff --git a/core/components/target_if/pmo/src/target_if_pmo_static_config.c b/core/components/target_if/pmo/src/target_if_pmo_static_config.c new file mode 100644 index 000000000000..8207e361dd14 --- /dev/null +++ b/core/components/target_if/pmo/src/target_if_pmo_static_config.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/** + * DOC: target_if_pmo_static.c + * + * Target interface file for pmo component to + * send wow related cmd and process event. + */ + + +#include "target_if.h" +#include "target_if_pmo.h" +#include "wmi_unified_api.h" + +QDF_STATUS target_if_pmo_send_ra_filter_req(struct wlan_objmgr_vdev *vdev, + uint8_t default_pattern, uint16_t rate_limit_interval) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_wow_sta_ra_filter_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), vdev_id, + default_pattern, rate_limit_interval); + if (status) + target_if_err("Failed to send RA rate limit to fw"); + + return status; +} + +QDF_STATUS target_if_pmo_send_action_frame_patterns( + struct wlan_objmgr_vdev *vdev, + struct pmo_action_wakeup_set_params *ip_cmd) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_action_frame_patterns_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), ip_cmd); + if (status != QDF_STATUS_SUCCESS) + target_if_err("Failed to config wow action frame map, ret %d", + status); + + return status; +} + +QDF_STATUS target_if_pmo_send_enhance_mc_offload_req( + struct wlan_objmgr_vdev *vdev, bool enable) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_enable_enhance_multicast_offload_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), vdev_id, enable); + if (status) + target_if_err("Failed to config wow wakeup event"); + + return status; +} + diff --git a/core/components/target_if/pmo/src/target_if_pmo_suspend_resume.c b/core/components/target_if/pmo/src/target_if_pmo_suspend_resume.c new file mode 100644 index 000000000000..fbbd638d8932 --- /dev/null +++ b/core/components/target_if/pmo/src/target_if_pmo_suspend_resume.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/** + * DOC: target_if_pmo_static.c + * + * Target interface file for pmo component to + * send suspend / resume related cmd and process event. + */ + + +#include "target_if.h" +#include "target_if_pmo.h" +#include "wmi_unified_api.h" + +#define TGT_WILDCARD_PDEV_ID 0x0 + +QDF_STATUS target_if_pmo_send_vdev_update_param_req( + struct wlan_objmgr_vdev *vdev, + uint32_t param_id, uint32_t param_value) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + struct vdev_set_params param = {0}; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + switch (param_id) { + case pmo_vdev_param_listen_interval: + param_id = WMI_VDEV_PARAM_LISTEN_INTERVAL; + break; + case pmo_vdev_param_dtim_policy: + param_id = WMI_VDEV_PARAM_DTIM_POLICY; + break; + default: + target_if_err("invalid vdev param id %d", param_id); + return QDF_STATUS_E_INVAL; + } + + param.if_id = vdev_id; + param.param_id = param_id; + param.param_value = param_value; + target_if_info("set vdev param vdev_id: %d value: %d for param_id: %d", + vdev_id, param_value, param_id); + return wmi_unified_vdev_set_param_send(GET_WMI_HDL_FROM_PSOC(psoc), + ¶m); +} + +QDF_STATUS target_if_pmo_send_vdev_ps_param_req( + struct wlan_objmgr_vdev *vdev, + uint32_t param_id, + uint32_t param_value) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + struct sta_ps_params sta_ps_param = {0}; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + switch (param_id) { + case pmo_sta_ps_enable_qpower: + param_id = WMI_STA_PS_ENABLE_QPOWER; + break; + default: + target_if_err("invalid vdev param id %d", param_id); + return QDF_STATUS_E_INVAL; + } + + sta_ps_param.vdev_id = vdev_id; + sta_ps_param.param = param_id; + sta_ps_param.value = param_value; + target_if_info("set vdev param vdev_id: %d value: %d for param_id: %d", + vdev_id, param_value, param_id); + + status = wmi_unified_sta_ps_cmd_send(GET_WMI_HDL_FROM_PSOC(psoc), + &sta_ps_param); + if (QDF_IS_STATUS_ERROR(status)) + return status; + + return status; + +} + +void target_if_pmo_psoc_update_bus_suspend(struct wlan_objmgr_psoc *psoc, + uint8_t value) +{ + wmi_set_is_wow_bus_suspended(GET_WMI_HDL_FROM_PSOC(psoc), value); +} + +int target_if_pmo_psoc_get_host_credits(struct wlan_objmgr_psoc *psoc) +{ + return wmi_get_host_credits(GET_WMI_HDL_FROM_PSOC(psoc)); +} + +int target_if_pmo_psoc_get_pending_cmnds(struct wlan_objmgr_psoc *psoc) +{ + return wmi_get_pending_cmds(GET_WMI_HDL_FROM_PSOC(psoc)); +} + +void target_if_pmo_update_target_suspend_flag(struct wlan_objmgr_psoc *psoc, + uint8_t value) +{ + wmi_set_target_suspend(GET_WMI_HDL_FROM_PSOC(psoc), value); +} + +QDF_STATUS target_if_pmo_psoc_send_wow_enable_req( + struct wlan_objmgr_psoc *psoc, + struct pmo_wow_cmd_params *param) +{ + return wmi_unified_wow_enable_send(GET_WMI_HDL_FROM_PSOC(psoc), + (struct wow_cmd_params *)param, + TGT_WILDCARD_PDEV_ID); +} + +QDF_STATUS target_if_pmo_psoc_send_suspend_req( + struct wlan_objmgr_psoc *psoc, + struct pmo_suspend_params *param) +{ + return wmi_unified_suspend_send(GET_WMI_HDL_FROM_PSOC(psoc), + (struct suspend_params *) param, + TGT_WILDCARD_PDEV_ID); +} + +void target_if_pmo_set_runtime_pm_in_progress(struct wlan_objmgr_psoc *psoc, + bool value) +{ + return wmi_set_runtime_pm_inprogress(GET_WMI_HDL_FROM_PSOC(psoc), + value); +} + +bool target_if_pmo_get_runtime_pm_in_progress( + struct wlan_objmgr_psoc *psoc) +{ + return wmi_get_runtime_pm_inprogress(GET_WMI_HDL_FROM_PSOC(psoc)); +} + +QDF_STATUS target_if_pmo_psoc_send_host_wakeup_ind( + struct wlan_objmgr_psoc *psoc) +{ + return wmi_unified_host_wakeup_ind_to_fw_cmd( + GET_WMI_HDL_FROM_PSOC(psoc)); +} + +QDF_STATUS target_if_pmo_psoc_send_target_resume_req( + struct wlan_objmgr_psoc *psoc) +{ + return wmi_unified_resume_send(GET_WMI_HDL_FROM_PSOC(psoc), + TGT_WILDCARD_PDEV_ID); +} + diff --git a/core/components/target_if/pmo/src/target_if_pmo_wow.c b/core/components/target_if/pmo/src/target_if_pmo_wow.c new file mode 100644 index 000000000000..828f0cf26eb9 --- /dev/null +++ b/core/components/target_if/pmo/src/target_if_pmo_wow.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/** + * DOC: target_if_pmo_wow.c + * + * Target interface file for pmo component to + * send wow related cmd and process event. + */ + + +#include "target_if.h" +#include "target_if_pmo.h" +#include "wmi_unified_api.h" + +QDF_STATUS target_if_pmo_enable_wow_wakeup_event(struct wlan_objmgr_vdev *vdev, + uint32_t *bitmap) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_add_wow_wakeup_event_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), vdev_id, bitmap, true); + if (status) + target_if_err("Failed to config wow wakeup event"); + + return status; +} + +QDF_STATUS target_if_pmo_disable_wow_wakeup_event(struct wlan_objmgr_vdev *vdev, + uint32_t *bitmap) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_add_wow_wakeup_event_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), vdev_id, bitmap, false); + if (status) + target_if_err("Failed to config wow wakeup event"); + + return status; +} + +QDF_STATUS target_if_pmo_send_wow_patterns_to_fw(struct wlan_objmgr_vdev *vdev, + uint8_t ptrn_id, + const uint8_t *ptrn, uint8_t ptrn_len, + uint8_t ptrn_offset, const uint8_t *mask, + uint8_t mask_len, bool user) +{ + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + vdev_id = wlan_vdev_get_id(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_wow_patterns_to_fw_cmd( + GET_WMI_HDL_FROM_PSOC(psoc), + vdev_id, ptrn_id, ptrn, + ptrn_len, ptrn_offset, mask, + mask_len, user, 0); + + return status; +} + diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 92c45376433f..9807393bc68e 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -10724,6 +10724,26 @@ static void wlan_hdd_state_ctrl_param_destroy(void) pr_info("Device node unregistered"); } +/** + * component_init - API to init cld component's + * + * Return: None + */ +static void component_init(void) +{ + pmo_init(); +} + +/** + * component_deinit - API to deinit cld component's + * + * Return: None + */ +static void component_deinit(void) +{ + pmo_deinit(); +} + /** * __hdd_module_init - Module init helper * @@ -10757,6 +10777,9 @@ static int __hdd_module_init(void) dispatcher_init(); + /* Ensure to call post objmgr init */ + component_init(); + qdf_wake_lock_create(&wlan_wake_lock, "wlan"); hdd_set_conparam((uint32_t) con_mode); @@ -10825,6 +10848,9 @@ static void __hdd_module_exit(void) qdf_wake_lock_destroy(&wlan_wake_lock); + /* Ensure to call prior to objmgr deinit */ + component_deinit(); + dispatcher_deinit(); hdd_deinit(); pld_deinit(); diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index ffaad5dd7076..f544878830e7 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -11665,7 +11665,7 @@ static int wlan_hdd_set_filter(hdd_context_t *hdd_ctx, pmo_set_pkt_fltr_req = qdf_mem_malloc(sizeof(*pmo_set_pkt_fltr_req)); if (!pmo_set_pkt_fltr_req) { - pmo_err("unable to allocate pmo_set_pkt_fltr_req"); + hdd_err("unable to allocate pmo_set_pkt_fltr_req"); return QDF_STATUS_E_NOMEM; }