diff --git a/components/pmo/core/inc/wlan_pmo_arp.h b/components/pmo/core/inc/wlan_pmo_arp.h index d577cd2b8d3e..f5035b4fcc92 100644 --- a/components/pmo/core/inc/wlan_pmo_arp.h +++ b/components/pmo/core/inc/wlan_pmo_arp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 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 @@ -36,6 +36,18 @@ */ QDF_STATUS pmo_core_cache_arp_offload_req(struct pmo_arp_req *arp_req); +/** + * pmo_core_arp_check_offload(): API to check if arp offload cache/send is req + * @psoc: objmgr psoc handle + * @trigger: trigger reason + * @vdev_id: vdev id + * + * Return QDF_STATUS_SUCCESS -in case of success else return error + */ +QDF_STATUS pmo_core_arp_check_offload(struct wlan_objmgr_psoc *psoc, + enum pmo_offload_trigger trigger, + uint8_t vdev_id); + /** * pmo_core_flush_arp_offload_req() - API to flush arp req from pmo vdev ctx * @vdev: objmgr vdev diff --git a/components/pmo/core/inc/wlan_pmo_ns.h b/components/pmo/core/inc/wlan_pmo_ns.h index 26662dd74969..c53d4c67bf20 100644 --- a/components/pmo/core/inc/wlan_pmo_ns.h +++ b/components/pmo/core/inc/wlan_pmo_ns.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 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 @@ -37,6 +37,18 @@ */ QDF_STATUS pmo_core_cache_ns_offload_req(struct pmo_ns_req *ns_req); +/** + * pmo_core_ns_check_offload() - API to check if offload cache/send is required + * @psoc: objmgr psoc handle + * @trigger: trigger reason enable ns offload + * @vdev_id: vdev id + * + * Return:QDF_STATUS_SUCCESS in case of success else return error + */ +QDF_STATUS pmo_core_ns_check_offload(struct wlan_objmgr_psoc *psoc, + enum pmo_offload_trigger trigger, + uint8_t vdev_id); + /** * pmo_core_flush_ns_offload_req() - API to flush ns req from pmo vdev priv ctx * @vdev: vdev objmgr handle diff --git a/components/pmo/core/src/wlan_pmo_arp.c b/components/pmo/core/src/wlan_pmo_arp.c index 43857289190a..541ce195ae0b 100644 --- a/components/pmo/core/src/wlan_pmo_arp.c +++ b/components/pmo/core/src/wlan_pmo_arp.c @@ -134,12 +134,6 @@ 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: - if (psoc_ctx->psoc_cfg.active_mode_offload) { - pmo_debug("active offload is enabled, skip in mode %d", - trigger); - status = QDF_STATUS_SUCCESS; - goto out; - } /* enable arp when active offload is false (apps suspend) */ status = pmo_tgt_enable_arp_offload_req(vdev, vdev_id); break; @@ -174,12 +168,6 @@ static QDF_STATUS pmo_core_do_disable_arp_offload(struct wlan_objmgr_vdev *vdev, switch (trigger) { case pmo_apps_resume: - if (psoc_ctx->psoc_cfg.active_mode_offload) { - pmo_debug("active offload is enabled, skip in mode: %d", - trigger); - status = QDF_STATUS_SUCCESS; - goto out; - } /* disable arp on apps resume when active offload is disable */ status = pmo_tgt_disable_arp_offload_req(vdev, vdev_id); break; @@ -222,6 +210,51 @@ static QDF_STATUS pmo_core_arp_offload_sanity( return QDF_STATUS_SUCCESS; } +QDF_STATUS pmo_core_arp_check_offload(struct wlan_objmgr_psoc *psoc, + enum pmo_offload_trigger trigger, + uint8_t vdev_id) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct pmo_psoc_priv_obj *psoc_ctx; + struct pmo_vdev_priv_obj *vdev_ctx; + struct wlan_objmgr_vdev *vdev; + bool active_offload_cond, is_applied_cond; + + pmo_enter(); + + vdev = pmo_psoc_get_vdev(psoc, 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; + + vdev_ctx = pmo_vdev_get_priv(vdev); + psoc_ctx = vdev_ctx->pmo_psoc_ctx; + + if (trigger == pmo_apps_suspend || trigger == pmo_apps_resume) { + active_offload_cond = psoc_ctx->psoc_cfg.active_mode_offload; + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + is_applied_cond = vdev_ctx->vdev_arp_req.enable && + vdev_ctx->vdev_arp_req.is_offload_applied; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + if (active_offload_cond && is_applied_cond) { + pmo_debug("active offload is enabled and offload already sent"); + pmo_vdev_put_ref(vdev); + return QDF_STATUS_E_INVAL; + } + } + pmo_vdev_put_ref(vdev); +out: + return status; +} + QDF_STATUS pmo_core_cache_arp_offload_req(struct pmo_arp_req *arp_req) { QDF_STATUS status; diff --git a/components/pmo/core/src/wlan_pmo_ns.c b/components/pmo/core/src/wlan_pmo_ns.c index 8255db3590dc..9653b87fbeb6 100644 --- a/components/pmo/core/src/wlan_pmo_ns.c +++ b/components/pmo/core/src/wlan_pmo_ns.c @@ -170,11 +170,6 @@ 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: - if (psoc_ctx->psoc_cfg.active_mode_offload) { - pmo_debug("active offload is enabled, skip in mode: %d", - trigger); - goto out; - } /* enable arp when active offload is false (apps suspend) */ status = pmo_tgt_enable_ns_offload_req(vdev, vdev_id); break; @@ -211,12 +206,6 @@ 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: - if (psoc_ctx->psoc_cfg.active_mode_offload) { - pmo_debug("active offload is enabled, skip in mode: %d", - trigger); - goto out; - } - /* config arp/ns when active offload is disable */ status = pmo_tgt_disable_ns_offload_req(vdev, vdev_id); break; default: @@ -259,8 +248,52 @@ static QDF_STATUS pmo_core_ns_offload_sanity(struct wlan_objmgr_vdev *vdev) return QDF_STATUS_SUCCESS; } -QDF_STATUS pmo_core_cache_ns_offload_req( - struct pmo_ns_req *ns_req) +QDF_STATUS pmo_core_ns_check_offload(struct wlan_objmgr_psoc *psoc, + enum pmo_offload_trigger trigger, + uint8_t vdev_id) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct pmo_psoc_priv_obj *psoc_ctx; + struct pmo_vdev_priv_obj *vdev_ctx; + struct wlan_objmgr_vdev *vdev; + bool active_offload_cond, is_applied_cond; + + pmo_enter(); + + vdev = pmo_psoc_get_vdev(psoc, 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; + + vdev_ctx = pmo_vdev_get_priv(vdev); + psoc_ctx = vdev_ctx->pmo_psoc_ctx; + + if (trigger == pmo_apps_suspend || trigger == pmo_apps_resume) { + active_offload_cond = psoc_ctx->psoc_cfg.active_mode_offload; + + qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock); + is_applied_cond = vdev_ctx->vdev_ns_req.enable && + vdev_ctx->vdev_ns_req.is_offload_applied; + qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock); + + if (active_offload_cond && is_applied_cond) { + pmo_debug("active offload is enabled and offload already sent"); + pmo_vdev_put_ref(vdev); + return QDF_STATUS_E_INVAL; + } + } + pmo_vdev_put_ref(vdev); +out: + return status; +} + +QDF_STATUS pmo_core_cache_ns_offload_req(struct pmo_ns_req *ns_req) { QDF_STATUS status; struct wlan_objmgr_vdev *vdev; diff --git a/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h b/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h index 1042c4a7df90..7c91c1c8c147 100644 --- a/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h +++ b/components/pmo/dispatcher/inc/wlan_pmo_ucfg_api.h @@ -290,6 +290,18 @@ void ucfg_pmo_disable_wakeup_event(struct wlan_objmgr_psoc *psoc, */ QDF_STATUS ucfg_pmo_cache_arp_offload_req(struct pmo_arp_req *arp_req); +/** + * ucfg_pmo_check_arp_offload(): API to check if arp offload cache/send is req + * @psoc: objmgr psoc handle + * @trigger: trigger reason + * @vdev_id: vdev_id + * + * Return QDF_STATUS -in case of success else return error + */ +QDF_STATUS ucfg_pmo_check_arp_offload(struct wlan_objmgr_psoc *psoc, + enum pmo_offload_trigger trigger, + uint8_t vdev_id); + /** * ucfg_pmo_flush_arp_offload_req(): API to flush arp req from pmo vdev priv ctx * @vdev: objmgr vdev param @@ -342,6 +354,18 @@ ucfg_pmo_get_arp_offload_params(struct wlan_objmgr_vdev *vdev, */ QDF_STATUS ucfg_pmo_cache_ns_offload_req(struct pmo_ns_req *ns_req); +/** + * ucfg_pmo_ns_offload_check(): API to check if offload cache/send is required + * @psoc: pbjmgr psoc handle + * @trigger: trigger reason to enable ns offload + * @vdev_id: vdev id + * + * Return QDF_STATUS -in case of success else return error + */ +QDF_STATUS ucfg_pmo_ns_offload_check(struct wlan_objmgr_psoc *psoc, + enum pmo_offload_trigger trigger, + uint8_t vdev_id); + /** * ucfg_pmo_flush_ns_offload_req(): API to flush ns req from pmo vdev priv ctx * @vdev: vdev ojbmgr handle @@ -1171,6 +1195,14 @@ ucfg_pmo_cache_arp_offload_req(struct pmo_arp_req *arp_req) return QDF_STATUS_SUCCESS; } +static inline +QDF_STATUS ucfg_pmo_check_arp_offload(struct wlan_objmgr_psoc *psoc, + enum pmo_offload_trigger trigger, + uint8_t vdev_id) +{ + return QDF_STATUS_SUCCESS; +} + static inline QDF_STATUS ucfg_pmo_flush_arp_offload_req(struct wlan_objmgr_vdev *vdev) { @@ -1206,6 +1238,13 @@ ucfg_pmo_cache_ns_offload_req(struct pmo_ns_req *ns_req) return QDF_STATUS_SUCCESS; } +QDF_STATUS ucfg_pmo_ns_offload_check(struct wlan_objmgr_psoc *psoc, + enum pmo_offload_trigger trigger, + uint8_t vdev_id) +{ + return QDF_STATUS_SUCCESS; +} + static inline QDF_STATUS ucfg_pmo_flush_ns_offload_req(struct wlan_objmgr_vdev *vdev) { diff --git a/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c b/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c index d4c9b027d1cb..43ef27b79f44 100644 --- a/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c +++ b/components/pmo/dispatcher/src/wlan_pmo_ucfg_api.c @@ -129,6 +129,13 @@ QDF_STATUS ucfg_pmo_cache_arp_offload_req(struct pmo_arp_req *arp_req) return pmo_core_cache_arp_offload_req(arp_req); } +QDF_STATUS ucfg_pmo_check_arp_offload(struct wlan_objmgr_psoc *psoc, + enum pmo_offload_trigger trigger, + uint8_t vdev_id) +{ + return pmo_core_arp_check_offload(psoc, trigger, vdev_id); +} + QDF_STATUS ucfg_pmo_flush_arp_offload_req(struct wlan_objmgr_vdev *vdev) { return pmo_core_flush_arp_offload_req(vdev); @@ -160,6 +167,13 @@ QDF_STATUS ucfg_pmo_cache_ns_offload_req(struct pmo_ns_req *ns_req) return pmo_core_cache_ns_offload_req(ns_req); } +QDF_STATUS ucfg_pmo_ns_offload_check(struct wlan_objmgr_psoc *psoc, + enum pmo_offload_trigger trigger, + uint8_t vdev_id) +{ + return pmo_core_ns_check_offload(psoc, trigger, vdev_id); +} + QDF_STATUS ucfg_pmo_flush_ns_offload_req(struct wlan_objmgr_vdev *vdev) { return pmo_core_flush_ns_offload_req(vdev); diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 4bfb2a80d979..8260495c72ad 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -403,6 +403,13 @@ void hdd_enable_ns_offload(struct hdd_adapter *adapter, ns_req->trigger = trigger; ns_req->count = 0; + /* 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_info("NS offload is not required"); + goto free_req; + } + /* Unicast Addresses */ errno = hdd_fill_ipv6_uc_addr(in6_dev, ns_req->ipv6_addr, ns_req->ipv6_addr_type, ns_req->scope, @@ -450,8 +457,17 @@ void hdd_disable_ns_offload(struct hdd_adapter *adapter, enum pmo_offload_trigger trigger) { QDF_STATUS status; + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); hdd_enter(); + + status = ucfg_pmo_ns_offload_check(hdd_ctx->psoc, trigger, + adapter->vdev_id); + if (status != QDF_STATUS_SUCCESS) { + hdd_err("Flushing of NS offload not required"); + goto out; + } + status = ucfg_pmo_flush_ns_offload_req(adapter->vdev); if (status != QDF_STATUS_SUCCESS) { hdd_err("Failed to flush NS Offload"); @@ -938,6 +954,12 @@ void hdd_enable_arp_offload(struct hdd_adapter *adapter, arp_req->vdev_id = adapter->vdev_id; arp_req->trigger = trigger; + status = ucfg_pmo_check_arp_offload(psoc, trigger, adapter->vdev_id); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_info("ARP offload not required"); + goto free_req; + } + ifa = hdd_get_ipv4_local_interface(adapter); if (!ifa || !ifa->ifa_local) { hdd_info("IP Address is not assigned"); @@ -972,8 +994,17 @@ void hdd_disable_arp_offload(struct hdd_adapter *adapter, enum pmo_offload_trigger trigger) { QDF_STATUS status; + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); hdd_enter(); + + status = ucfg_pmo_check_arp_offload(hdd_ctx->psoc, trigger, + adapter->vdev_id); + if (status != QDF_STATUS_SUCCESS) { + hdd_err("Flushing of ARP offload not required"); + goto out; + } + status = ucfg_pmo_flush_arp_offload_req(adapter->vdev); if (status != QDF_STATUS_SUCCESS) { hdd_err("Failed to flush arp Offload");