diff --git a/components/pmo/core/inc/wlan_pmo_suspend_resume.h b/components/pmo/core/inc/wlan_pmo_suspend_resume.h index 22ba29ac8f..88ab1ccf0a 100644 --- a/components/pmo/core/inc/wlan_pmo_suspend_resume.h +++ b/components/pmo/core/inc/wlan_pmo_suspend_resume.h @@ -372,7 +372,27 @@ QDF_STATUS pmo_core_config_forced_dtim(struct wlan_objmgr_vdev *vdev, void pmo_core_system_resume(struct wlan_objmgr_psoc *psoc); #else static inline void pmo_core_system_resume(struct wlan_objmgr_psoc *psoc) +{} +#endif +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +/** + * pmo_core_enable_igmp_offload() - function to offload igmp + * @vdev: objmgr vdev handle + * @pmo_igmp_req: igmp req + * + * This function to offload igmp to fw + * + * Return: QDF_STATUS + */ +QDF_STATUS +pmo_core_enable_igmp_offload(struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *pmo_igmp_req); +#else +static inline QDF_STATUS +pmo_core_enable_igmp_offload(struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *pmo_igmp_req) { + return QDF_STATUS_SUCCESS; } #endif #endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */ diff --git a/components/pmo/core/src/wlan_pmo_suspend_resume.c b/components/pmo/core/src/wlan_pmo_suspend_resume.c index b87e595edc..97932b6ecf 100644 --- a/components/pmo/core/src/wlan_pmo_suspend_resume.c +++ b/components/pmo/core/src/wlan_pmo_suspend_resume.c @@ -1697,6 +1697,45 @@ out: return status; } +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +QDF_STATUS +pmo_core_enable_igmp_offload(struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *pmo_igmp_req) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + uint8_t vdev_id; + enum QDF_OPMODE op_mode; + struct pmo_vdev_priv_obj *vdev_ctx; + uint32_t version_support; + + if (wlan_vdev_is_up(vdev) != QDF_STATUS_SUCCESS) + return QDF_STATUS_E_INVAL; + + op_mode = pmo_get_vdev_opmode(vdev); + if (QDF_STA_MODE != op_mode) { + pmo_debug("igmp offload supported in STA mode"); + return QDF_STATUS_E_INVAL; + } + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.igmp_offload_enable) { + pmo_debug("igmp offload not supported"); + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + return QDF_STATUS_E_NOSUPPORT; + } + version_support = + vdev_ctx->pmo_psoc_ctx->psoc_cfg.igmp_version_support; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + vdev_id = pmo_vdev_get_id(vdev); + pmo_igmp_req->vdev_id = vdev_id; + pmo_igmp_req->version_support = version_support; + status = pmo_tgt_send_igmp_offload_req(vdev, pmo_igmp_req); + + return status; +} +#endif + QDF_STATUS pmo_core_config_forced_dtim(struct wlan_objmgr_vdev *vdev, uint32_t dynamic_dtim) { diff --git a/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h b/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h index 8b4cf942fd..a18cc32269 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h @@ -51,6 +51,9 @@ #define PMO_WOW_REQUIRED_CREDITS 1 +#define MAX_MC_IP_ADDR 10 +#define IGMP_QUERY_ADDRESS 0x10000e0 + /** * enum pmo_vdev_param_id: tell vdev param id * @pmo_vdev_param_listen_interval: vdev listen interval param id @@ -425,4 +428,21 @@ struct pmo_device_caps { bool li_offload; }; +/** + * pmo_igmp_offload_req - structure to hold igmp param + * + * @vdev_id: vdev id + * @enable: enable/disable + * @version_support: version support + * @num_grp_ip_address: num grp ip addr + * @grp_ip_address: array of grp_ip_address + * + **/ +struct pmo_igmp_offload_req { + uint32_t vdev_id; + bool enable; + uint32_t version_support; + uint32_t num_grp_ip_address; + uint32_t grp_ip_address[MAX_MC_IP_ADDR]; +}; #endif /* end of _WLAN_PMO_COMMONP_STRUCT_H_ */ diff --git a/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h b/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h index 4fb2a5db02..fee75ee8e9 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 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 @@ -201,6 +201,11 @@ struct wlan_pmo_tx_ops { QDF_STATUS (*send_vdev_sta_ps_param_req)( struct wlan_objmgr_vdev *vdev, uint32_t ps_mode, uint32_t value); +#ifdef WLAN_FEATURE_IGMP_OFFLOAD + QDF_STATUS (*send_igmp_offload_req)( + struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *pmo_igmp_req); +#endif void (*psoc_update_wow_bus_suspend)( struct wlan_objmgr_psoc *psoc, uint8_t value); int (*psoc_get_host_credits)( diff --git a/components/pmo/dispatcher/inc/wlan_pmo_tgt_api.h b/components/pmo/dispatcher/inc/wlan_pmo_tgt_api.h index 128fb038c1..bc9b8187b7 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_tgt_api.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_tgt_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 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 @@ -346,6 +346,26 @@ QDF_STATUS pmo_tgt_vdev_update_param_req(struct wlan_objmgr_vdev *vdev, 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); +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +/** + * pmo_tgt_send_igmp_offload_req() - Send igmp offload request to fw + * @vdev: objmgr vdev + * @pmo_igmp_req: igmp offload params + * + * Return: QDF status + */ +QDF_STATUS +pmo_tgt_send_igmp_offload_req(struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *pmo_igmp_req); +#else +static inline QDF_STATUS +pmo_tgt_send_igmp_offload_req(struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *pmo_igmp_req) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * pmo_tgt_update_wow_bus_suspend_state() - update wow bus suspend state flag * @psoc: objmgr psoc diff --git a/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h b/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h index 9c29f926d3..837d3b5243 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h @@ -140,6 +140,28 @@ QDF_STATUS ucfg_pmo_psoc_set_caps(struct wlan_objmgr_psoc *psoc, bool ucfg_pmo_is_arp_offload_enabled(struct wlan_objmgr_psoc *psoc); +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +/** + * ucfg_pmo_is_igmp_offload_enabled() - Get igmp offload enable or not + * @psoc: pointer to psoc object + * + * Return: igmp offload enable or not + */ +bool +ucfg_pmo_is_igmp_offload_enabled(struct wlan_objmgr_psoc *psoc); + +/** + * ucfg_pmo_set_igmp_offload_enabled() - Set igmp offload enable or not + * @psoc: pointer to psoc object + * @val: enable/disable igmp offload + * + * Return: None + */ +void +ucfg_pmo_set_igmp_offload_enabled(struct wlan_objmgr_psoc *psoc, + bool val); +#endif + /** * ucfg_pmo_set_arp_offload_enabled() - Set arp offload enable or not * @psoc: pointer to psoc object @@ -593,6 +615,27 @@ QDF_STATUS ucfg_pmo_flush_gtk_offload_req(struct wlan_objmgr_vdev *vdev); */ QDF_STATUS ucfg_pmo_enable_gtk_offload_in_fwr(struct wlan_objmgr_vdev *vdev); +#ifdef WLAN_FEATURE_BIG_DATA_STATS +/** + * ucfg_pmo_enable_igmp_offload(): enable igmp request in fwr + * @vdev: objmgr vdev handle + * @pmo_igmp_req: struct pmo_igmp_offload_req + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS ucfg_pmo_enable_igmp_offload( + struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *pmo_igmp_req); +#else +static inline +QDF_STATUS ucfg_pmo_enable_igmp_offload( + struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *pmo_igmp_req) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * ucfg_pmo_disable_gtk_offload_in_fwr(): disable cached gtk request in fwr * @vdev: objmgr vdev handle @@ -1451,6 +1494,13 @@ ucfg_pmo_enable_gtk_offload_in_fwr(struct wlan_objmgr_vdev *vdev) return QDF_STATUS_SUCCESS; } +static inline QDF_STATUS +ucfg_pmo_enable_igmp_offload(struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *pmo_igmp_req) +{ + return QDF_STATUS_E_NOSUPPORT; +} + static inline QDF_STATUS ucfg_pmo_disable_gtk_offload_in_fwr(struct wlan_objmgr_vdev *vdev) { @@ -1713,12 +1763,24 @@ ucfg_pmo_is_arp_offload_enabled(struct wlan_objmgr_psoc *psoc) return false; } +static inline bool +ucfg_pmo_is_igmp_offload_enabled(struct wlan_objmgr_psoc *psoc) +{ + return false; +} + static inline void ucfg_pmo_set_arp_offload_enabled(struct wlan_objmgr_psoc *psoc, bool val) { } +static inline void +ucfg_pmo_set_igmp_offload_enabled(struct wlan_objmgr_psoc *psoc, + bool val) +{ +} + static inline bool ucfg_pmo_is_wow_pulse_enabled(struct wlan_objmgr_psoc *psoc) { diff --git a/components/pmo/dispatcher/src/wlan_pmo_tgt_suspend_resume.c b/components/pmo/dispatcher/src/wlan_pmo_tgt_suspend_resume.c index 753705affb..9c93431fdb 100644 --- a/components/pmo/dispatcher/src/wlan_pmo_tgt_suspend_resume.c +++ b/components/pmo/dispatcher/src/wlan_pmo_tgt_suspend_resume.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 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 @@ -51,6 +51,29 @@ out: return status; } +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +QDF_STATUS +pmo_tgt_send_igmp_offload_req(struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *pmo_igmp_req) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wlan_pmo_tx_ops pmo_tx_ops; + + psoc = pmo_vdev_get_psoc(vdev); + + pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc); + if (!pmo_tx_ops.send_igmp_offload_req) { + pmo_err("send_vdev_param_set_req is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + status = pmo_tx_ops.send_igmp_offload_req(vdev, pmo_igmp_req); + + return status; +} +#endif + 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) { diff --git a/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c b/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c index 2303cffd56..57e447efa9 100644 --- a/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c +++ b/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c @@ -280,6 +280,14 @@ QDF_STATUS ucfg_pmo_enable_gtk_offload_in_fwr(struct wlan_objmgr_vdev *vdev) return pmo_core_enable_gtk_offload_in_fwr(vdev); } +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +QDF_STATUS ucfg_pmo_enable_igmp_offload(struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *igmp_req) +{ + return pmo_core_enable_igmp_offload(vdev, igmp_req); +} +#endif + QDF_STATUS ucfg_pmo_disable_gtk_offload_in_fwr(struct wlan_objmgr_vdev *vdev) { return pmo_core_disable_gtk_offload_in_fwr(vdev); @@ -547,6 +555,16 @@ ucfg_pmo_is_arp_offload_enabled(struct wlan_objmgr_psoc *psoc) return pmo_psoc_ctx->psoc_cfg.arp_offload_enable; } +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +bool +ucfg_pmo_is_igmp_offload_enabled(struct wlan_objmgr_psoc *psoc) +{ + struct pmo_psoc_priv_obj *pmo_psoc_ctx = pmo_psoc_get_priv(psoc); + + return pmo_psoc_ctx->psoc_cfg.igmp_offload_enable; +} +#endif + void ucfg_pmo_set_arp_offload_enabled(struct wlan_objmgr_psoc *psoc, bool val) @@ -556,6 +574,17 @@ ucfg_pmo_set_arp_offload_enabled(struct wlan_objmgr_psoc *psoc, pmo_psoc_ctx->psoc_cfg.arp_offload_enable = val; } +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +void +ucfg_pmo_set_igmp_offload_enabled(struct wlan_objmgr_psoc *psoc, + bool val) +{ + struct pmo_psoc_priv_obj *pmo_psoc_ctx = pmo_psoc_get_priv(psoc); + + pmo_psoc_ctx->psoc_cfg.igmp_offload_enable = val; +} +#endif + enum pmo_auto_pwr_detect_failure_mode ucfg_pmo_get_auto_power_fail_mode(struct wlan_objmgr_psoc *psoc) { diff --git a/components/target_if/pmo/inc/target_if_pmo.h b/components/target_if/pmo/inc/target_if_pmo.h index c858bcb4db..1195d58499 100644 --- a/components/target_if/pmo/inc/target_if_pmo.h +++ b/components/target_if/pmo/inc/target_if_pmo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 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 @@ -351,6 +351,28 @@ QDF_STATUS target_if_pmo_send_vdev_ps_param_req( uint32_t param_id, uint32_t param_value); +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +/** + * target_if_pmo_send_igmp_offload_req() - Send igmp offload req to fw + * @vdev: objmgr vdev + * @pmo_igmp_req: igmp req + * + * Return: QDF status + */ +QDF_STATUS +target_if_pmo_send_igmp_offload_req( + struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *pmo_igmp_req); +#else +static inline QDF_STATUS +target_if_pmo_send_igmp_offload_req( + struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *pmo_igmp_req) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * target_if_pmo_psoc_update_bus_suspend() - update wmi bus suspend flag * @psoc: objmgr psoc diff --git a/components/target_if/pmo/src/target_if_pmo_main.c b/components/target_if/pmo/src/target_if_pmo_main.c index a0134d0828..0ef183e16a 100644 --- a/components/target_if/pmo/src/target_if_pmo_main.c +++ b/components/target_if/pmo/src/target_if_pmo_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 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 @@ -34,12 +34,23 @@ void tgt_if_pmo_reg_pkt_filter_ops(struct wlan_pmo_tx_ops *pmo_tx_ops) target_if_pmo_clear_pkt_filter_req; } #else -static inline -void tgt_if_pmo_reg_pkt_filter_ops(struct wlan_pmo_tx_ops *pmo_tx_ops) +static inline void +tgt_if_pmo_reg_pkt_filter_ops(struct wlan_pmo_tx_ops *pmo_tx_ops) { } #endif - +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +static void +update_pmo_igmp_tx_ops(struct wlan_pmo_tx_ops *pmo_tx_ops) +{ + pmo_tx_ops->send_igmp_offload_req = + target_if_pmo_send_igmp_offload_req; +} +#else +static inline void +update_pmo_igmp_tx_ops(struct wlan_pmo_tx_ops *pmo_tx_ops) +{} +#endif void target_if_pmo_register_tx_ops(struct wlan_pmo_tx_ops *pmo_tx_ops) { if (!pmo_tx_ops) { @@ -99,6 +110,7 @@ void target_if_pmo_register_tx_ops(struct wlan_pmo_tx_ops *pmo_tx_ops) target_if_pmo_psoc_update_bus_suspend; pmo_tx_ops->psoc_get_host_credits = target_if_pmo_psoc_get_host_credits; + update_pmo_igmp_tx_ops(pmo_tx_ops); pmo_tx_ops->psoc_get_pending_cmnds = target_if_pmo_psoc_get_pending_cmnds; pmo_tx_ops->update_target_suspend_flag = diff --git a/components/target_if/pmo/src/target_if_pmo_suspend_resume.c b/components/target_if/pmo/src/target_if_pmo_suspend_resume.c index 23c5909b53..f83b995a53 100644 --- a/components/target_if/pmo/src/target_if_pmo_suspend_resume.c +++ b/components/target_if/pmo/src/target_if_pmo_suspend_resume.c @@ -87,6 +87,36 @@ QDF_STATUS target_if_pmo_send_vdev_update_param_req( return wmi_unified_vdev_set_param_send(wmi_handle, ¶m); } +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +QDF_STATUS target_if_pmo_send_igmp_offload_req( + struct wlan_objmgr_vdev *vdev, + struct pmo_igmp_offload_req *pmo_igmp_req) +{ + struct wlan_objmgr_psoc *psoc; + wmi_unified_t wmi_handle; + + if (!vdev) { + target_if_err("vdev ptr passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + target_if_err("psoc handle is NULL"); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid wmi handle"); + return QDF_STATUS_E_INVAL; + } + + return wmi_unified_send_igmp_offload_cmd(wmi_handle, + pmo_igmp_req); +} +#endif + QDF_STATUS target_if_pmo_send_vdev_ps_param_req( struct wlan_objmgr_vdev *vdev, uint32_t param_id, diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 65d7a97065..966378da25 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1659,6 +1659,26 @@ hdd_init_get_sta_in_ll_stats_config(struct hdd_adapter *adapter) } #endif /* FEATURE_CLUB_LL_STATS_AND_GET_STATION */ +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +static void +hdd_intersect_igmp_offload_setting(struct wlan_objmgr_psoc *psoc, + struct wma_tgt_services *cfg) +{ + bool igmp_offload_enable; + + igmp_offload_enable = + ucfg_pmo_is_igmp_offload_enabled(psoc); + ucfg_pmo_set_igmp_offload_enabled(psoc, + igmp_offload_enable & + cfg->igmp_offload_enable); +} +#else +static inline void +hdd_intersect_igmp_offload_setting(struct wlan_objmgr_psoc *psoc, + struct wma_tgt_services *cfg) +{} +#endif + static void hdd_update_tgt_services(struct hdd_context *hdd_ctx, struct wma_tgt_services *cfg) { @@ -1691,6 +1711,10 @@ static void hdd_update_tgt_services(struct hdd_context *hdd_ctx, ucfg_pmo_is_arp_offload_enabled(hdd_ctx->psoc); ucfg_pmo_set_arp_offload_enabled(hdd_ctx->psoc, arp_offload_enable & cfg->arp_offload); + + /* Intersect igmp offload ini configuration and fw cap*/ + hdd_intersect_igmp_offload_setting(hdd_ctx->psoc, cfg); + #ifdef FEATURE_WLAN_SCAN_PNO /* PNO offload */ hdd_debug("PNO Capability in f/w = %d", cfg->pno_offload); diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index ac13bb4045..9cb0ba00bf 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -85,6 +85,8 @@ #include "wlan_pkt_capture_ucfg_api.h" #include "wlan_hdd_thermal.h" #include "wlan_hdd_object_manager.h" +#include +#include "qdf_types.h" /* Preprocessor definitions and constants */ #ifdef QCA_WIFI_EMULATION #define HDD_SSR_BRING_UP_TIME 3000000 @@ -192,6 +194,96 @@ static void hdd_enable_gtk_offload(struct hdd_adapter *adapter) hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID); } +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +/** + * hdd_send_igmp_offload_params() - enable igmp offload + * @adapter: pointer to the adapter + * @enable: enable/disable + * + * Return: nothing + */ +static QDF_STATUS +hdd_send_igmp_offload_params(struct hdd_adapter *adapter, + bool enable) +{ + struct in_device *in_dev = in_dev_get(adapter->dev); + struct ip_mc_list *ip_list = in_dev->mc_list; + struct pmo_igmp_offload_req *igmp_req = NULL; + int count = 0; + QDF_STATUS status; + + if (!ip_list) { + hdd_debug("ip list empty"); + return QDF_STATUS_E_FAILURE; + } + + igmp_req = qdf_mem_malloc(sizeof(*igmp_req)); + if (!igmp_req) + return QDF_STATUS_E_FAILURE; + + while (ip_list && ip_list->multiaddr && enable && + count < MAX_MC_IP_ADDR) { + if (IGMP_QUERY_ADDRESS != ip_list->multiaddr) { + igmp_req->grp_ip_address[count] = ip_list->multiaddr; + count++; + } + + ip_list = ip_list->next; + } + igmp_req->enable = enable; + igmp_req->num_grp_ip_address = count; + + status = ucfg_pmo_enable_igmp_offload(adapter->vdev, igmp_req); + if (status != QDF_STATUS_SUCCESS) + hdd_info("Failed to enable igmp offload"); + + qdf_mem_free(igmp_req); + return status; +} + +/** + * hdd_enable_igmp_offload() - enable GTK offload + * @adapter: pointer to the adapter + * + * Enable IGMP offload in suspended case to save power + * + * Return: nothing + */ +static void hdd_enable_igmp_offload(struct hdd_adapter *adapter) +{ + QDF_STATUS status; + struct wlan_objmgr_vdev *vdev; + + vdev = hdd_objmgr_get_vdev_by_user(adapter, WLAN_OSIF_POWER_ID); + if (!vdev) { + hdd_err("vdev is NULL"); + return; + } + status = hdd_send_igmp_offload_params(adapter, true); + if (status != QDF_STATUS_SUCCESS) + hdd_info("Failed to enable gtk offload"); + hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID); +} +#else +static inline void +hdd_enable_igmp_offload(struct hdd_adapter *adapter) +{} + +static inline QDF_STATUS +hdd_send_igmp_offload_params(struct hdd_adapter *adapter, + bool enable) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS +wlan_hdd_send_igmp_offload_params(struct hdd_adapter *adapter, bool enable, + uint32_t *mc_address, uint32_t count) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * hdd_disable_gtk_offload() - disable GTK offload * @adapter: pointer to the adapter @@ -720,6 +812,9 @@ void hdd_enable_host_offloads(struct hdd_adapter *adapter, hdd_enable_arp_offload(adapter, trigger); hdd_enable_ns_offload(adapter, trigger); hdd_enable_mc_addr_filtering(adapter, trigger); + if (adapter->device_mode == QDF_STA_MODE) + hdd_enable_igmp_offload(adapter); + if (adapter->device_mode != QDF_NDI_MODE) hdd_enable_hw_filter(adapter); hdd_enable_action_frame_patterns(adapter); diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h index fb2268970b..4d6a18b04d 100644 --- a/core/wma/inc/wma_tgt_cfg.h +++ b/core/wma/inc/wma_tgt_cfg.h @@ -48,6 +48,7 @@ * @is_get_station_clubbed_in_ll_stats_req: Get station req support within ll * stats req * @is_fw_therm_throt_supp: Get thermal throttling threshold + * @igmp_offload_enable: Get igmp offload enable or disable */ struct wma_tgt_services { uint32_t sta_power_save; @@ -86,6 +87,9 @@ struct wma_tgt_services { bool is_get_station_clubbed_in_ll_stats_req; #endif bool is_fw_therm_throt_supp; +#ifdef WLAN_FEATURE_IGMP_OFFLOAD + bool igmp_offload_enable; +#endif }; /** diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 75d706eaaa..f0ac02c17d 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -4535,6 +4535,29 @@ static void wma_set_tx_partition_base(uint32_t value) } #endif +#ifdef WLAN_FEATURE_IGMP_OFFLOAD +/** + * wma_get_igmp_offload_enable() - update tgt service with igmp offload support + * @wmi_handle: Unified wmi handle + * @cfg: target services + * + * Return: none + */ +static inline void +wma_get_igmp_offload_enable(struct wmi_unified *wmi_handle, + struct wma_tgt_services *cfg) +{ + cfg->igmp_offload_enable = wmi_service_enabled( + wmi_handle, + wmi_service_igmp_offload_support); +} +#else +static inline void +wma_get_igmp_offload_enable(struct wmi_unified *wmi_handle, + struct wma_tgt_services *cfg) +{} +#endif + /** * wma_update_target_services() - update target services from wma handle * @wmi_handle: Unified wmi handle @@ -4675,6 +4698,7 @@ static inline void wma_update_target_services(struct wmi_unified *wmi_handle, wma_get_service_cap_club_get_sta_in_ll_stats_req(wmi_handle, cfg); + wma_get_igmp_offload_enable(wmi_handle, cfg); } /**