diff options
| author | Sravan Kumar Kairam <sgoud@codeaurora.org> | 2017-01-04 15:27:56 +0530 |
|---|---|---|
| committer | qcabuildsw <qcabuildsw@localhost> | 2017-01-31 08:50:55 -0800 |
| commit | f4ee39fe5413d703937a03e2f304c54648939c9f (patch) | |
| tree | e04e11c688be615a2822ba82a9f8cd97f3677dae | |
| parent | a05a6588c8b7a41249e800806e6e6e7f0971363d (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.c | 65 |
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); |
