Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f3ef66d authored by Subash Abhinov Kasiviswanathan's avatar Subash Abhinov Kasiviswanathan
Browse files

dfc: Use alarm timer to trigger powersave work



The timer in the delayed powersave work may not get fired at specified
interval during system suspend. The delay of the powersave work could
cause unexpected wakeups. Change to use alarm timer to trigger the
powersave work.

Change-Id: Ibd04c36e5f38988829c28684e8e9a9e6c2dbdfe9
Acked-by: default avatarWeiyi Chen <weiyic@qti.qualcomm.com>
Signed-off-by: default avatarSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>
parent eb45ec3a
Loading
Loading
Loading
Loading
+27 −3
Original line number Original line Diff line number Diff line
@@ -13,6 +13,7 @@
#include <trace/events/dfc.h>
#include <trace/events/dfc.h>
#include <linux/ip.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/ipv6.h>
#include <linux/alarmtimer.h>


#define NLMSG_FLOW_ACTIVATE 1
#define NLMSG_FLOW_ACTIVATE 1
#define NLMSG_FLOW_DEACTIVATE 2
#define NLMSG_FLOW_DEACTIVATE 2
@@ -43,6 +44,7 @@ unsigned int rmnet_wq_frequency __read_mostly = 1000;
#define PS_INTERVAL (((!rmnet_wq_frequency) ?                             \
#define PS_INTERVAL (((!rmnet_wq_frequency) ?                             \
					1 : rmnet_wq_frequency/10) * (HZ/100))
					1 : rmnet_wq_frequency/10) * (HZ/100))
#define NO_DELAY (0x0000 * HZ)
#define NO_DELAY (0x0000 * HZ)
#define PS_INTERVAL_KT (ms_to_ktime(1000))


#ifdef CONFIG_QCOM_QMI_DFC
#ifdef CONFIG_QCOM_QMI_DFC
static unsigned int qmi_rmnet_scale_factor = 5;
static unsigned int qmi_rmnet_scale_factor = 5;
@@ -917,6 +919,7 @@ static LIST_HEAD(ps_list);


struct rmnet_powersave_work {
struct rmnet_powersave_work {
	struct delayed_work work;
	struct delayed_work work;
	struct alarm atimer;
	void *port;
	void *port;
	u64 old_rx_pkts;
	u64 old_rx_pkts;
	u64 old_tx_pkts;
	u64 old_tx_pkts;
@@ -1001,6 +1004,16 @@ static void qmi_rmnet_work_restart(void *port)
	rcu_read_unlock();
	rcu_read_unlock();
}
}


static enum alarmtimer_restart qmi_rmnet_work_alarm(struct alarm *atimer,
						    ktime_t now)
{
	struct rmnet_powersave_work *real_work;

	real_work = container_of(atimer, struct rmnet_powersave_work, atimer);
	qmi_rmnet_work_restart(real_work->port);
	return ALARMTIMER_NORESTART;
}

static void qmi_rmnet_check_stats(struct work_struct *work)
static void qmi_rmnet_check_stats(struct work_struct *work)
{
{
	struct rmnet_powersave_work *real_work;
	struct rmnet_powersave_work *real_work;
@@ -1008,6 +1021,7 @@ static void qmi_rmnet_check_stats(struct work_struct *work)
	u64 rxd, txd;
	u64 rxd, txd;
	u64 rx, tx;
	u64 rx, tx;
	bool dl_msg_active;
	bool dl_msg_active;
	bool use_alarm_timer = true;


	real_work = container_of(to_delayed_work(work),
	real_work = container_of(to_delayed_work(work),
				 struct rmnet_powersave_work, work);
				 struct rmnet_powersave_work, work);
@@ -1053,8 +1067,10 @@ static void qmi_rmnet_check_stats(struct work_struct *work)
		 * (likely in RLF), no need to enter powersave
		 * (likely in RLF), no need to enter powersave
		 */
		 */
		if (!dl_msg_active &&
		if (!dl_msg_active &&
		    !rmnet_all_flows_enabled(real_work->port))
		    !rmnet_all_flows_enabled(real_work->port)) {
			use_alarm_timer = false;
			goto end;
			goto end;
		}


		/* Deregister to suppress QMI DFC and DL marker */
		/* Deregister to suppress QMI DFC and DL marker */
		if (qmi_rmnet_set_powersave_mode(real_work->port, 1) < 0)
		if (qmi_rmnet_set_powersave_mode(real_work->port, 1) < 0)
@@ -1078,8 +1094,14 @@ static void qmi_rmnet_check_stats(struct work_struct *work)
	}
	}
end:
end:
	rcu_read_lock();
	rcu_read_lock();
	if (!rmnet_work_quit)
	if (!rmnet_work_quit) {
		queue_delayed_work(rmnet_ps_wq, &real_work->work, PS_INTERVAL);
		if (use_alarm_timer)
			alarm_start_relative(&real_work->atimer,
					     PS_INTERVAL_KT);
		else
			queue_delayed_work(rmnet_ps_wq, &real_work->work,
					   PS_INTERVAL);
	}
	rcu_read_unlock();
	rcu_read_unlock();
}
}


@@ -1115,6 +1137,7 @@ void qmi_rmnet_work_init(void *port)
		return;
		return;
	}
	}
	INIT_DEFERRABLE_WORK(&rmnet_work->work, qmi_rmnet_check_stats);
	INIT_DEFERRABLE_WORK(&rmnet_work->work, qmi_rmnet_check_stats);
	alarm_init(&rmnet_work->atimer, ALARM_BOOTTIME, qmi_rmnet_work_alarm);
	rmnet_work->port = port;
	rmnet_work->port = port;
	rmnet_get_packets(rmnet_work->port, &rmnet_work->old_rx_pkts,
	rmnet_get_packets(rmnet_work->port, &rmnet_work->old_rx_pkts,
			  &rmnet_work->old_tx_pkts);
			  &rmnet_work->old_tx_pkts);
@@ -1146,6 +1169,7 @@ void qmi_rmnet_work_exit(void *port)
	rmnet_work_quit = true;
	rmnet_work_quit = true;
	synchronize_rcu();
	synchronize_rcu();


	alarm_cancel(&rmnet_work->atimer);
	cancel_delayed_work_sync(&rmnet_work->work);
	cancel_delayed_work_sync(&rmnet_work->work);
	destroy_workqueue(rmnet_ps_wq);
	destroy_workqueue(rmnet_ps_wq);
	qmi_rmnet_work_set_active(port, 0);
	qmi_rmnet_work_set_active(port, 0);