summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSravan Kumar Kairam <sgoud@codeaurora.org>2017-01-04 15:27:56 +0530
committerqcabuildsw <qcabuildsw@localhost>2017-01-31 08:50:55 -0800
commitf4ee39fe5413d703937a03e2f304c54648939c9f (patch)
treee04e11c688be615a2822ba82a9f8cd97f3677dae
parenta05a6588c8b7a41249e800806e6e6e7f0971363d (diff)
qcacld-3.0: Do not acquire rx wake lock for non local ARP
Propagation from qcacld-2.0 to qcacld-3.0 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: I5fcd0cf0edc5c28a4662ae49a33cc55a77f3d3e4 CRs-Fixed: 1088974
-rw-r--r--core/hdd/src/wlan_hdd_tx_rx.c65
1 files changed, 62 insertions, 3 deletions
diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c
index 44030cee8fad..2135aa5dd0f9 100644
--- a/core/hdd/src/wlan_hdd_tx_rx.c
+++ b/core/hdd/src/wlan_hdd_tx_rx.c
@@ -38,6 +38,7 @@
#include <linux/skbuff.h>
#include <linux/etherdevice.h>
#include <linux/if_ether.h>
+#include <linux/inetdevice.h>
#include <cds_sched.h>
#include <cds_utils.h>
@@ -922,6 +923,62 @@ static bool hdd_is_mcast_replay(struct sk_buff *skb)
}
/**
+* 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)) {
+ in_dev = __in_dev_get_rtnl(skb->dev);
+ if (in_dev) {
+ 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);
+ hdd_info("ARP packet: local IP: %x dest IP: %x",
+ ifa->ifa_local, tip);
+ if (ifa->ifa_local != tip)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+* hdd_is_rx_wake_lock_needed() - check if wake lock is needed
+* @skb: pointer to sk_buff
+*
+* Return: true if wake lock is needed or false otherwise.
+*/
+static bool hdd_is_rx_wake_lock_needed(struct sk_buff *skb)
+{
+ if ((skb->pkt_type != PACKET_BROADCAST &&
+ skb->pkt_type != PACKET_MULTICAST) || hdd_is_arp_local(skb))
+ return true;
+
+ return false;
+}
+
+/**
* hdd_rx_packet_cbk() - Receive packet handler
* @context: pointer to HDD context
* @rxBuf: pointer to rx qdf_nbuf
@@ -941,6 +998,7 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
struct sk_buff *skb = NULL;
hdd_station_ctx_t *pHddStaCtx = NULL;
unsigned int cpu_index;
+ bool wake_lock = false;
/* Sanity check on inputs */
if (unlikely((NULL == context) || (NULL == rxBuf))) {
@@ -1007,9 +1065,10 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
}
/* hold configurable wakelock for unicast traffic */
- if (pHddCtx->config->rx_wakelock_timeout &&
- skb->pkt_type != PACKET_BROADCAST &&
- skb->pkt_type != PACKET_MULTICAST) {
+ if (pHddCtx->config->rx_wakelock_timeout)
+ wake_lock = hdd_is_rx_wake_lock_needed(skb);
+
+ if (wake_lock) {
cds_host_diag_log_work(&pHddCtx->rx_wake_lock,
pHddCtx->config->rx_wakelock_timeout,
WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);