summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnurag Chouhan <achouhan@codeaurora.org>2017-02-23 20:43:24 +0530
committerSandeep Puligilla <spuligil@codeaurora.org>2017-03-15 08:40:14 -0700
commite8611a91f1a32606ff764601a0b82101ea4e8d6e (patch)
tree8d6492a4d4ce41e6db8a75cda3ab6311e57c4eaf
parent246097a6aac6cc9d4e9a99bf03b575a3321af609 (diff)
qcacld-3.0: Add Vendor command to set/get NUD debug stats
Add vendor commands to set/reset and get NUD debug stats from firmware. Change-Id: I773c04bb3f7c6d5ed28528cf2174b3d63de57d98 CRs-Fixed: 2011456
-rw-r--r--core/hdd/inc/wlan_hdd_main.h45
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.c311
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.h72
-rw-r--r--core/hdd/src/wlan_hdd_main.c66
-rw-r--r--core/mac/inc/sir_api.h46
-rw-r--r--core/mac/src/include/sir_params.h4
-rw-r--r--core/sme/inc/sme_api.h10
-rw-r--r--core/sme/inc/sme_internal.h1
-rw-r--r--core/sme/src/common/sme_api.c108
-rw-r--r--core/wma/inc/wma_internal.h2
-rw-r--r--core/wma/inc/wma_types.h2
-rw-r--r--core/wma/src/wma_features.c62
-rw-r--r--core/wma/src/wma_main.c59
13 files changed, 786 insertions, 2 deletions
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index 9e8ef1dcc1db..b4e1fcbf6c9a 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -270,6 +270,13 @@
#define SCAN_REJECT_THRESHOLD_TIME 300000 /* Time is in msec, equal to 5 mins */
+/* wait time for nud stats in milliseconds */
+#define WLAN_WAIT_TIME_NUD_STATS 800
+/* nud stats skb max length */
+#define WLAN_NUD_STATS_LEN 800
+/* ARP packet type for NUD debug stats */
+#define WLAN_NUD_STATS_ARP_PKT_TYPE 1
+
/*
* @eHDD_SCAN_REJECT_DEFAULT: default value
* @eHDD_CONNECTION_IN_PROGRESS: connection is in progress
@@ -410,6 +417,20 @@ typedef struct hdd_pmf_stats_s {
} hdd_pmf_stats_t;
#endif
+struct hdd_arp_stats_s {
+ uint16_t tx_count;
+ uint16_t rx_count;
+ uint16_t tx_dropped;
+ uint16_t rx_dropped;
+ uint16_t rx_delivered;
+ uint16_t rx_refused;
+ uint16_t tx_host_fw_sent;
+ uint16_t rx_host_drop_reorder;
+ uint16_t tx_fw_cnt;
+ uint16_t rx_fw_cnt;
+ uint16_t tx_ack_cnt;
+};
+
typedef struct hdd_stats_s {
tCsrSummaryStatsInfo summary_stat;
tCsrGlobalClassAStatsInfo ClassA_stat;
@@ -419,6 +440,7 @@ typedef struct hdd_stats_s {
tCsrPerStaStatsInfo perStaStats;
struct csr_per_chain_rssi_stats_info per_chain_rssi_stats;
hdd_tx_rx_stats_t hddTxRxStats;
+ struct hdd_arp_stats_s hdd_arp_stats;
#ifdef WLAN_FEATURE_11W
hdd_pmf_stats_t hddPmfStats;
#endif
@@ -1192,6 +1214,8 @@ struct hdd_adapter_s {
*/
uint8_t cfg80211_disconnect_reason;
struct lfr_firmware_status lfr_fw_status;
+ bool con_status;
+ bool dad;
};
/*
@@ -1379,6 +1403,14 @@ struct suspend_resume_stats {
uint32_t suspend_fail[SUSPEND_FAIL_MAX_COUNT];
};
+/**
+ * struct hdd_nud_stats_context - hdd NUD stats context
+ * @response_event: NUD stats request wait event
+ */
+struct hdd_nud_stats_context {
+ struct completion response_event;
+};
+
/** Adapter structure definition */
struct hdd_context_s {
/** Global CDS context */
@@ -1662,6 +1694,7 @@ struct hdd_context_s {
uint32_t no_of_probe_req_ouis;
struct vendor_oui *probe_req_voui;
+ struct hdd_nud_stats_context nud_stats_context;
};
/*---------------------------------------------------------------------------
@@ -2119,4 +2152,16 @@ void hdd_set_roaming_in_progress(bool value);
bool hdd_check_for_opened_interfaces(hdd_context_t *hdd_ctx);
void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter, bool reinit);
void hdd_set_rx_mode_rps(hdd_context_t *hdd_ctx, void *padapter, bool enable);
+
+/**
+ * hdd_init_nud_stats_ctx() - initialize NUD stats context
+ * @hdd_ctx: Pointer to hdd context
+ *
+ * Return: none
+ */
+static inline void hdd_init_nud_stats_ctx(hdd_context_t *hdd_ctx)
+{
+ init_completion(&hdd_ctx->nud_stats_context.response_event);
+ return;
+}
#endif /* end #if !defined(WLAN_HDD_MAIN_H) */
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 836d6dc46582..64f99d868aed 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -1083,6 +1083,10 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] =
.vendor_id = QCA_NL80211_VENDOR_ID,
.subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
},
+ [QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX] = {
+ .vendor_id = QCA_NL80211_VENDOR_ID,
+ .subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
+ },
};
/**
@@ -8564,6 +8568,297 @@ static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
return ret;
}
+/*
+ * define short names for the global vendor params
+ * used by wlan_hdd_cfg80211_setarp_stats_cmd()
+ */
+#define STATS_SET_INVALID \
+ QCA_ATTR_NUD_STATS_SET_INVALID
+#define STATS_SET_START \
+ QCA_ATTR_NUD_STATS_SET_START
+#define STATS_GW_IPV4 \
+ QCA_ATTR_NUD_STATS_GW_IPV4
+#define STATS_SET_MAX \
+ QCA_ATTR_NUD_STATS_SET_MAX
+
+const struct nla_policy
+qca_wlan_vendor_set_nud_stats[STATS_SET_MAX + 1] = {
+ [STATS_SET_START] = {.type = NLA_FLAG },
+ [STATS_GW_IPV4] = {.type = NLA_U32 },
+};
+
+/**
+ * __wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
+ * @wiphy: pointer to wireless wiphy structure.
+ * @wdev: pointer to wireless_dev structure.
+ * @data: pointer to apfind configuration data.
+ * @data_len: the length in byte of apfind data.
+ *
+ * This is called when wlan driver needs to send arp stats to
+ * firmware.
+ *
+ * Return: An error code or 0 on success.
+ */
+static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct nlattr *tb[STATS_SET_MAX + 1];
+ struct net_device *dev = wdev->netdev;
+ hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
+ struct set_arp_stats_params arp_stats_params;
+ int err = 0;
+
+ ENTER();
+
+ err = wlan_hdd_validate_context(hdd_ctx);
+ if (0 != err)
+ return err;
+
+ err = nla_parse(tb, STATS_SET_MAX, data, data_len,
+ qca_wlan_vendor_set_nud_stats);
+ if (err) {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+ "%s STATS_SET_START ATTR", __func__);
+ return err;
+ }
+
+ if (tb[STATS_SET_START]) {
+ if (!tb[STATS_GW_IPV4]) {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+ "%s STATS_SET_START CMD", __func__);
+ return -EINVAL;
+ }
+ arp_stats_params.flag = true;
+ arp_stats_params.ip_addr = nla_get_u32(tb[STATS_GW_IPV4]);
+ } else {
+ arp_stats_params.flag = false;
+ }
+ if (arp_stats_params.flag) {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
+ "%s STATS_SET_START Cleared!!", __func__);
+ qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
+ sizeof(adapter->hdd_stats.hdd_arp_stats));
+ }
+
+ arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
+ arp_stats_params.vdev_id = adapter->sessionId;
+
+ if (QDF_STATUS_SUCCESS !=
+ sme_set_nud_debug_stats(hdd_ctx->hHal, &arp_stats_params)) {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+ "%s STATS_SET_START CMD Failed!!", __func__);
+ return -EINVAL;
+ }
+
+ EXIT();
+
+ return err;
+}
+
+/**
+ * wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
+ * @wiphy: pointer to wireless wiphy structure.
+ * @wdev: pointer to wireless_dev structure.
+ * @data: pointer to apfind configuration data.
+ * @data_len: the length in byte of apfind data.
+ *
+ * This is called when wlan driver needs to send arp stats to
+ * firmware.
+ *
+ * Return: An error code or 0 on success.
+ */
+static int wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ int ret;
+
+ cds_ssr_protect(__func__);
+ ret = __wlan_hdd_cfg80211_set_nud_stats(wiphy, wdev, data, data_len);
+ cds_ssr_unprotect(__func__);
+
+ return ret;
+}
+
+#undef STATS_SET_INVALID
+#undef STATS_SET_START
+#undef STATS_GW_IPV4
+#undef STATS_SET_MAX
+
+/*
+ * define short names for the global vendor params
+ * used by wlan_hdd_cfg80211_setarp_stats_cmd()
+ */
+#define STATS_GET_INVALID \
+ QCA_ATTR_NUD_STATS_SET_INVALID
+#define COUNT_FROM_NETDEV \
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
+#define COUNT_TO_LOWER_MAC \
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
+#define RX_COUNT_BY_LOWER_MAC \
+ QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
+#define COUNT_TX_SUCCESS \
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
+#define RSP_RX_COUNT_BY_LOWER_MAC \
+ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
+#define RSP_RX_COUNT_BY_UPPER_MAC \
+ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
+#define RSP_COUNT_TO_NETDEV \
+ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
+#define RSP_COUNT_OUT_OF_ORDER_DROP \
+ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
+#define AP_LINK_ACTIVE \
+ QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
+#define AP_LINK_DAD \
+ QCA_ATTR_NUD_STATS_AP_LINK_DAD
+#define STATS_GET_MAX \
+ QCA_ATTR_NUD_STATS_GET_MAX
+
+const struct nla_policy
+qca_wlan_vendor_get_nud_stats[STATS_GET_MAX + 1] = {
+ [COUNT_FROM_NETDEV] = {.type = NLA_U16 },
+ [COUNT_TO_LOWER_MAC] = {.type = NLA_U16 },
+ [RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
+ [COUNT_TX_SUCCESS] = {.type = NLA_U16 },
+ [RSP_RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
+ [RSP_RX_COUNT_BY_UPPER_MAC] = {.type = NLA_U16 },
+ [RSP_COUNT_TO_NETDEV] = {.type = NLA_U16 },
+ [RSP_COUNT_OUT_OF_ORDER_DROP] = {.type = NLA_U16 },
+ [AP_LINK_ACTIVE] = {.type = NLA_FLAG },
+ [AP_LINK_DAD] = {.type = NLA_FLAG },
+};
+
+/**
+ * __wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
+ * @wiphy: pointer to wireless wiphy structure.
+ * @wdev: pointer to wireless_dev structure.
+ * @data: pointer to apfind configuration data.
+ * @data_len: the length in byte of apfind data.
+ *
+ * This is called when wlan driver needs to get arp stats to
+ * firmware.
+ *
+ * Return: An error code or 0 on success.
+ */
+static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ int err = 0;
+ unsigned long rc;
+ struct hdd_nud_stats_context *context;
+ struct net_device *dev = wdev->netdev;
+ hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
+ struct get_arp_stats_params arp_stats_params;
+ struct sk_buff *skb;
+
+ ENTER();
+
+ err = wlan_hdd_validate_context(hdd_ctx);
+ if (0 != err)
+ return err;
+
+ arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
+ arp_stats_params.vdev_id = adapter->sessionId;
+
+ spin_lock(&hdd_context_lock);
+ context = &hdd_ctx->nud_stats_context;
+ INIT_COMPLETION(context->response_event);
+ spin_unlock(&hdd_context_lock);
+
+ if (QDF_STATUS_SUCCESS !=
+ sme_get_nud_debug_stats(hdd_ctx->hHal, &arp_stats_params)) {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+ "%s STATS_SET_START CMD Failed!!", __func__);
+ return -EINVAL;
+ }
+
+ rc = wait_for_completion_timeout(&context->response_event,
+ msecs_to_jiffies(
+ WLAN_WAIT_TIME_NUD_STATS));
+ if (!rc) {
+ hdd_err("Target response timed out request ");
+ return -ETIMEDOUT;
+ }
+
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
+ WLAN_NUD_STATS_LEN);
+ if (!skb) {
+ hdd_err("%s: cfg80211_vendor_cmd_alloc_reply_skb failed",
+ __func__);
+ return -ENOMEM;
+ }
+
+ if (nla_put_u16(skb, COUNT_FROM_NETDEV,
+ adapter->hdd_stats.hdd_arp_stats.tx_count) ||
+ nla_put_u16(skb, COUNT_TO_LOWER_MAC,
+ adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
+ nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC,
+ adapter->hdd_stats.hdd_arp_stats.tx_fw_cnt) ||
+ nla_put_u16(skb, COUNT_TX_SUCCESS,
+ adapter->hdd_stats.hdd_arp_stats.tx_ack_cnt) ||
+ nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC,
+ adapter->hdd_stats.hdd_arp_stats.rx_fw_cnt) ||
+ nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC,
+ adapter->hdd_stats.hdd_arp_stats.rx_count) ||
+ nla_put_u16(skb, RSP_COUNT_TO_NETDEV,
+ adapter->hdd_stats.hdd_arp_stats.rx_delivered) ||
+ nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP,
+ adapter->hdd_stats.hdd_arp_stats.
+ rx_host_drop_reorder)) {
+ hdd_err("nla put fail");
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+ if (adapter->con_status)
+ nla_put_flag(skb, AP_LINK_ACTIVE);
+ if (adapter->dad)
+ nla_put_flag(skb, AP_LINK_DAD);
+
+ cfg80211_vendor_cmd_reply(skb);
+ return err;
+}
+
+/**
+ * wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
+ * @wiphy: pointer to wireless wiphy structure.
+ * @wdev: pointer to wireless_dev structure.
+ * @data: pointer to apfind configuration data.
+ * @data_len: the length in byte of apfind data.
+ *
+ * This is called when wlan driver needs to get arp stats to
+ * firmware.
+ *
+ * Return: An error code or 0 on success.
+ */
+static int wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ int ret;
+
+ cds_ssr_protect(__func__);
+ ret = __wlan_hdd_cfg80211_get_nud_stats(wiphy, wdev, data, data_len);
+ cds_ssr_unprotect(__func__);
+
+ return ret;
+}
+
+#undef QCA_ATTR_NUD_STATS_SET_INVALID
+#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
+#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
+#undef QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
+#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
+#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
+#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
+#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
+#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
+#undef QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
+#undef QCA_ATTR_NUD_STATS_GET_MAX
+
const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
{
.info.vendor_id = QCA_NL80211_VENDOR_ID,
@@ -9185,6 +9480,22 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
WIPHY_VENDOR_CMD_NEED_RUNNING,
.doit = wlan_hdd_cfg80211_set_sar_power_limits
},
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_NETDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wlan_hdd_cfg80211_set_nud_stats
+ },
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_NETDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wlan_hdd_cfg80211_get_nud_stats
+ },
};
/**
diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h
index c667d9b41db7..172fe7166f9d 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.h
+++ b/core/hdd/src/wlan_hdd_cfg80211.h
@@ -304,6 +304,10 @@ typedef enum {
* (SAR) power limits. A critical regulation for FCC compliance, OEMs
* require methods to set SAR limits on TX power of WLAN/WWAN.
* enum qca_vendor_attr_sar_limits attributes are used with this command.
+ * @QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET
+ * Start / Stop the NUD stats collections
+ * @QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET
+ * Get the NUD stats, represented by the enum qca_attr_nud_stats_get
*/
enum qca_nl80211_vendor_subcmds {
@@ -460,6 +464,8 @@ enum qca_nl80211_vendor_subcmds {
/* Set Specific Absorption Rate(SAR) Power Limits */
QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS = 146,
+ QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET = 149,
+ QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET = 150,
};
/**
@@ -665,6 +671,7 @@ enum qca_wlan_vendor_attr_get_station_info {
* P2P listen offload index
* @QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX: SAP
* conditional channel switch index
+ * @QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX: NUD DEBUG Stats index
*/
enum qca_nl80211_vendor_subcmds_index {
@@ -739,6 +746,71 @@ enum qca_nl80211_vendor_subcmds_index {
#endif /* WLAN_FEATURE_NAN_DATAPATH */
QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX,
+ QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX,
+};
+
+/**
+ * enum qca_attr_nud_stats_set - attribute to vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET. This carry the requisite
+ * information to start / stop the NUD stats collection.
+ * @QCA_ATTR_NUD_STATS_SET_START: set nud debug stats
+ * Flag to Start / Stop the NUD stats collection
+ * Start - If included , Stop - If not included
+ * @QCA_ATTR_NUD_STATS_GW_IPV4: set gatway ipv4 address
+ * IPv4 address of Default Gateway (in network byte order)
+ */
+enum qca_attr_nud_stats_set {
+ QCA_ATTR_NUD_STATS_SET_INVALID = 0,
+ QCA_ATTR_NUD_STATS_SET_START = 1,
+ QCA_ATTR_NUD_STATS_GW_IPV4 = 2,
+ /* keep last */
+ QCA_ATTR_NUD_STATS_SET_LAST,
+ QCA_ATTR_NUD_STATS_SET_MAX =
+ QCA_ATTR_NUD_STATS_SET_LAST - 1,
+};
+
+/**
+ * enum qca_attr_nud_stats_get - attribute to vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET. This carry the requisite
+ * NUD stats collected when queried.
+ * @QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV: ARP Request Count from net
+ * dev
+ * @QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC: ARP Request Count sent
+ * to lower MAC from upper MAC
+ * @QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC: ARP Request Count
+ * received by lower MAC from upper MAC
+ * @QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS: ARP Request Count successfully
+ * transmitted by the device
+ * @QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC: ARP Response Count
+ * received by lower MAC
+ * @QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC: ARP Response Count
+ * received by upper MAC
+ * @QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV: ARP Response Count delivered
+ * to netdev
+ * @QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP: ARP Response Count
+ * delivered to netdev
+ * @QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE: Flag indicating if the Stations
+ * Link to AP is active.
+ * Active Link - If exists, Inactive link - If not included
+ * @QCA_ATTR_NUD_STATS_AP_LINK_DAD: Flag indicating if the Stations
+ * Duplicate Address detected.
+ */
+enum qca_attr_nud_stats_get {
+ QCA_ATTR_NUD_STATS_GET_INVALID = 0,
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV = 1,
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC = 2,
+ QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC = 3,
+ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS = 4,
+ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC = 5,
+ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC = 6,
+ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV = 7,
+ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP = 8,
+ QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE = 9,
+ QCA_ATTR_NUD_STATS_AP_LINK_DAD = 10,
+ /* keep last */
+ QCA_ATTR_NUD_STATS_GET_LAST,
+ QCA_ATTR_NUD_STATS_GET_MAX =
+ QCA_ATTR_NUD_STATS_GET_LAST - 1,
};
/**
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 5f32fcbe3125..dadc7a7bd7b3 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -6766,6 +6766,7 @@ static int hdd_context_init(hdd_context_t *hdd_ctx)
hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
hdd_init_ll_stats_ctx();
+ hdd_init_nud_stats_ctx(hdd_ctx);
init_completion(&hdd_ctx->mc_sus_event_var);
init_completion(&hdd_ctx->ready_to_suspend);
@@ -8801,6 +8802,66 @@ void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
}
/**
+ * hdd_get_nud_stats_cb() - callback api to update the stats
+ * received from the firmware
+ * @data: pointer to adapter.
+ * @rsp: pointer to data received from FW.
+ *
+ * This is called when wlan driver received response event for
+ * get arp stats to firmware.
+ *
+ * Return: None
+ */
+static void hdd_get_nud_stats_cb(void *data, struct rsp_stats *rsp)
+{
+ hdd_context_t *hdd_ctx = (hdd_context_t *)data;
+ struct hdd_nud_stats_context *context;
+ int status;
+ hdd_adapter_t *adapter = NULL;
+
+ ENTER();
+
+ adapter = hdd_get_adapter_by_vdev(hdd_ctx, rsp->vdev_id);
+ if (NULL == adapter)
+ return;
+
+ status = wlan_hdd_validate_context(hdd_ctx);
+ if (0 != status)
+ return;
+
+ if (!rsp) {
+ hdd_err("data is null");
+ return;
+ }
+
+ hdd_notice("rsp->arp_req_enqueue :%x", rsp->arp_req_enqueue);
+ hdd_notice("rsp->arp_req_tx_success :%x", rsp->arp_req_tx_success);
+ hdd_notice("rsp->arp_req_tx_failure :%x", rsp->arp_req_tx_failure);
+ hdd_notice("rsp->arp_rsp_recvd :%x", rsp->arp_rsp_recvd);
+ hdd_notice("rsp->out_of_order_arp_rsp_drop_cnt :%x",
+ rsp->out_of_order_arp_rsp_drop_cnt);
+ hdd_notice("rsp->dad_detected :%x", rsp->dad_detected);
+ hdd_notice("rsp->connect_status :%x", rsp->connect_status);
+ hdd_notice("rsp->ba_session_establishment_status :%x",
+ rsp->ba_session_establishment_status);
+
+ adapter->hdd_stats.hdd_arp_stats.tx_fw_cnt = rsp->arp_req_enqueue;
+ adapter->hdd_stats.hdd_arp_stats.rx_fw_cnt = rsp->arp_rsp_recvd;
+ adapter->hdd_stats.hdd_arp_stats.tx_ack_cnt = rsp->arp_req_tx_success;
+ adapter->dad |= rsp->dad_detected;
+ adapter->con_status = rsp->connect_status;
+
+ spin_lock(&hdd_context_lock);
+ context = &hdd_ctx->nud_stats_context;
+ complete(&context->response_event);
+ spin_unlock(&hdd_context_lock);
+
+ EXIT();
+
+ return;
+}
+
+/**
* hdd_register_cb - Register HDD callbacks.
* @hdd_ctx: HDD context
*
@@ -8847,7 +8908,10 @@ int hdd_register_cb(hdd_context_t *hdd_ctx)
}
sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
- hdd_rssi_threshold_breached);
+ hdd_rssi_threshold_breached);
+
+ sme_set_nud_debug_stats_cb(hdd_ctx->hHal,
+ hdd_get_nud_stats_cb);
status = sme_bpf_offload_register_callback(hdd_ctx->hHal,
hdd_get_bpf_offload_cb);
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index 644b8a8476c2..e3a32c780cd5 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -7027,4 +7027,50 @@ struct sme_rcpi_req {
struct qdf_mac_addr mac_addr;
};
+/**
+ * struct rsp_stats - arp packet stats
+ * @arp_req_enqueue: fw tx count
+ * @arp_req_tx_success: tx ack count
+ * @arp_req_tx_failure: tx ack fail count
+ * @arp_rsp_recvd: rx fw count
+ * @out_of_order_arp_rsp_drop_cnt: out of order count
+ * @dad_detected: dad detected
+ * @connect_status: connection status
+ * @ba_session_establishment_status: BA session status
+ */
+struct rsp_stats {
+ uint32_t vdev_id;
+ uint32_t arp_req_enqueue;
+ uint32_t arp_req_tx_success;
+ uint32_t arp_req_tx_failure;
+ uint32_t arp_rsp_recvd;
+ uint32_t out_of_order_arp_rsp_drop_cnt;
+ uint32_t dad_detected;
+ uint32_t connect_status;
+ uint32_t ba_session_establishment_status;
+};
+
+/**
+ * struct set_arp_stats_params - set/reset arp stats
+ * @vdev_id: session id
+ * @flag: enable/disable stats
+ * @pkt_type: type of packet(1 - arp)
+ * @ip_addr: subnet ipv4 address in case of encrypted packets
+ */
+struct set_arp_stats_params {
+ uint32_t vdev_id;
+ uint8_t flag;
+ uint8_t pkt_type;
+ uint32_t ip_addr;
+};
+
+/**
+ * struct get_arp_stats_params - get arp stats from firmware
+ * @pkt_type: packet type(1 - ARP)
+ * @vdev_id: session id
+ */
+struct get_arp_stats_params {
+ uint8_t pkt_type;
+ uint32_t vdev_id;
+};
#endif /* __SIR_API_H */
diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h
index 87455ced90a1..05805f6dabcc 100644
--- a/core/mac/src/include/sir_params.h
+++ b/core/mac/src/include/sir_params.h
@@ -99,7 +99,6 @@ typedef enum {
ADVANCE_TDLS = 29,
TDLS_OFF_CHANNEL = 30,
#endif
-
/* MAX_FEATURE_SUPPORTED = 128 */
} placeHolderInCapBitmap;
@@ -652,6 +651,9 @@ typedef struct sSirMbMsgP2p {
#define SIR_HAL_ENABLE_BCAST_FILTER (SIR_HAL_ITC_MSG_TYPES_BEGIN + 373)
#define SIR_HAL_DISABLE_BCAST_FILTER (SIR_HAL_ITC_MSG_TYPES_BEGIN + 374)
+/* ARP Debug stats */
+#define SIR_HAL_SET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 375)
+#define SIR_HAL_GET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 376)
#define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index d272398257ec..884c84164691 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -1452,6 +1452,16 @@ void sme_set_cc_src(tHalHandle hal_handle, enum country_src);
#ifdef WLAN_FEATURE_WOW_PULSE
QDF_STATUS sme_set_wow_pulse(struct wow_pulse_mode *wow_pulse_set_info);
#endif
+/* ARP DEBUG STATS */
+QDF_STATUS sme_set_nud_debug_stats(tHalHandle hal,
+ struct set_arp_stats_params
+ *set_stats_param);
+QDF_STATUS sme_get_nud_debug_stats(tHalHandle hal,
+ struct get_arp_stats_params
+ *get_stats_param);
+QDF_STATUS sme_set_nud_debug_stats_cb(tHalHandle hal,
+ void (*cb)(void *, struct rsp_stats *));
+
#ifdef WLAN_FEATURE_UDP_RESPONSE_OFFLOAD
QDF_STATUS sme_set_udp_resp_offload(struct udp_resp_offload *pudp_resp_cmd);
diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h
index 7052d49bb90b..50f2f8b13633 100644
--- a/core/sme/inc/sme_internal.h
+++ b/core/sme/inc/sme_internal.h
@@ -259,6 +259,7 @@ typedef struct tagSmeStruct {
struct sir_lost_link_info *lost_link_info);
void (*rso_cmd_status_cb)(void *hdd_context,
struct rso_cmd_status *rso_status);
+ void (*get_arp_stats_cb)(void *, struct rsp_stats *);
} tSmeStruct, *tpSmeStruct;
#endif /* #if !defined( __SMEINTERNAL_H ) */
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 88c337211272..031fda30ab18 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -15364,6 +15364,41 @@ QDF_STATUS sme_set_rssi_threshold_breached_cb(tHalHandle h_hal,
}
/**
+ * sme_set_nud_debug_stats_cb() - set nud debug stats callback
+ * @hal: global hal handle
+ * @cb: callback function pointer
+ *
+ * This function stores nud debug stats callback function.
+ *
+ * Return: QDF_STATUS enumeration.
+ */
+QDF_STATUS sme_set_nud_debug_stats_cb(tHalHandle hal,
+ void (*cb)(void *, struct rsp_stats *))
+{
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
+ tpAniSirGlobal mac;
+
+ if (!hal) {
+ QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+ FL("hal is not valid"));
+ return QDF_STATUS_E_INVAL;
+ }
+ mac = PMAC_STRUCT(hal);
+
+ status = sme_acquire_global_lock(&mac->sme);
+ if (!QDF_IS_STATUS_SUCCESS(status)) {
+ QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+ FL("sme_acquire_global_lock failed!(status=%d)"),
+ status);
+ return status;
+ }
+
+ mac->sme.get_arp_stats_cb = cb;
+ sme_release_global_lock(&mac->sme);
+ return status;
+}
+
+/**
* sme_set_rssi_threshold_breached_cb() - Reset rssi threshold breached callback
* @hal: global hal handle
*
@@ -17616,3 +17651,76 @@ free_scan_flter:
return status;
}
+/* ARP DEBUG STATS */
+
+/**
+ * sme_set_nud_debug_stats() - sme api to set nud debug stats
+ * @hal: handle to hal
+ * @set_stats_param: pointer to set stats param
+ *
+ * Return: Return QDF_STATUS.
+ */
+QDF_STATUS sme_set_nud_debug_stats(tHalHandle hal,
+ struct set_arp_stats_params
+ *set_stats_param)
+{
+ struct set_arp_stats_params *arp_set_param;
+ cds_msg_t msg;
+
+ arp_set_param = qdf_mem_malloc(sizeof(*arp_set_param));
+ if (arp_set_param == NULL) {
+ hdd_err("Memory allocation failure");
+ return QDF_STATUS_E_NOMEM;
+ }
+
+ qdf_mem_copy(arp_set_param, set_stats_param, sizeof(*arp_set_param));
+
+ msg.type = WMA_SET_ARP_STATS_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = arp_set_param;
+
+ if (QDF_STATUS_SUCCESS !=
+ cds_mq_post_message(QDF_MODULE_ID_WMA, &msg)) {
+ hdd_err("Not able to post message to WDA");
+ qdf_mem_free(arp_set_param);
+ return QDF_STATUS_E_FAILURE;
+ }
+
+ return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * sme_get_nud_debug_stats() - sme api to get nud debug stats
+ * @hal: handle to hal
+ * @get_stats_param: pointer to set stats param
+ *
+ * Return: Return QDF_STATUS.
+ */
+QDF_STATUS sme_get_nud_debug_stats(tHalHandle hal,
+ struct get_arp_stats_params
+ *get_stats_param)
+{
+ struct get_arp_stats_params *arp_get_param;
+ cds_msg_t msg;
+
+ arp_get_param = qdf_mem_malloc(sizeof(*arp_get_param));
+ if (arp_get_param == NULL) {
+ hdd_err("Memory allocation failure");
+ return QDF_STATUS_E_NOMEM;
+ }
+
+ qdf_mem_copy(arp_get_param, get_stats_param, sizeof(*arp_get_param));
+
+ msg.type = WMA_GET_ARP_STATS_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = arp_get_param;
+
+ if (QDF_STATUS_SUCCESS !=
+ cds_mq_post_message(QDF_MODULE_ID_WMA, &msg)) {
+ hdd_err("Not able to post message to WDA");
+ qdf_mem_free(arp_get_param);
+ return QDF_STATUS_E_FAILURE;
+ }
+
+ return QDF_STATUS_SUCCESS;
+}
diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h
index ee3454b40eb7..45f1c72f0e90 100644
--- a/core/wma/inc/wma_internal.h
+++ b/core/wma/inc/wma_internal.h
@@ -1348,4 +1348,6 @@ wma_send_vdev_start_to_fw(t_wma_handle *wma, struct vdev_start_params *params);
*/
QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id);
+int wma_get_arp_stats_handler(void *handle, uint8_t *data,
+ uint32_t data_len);
#endif
diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h
index 0cde7ff2cab4..2ea83e7fe949 100644
--- a/core/wma/inc/wma_types.h
+++ b/core/wma/inc/wma_types.h
@@ -494,6 +494,8 @@
#define WDA_SET_UDP_RESP_OFFLOAD SIR_HAL_SET_UDP_RESP_OFFLOAD
#define WMA_SET_PER_ROAM_CONFIG_CMD SIR_HAL_SET_PER_ROAM_CONFIG_CMD
+#define WMA_SET_ARP_STATS_REQ SIR_HAL_SET_ARP_STATS_REQ
+#define WMA_GET_ARP_STATS_REQ SIR_HAL_GET_ARP_STATS_REQ
/* Bit 6 will be used to control BD rate for Management frames */
#define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40
diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c
index f1f3a3ac4ccd..4a89445b2109 100644
--- a/core/wma/src/wma_features.c
+++ b/core/wma/src/wma_features.c
@@ -8626,6 +8626,68 @@ QDF_STATUS wma_encrypt_decrypt_msg(WMA_HANDLE handle,
}
/**
+ * wma_get_arp_stats_handler() - handle arp stats data
+ * indicated by FW
+ * @handle: wma context
+ * @data: event buffer
+ * @data len: length of event buffer
+ *
+ * Return: 0 on success
+ */
+int wma_get_arp_stats_handler(void *handle, uint8_t *data,
+ uint32_t data_len)
+{
+ WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *param_buf;
+ wmi_vdev_get_arp_stats_event_fixed_param *data_event;
+ struct rsp_stats rsp;
+ tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
+
+ ENTER();
+
+ if (!mac) {
+ WMA_LOGE("%s: Invalid mac context", __func__);
+ return -EINVAL;
+ }
+
+ if (!mac->sme.get_arp_stats_cb) {
+ WMA_LOGE("%s: Callback not registered", __func__);
+ return -EINVAL;
+ }
+
+ if (data == NULL) {
+ WMA_LOGE("%s: invalid pointer", __func__);
+ return -EINVAL;
+ }
+ param_buf = (WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *)data;
+ if (!param_buf) {
+ WMA_LOGE("%s: Invalid get arp stats event", __func__);
+ return -EINVAL;
+ }
+ data_event = param_buf->fixed_param;
+ if (!data_event) {
+ WMA_LOGE("%s: Invalid get arp stats data event", __func__);
+ return -EINVAL;
+ }
+ rsp.arp_req_enqueue = data_event->arp_req_enqueue;
+ rsp.vdev_id = data_event->vdev_id;
+ rsp.arp_req_tx_success = data_event->arp_req_tx_success;
+ rsp.arp_req_tx_failure = data_event->arp_req_tx_failure;
+ rsp.arp_rsp_recvd = data_event->arp_rsp_recvd;
+ rsp.out_of_order_arp_rsp_drop_cnt =
+ data_event->out_of_order_arp_rsp_drop_cnt;
+ rsp.dad_detected = data_event->dad_detected;
+ rsp.connect_status = data_event->connect_status;
+ rsp.ba_session_establishment_status =
+ data_event->ba_session_establishment_status;
+
+ mac->sme.get_arp_stats_cb(mac->hHdd, &rsp);
+
+ EXIT();
+
+ return 0;
+}
+
+/**
* wma_encrypt_decrypt_msg_handler() - handle encrypt/decrypt data
* indicated by FW
* @handle: wma context
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index cf49754a4eeb..7475cd99825e 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -2329,6 +2329,13 @@ QDF_STATUS wma_open(void *cds_context,
wma_stats_event_handler,
WMA_RX_SERIALIZER_CTX);
+ /* register for stats response event */
+ wmi_unified_register_event_handler(wma_handle->wmi_handle,
+ WMI_VDEV_GET_ARP_STAT_EVENTID,
+ wma_get_arp_stats_handler,
+ WMA_RX_SERIALIZER_CTX);
+
+
#ifdef WLAN_POWER_DEBUGFS
/* register for Chip Power stats event */
wmi_unified_register_event_handler(wma_handle->wmi_handle,
@@ -6325,6 +6332,48 @@ void wma_mc_discard_msg(cds_msg_t *msg)
msg->type = 0;
}
+static void wma_set_arp_req_stats(WMA_HANDLE handle,
+ struct set_arp_stats_params *req_buf)
+{
+ int status;
+ struct set_arp_stats *arp_stats;
+ tp_wma_handle wma_handle = (tp_wma_handle) handle;
+
+ if (!wma_handle || !wma_handle->wmi_handle) {
+ WMA_LOGE("%s: WMA is closed, cannot send per roam config",
+ __func__);
+ return;
+ }
+
+ arp_stats = (struct set_arp_stats *)req_buf;
+ status = wmi_unified_set_arp_stats_req(wma_handle->wmi_handle,
+ arp_stats);
+ if (status != EOK)
+ WMA_LOGE("%s: failed to set arp stats to FW",
+ __func__);
+}
+
+static void wma_get_arp_req_stats(WMA_HANDLE handle,
+ struct get_arp_stats_params *req_buf)
+{
+ int status;
+ struct get_arp_stats *arp_stats;
+ tp_wma_handle wma_handle = (tp_wma_handle) handle;
+
+ if (!wma_handle || !wma_handle->wmi_handle) {
+ WMA_LOGE("%s: WMA is closed, cannot send per roam config",
+ __func__);
+ return;
+ }
+
+ arp_stats = (struct get_arp_stats *)req_buf;
+ status = wmi_unified_get_arp_stats_req(wma_handle->wmi_handle,
+ arp_stats);
+ if (status != EOK)
+ WMA_LOGE("%s: failed to send get arp stats to FW",
+ __func__);
+}
+
/**
* wma_mc_process_msg() - process wma messages and call appropriate function.
* @cds_context: cds context
@@ -7179,6 +7228,16 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg)
wma_configure_non_arp_broadcast_filter(wma_handle,
(struct broadcast_filter_request *) msg->bodyptr);
break;
+ case WMA_SET_ARP_STATS_REQ:
+ wma_set_arp_req_stats(wma_handle,
+ (struct set_arp_stats_params *)msg->bodyptr);
+ qdf_mem_free(msg->bodyptr);
+ break;
+ case WMA_GET_ARP_STATS_REQ:
+ wma_get_arp_req_stats(wma_handle,
+ (struct get_arp_stats_params *)msg->bodyptr);
+ qdf_mem_free(msg->bodyptr);
+ break;
default:
WMA_LOGE("Unhandled WMA message of type %d", msg->type);
if (msg->bodyptr)