From mboxrd@z Thu Jan 1 00:00:00 1970 From: Tejaswi Tanikella Subject: [PATCH net] ipv4: igmp: hold wakelock to prevent delayed reports Date: Fri, 1 Jun 2018 19:35:41 +0530 Message-ID: <20180601140532.GA13253@tejaswit-linux.qualcomm.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii To: netdev@vger.kernel.org Return-path: Received: from smtp.codeaurora.org ([198.145.29.96]:56502 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750850AbeFAOF4 (ORCPT ); Fri, 1 Jun 2018 10:05:56 -0400 Received: from tejaswit-linux.qualcomm.com (blr-c-bdr-fw-01_globalnat_allzones-outside.qualcomm.com [103.229.19.19]) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) (Authenticated sender: tejaswit@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 1164B60263 for ; Fri, 1 Jun 2018 14:05:54 +0000 (UTC) Content-Disposition: inline Sender: netdev-owner@vger.kernel.org List-ID: On receiving a IGMPv2/v3 query, based on max_delay set in the header a timer is started to send out a response after a random time within max_delay. If the system then moves into suspend state, Report is delayed until system wakes up. In one reported scenario, on arm64 devices, max_delay was set to 10s, Reports were consistantly delayed if the timer is scheduled after 5 plus seconds. Hold wakelock while starting the timer to prevent moving into suspend state. Signed-off-by: Tejaswi Tanikella --- include/linux/igmp.h | 1 + net/ipv4/igmp.c | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/linux/igmp.h b/include/linux/igmp.h index f823185..9be1c58 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -84,6 +84,7 @@ struct ip_mc_list { }; struct ip_mc_list __rcu *next_hash; struct timer_list timer; + struct wakeup_source *wakeup_src; int users; refcount_t refcnt; spinlock_t lock; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index b26a81a..c695e2c 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -107,6 +107,9 @@ #include #include #endif +#ifdef CONFIG_IP_MULTICAST +#include +#endif #ifdef CONFIG_IP_MULTICAST /* Parameter names and values are taken from igmp-v2-06 draft */ @@ -174,7 +177,13 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode, static void ip_ma_put(struct ip_mc_list *im) { +#ifdef CONFIG_IP_MULTICAST + __pm_relax(im->wakeup_src); +#endif if (refcount_dec_and_test(&im->refcnt)) { +#ifdef CONFIG_IP_MULTICAST + wakeup_source_unregister(im->wakeup_src); +#endif in_dev_put(im->interface); kfree_rcu(im, rcu); } @@ -199,8 +208,10 @@ static void ip_ma_put(struct ip_mc_list *im) static void igmp_stop_timer(struct ip_mc_list *im) { spin_lock_bh(&im->lock); - if (del_timer(&im->timer)) + if (del_timer(&im->timer)) { + __pm_relax(im->wakeup_src); refcount_dec(&im->refcnt); + } im->tm_running = 0; im->reporter = 0; im->unsolicit_count = 0; @@ -213,8 +224,10 @@ static void igmp_start_timer(struct ip_mc_list *im, int max_delay) int tv = prandom_u32() % max_delay; im->tm_running = 1; - if (!mod_timer(&im->timer, jiffies+tv+2)) + if (!mod_timer(&im->timer, jiffies+tv+2)) { refcount_inc(&im->refcnt); + __pm_stay_awake(im->wakeup_src); + } } static void igmp_gq_start_timer(struct in_device *in_dev) @@ -250,6 +263,7 @@ static void igmp_mod_timer(struct ip_mc_list *im, int max_delay) spin_unlock_bh(&im->lock); return; } + __pm_relax(im->wakeup_src); refcount_dec(&im->refcnt); } igmp_start_timer(im, max_delay); @@ -1415,6 +1429,8 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr) #ifdef CONFIG_IP_MULTICAST timer_setup(&im->timer, igmp_timer_expire, 0); im->unsolicit_count = net->ipv4.sysctl_igmp_qrv; + im->wakeup_src = wakeup_source_create("igmp_wakeup_source"); + wakeup_source_add(im->wakeup_src); #endif im->next_rcu = in_dev->mc_list; -- 1.9.1