summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSravan Kumar Kairam <sgoud@codeaurora.org>2016-11-11 20:32:55 +0530
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-11-12 12:41:14 +0530
commit6d4eb3ed2bcc1fb20facba91fc97a8904624dda7 (patch)
tree3686b8c2a624b6803d6c4ede22e3628e7dc5f802
parent435c66836aecfacf21dba40d5d4ea9ff7198aaa5 (diff)
qcacld-2.0: Do not acquire rx wake lock for non local ARP
Currently even for non local ARP requests wake lock is getting acquired which is preventing the system suspend which is a power penalty. Do not acquire wake lock for the non local ARP requests. Change-Id: Iec8f5870a03ed48ae08f20363c473cef8d5c19dc CRs-Fixed: 1088974
-rw-r--r--CORE/HDD/src/wlan_hdd_tx_rx.c59
1 files changed, 58 insertions, 1 deletions
diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c
index d7448e1192e0..da354651cc07 100644
--- a/CORE/HDD/src/wlan_hdd_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_tx_rx.c
@@ -52,6 +52,7 @@
#include <linux/if_ether.h>
#endif
+#include <linux/inetdevice.h>
#include <wlan_hdd_p2p.h>
#include <linux/wireless.h>
#include <net/cfg80211.h>
@@ -1193,6 +1194,49 @@ VOS_STATUS hdd_mon_rx_packet_cbk(v_VOID_t *vos_ctx, adf_nbuf_t rx_buf,
return VOS_STATUS_SUCCESS;
}
+
+#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
+/**
+ * hdd_is_arp_local() - check if local or non local arp
+ * @skb: pointer to sk_buff
+ *
+ * Return: true if local arp or false otherwise.
+ */
+static bool hdd_is_arp_local(struct sk_buff *skb)
+{
+
+ struct arphdr *arp;
+ struct in_ifaddr **ifap = NULL;
+ struct in_ifaddr *ifa = NULL;
+ struct in_device *in_dev;
+ unsigned char *arp_ptr;
+ __be32 tip;
+
+ arp = (struct arphdr *)skb->data;
+ if (arp->ar_op == htons(ARPOP_REQUEST)) {
+ if ((in_dev = __in_dev_get_rtnl(skb->dev)) != NULL) {
+ for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
+ ifap = &ifa->ifa_next) {
+ if (!strcmp(skb->dev->name,
+ ifa->ifa_label))
+ break;
+ }
+ }
+
+ if (ifa && ifa->ifa_local) {
+ arp_ptr = (unsigned char *)(arp + 1);
+ arp_ptr += (skb->dev->addr_len + 4 + skb->dev->addr_len);
+ memcpy(&tip, arp_ptr, 4);
+ hddLog(VOS_TRACE_LEVEL_INFO, "ARP packets: local IP: %x dest IP: %x\n",
+ ifa->ifa_local, tip);
+ if (ifa->ifa_local != tip)
+ return false;
+ }
+ }
+ return true;
+}
+#endif
+
/**============================================================================
@brief hdd_rx_packet_cbk() - Receive callback registered with TL.
TL will call this to notify the HDD when one or more packets were
@@ -1218,7 +1262,9 @@ VOS_STATUS hdd_rx_packet_cbk(v_VOID_t *vosContext,
v_U8_t proto_type;
#endif /* QCA_PKT_PROTO_TRACE */
hdd_station_ctx_t *pHddStaCtx = NULL;
-
+#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
+ bool wake_lock = false;
+#endif
//Sanity check on inputs
if ((NULL == vosContext) || (NULL == rxBuf))
{
@@ -1325,6 +1371,16 @@ VOS_STATUS hdd_rx_packet_cbk(v_VOID_t *vosContext,
*/
adf_net_buf_debug_release_skb(skb);
+#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
+ if (!wake_lock) {
+ if (skb->protocol == htons(ETH_P_ARP)) {
+ if (hdd_is_arp_local(skb))
+ wake_lock = true;
+ }
+ else
+ wake_lock = true;
+ }
+#endif
/*
* If this is not a last packet on the chain
* Just put packet into backlog queue, not scheduling RX sirq
@@ -1333,6 +1389,7 @@ VOS_STATUS hdd_rx_packet_cbk(v_VOID_t *vosContext,
rxstat = netif_rx(skb);
} else {
#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
+ if (wake_lock)
vos_wake_lock_timeout_acquire(&pHddCtx->rx_wake_lock,
HDD_WAKE_LOCK_DURATION,
WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);