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

Commit 680d6fcb authored by Skylar Chang's avatar Skylar Chang Committed by Gerrit - the friendly Code Review server
Browse files

msm: ipa: rm: enhance inactivity timer logic



The current implementation of IPA RM inactivity timer is to set
or cancel the inactivity timer per TX packet to IPA.
For better performance, instead of canceling the timer, a flag is set
to indicate that timer needs to be set again after expiration.
In this was the setting the inactivity timer happens on control path
every 1 second instead of on data path on each TX packet to IPA.

Change-Id: Ibaf34f3549f63feb3fb7b980d2915e30bb700549
Acked-by: default avatarAdy Abraham <adya@qti.qualcomm.com>
Signed-off-by: default avatarSkylar Chang <chiaweic@codeaurora.org>
parent 6b6b4c37
Loading
Loading
Loading
Loading
+35 −22
Original line number Diff line number Diff line
/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -28,8 +28,10 @@
 * @resource_name - resource name
 * @work: delayed work object for running delayed releas
 *	function
 * @release_in_prog: boolean flag indicates if release resource
 *			is scheduled for happen in the future.
 * @resource_requested: boolean flag indicates if resource was requested
 * @reschedule_work: boolean flag indicates to not release and to
 *	reschedule the release work.
 * @work_in_progress: boolean flag indicates is release work was scheduled.
 * @jiffies: number of jiffies for timeout
 *
 * WWAN private - holds all relevant info about WWAN driver
@@ -39,7 +41,9 @@ struct ipa_rm_it_private {
	enum ipa_rm_resource_name resource_name;
	spinlock_t lock;
	struct delayed_work work;
	bool release_in_prog;
	bool resource_requested;
	bool reschedule_work;
	bool work_in_progress;
	unsigned long jiffies;
};

@@ -47,13 +51,11 @@ static struct ipa_rm_it_private ipa_rm_it_handles[IPA_RM_RESOURCE_MAX];

/**
 * ipa_rm_inactivity_timer_func() - called when timer expired in
 * the context of the shared workqueue. Checks internally is
 * release_in_prog flag is set and calls to
 * ipa_rm_release_resource(). release_in_prog is cleared when
 * calling to ipa_rm_inactivity_timer_request_resource(). In
 * this situation this function shall not call to
 * ipa_rm_release_resource() since the resource needs to remain
 * up
 * the context of the shared workqueue. Checks internally if
 * reschedule_work flag is set. In case it is not set this function calls to
 * ipa_rm_release_resource(). In case reschedule_work is set this function
 * reschedule the work. This flag is cleared cleared when
 * calling to ipa_rm_inactivity_timer_release_resource().
 *
 * @work: work object provided by the work queue
 *
@@ -71,14 +73,22 @@ static void ipa_rm_inactivity_timer_func(struct work_struct *work)
	IPADBG("%s: timer expired for resource %d!\n", __func__,
	    me->resource_name);

	/* check that release still need to be performed */
	spin_lock_irqsave(
		&ipa_rm_it_handles[me->resource_name].lock, flags);
	if (ipa_rm_it_handles[me->resource_name].release_in_prog) {
	if (ipa_rm_it_handles[me->resource_name].reschedule_work) {
		IPADBG("%s: setting delayed work\n", __func__);
		ipa_rm_it_handles[me->resource_name].reschedule_work = false;
		schedule_delayed_work(
			&ipa_rm_it_handles[me->resource_name].work,
			ipa_rm_it_handles[me->resource_name].jiffies);
	} else if (ipa_rm_it_handles[me->resource_name].resource_requested) {
		IPADBG("%s: not calling release\n", __func__);
		ipa_rm_it_handles[me->resource_name].work_in_progress = false;
	} else {
		IPADBG("%s: calling release_resource on resource %d!\n",
			__func__, me->resource_name);
		ipa_rm_release_resource(me->resource_name);
		ipa_rm_it_handles[me->resource_name].release_in_prog = false;
		ipa_rm_it_handles[me->resource_name].work_in_progress = false;
	}
	spin_unlock_irqrestore(
		&ipa_rm_it_handles[me->resource_name].lock, flags);
@@ -117,7 +127,9 @@ int ipa_rm_inactivity_timer_init(enum ipa_rm_resource_name resource_name,
	spin_lock_init(&ipa_rm_it_handles[resource_name].lock);
	ipa_rm_it_handles[resource_name].resource_name = resource_name;
	ipa_rm_it_handles[resource_name].jiffies = msecs_to_jiffies(msecs);
	ipa_rm_it_handles[resource_name].release_in_prog = false;
	ipa_rm_it_handles[resource_name].resource_requested = false;
	ipa_rm_it_handles[resource_name].reschedule_work = false;
	ipa_rm_it_handles[resource_name].work_in_progress = false;

	INIT_DELAYED_WORK(&ipa_rm_it_handles[resource_name].work,
			  ipa_rm_inactivity_timer_func);
@@ -193,8 +205,7 @@ int ipa_rm_inactivity_timer_request_resource(
	}

	spin_lock_irqsave(&ipa_rm_it_handles[resource_name].lock, flags);
	cancel_delayed_work(&ipa_rm_it_handles[resource_name].work);
	ipa_rm_it_handles[resource_name].release_in_prog = false;
	ipa_rm_it_handles[resource_name].resource_requested = true;
	spin_unlock_irqrestore(&ipa_rm_it_handles[resource_name].lock, flags);
	ret = ipa_rm_request_resource(resource_name);
	IPADBG("%s: resource %d: returning %d\n", __func__, resource_name, ret);
@@ -235,19 +246,21 @@ int ipa_rm_inactivity_timer_release_resource(
	}

	spin_lock_irqsave(&ipa_rm_it_handles[resource_name].lock, flags);
	if (ipa_rm_it_handles[resource_name].release_in_prog) {
	ipa_rm_it_handles[resource_name].resource_requested = false;
	if (ipa_rm_it_handles[resource_name].work_in_progress) {
		IPADBG("%s: Timer already set, not scheduling again %d\n",
		    __func__, resource_name);
		ipa_rm_it_handles[resource_name].reschedule_work = true;
		spin_unlock_irqrestore(
			&ipa_rm_it_handles[resource_name].lock, flags);
		return 0;
	}
	ipa_rm_it_handles[resource_name].release_in_prog = true;
	spin_unlock_irqrestore(&ipa_rm_it_handles[resource_name].lock, flags);

	ipa_rm_it_handles[resource_name].work_in_progress = true;
	ipa_rm_it_handles[resource_name].reschedule_work = false;
	IPADBG("%s: setting delayed work\n", __func__);
	schedule_delayed_work(&ipa_rm_it_handles[resource_name].work,
			      ipa_rm_it_handles[resource_name].jiffies);
	spin_unlock_irqrestore(&ipa_rm_it_handles[resource_name].lock, flags);

	return 0;
}