wlan: Add changes to collect Arp packet stats
Add changes to collect arp packet stats along
with existing hdd stats to debug the arp packet
related issues.
Change-Id: I3574d512744bcdd0021f8a57d2f9f70e1b154458
CRs-Fixed: 1115366
diff --git a/CORE/DXE/src/wlan_qct_dxe.c b/CORE/DXE/src/wlan_qct_dxe.c
index c7f7235..de64b93 100644
--- a/CORE/DXE/src/wlan_qct_dxe.c
+++ b/CORE/DXE/src/wlan_qct_dxe.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -3445,6 +3445,12 @@
//HDXE_ASSERT(0);
}
+ if(wpalIsArpPkt(palPacket))
+ {
+ HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
+ "%s :ARP packet", __func__);
+ }
+
/* Everything is ready
* Trigger to start DMA */
status = wpalWriteRegister(channelEntry->channelRegister.chDXECtrlRegAddr,
@@ -3695,6 +3701,14 @@
}
return status;
}
+
+ if(wpalIsArpPkt(currentCtrlBlk->xfrFrame))
+ {
+ HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR,
+ "%s :ARP packet DMA-ed ", __func__);
+ wpalUpdateTXArpFWdeliveredStats();
+ }
+
hostCtxt->txCompCB(hostCtxt->clientCtxt,
currentCtrlBlk->xfrFrame,
eWLAN_PAL_STATUS_SUCCESS);
diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c
index 9a42301..fad7736 100644
--- a/CORE/HDD/src/wlan_hdd_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_tx_rx.c
@@ -819,6 +819,7 @@
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
v_BOOL_t txSuspended = VOS_FALSE;
struct sk_buff *skb1;
+ v_BOOL_t arp_pkt;
if (NULL == pHddCtx) {
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
@@ -835,6 +836,15 @@
return NETDEV_TX_BUSY;
}
+ arp_pkt = vos_is_arp_pkt(skb, false);
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.txCount;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s :ARP packet received form net_dev", __func__);
+ }
+
//Get TL Q index corresponding to Qdisc queue index/AC.
qid = hdd_QdiscAcToTlAC[skb->queue_mapping];
ac = qid;
@@ -852,6 +862,15 @@
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_INFO,
FL("Tx frame in not associated state in %d context"),
pAdapter->device_mode);
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.txDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_TX_FRAME_IN_NOT_ASSOCIATED_STATE;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s :Tx frame in not associated state, ARP packet Dropped ",
+ __func__);
+ }
++pAdapter->stats.tx_dropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
@@ -895,6 +914,15 @@
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
"%s: WLANTL_STAPktPending() returned error code %d",
__func__, status);
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.txDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_WLANTL_STAPKTPENDING_RETURNED_ERROR_CODE;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s:ARP Packet Dropped WLANTL_STAPktPending returned error %d",
+ __func__, status);
+ }
++pAdapter->stats.tx_dropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
@@ -984,6 +1012,14 @@
if ( !VOS_IS_STATUS_SUCCESS( status ) )
{
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s:Insert Tx queue failed. Pkt dropped", __func__);
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.txDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_INSERT_TX_QUEUE_FAILED;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s:Insert Tx queue failed. ARP packet dropped", __func__);
+ }
++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
++pAdapter->stats.tx_dropped;
@@ -1045,6 +1081,15 @@
skb1 = pktNode->skb;
kfree_skb(skb1);
}
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.txDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_FAILED_TO_SIGNAL_TL;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: ARP packet Dropped : Failed to signal TL for QId=%d",
+ __func__, qid );
+ }
++pAdapter->stats.tx_dropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[qid];
@@ -1956,6 +2001,7 @@
tANI_U8 acAdmitted, i;
v_U8_t proto_type = 0;
WLANTL_ACEnumType actualAC;
+ v_BOOL_t arp_pkt;
//Sanity check on inputs
if ( ( NULL == vosContext ) ||
@@ -2093,10 +2139,20 @@
vos_pkt_return_packet(pVosPacket);
return VOS_STATUS_E_FAILURE;
}
+ arp_pkt = vos_is_arp_pkt(skb, false);
//Attach skb to VOS packet.
status = vos_pkt_set_os_packet( pVosPacket, skb );
if (status != VOS_STATUS_SUCCESS)
{
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.txDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_ERROR_ATTACHING_SKB;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s :Error attaching skb,ARP packet droped", __func__);
+ }
+
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __func__);
vos_pkt_return_packet(pVosPacket);
++pAdapter->stats.tx_dropped;
@@ -2108,6 +2164,16 @@
//Just being paranoid. To be removed later
if(pVosPacket == NULL)
{
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.txDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_VOS_PACKET_RETURNED_BY_VOSS_IS_NULL;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s :VOS packet returned by VOSS is NULL,ARP packet droped",
+ __func__);
+ }
+
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,"%s: VOS packet returned by VOSS is NULL", __func__);
++pAdapter->stats.tx_dropped;
++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError;
@@ -2166,6 +2232,12 @@
if( HDD_ETHERTYPE_ARP_SIZE == packet_size )
pPktMetaInfo->ucIsArp = hdd_IsARP( pVosPacket ) ? 1 : 0;
+ if(pPktMetaInfo->ucIsArp)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s :STA TX ARP Received in TL ",__func__);
+ }
+
#ifdef FEATURE_WLAN_WAPI
// Override usIsEapol value when its zero for WAPI case
pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0;
@@ -2587,6 +2659,7 @@
vos_pkt_t* pVosPacket;
vos_pkt_t* pNextVosPacket;
v_U8_t proto_type = 0;
+ v_BOOL_t arp_pkt;
//Sanity check on inputs
if ( ( NULL == vosContext ) ||
@@ -2627,6 +2700,14 @@
// both "success" and "empty" are acceptable results
if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
{
+
+ if(hdd_IsARP(pVosPacket))
+ {
+ ++pAdapter->hdd_stats.hddArpStats.rxDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_FAILURE_WALKING_PACKET_CHAIN;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: ARP packet Drop: Failure walking packet chain", __func__);
+ }
++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
"%s: Failure walking packet chain", __func__);
@@ -2637,6 +2718,15 @@
status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_FALSE );
if(!VOS_IS_STATUS_SUCCESS( status ))
{
+
+ if(hdd_IsARP(pVosPacket))
+ {
+ ++pAdapter->hdd_stats.hddArpStats.rxDropped;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_FAILURE_EXTRACTING_SKB_FROM_VOS_PKT;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: ARP packet Dropped: Failure extracting skb from vos pkt",
+ __func__);
+ }
++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
"%s: Failure extracting skb from vos pkt", __func__);
@@ -2698,6 +2788,15 @@
}
}
+ arp_pkt = vos_is_arp_pkt(skb, false);
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.rxCount;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s :STA RX ARP received",__func__);
+ }
+
if (pHddCtx->rx_wow_dump) {
if (!(VOS_PKT_PROTO_TYPE_ARP & proto_type) &&
!(VOS_PKT_PROTO_TYPE_EAPOL & proto_type))
@@ -2737,11 +2836,28 @@
if (NET_RX_SUCCESS == rxstat)
{
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.rxDelivered;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "STA RX ARP packet Delivered to net stack");
+ }
+
++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
}
else
{
+
+ if (arp_pkt)
+ {
+ ++pAdapter->hdd_stats.hddArpStats.rxRefused;
+ pAdapter->hdd_stats.hddArpStats.reason = HDD_STA_RX_ARP_PACKET_REFUSED_IN_NET_STACK;
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s :STA RX ARP packet Refused in net stack", __func__);
+ }
+
++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
}
// now process the next packet in the chain
diff --git a/CORE/TL/src/wlan_qct_tl_ba.c b/CORE/TL/src/wlan_qct_tl_ba.c
index f940585..b97af6c 100644
--- a/CORE/TL/src/wlan_qct_tl_ba.c
+++ b/CORE/TL/src/wlan_qct_tl_ba.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1165,6 +1165,9 @@
TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
"(QCUR_FWDBUF) dropping old frame, SN=%d LastSN=%d",
CSN, currentReorderInfo->LastSN));
+ if (vos_is_arp_pkt((*vosDataBuff)->pSkb, true))
+ vos_update_arp_rx_drop_reorder();
+
status = vos_pkt_return_packet(*vosDataBuff);
if (!VOS_IS_STATUS_SUCCESS(status))
{
diff --git a/CORE/VOSS/inc/vos_api.h b/CORE/VOSS/inc/vos_api.h
index abcef0a..5c7fd8c 100644
--- a/CORE/VOSS/inc/vos_api.h
+++ b/CORE/VOSS/inc/vos_api.h
@@ -532,4 +532,6 @@
void vos_dump_wdi_events(void);
bool vos_check_arp_target_ip(vos_pkt_t *pPacket);
+void vos_update_arp_fw_tx_delivered(void);
+void vos_update_arp_rx_drop_reorder(void);
#endif // if !defined __VOS_NVITEM_H
diff --git a/CORE/VOSS/inc/vos_packet.h b/CORE/VOSS/inc/vos_packet.h
index 3aa0a33..ad838d7 100644
--- a/CORE/VOSS/inc/vos_packet.h
+++ b/CORE/VOSS/inc/vos_packet.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1170,4 +1170,16 @@
*/
v_VOID_t vos_recover_tail(vos_pkt_t *pPacket);
+/**
+ @breaf vos_is_arp_pkt() - Check the packet is ARP or not.
+
+ @param
+ pskb - pointer to skb
+ is_translated - header translation check
+ @return
+ TRUE - if packet is ARP
+ FALSE -if packet is not ARP
+*/
+bool vos_is_arp_pkt(void *pskb, bool is_translated);
+
#endif // !defined( __VOS_PKT_H )
diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c
index 68e93f8..42e623e 100644
--- a/CORE/VOSS/src/vos_api.c
+++ b/CORE/VOSS/src/vos_api.c
@@ -3809,3 +3809,85 @@
return false;
}
+
+/**
+ * vos_update_arp_fw_tx_delivered() - update the ARP stats host to FW deliver
+ * count
+ *
+ * Return: None
+ */
+void vos_update_arp_fw_tx_delivered(void)
+{
+ v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ hdd_context_t *pHddCtx = NULL;
+ hdd_adapter_t * pAdapter;
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ uint8_t status;
+
+ if(!pVosContext) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ return;
+ }
+
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
+ if(!pHddCtx) {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD context is Null", __func__);
+ return;
+ }
+
+ status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
+
+ while (NULL != pAdapterNode && 0 == status)
+ {
+ pAdapter = pAdapterNode->pAdapter;
+ if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
+ break;
+
+ status = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext);
+ pAdapterNode = pNext;
+ }
+
+ pAdapter->hdd_stats.hddArpStats.tx_host_fw_sent++;
+}
+
+/**
+ * vos_update_arp_rx_drop_reorder() - update the RX ARP stats drop due
+ * reorder logic at host
+ *
+ * Return: None
+ */
+void vos_update_arp_rx_drop_reorder(void)
+{
+ v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+ hdd_context_t *pHddCtx = NULL;
+ hdd_adapter_t * pAdapter;
+ hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+ uint8_t status;
+
+ if(!pVosContext) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+ return;
+ }
+
+ pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
+ if(!pHddCtx) {
+ VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+ "%s: HDD context is Null", __func__);
+ return;
+ }
+
+ status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
+
+ while (NULL != pAdapterNode && 0 == status)
+ {
+ pAdapter = pAdapterNode->pAdapter;
+ if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
+ break;
+
+ status = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext);
+ pAdapterNode = pNext;
+ }
+
+ pAdapter->hdd_stats.hddArpStats.rx_host_drop_reorder++;
+}
diff --git a/CORE/VOSS/src/vos_packet.c b/CORE/VOSS/src/vos_packet.c
index 43daf9f..7332176 100644
--- a/CORE/VOSS/src/vos_packet.c
+++ b/CORE/VOSS/src/vos_packet.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -3100,6 +3100,35 @@
return pkt_proto_type;
}
+bool vos_is_arp_pkt(void *pskb, bool is_translated)
+{
+ v_U16_t ether_type;
+ struct sk_buff *skb = NULL;
+#define HEADER_OFFSET_802_11 20
+
+ if (NULL == pskb)
+ {
+ return FALSE;
+ }
+
+ skb = (struct sk_buff *)pskb;
+
+ if (is_translated)
+ ether_type = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_PROT_ETH_TYPE_OFFSET + HEADER_OFFSET_802_11));
+ else
+ ether_type = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_PROT_ETH_TYPE_OFFSET));
+
+ if (VOS_PKT_PROT_ARP_ETH_TYPE == VOS_SWAP_U16(ether_type))
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+#undef HEADER_OFFSET_802_11
+}
+
v_PVOID_t vos_get_pkt_head(vos_pkt_t *pPacket)
{
struct sk_buff *skb;
diff --git a/CORE/WDI/DP/src/wlan_qct_wdi_ds.c b/CORE/WDI/DP/src/wlan_qct_wdi_ds.c
index e0f2c53..ac4512a 100644
--- a/CORE/WDI/DP/src/wlan_qct_wdi_ds.c
+++ b/CORE/WDI/DP/src/wlan_qct_wdi_ds.c
@@ -213,6 +213,13 @@
WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
"Packet Length is %d\n", pTxMetadata->fPktlen);
}
+
+ if (pTxMetadata->isArp)
+ {
+ WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+ "%s :Transmitting ARP packet",__func__);
+ }
+
wdiStatus = WDI_FillTxBd(pContext, ucTypeSubtype, pSTAMACAddress, pAddr2MACAddress,
&ucUP, 1, pvBDHeader, ucTxFlag /* No ACK */, ucProtMgmtFrame, 0, isEapol, isArp,
&staId, pTxMetadata->txBdToken);
diff --git a/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c b/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
index ae1afe5..15a44bc 100644
--- a/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
+++ b/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1296,6 +1296,13 @@
#else
((pTxMetadata->isEapol) ? WDTS_CHANNEL_TX_HIGH_PRI : WDTS_CHANNEL_TX_LOW_PRI) : WDTS_CHANNEL_TX_HIGH_PRI;
#endif
+
+ if (pTxMetadata->isArp)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s :Transmitting ARP packet", __func__);
+ }
+
// Send packet to Transport Driver.
status = gTransportDriver.xmit(pDTDriverContext, pFrame, channel);
if ((WLAN_LOG_LEVEL_ACTIVE ==
diff --git a/CORE/WDI/WPAL/inc/wlan_qct_pal_api.h b/CORE/WDI/WPAL/inc/wlan_qct_pal_api.h
index c1a8d18..aeacf6f 100644
--- a/CORE/WDI/WPAL/inc/wlan_qct_pal_api.h
+++ b/CORE/WDI/WPAL/inc/wlan_qct_pal_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015,2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -389,4 +389,6 @@
wpt_uint8 wpalIsFwLoggingEnabled(void);
wpt_uint8 wpalIsFwLoggingSupported(void);
wpt_uint8 wpalIsFwEvLoggingEnabled(void);
+bool wpalIsArpPkt(void *pPacket);
+void wpalUpdateTXArpFWdeliveredStats(void);
#endif // __WLAN_QCT_PAL_API_H
diff --git a/CORE/WDI/WPAL/src/wlan_qct_pal_api.c b/CORE/WDI/WPAL/src/wlan_qct_pal_api.c
index 9e0f047..a6019cb 100644
--- a/CORE/WDI/WPAL/src/wlan_qct_pal_api.c
+++ b/CORE/WDI/WPAL/src/wlan_qct_pal_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012,2014-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012,2014-2015,2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -542,3 +542,14 @@
return vos_get_dxeSSREnable();
}
+bool wpalIsArpPkt(void *pPacket)
+{
+ vos_pkt_t *pkt = (vos_pkt_t*)pPacket;
+
+ return vos_is_arp_pkt(pkt->pSkb, true);
+}
+
+void wpalUpdateTXArpFWdeliveredStats(void)
+{
+ vos_update_arp_fw_tx_delivered();
+}