qcacld-3.0: Add Support to offload icmp feature to fw

Add support to offload icmp feature to fw in case of
suspended state to avoid high power consumption.

Change-Id: I3ff19d71eac530c75be57e6b52b975e755ff2a53
CRs-Fixed: 3042452
This commit is contained in:
Aditya Kodukula
2021-09-07 23:30:16 -07:00
committed by Madan Koyyalamudi
parent 29adcfaef4
commit 37026bc3ff
16 changed files with 530 additions and 3 deletions

8
Kbuild
View File

@@ -1331,6 +1331,11 @@ PMO_OBJS += $(PMO_DIR)/core/src/wlan_pmo_ns.o \
$(PMO_DIR)/dispatcher/src/wlan_pmo_tgt_ns.o
endif
ifeq ($(CONFIG_WLAN_FEATURE_ICMP_OFFLOAD), y)
PMO_OBJS += $(PMO_DIR)/core/src/wlan_pmo_icmp.o \
$(PMO_DIR)/dispatcher/src/wlan_pmo_tgt_icmp.o
endif
$(call add-wlan-objs,pmo,$(PMO_OBJS))
########## DISA (ENCRYPTION TEST) ##########
@@ -1625,6 +1630,9 @@ endif
ifeq ($(CONFIG_WLAN_FEATURE_PACKET_FILTERING), y)
CLD_TARGET_IF_OBJ += $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_pkt_filter.o
endif
ifeq ($(CONFIG_WLAN_FEATURE_ICMP_OFFLOAD), y)
CLD_TARGET_IF_OBJ += $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_icmp.o
endif
endif
ifeq ($(CONFIG_WLAN_FEATURE_DSRC), y)

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 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 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 icmp offload feature API's
*/
#ifndef _WLAN_PMO_ICMP_H_
#define _WLAN_PMO_ICMP_H_
#ifdef WLAN_POWER_MANAGEMENT_OFFLOAD
#include "wlan_pmo_obj_mgmt_public_struct.h"
/**
* pmo_core_icmp_check_offload(): API to check if icmp offload is enabled
* @psoc: objmgr psoc handle
* @vdev_id: vdev id
*
* Return: QDF_STATUS_SUCCESS for success or error code
*/
QDF_STATUS pmo_core_icmp_check_offload(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id);
#endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */
#endif /* end of _WLAN_PMO_ICMP_H_ */

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 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 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 icmp offload feature API's
*/
#include "wlan_pmo_icmp.h"
#include "wlan_pmo_main.h"
#include "wlan_pmo_obj_mgmt_public_struct.h"
QDF_STATUS pmo_core_icmp_check_offload(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct wlan_objmgr_vdev *vdev;
enum QDF_OPMODE opmode;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_PMO_ID);
if (!vdev) {
pmo_err("vdev is NULL. vdev_id is %d", vdev_id);
return QDF_STATUS_E_INVAL;
}
opmode = pmo_get_vdev_opmode(vdev);
if (opmode != QDF_STA_MODE) {
pmo_debug("ICMP offload is supported in STA mode only");
status = QDF_STATUS_E_INVAL;
goto out;
}
out:
wlan_objmgr_vdev_release_ref(vdev, WLAN_PMO_ID);
return status;
}

View File

@@ -26,6 +26,7 @@
#include "cfg_ucfg_api.h"
#include "wlan_fwol_ucfg_api.h"
#include "wlan_ipa_obj_mgmt_api.h"
#include "wlan_pmo_icmp.h"
static struct wlan_pmo_ctx *gp_pmo_ctx;
@@ -218,6 +219,21 @@ wlan_pmo_get_igmp_offload_enable_cfg(struct wlan_objmgr_psoc *psoc,
{}
#endif
#ifdef WLAN_FEATURE_ICMP_OFFLOAD
static void
wlan_pmo_get_icmp_offload_enable_cfg(struct wlan_objmgr_psoc *psoc,
struct pmo_psoc_cfg *psoc_cfg)
{
psoc_cfg->is_icmp_offload_enable =
cfg_get(psoc, CFG_ENABLE_ICMP_OFFLOAD);
}
#else
static inline void
wlan_pmo_get_icmp_offload_enable_cfg(struct wlan_objmgr_psoc *psoc,
struct pmo_psoc_cfg *psoc_cfg)
{}
#endif
static void wlan_pmo_init_cfg(struct wlan_objmgr_psoc *psoc,
struct pmo_psoc_cfg *psoc_cfg)
{
@@ -275,8 +291,7 @@ static void wlan_pmo_init_cfg(struct wlan_objmgr_psoc *psoc,
wlan_pmo_get_igmp_offload_enable_cfg(psoc, psoc_cfg);
psoc_cfg->disconnect_sap_tdls_in_wow =
cfg_get(psoc, CFG_DISCONNECT_SAP_TDLS_IN_WOW);
psoc_cfg->is_icmp_offload_enable =
cfg_get(psoc, CFG_ENABLE_ICMP_OFFLOAD);
wlan_pmo_get_icmp_offload_enable_cfg(psoc, psoc_cfg);
}
QDF_STATUS pmo_psoc_open(struct wlan_objmgr_psoc *psoc)

View File

@@ -603,6 +603,8 @@
* This ini is used to enable/disable firmware's capability of sending ICMP
* response to clients.
*
* Supported Feature: STA
*
* Usage: External
*
* </ini>

View File

@@ -285,6 +285,30 @@ enum pmo_gpio_wakeup_mode {
PMO_GPIO_WAKEUP_MODE_LOW,
};
#ifdef WLAN_FEATURE_ICMP_OFFLOAD
#define ICMP_MAX_IPV6_ADDRESS 16
/**
* pmo_icmp_offload - structure to hold icmp param
*
* @vdev_id: vdev id
* @enable: enable/disable
* @trigger: icmp offload trigger information
* @ipv6_count: number of host ipv6 address
* @ipv4_addr: host interface ipv4 address
* @ipv6_addr: array of host ipv6 address
*
**/
struct pmo_icmp_offload {
uint8_t vdev_id;
bool enable;
enum pmo_offload_trigger trigger;
uint8_t ipv6_count;
uint8_t ipv4_addr[QDF_IPV4_ADDR_SIZE];
uint8_t ipv6_addr[ICMP_MAX_IPV6_ADDRESS][QDF_IPV6_ADDR_SIZE];
};
#endif
/**
* struct pmo_psoc_cfg - user configuration required for pmo
* @ptrn_match_enable_all_vdev: true when pattern match is enable for all vdev
@@ -429,7 +453,9 @@ struct pmo_psoc_cfg {
bool igmp_offload_enable;
#endif
bool disconnect_sap_tdls_in_wow;
#ifdef WLAN_FEATURE_ICMP_OFFLOAD
bool is_icmp_offload_enable;
#endif
};
/**

View File

@@ -123,6 +123,7 @@ typedef int (*pmo_pld_auto_resume_cb)(void);
* @psoc_send_d0wow_disable_req: fp to send D0 WOW disable request
* @psoc_send_idle_roam_suspend_mode: fp to send suspend mode for
* idle roam trigger to firmware.
* @send_icmp_offload_req: fp to send icmp offload request
*/
struct wlan_pmo_tx_ops {
QDF_STATUS (*send_arp_offload_req)(struct wlan_objmgr_vdev *vdev,
@@ -233,7 +234,11 @@ struct wlan_pmo_tx_ops {
struct wlan_objmgr_psoc *psoc);
QDF_STATUS (*psoc_send_idle_roam_suspend_mode)(
struct wlan_objmgr_psoc *psoc, uint8_t val);
#ifdef WLAN_FEATURE_ICMP_OFFLOAD
QDF_STATUS (*send_icmp_offload_req)(
struct wlan_objmgr_psoc *psoc,
struct pmo_icmp_offload *pmo_icmp_req);
#endif
};
#endif /* end of _WLAN_PMO_OBJ_MGMT_PUBLIC_STRUCT_H_ */

View File

@@ -486,4 +486,16 @@ QDF_STATUS pmo_tgt_psoc_send_target_resume_req(struct wlan_objmgr_psoc *psoc);
QDF_STATUS pmo_tgt_psoc_send_idle_roam_monitor(struct wlan_objmgr_psoc *psoc,
uint8_t val);
#ifdef WLAN_FEATURE_ICMP_OFFLOAD
/**
* pmo_tgt_config_icmp_offload_req() - Configure icmp offload req to target
* @psoc: objmgr psoc
* @pmo_icmp_req: ICMP offload parameters
*
* Return: QDF status
*/
QDF_STATUS
pmo_tgt_config_icmp_offload_req(struct wlan_objmgr_psoc *psoc,
struct pmo_icmp_offload *pmo_icmp_req);
#endif
#endif /* end of _WLAN_PMO_TGT_API_H_ */

View File

@@ -1284,6 +1284,37 @@ uint32_t ucfg_pmo_get_moddtim_user(struct wlan_objmgr_vdev *vdev);
*/
bool
ucfg_pmo_get_disconnect_sap_tdls_in_wow(struct wlan_objmgr_psoc *psoc);
#ifdef WLAN_FEATURE_ICMP_OFFLOAD
/**
* ucfg_pmo_check_icmp_offload(): API to check if icmp offload is enabled
* @psoc: objmgr psoc handle
* @vdev_id: vdev_id
*
* Return: QDF_STATUS_SUCCESS for success or error code
*/
QDF_STATUS ucfg_pmo_check_icmp_offload(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id);
/**
* ucfg_pmo_is_icmp_offload_enabled() - Get icmp offload enable or not
* @psoc: pointer to psoc object
*
* Return: icmp offload enable or not
*/
bool
ucfg_pmo_is_icmp_offload_enabled(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_pmo_config_icmp_offload() - API to enable icmp offload request
* @psoc: pointer to psoc object
* @pmo_icmp_req: ICMP offload parameters
*
* Return: QDF_STATUS_SUCCESS for success or error code
*/
QDF_STATUS
ucfg_pmo_config_icmp_offload(struct wlan_objmgr_psoc *psoc,
struct pmo_icmp_offload *pmo_icmp_req);
#endif
#else /* WLAN_POWER_MANAGEMENT_OFFLOAD */
static inline QDF_STATUS
ucfg_pmo_psoc_open(struct wlan_objmgr_psoc *psoc)
@@ -1992,6 +2023,26 @@ ucfg_pmo_get_disconnect_sap_tdls_in_wow(struct wlan_objmgr_psoc *psoc)
{
return false;
}
static inline
QDF_STATUS ucfg_pmo_check_icmp_offload(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id)
{
return QDF_STATUS_SUCCESS;
}
static inline bool
ucfg_pmo_is_icmp_offload_enabled(struct wlan_objmgr_psoc *psoc)
{
return false;
}
QDF_STATUS
ucfg_pmo_config_icmp_offload(struct wlan_objmgr_psoc *psoc,
struct pmo_icmp_offload *pmo_icmp_req)
{
return QDF_STATUS_SUCCESS;
}
#endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */
#ifdef WLAN_FEATURE_EXTWOW_SUPPORT

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 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 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_obj_mgmt_public_struct.h"
#include "wlan_pmo_main.h"
QDF_STATUS
pmo_tgt_config_icmp_offload_req(struct wlan_objmgr_psoc *psoc,
struct pmo_icmp_offload *pmo_icmp_req)
{
QDF_STATUS status;
struct wlan_pmo_tx_ops pmo_tx_ops;
pmo_debug("vdev_id: %d: ICMP offload %d", pmo_icmp_req->vdev_id,
pmo_icmp_req->enable);
pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
if (!pmo_tx_ops.send_icmp_offload_req) {
pmo_err("send_icmp_offload_req is null");
status = QDF_STATUS_E_NULL_VALUE;
return status;
}
status = pmo_tx_ops.send_icmp_offload_req(psoc, pmo_icmp_req);
return status;
}

View File

@@ -34,6 +34,7 @@
#include "wlan_pmo_cfg.h"
#include "wlan_pmo_static_config.h"
#include "cfg_ucfg_api.h"
#include "wlan_pmo_icmp.h"
QDF_STATUS ucfg_pmo_psoc_open(struct wlan_objmgr_psoc *psoc)
{
@@ -1000,3 +1001,25 @@ ucfg_pmo_get_disconnect_sap_tdls_in_wow(struct wlan_objmgr_psoc *psoc)
return pmo_psoc_ctx->psoc_cfg.disconnect_sap_tdls_in_wow;
}
#ifdef WLAN_FEATURE_ICMP_OFFLOAD
QDF_STATUS ucfg_pmo_check_icmp_offload(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id)
{
return pmo_core_icmp_check_offload(psoc, vdev_id);
}
bool
ucfg_pmo_is_icmp_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.is_icmp_offload_enable;
}
QDF_STATUS ucfg_pmo_config_icmp_offload(struct wlan_objmgr_psoc *psoc,
struct pmo_icmp_offload *pmo_icmp_req)
{
return pmo_tgt_config_icmp_offload_req(psoc, pmo_icmp_req);
}
#endif

View File

@@ -522,5 +522,19 @@ target_if_pmo_psoc_send_idle_monitor_cmd(struct wlan_objmgr_psoc *psoc,
*/
void target_if_pmo_register_tx_ops(struct wlan_pmo_tx_ops *tx_ops);
#ifdef WLAN_FEATURE_ICMP_OFFLOAD
/**
* target_if_pmo_send_icmp_offload_req() - sends icmp request to fwr
* @psoc: objmgr psoc
* @pmo_icmp_req: icmp offload request
*
* This functions sends icmp request to fwr.
*
* Return: QDF_STATUS_SUCCESS for success or error code
*/
QDF_STATUS
target_if_pmo_send_icmp_offload_req(struct wlan_objmgr_psoc *psoc,
struct pmo_icmp_offload *pmo_icmp_req);
#endif
#endif

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 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 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_icmp.c
*
* Target interface file for pmo component to
* send icmp 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_icmp_offload_req(struct wlan_objmgr_psoc *psoc,
struct pmo_icmp_offload *pmo_icmp_req)
{
QDF_STATUS status;
wmi_unified_t wmi_handle;
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;
}
status = wmi_unified_config_icmp_offload_cmd(wmi_handle, pmo_icmp_req);
return status;
}

View File

@@ -23,6 +23,7 @@
#include "target_if_pmo.h"
#include "wlan_pmo_common_public_struct.h"
#include "wlan_pmo_icmp.h"
#ifdef WLAN_FEATURE_PACKET_FILTERING
static inline
@@ -51,6 +52,17 @@ static inline void
update_pmo_igmp_tx_ops(struct wlan_pmo_tx_ops *pmo_tx_ops)
{}
#endif
#ifdef WLAN_FEATURE_ICMP_OFFLOAD
static void tgt_if_pmo_icmp_tx_ops(struct wlan_pmo_tx_ops *pmo_tx_ops)
{
pmo_tx_ops->send_icmp_offload_req =
target_if_pmo_send_icmp_offload_req;
}
#else
static inline void
tgt_if_pmo_icmp_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) {
@@ -138,5 +150,6 @@ void target_if_pmo_register_tx_ops(struct wlan_pmo_tx_ops *pmo_tx_ops)
pmo_tx_ops->psoc_send_idle_roam_suspend_mode =
target_if_pmo_psoc_send_idle_monitor_cmd;
tgt_if_pmo_reg_pkt_filter_ops(pmo_tx_ops);
tgt_if_pmo_icmp_tx_ops(pmo_tx_ops);
}

View File

@@ -636,4 +636,22 @@ QDF_STATUS wlan_hdd_get_ani_level(struct hdd_adapter *adapter,
uint32_t *parsed_freqs,
uint8_t num_freqs);
#endif /* FEATURE_ANI_LEVEL_REQUEST */
#ifdef WLAN_FEATURE_ICMP_OFFLOAD
/**
* hdd_enable_icmp_offload() - API to enable ICMP offload
* @adapter: Adapter context for which ICMP offload is to be configured
* @trigger: trigger reason for request
*
* Return: None
*/
void hdd_enable_icmp_offload(struct hdd_adapter *adapter,
enum pmo_offload_trigger trigger);
#else
static inline
void hdd_enable_icmp_offload(struct hdd_adapter *adapter,
enum pmo_offload_trigger trigger)
{}
#endif /* FEATURE_ICMP_OFFLOAD */
#endif /* __WLAN_HDD_POWER_H */

View File

@@ -724,6 +724,7 @@ static void __hdd_ipv6_notifier_work_queue(struct hdd_adapter *adapter)
goto exit;
hdd_enable_ns_offload(adapter, pmo_ipv6_change_notify);
hdd_enable_icmp_offload(adapter, pmo_ipv6_change_notify);
hdd_send_ps_config_to_fw(adapter);
exit:
@@ -1070,6 +1071,7 @@ static void __hdd_ipv4_notifier_work_queue(struct hdd_adapter *adapter)
goto exit;
hdd_enable_arp_offload(adapter, pmo_ipv4_change_notify);
hdd_enable_icmp_offload(adapter, pmo_ipv4_change_notify);
status = ucfg_mlme_get_sta_keepalive_method(hdd_ctx->psoc, &val);
if (QDF_IS_STATUS_ERROR(status))
@@ -1340,6 +1342,161 @@ free_req:
qdf_mem_free(arp_req);
}
#ifdef WLAN_FEATURE_ICMP_OFFLOAD
/**
* hdd_fill_ipv4_addr() - fill IPv4 addresses
* @adapter: Adapter context for which ICMP offload is to be configured
* @pmo_icmp_req: pointer to ICMP offload request params
*
* This is the IPv4 utility function to populate address.
*
* Return: 0 on success, error number otherwise.
*/
static int hdd_fill_ipv4_addr(struct hdd_adapter *adapter,
struct pmo_icmp_offload *pmo_icmp_req)
{
struct in_ifaddr *ifa;
uint8_t ipv4_addr_array[QDF_IPV4_ADDR_SIZE];
int i;
ifa = hdd_get_ipv4_local_interface(adapter);
if (!ifa || !ifa->ifa_local) {
hdd_debug("IP Address is not assigned");
return -EINVAL;
}
/* converting u32 to IPv4 address */
for (i = 0; i < QDF_IPV4_ADDR_SIZE; i++)
ipv4_addr_array[i] = (ifa->ifa_local >> i * 8) & 0xff;
qdf_mem_copy(pmo_icmp_req->ipv4_addr, &ipv4_addr_array,
QDF_IPV4_ADDR_SIZE);
return 0;
}
/**
* hdd_fill_ipv6_addr() - fill IPv6 addresses
* @adapter: Adapter context for which ICMP offload is to be configured
* @pmo_icmp_req: pointer to ICMP offload request params
*
* This is the IPv6 utility function to populate addresses.
*
* Return: 0 on success, error number otherwise.
*/
static int hdd_fill_ipv6_addr(struct hdd_adapter *adapter,
struct pmo_icmp_offload *pmo_icmp_req)
{
struct inet6_dev *in6_dev;
struct pmo_ns_req *ns_req;
int i, errno;
in6_dev = __in6_dev_get(adapter->dev);
if (!in6_dev) {
hdd_err_rl("IPv6 dev does not exist");
return -EINVAL;
}
ns_req = qdf_mem_malloc(sizeof(*ns_req));
if (!ns_req)
return -ENOMEM;
ns_req->count = 0;
/* Unicast Addresses */
errno = hdd_fill_ipv6_uc_addr(in6_dev, ns_req->ipv6_addr,
ns_req->ipv6_addr_type, ns_req->scope,
&ns_req->count);
if (errno) {
hdd_debug("Reached Max IPv6 supported address %d",
ns_req->count);
goto free_req;
}
/* Anycast Addresses */
errno = hdd_fill_ipv6_ac_addr(in6_dev, ns_req->ipv6_addr,
ns_req->ipv6_addr_type, ns_req->scope,
&ns_req->count);
if (errno) {
hdd_debug("Reached Max IPv6 supported address %d",
ns_req->count);
goto free_req;
}
pmo_icmp_req->ipv6_count = ns_req->count;
for (i = 0; i < pmo_icmp_req->ipv6_count; i++) {
qdf_mem_copy(&pmo_icmp_req->ipv6_addr[i], &ns_req->ipv6_addr[i],
QDF_IPV6_ADDR_SIZE);
}
free_req:
qdf_mem_free(ns_req);
return errno;
}
void hdd_enable_icmp_offload(struct hdd_adapter *adapter,
enum pmo_offload_trigger trigger)
{
struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
struct pmo_icmp_offload *pmo_icmp_req;
struct wlan_objmgr_vdev *vdev;
bool is_icmp_enable;
QDF_STATUS status;
is_icmp_enable = ucfg_pmo_is_icmp_offload_enabled(psoc);
if (!is_icmp_enable) {
hdd_debug("ICMP Offload not enabled");
return;
}
pmo_icmp_req = qdf_mem_malloc(sizeof(*pmo_icmp_req));
if (!pmo_icmp_req)
return;
vdev = hdd_objmgr_get_vdev_by_user(adapter, WLAN_OSIF_POWER_ID);
if (!vdev) {
hdd_err("vdev is NULL");
goto free_req;
}
status = ucfg_pmo_check_icmp_offload(psoc, adapter->vdev_id);
if (QDF_IS_STATUS_ERROR(status))
goto put_vdev;
pmo_icmp_req->vdev_id = adapter->vdev_id;
pmo_icmp_req->enable = is_icmp_enable;
pmo_icmp_req->trigger = trigger;
switch (trigger) {
case pmo_ipv4_change_notify:
if (hdd_fill_ipv4_addr(adapter, pmo_icmp_req)) {
hdd_debug("Unable to populate IPv4 Address");
goto put_vdev;
}
break;
case pmo_ipv6_change_notify:
if (hdd_fill_ipv6_addr(adapter, pmo_icmp_req)) {
hdd_debug("Unable to populate IPv6 Address");
goto put_vdev;
}
break;
default:
QDF_DEBUG_PANIC("The trigger %d is not supported", trigger);
goto put_vdev;
}
status = ucfg_pmo_config_icmp_offload(psoc, pmo_icmp_req);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err_rl("icmp offload config in fw failed: %d", status);
goto put_vdev;
}
put_vdev:
hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
free_req:
qdf_mem_free(pmo_icmp_req);
}
#endif
void hdd_disable_arp_offload(struct hdd_adapter *adapter,
enum pmo_offload_trigger trigger)
{