diff --git a/Kbuild b/Kbuild index 430e642a98..2f3bd323cd 100644 --- a/Kbuild +++ b/Kbuild @@ -2901,6 +2901,7 @@ cppflags-$(CONFIG_FEATURE_WLAN_SCAN_PNO) += -DFEATURE_WLAN_SCAN_PNO cppflags-$(CONFIG_WLAN_FEATURE_PACKET_FILTERING) += -DWLAN_FEATURE_PACKET_FILTERING cppflags-$(CONFIG_DHCP_SERVER_OFFLOAD) += -DDHCP_SERVER_OFFLOAD cppflags-$(CONFIG_WLAN_NS_OFFLOAD) += -DWLAN_NS_OFFLOAD +cppflags-$(CONFIG_WLAN_DYNAMIC_ARP_NS_OFFLOAD) += -DFEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD cppflags-$(CONFIG_WLAN_FEATURE_ICMP_OFFLOAD) += -DWLAN_FEATURE_ICMP_OFFLOAD cppflags-$(CONFIG_FEATURE_WLAN_RA_FILTERING) += -DFEATURE_WLAN_RA_FILTERING cppflags-$(CONFIG_FEATURE_WLAN_LPHB) += -DFEATURE_WLAN_LPHB diff --git a/components/pmo/core/inc/wlan_pmo_priv.h b/components/pmo/core/inc/wlan_pmo_priv.h index 76a93d059b..0b6da8ec03 100644 --- a/components/pmo/core/inc/wlan_pmo_priv.h +++ b/components/pmo/core/inc/wlan_pmo_priv.h @@ -112,6 +112,9 @@ struct wlan_pmo_ctx { * @dyn_listen_interval: dynamically user configured listen interval * @restore_dtim_setting: DTIM settings restore flag * @pmo_vdev_lock: spin lock for pmo vdev priv ctx + * @dyn_arp_ns_offload_disable: true when arp/ns offload is disable + * @dyn_arp_ns_offload_rt_lock: wake lock which prevent runtime pm happen if + * arp/ns offload is disable */ struct pmo_vdev_priv_obj { struct pmo_psoc_priv_obj *pmo_psoc_ctx; @@ -136,6 +139,10 @@ struct pmo_vdev_priv_obj { uint32_t dyn_listen_interval; bool restore_dtim_setting; qdf_spinlock_t pmo_vdev_lock; +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD + bool dyn_arp_ns_offload_disable; + qdf_runtime_lock_t dyn_arp_ns_offload_rt_lock; +#endif }; #endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */ diff --git a/components/pmo/core/inc/wlan_pmo_suspend_resume.h b/components/pmo/core/inc/wlan_pmo_suspend_resume.h index 09e256e409..3f20b23cb6 100644 --- a/components/pmo/core/inc/wlan_pmo_suspend_resume.h +++ b/components/pmo/core/inc/wlan_pmo_suspend_resume.h @@ -179,6 +179,112 @@ bool pmo_core_vdev_get_restore_dtim(struct wlan_objmgr_vdev *vdev) return value; } +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD +/** + * pmo_core_dynamic_arp_ns_offload_enable() - Enable vdev arp/ns offload + * @vdev: objmgr vdev handle + * + * Return: QDF_STATUS_E_ALREADY if arp/ns offload already enable + */ +static inline QDF_STATUS +pmo_core_dynamic_arp_ns_offload_enable(struct wlan_objmgr_vdev *vdev) +{ + bool value; + QDF_STATUS status = QDF_STATUS_SUCCESS; + 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->dyn_arp_ns_offload_disable; + if (!value) + status = QDF_STATUS_E_ALREADY; + else + vdev_ctx->dyn_arp_ns_offload_disable = false; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return status; +} + +/** + * pmo_core_dynamic_arp_ns_offload_disable() - Disable vdev arp/ns offload + * @vdev: objmgr vdev handle + * + * Return: QDF_STATUS_E_ALREADY if arp/ns offload already disable + */ +static inline QDF_STATUS +pmo_core_dynamic_arp_ns_offload_disable(struct wlan_objmgr_vdev *vdev) +{ + bool value; + QDF_STATUS status = QDF_STATUS_SUCCESS; + 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->dyn_arp_ns_offload_disable; + if (value) + status = QDF_STATUS_E_ALREADY; + else + vdev_ctx->dyn_arp_ns_offload_disable = true; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return status; +} + +/** + * pmo_core_get_dynamic_arp_ns_offload_disable() - Get arp/ns offload state + * @vdev: objmgr vdev handle + * + * Return: true if vdev arp/ns offload is disable + */ +static inline bool +pmo_core_get_dynamic_arp_ns_offload_disable(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); + value = vdev_ctx->dyn_arp_ns_offload_disable; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + return value; +} + +/** + * pmo_core_dynamic_arp_ns_offload_runtime_prevent() - Prevent runtime suspend + * @vdev: objmgr vdev handle + * + * API to prevent runtime suspend happen when arp/ns offload is disable + * + * Return: None + */ +static inline void +pmo_core_dynamic_arp_ns_offload_runtime_prevent(struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_runtime_pm_prevent_suspend(&vdev_ctx->dyn_arp_ns_offload_rt_lock); +} + +/** + * pmo_core_dynamic_arp_ns_offload_runtime_allow() - Allow runtime suspend + * @vdev: objmgr vdev handle + * + * API to allow runtime suspend happen when arp/ns offload is enable + * + * Return: None + */ +static inline void +pmo_core_dynamic_arp_ns_offload_runtime_allow(struct wlan_objmgr_vdev *vdev) +{ + struct pmo_vdev_priv_obj *vdev_ctx; + + vdev_ctx = pmo_vdev_get_priv(vdev); + qdf_runtime_pm_allow_suspend(&vdev_ctx->dyn_arp_ns_offload_rt_lock); +} +#endif + /** * pmo_core_update_power_save_mode() - update power save mode * @vdev: objmgr vdev handle diff --git a/components/pmo/core/src/wlan_pmo_arp.c b/components/pmo/core/src/wlan_pmo_arp.c index c40e4a2e8f..5ad054ab70 100644 --- a/components/pmo/core/src/wlan_pmo_arp.c +++ b/components/pmo/core/src/wlan_pmo_arp.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 @@ -128,6 +128,7 @@ pmo_core_do_enable_arp_offload(struct wlan_objmgr_vdev *vdev, status = pmo_tgt_enable_arp_offload_req(vdev, vdev_id); break; case pmo_apps_suspend: + case pmo_arp_ns_offload_dynamic_update: /* enable arp when active offload is false (apps suspend) */ status = pmo_tgt_enable_arp_offload_req(vdev, vdev_id); break; @@ -161,6 +162,7 @@ static QDF_STATUS pmo_core_do_disable_arp_offload(struct wlan_objmgr_vdev *vdev, switch (trigger) { case pmo_apps_resume: + case pmo_arp_ns_offload_dynamic_update: /* disable arp on apps resume when active offload is disable */ status = pmo_tgt_disable_arp_offload_req(vdev, vdev_id); break; diff --git a/components/pmo/core/src/wlan_pmo_ns.c b/components/pmo/core/src/wlan_pmo_ns.c index edab499bb0..c335fd6922 100644 --- a/components/pmo/core/src/wlan_pmo_ns.c +++ b/components/pmo/core/src/wlan_pmo_ns.c @@ -169,6 +169,7 @@ static QDF_STATUS pmo_core_do_enable_ns_offload(struct wlan_objmgr_vdev *vdev, status = pmo_tgt_enable_ns_offload_req(vdev, vdev_id); break; case pmo_apps_suspend: + case pmo_arp_ns_offload_dynamic_update: /* enable arp when active offload is false (apps suspend) */ status = pmo_tgt_enable_ns_offload_req(vdev, vdev_id); break; @@ -204,6 +205,7 @@ static QDF_STATUS pmo_core_do_disable_ns_offload(struct wlan_objmgr_vdev *vdev, status = pmo_tgt_disable_ns_offload_req(vdev, vdev_id); break; case pmo_apps_resume: + case pmo_arp_ns_offload_dynamic_update: status = pmo_tgt_disable_ns_offload_req(vdev, vdev_id); break; default: 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 6d8b1ba5af..512cf406d8 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_common_public_struct.h @@ -220,6 +220,7 @@ typedef QDF_STATUS(*pmo_psoc_resume_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_arp_ns_offload_dynamic_update: enable/disable arp/ns offload on the fly * * @pmo_offload_trigger_max: Max trigger value */ @@ -234,6 +235,7 @@ enum pmo_offload_trigger { pmo_ns_offload_dynamic_update, pmo_peer_disconnect, pmo_mcbc_setting_dynamic_update, + pmo_arp_ns_offload_dynamic_update, pmo_offload_trigger_max, }; diff --git a/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h b/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h index 4a7749358c..5f3570cc10 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h @@ -545,6 +545,79 @@ ucfg_pmo_enhanced_mc_filter_disable(struct wlan_objmgr_vdev *vdev) return pmo_core_enhanced_mc_filter_disable(vdev); } +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD +/** + * ucfg_pmo_dynamic_arp_ns_offload_enable() - enable arp/ns offload + * @vdev: vdev objmgr handle + * + * Return: QDF_STATUS + */ +QDF_STATUS +ucfg_pmo_dynamic_arp_ns_offload_enable(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_pmo_dynamic_arp_ns_offload_disable() - disable arp/ns offload + * @vdev: vdev objmgr handle + * + * Return: QDF_STATUS + */ +QDF_STATUS +ucfg_pmo_dynamic_arp_ns_offload_disable(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_pmo_get_arp_ns_offload_dynamic_disable() - get arp/ns offload state + * @vdev: vdev objmgr handle + * + * Return: QDF_STATUS + */ +bool +ucfg_pmo_get_arp_ns_offload_dynamic_disable(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_pmo_dynamic_arp_ns_offload_runtime_prevent() - prevent runtime suspend + * @vdev: vdev objmgr handle + * + * Return: none + */ +void +ucfg_pmo_dynamic_arp_ns_offload_runtime_prevent(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_pmo_dynamic_arp_ns_offload_runtime_allow() - allow runtime suspend + * @vdev: vdev objmgr handle + * + * Return: none + */ +void +ucfg_pmo_dynamic_arp_ns_offload_runtime_allow(struct wlan_objmgr_vdev *vdev); +#else +static inline QDF_STATUS +ucfg_pmo_dynamic_arp_ns_offload_enable(struct wlan_objmgr_vdev *vdev) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS +ucfg_pmo_dynamic_arp_ns_offload_disable(struct wlan_objmgr_vdev *vdev) +{ + return QDF_STATUS_SUCCESS; +} + +static inline bool +ucfg_pmo_get_arp_ns_offload_dynamic_disable(struct wlan_objmgr_vdev *vdev) +{ + return false; +} + +static inline void +ucfg_pmo_dynamic_arp_ns_offload_runtime_prevent(struct wlan_objmgr_vdev *vdev) +{ +} + +static inline void +ucfg_pmo_dynamic_arp_ns_offload_runtime_allow(struct wlan_objmgr_vdev *vdev) {} +#endif + /** * ucfg_pmo_enable_mc_addr_filtering_in_fwr(): Enable cached mc add list in fwr * @psoc: objmgr psoc handle diff --git a/components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c b/components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c index 7de83e20f4..be4c3e56ab 100644 --- a/components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c +++ b/components/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c @@ -227,6 +227,26 @@ out: return status; } +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD +static inline void +pmo_vdev_dynamic_arp_ns_offload_init(struct pmo_vdev_priv_obj *vdev_ctx) +{ + qdf_runtime_lock_init(&vdev_ctx->dyn_arp_ns_offload_rt_lock); +} + +static inline void +pmo_vdev_dynamic_arp_ns_offload_deinit(struct pmo_vdev_priv_obj *vdev_ctx) +{ + qdf_runtime_lock_deinit(&vdev_ctx->dyn_arp_ns_offload_rt_lock); +} +#else +static inline void +pmo_vdev_dynamic_arp_ns_offload_init(struct pmo_vdev_priv_obj *vdev_ctx) {} + +static inline void +pmo_vdev_dynamic_arp_ns_offload_deinit(struct pmo_vdev_priv_obj *vdev_ctx) {} +#endif + QDF_STATUS pmo_vdev_object_created_notification( struct wlan_objmgr_vdev *vdev, void *arg) { @@ -263,6 +283,7 @@ QDF_STATUS pmo_vdev_object_created_notification( psoc_ctx->psoc_cfg.ptrn_match_enable_all_vdev; vdev_ctx->pmo_psoc_ctx = psoc_ctx; qdf_atomic_init(&vdev_ctx->gtk_err_enable); + pmo_vdev_dynamic_arp_ns_offload_init(vdev_ctx); out: pmo_exit(); @@ -308,6 +329,7 @@ QDF_STATUS pmo_vdev_object_destroyed_notification( pmo_err("Failed to detach vdev_ctx with vdev"); qdf_spinlock_destroy(&vdev_ctx->pmo_vdev_lock); + pmo_vdev_dynamic_arp_ns_offload_deinit(vdev_ctx); qdf_mem_free(vdev_ctx); return status; diff --git a/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c b/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c index 0527bcd601..e59a73518a 100644 --- a/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c +++ b/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c @@ -196,6 +196,38 @@ ucfg_pmo_disable_ns_offload_in_fwr(struct wlan_objmgr_vdev *vdev, } #endif /* WLAN_NS_OFFLOAD */ +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD +QDF_STATUS +ucfg_pmo_dynamic_arp_ns_offload_enable(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_dynamic_arp_ns_offload_enable(vdev); +} + +QDF_STATUS +ucfg_pmo_dynamic_arp_ns_offload_disable(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_dynamic_arp_ns_offload_disable(vdev); +} + +bool +ucfg_pmo_get_arp_ns_offload_dynamic_disable(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_get_dynamic_arp_ns_offload_disable(vdev); +} + +void +ucfg_pmo_dynamic_arp_ns_offload_runtime_prevent(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_dynamic_arp_ns_offload_runtime_prevent(vdev); +} + +void +ucfg_pmo_dynamic_arp_ns_offload_runtime_allow(struct wlan_objmgr_vdev *vdev) +{ + return pmo_core_dynamic_arp_ns_offload_runtime_allow(vdev); +} +#endif + QDF_STATUS ucfg_pmo_get_ns_offload_params(struct wlan_objmgr_vdev *vdev, struct pmo_ns_offload_params *params) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 9f6b71741a..c726bb71e8 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -7036,6 +7036,7 @@ const struct nla_policy wlan_hdd_wifi_config_policy[ [QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY] = { .type = NLA_U8 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD] = {.type = NLA_U8 }, }; static const struct nla_policy @@ -8975,6 +8976,103 @@ static int hdd_set_nss(struct hdd_adapter *adapter, return ret; } +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD +#define DYNAMIC_ARP_NS_ENABLE 1 +#define DYNAMIC_ARP_NS_DISABLE 0 + +/** + * hdd_set_arp_ns_offload() - enable/disable arp/ns offload feature + * @adapter: hdd adapter + * @attr: pointer to nla attr + * + * Return: 0 on success, negative errno on failure + */ +static int hdd_set_arp_ns_offload(struct hdd_adapter *adapter, + const struct nlattr *attr) +{ + uint8_t offload_state; + int errno; + QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE; + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + struct wlan_objmgr_vdev *vdev; + + errno = wlan_hdd_validate_context(hdd_ctx); + if (errno) + return errno; + + if (!ucfg_pmo_is_arp_offload_enabled(hdd_ctx->psoc) || + !ucfg_pmo_is_ns_offloaded(hdd_ctx->psoc)) { + hdd_err_rl("ARP/NS Offload is disabled by ini"); + return -EINVAL; + } + + if (!ucfg_pmo_is_active_mode_offloaded(hdd_ctx->psoc)) { + hdd_err_rl("active mode offload is disabled by ini"); + return -EINVAL; + } + + if (adapter->device_mode != QDF_STA_MODE && + adapter->device_mode != QDF_P2P_CLIENT_MODE) { + hdd_err_rl("only support on sta/p2p-cli mode"); + return -EINVAL; + } + + vdev = hdd_objmgr_get_vdev_by_user(adapter, WLAN_OSIF_ID); + if (!vdev) { + hdd_err("vdev is NULL"); + return -EINVAL; + } + + offload_state = nla_get_u8(attr); + + if (offload_state == DYNAMIC_ARP_NS_ENABLE) + qdf_status = ucfg_pmo_dynamic_arp_ns_offload_enable(vdev); + else if (offload_state == DYNAMIC_ARP_NS_DISABLE) + qdf_status = ucfg_pmo_dynamic_arp_ns_offload_disable(vdev); + + if (QDF_IS_STATUS_SUCCESS(qdf_status)) { + if (offload_state == DYNAMIC_ARP_NS_ENABLE) + ucfg_pmo_dynamic_arp_ns_offload_runtime_allow(vdev); + else + ucfg_pmo_dynamic_arp_ns_offload_runtime_prevent(vdev); + } + + hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID); + + if (QDF_IS_STATUS_ERROR(qdf_status)) { + if (qdf_status == QDF_STATUS_E_ALREADY) { + hdd_info_rl("already set arp/ns offload %d", + offload_state); + return 0; + } + return qdf_status_to_os_return(qdf_status); + } + + if (!hdd_is_vdev_in_conn_state(adapter)) { + hdd_info("set not in connect state, updated state %d", + offload_state); + return 0; + } + + if (offload_state == DYNAMIC_ARP_NS_ENABLE) { + hdd_enable_arp_offload(adapter, + pmo_arp_ns_offload_dynamic_update); + hdd_enable_ns_offload(adapter, + pmo_arp_ns_offload_dynamic_update); + } else if (offload_state == DYNAMIC_ARP_NS_DISABLE) { + hdd_disable_arp_offload(adapter, + pmo_arp_ns_offload_dynamic_update); + hdd_disable_ns_offload(adapter, + pmo_arp_ns_offload_dynamic_update); + } + + return 0; +} + +#undef DYNAMIC_ARP_NS_ENABLE +#undef DYNAMIC_ARP_NS_DISABLE +#endif + /** * typedef independent_setter_fn - independent attribute handler * @adapter: The adapter being configured @@ -9089,6 +9187,10 @@ static const struct independent_setters independent_setters[] = { hdd_set_primary_interface}, {QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS, hdd_set_ft_over_ds}, +#ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD + {QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD, + hdd_set_arp_ns_offload}, +#endif }; #ifdef WLAN_FEATURE_ELNA diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 8896e01f95..83eeda3da7 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -571,11 +571,23 @@ void hdd_enable_ns_offload(struct hdd_adapter *adapter, ns_req->trigger = trigger; ns_req->count = 0; + vdev = hdd_objmgr_get_vdev_by_user(adapter, WLAN_OSIF_POWER_ID); + if (!vdev) { + hdd_err("vdev is NULL"); + goto free_req; + } + /* check if offload cache and send is required or not */ status = ucfg_pmo_ns_offload_check(psoc, trigger, adapter->vdev_id); if (QDF_IS_STATUS_ERROR(status)) { hdd_debug("NS offload is not required"); - goto free_req; + goto put_vdev; + } + + if (ucfg_pmo_get_arp_ns_offload_dynamic_disable(vdev)) { + hdd_debug("Dynamic arp ns offload disabled"); + ucfg_pmo_flush_ns_offload_req(vdev); + goto skip_cache_ns; } /* Unicast Addresses */ @@ -585,7 +597,7 @@ void hdd_enable_ns_offload(struct hdd_adapter *adapter, if (errno) { hdd_disable_ns_offload(adapter, trigger); hdd_debug("Max supported addresses: disabling NS offload"); - goto free_req; + goto put_vdev; } /* Anycast Addresses */ @@ -595,21 +607,17 @@ void hdd_enable_ns_offload(struct hdd_adapter *adapter, if (errno) { hdd_disable_ns_offload(adapter, trigger); hdd_debug("Max supported addresses: disabling NS offload"); - goto free_req; + goto put_vdev; } /* cache ns request */ status = ucfg_pmo_cache_ns_offload_req(ns_req); if (QDF_IS_STATUS_ERROR(status)) { hdd_debug("Failed to cache ns request; status:%d", status); - goto free_req; + goto put_vdev; } - vdev = hdd_objmgr_get_vdev_by_user(adapter, WLAN_OSIF_POWER_ID); - if (!vdev) { - hdd_err("vdev is NULL"); - goto free_req; - } +skip_cache_ns: /* enable ns request */ status = ucfg_pmo_enable_ns_offload_in_fwr(vdev, trigger); if (QDF_IS_STATUS_ERROR(status)) { @@ -1313,6 +1321,12 @@ void hdd_enable_arp_offload(struct hdd_adapter *adapter, goto put_vdev; } + if (ucfg_pmo_get_arp_ns_offload_dynamic_disable(vdev)) { + hdd_debug("Dynamic arp ns offload disabled"); + ucfg_pmo_flush_arp_offload_req(vdev); + goto skip_cache_arp; + } + ifa = hdd_get_ipv4_local_interface(adapter); if (!ifa || !ifa->ifa_local) { hdd_info("IP Address is not assigned"); @@ -1328,6 +1342,7 @@ void hdd_enable_arp_offload(struct hdd_adapter *adapter, goto put_vdev; } +skip_cache_arp: status = ucfg_pmo_enable_arp_offload_in_fwr(vdev, trigger); if (QDF_IS_STATUS_ERROR(status)) { hdd_err("failed arp offload config in fw; status:%d", status);