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

Commit 12c0afc9 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "dfc: Use alarm timer to trigger powersave work"

parents 9d4b29a3 9f3ef66d
Loading
Loading
Loading
Loading
+27 −3
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <trace/events/dfc.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/alarmtimer.h>

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

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

struct rmnet_powersave_work {
	struct delayed_work work;
	struct alarm atimer;
	void *port;
	u64 old_rx_pkts;
	u64 old_tx_pkts;
@@ -1001,6 +1004,16 @@ static void qmi_rmnet_work_restart(void *port)
	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)
{
	struct rmnet_powersave_work *real_work;
@@ -1008,6 +1021,7 @@ static void qmi_rmnet_check_stats(struct work_struct *work)
	u64 rxd, txd;
	u64 rx, tx;
	bool dl_msg_active;
	bool use_alarm_timer = true;

	real_work = container_of(to_delayed_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
		 */
		if (!dl_msg_active &&
		    !rmnet_all_flows_enabled(real_work->port))
		    !rmnet_all_flows_enabled(real_work->port)) {
			use_alarm_timer = false;
			goto end;
		}

		/* Deregister to suppress QMI DFC and DL marker */
		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:
	rcu_read_lock();
	if (!rmnet_work_quit)
		queue_delayed_work(rmnet_ps_wq, &real_work->work, PS_INTERVAL);
	if (!rmnet_work_quit) {
		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();
}

@@ -1115,6 +1137,7 @@ void qmi_rmnet_work_init(void *port)
		return;
	}
	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_get_packets(rmnet_work->port, &rmnet_work->old_rx_pkts,
			  &rmnet_work->old_tx_pkts);
@@ -1146,6 +1169,7 @@ void qmi_rmnet_work_exit(void *port)
	rmnet_work_quit = true;
	synchronize_rcu();

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