dfc: hold wakelock while powersave timer is running
Powersave alarm timer could fail and delay suspend for 2 seconds if the timer expires in 2 seconds. Change to hold a wakelock for the actual duration of the timer so the suspend can be triggered after timer expiration without delay. Change-Id: Icc3cb835d4e174955e128c5a0c80198513213b2d Acked-by: Weiyi Chen <quic_weiyic@quicinc.com> Signed-off-by: Subash Abhinov Kasiviswanathan <quic_subashab@quicinc.com>
This commit is contained in:
parent
2959ed5eb8
commit
143e81f470
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <soc/qcom/qmi_rmnet.h>
|
||||
@ -45,7 +46,8 @@ 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))
|
||||
#define PS_INTERVAL_MS (1000)
|
||||
#define PS_INTERVAL_KT (ms_to_ktime(PS_INTERVAL_MS))
|
||||
#define WATCHDOG_EXPIRE_JF (msecs_to_jiffies(50))
|
||||
|
||||
#ifdef CONFIG_QCOM_QMI_DFC
|
||||
@ -617,6 +619,7 @@ qmi_rmnet_setup_client(void *port, struct qmi_info *qmi, struct tcmsg *tcm)
|
||||
if (!qmi)
|
||||
return -ENOMEM;
|
||||
|
||||
qmi->ws = wakeup_source_register(NULL, "RMNET_DFC");
|
||||
rmnet_init_qmi_pt(port, qmi);
|
||||
}
|
||||
|
||||
@ -665,6 +668,7 @@ __qmi_rmnet_delete_client(void *port, struct qmi_info *qmi, int idx)
|
||||
|
||||
if (!qmi_rmnet_has_client(qmi) && !qmi_rmnet_has_pending(qmi)) {
|
||||
rmnet_reset_qmi_pt(port);
|
||||
wakeup_source_unregister(qmi->ws);
|
||||
kfree(qmi);
|
||||
return 0;
|
||||
}
|
||||
@ -733,6 +737,7 @@ void qmi_rmnet_change_link(struct net_device *dev, void *port, void *tcm_pt)
|
||||
!qmi_rmnet_has_client(qmi) &&
|
||||
!qmi_rmnet_has_pending(qmi)) {
|
||||
rmnet_reset_qmi_pt(port);
|
||||
wakeup_source_unregister(qmi->ws);
|
||||
kfree(qmi);
|
||||
}
|
||||
} else if (tcm->tcm_ifindex & FLAG_POWERSAVE_MASK) {
|
||||
@ -1146,6 +1151,22 @@ static enum alarmtimer_restart qmi_rmnet_work_alarm(struct alarm *atimer,
|
||||
return ALARMTIMER_NORESTART;
|
||||
}
|
||||
|
||||
static void dfc_wakelock_acquire(struct qmi_info *qmi)
|
||||
{
|
||||
if (qmi && !qmi->wakelock_active) {
|
||||
__pm_stay_awake(qmi->ws);
|
||||
qmi->wakelock_active = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void dfc_wakelock_release(struct qmi_info *qmi)
|
||||
{
|
||||
if (qmi && qmi->wakelock_active) {
|
||||
__pm_relax(qmi->ws);
|
||||
qmi->wakelock_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void qmi_rmnet_check_stats(struct work_struct *work)
|
||||
{
|
||||
struct rmnet_powersave_work *real_work;
|
||||
@ -1165,6 +1186,17 @@ static void qmi_rmnet_check_stats(struct work_struct *work)
|
||||
if (unlikely(!qmi))
|
||||
return;
|
||||
|
||||
dfc_wakelock_release(qmi);
|
||||
|
||||
rmnet_get_packets(real_work->port, &rx, &tx);
|
||||
rxd = rx - real_work->old_rx_pkts;
|
||||
txd = tx - real_work->old_tx_pkts;
|
||||
real_work->old_rx_pkts = rx;
|
||||
real_work->old_tx_pkts = tx;
|
||||
|
||||
dl_msg_active = qmi->dl_msg_active;
|
||||
qmi->dl_msg_active = false;
|
||||
|
||||
if (qmi->ps_enabled) {
|
||||
|
||||
/* Ready to accept grant */
|
||||
@ -1185,15 +1217,6 @@ static void qmi_rmnet_check_stats(struct work_struct *work)
|
||||
goto end;
|
||||
}
|
||||
|
||||
rmnet_get_packets(real_work->port, &rx, &tx);
|
||||
rxd = rx - real_work->old_rx_pkts;
|
||||
txd = tx - real_work->old_tx_pkts;
|
||||
real_work->old_rx_pkts = rx;
|
||||
real_work->old_tx_pkts = tx;
|
||||
|
||||
dl_msg_active = qmi->dl_msg_active;
|
||||
qmi->dl_msg_active = false;
|
||||
|
||||
if (!rxd && !txd) {
|
||||
/* If no DL msg received and there is a flow disabled,
|
||||
* (likely in RLF), no need to enter powersave
|
||||
@ -1227,12 +1250,19 @@ static void qmi_rmnet_check_stats(struct work_struct *work)
|
||||
end:
|
||||
rcu_read_lock();
|
||||
if (!rmnet_work_quit) {
|
||||
if (use_alarm_timer)
|
||||
if (use_alarm_timer) {
|
||||
/* Suspend will fail and get delayed for 2s if
|
||||
* alarmtimer expires within 2s. Hold a wakelock
|
||||
* for the actual timer duration to prevent suspend
|
||||
*/
|
||||
if (PS_INTERVAL_MS < 2000)
|
||||
dfc_wakelock_acquire(qmi);
|
||||
alarm_start_relative(&real_work->atimer,
|
||||
PS_INTERVAL_KT);
|
||||
else
|
||||
} else {
|
||||
queue_delayed_work(rmnet_ps_wq, &real_work->work,
|
||||
PS_INTERVAL);
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
@ -1310,6 +1340,7 @@ void qmi_rmnet_work_exit(void *port)
|
||||
rmnet_ps_wq = NULL;
|
||||
kfree(rmnet_work);
|
||||
rmnet_work = NULL;
|
||||
dfc_wakelock_release((struct qmi_info *)rmnet_get_qmi_pt(port));
|
||||
}
|
||||
EXPORT_SYMBOL(qmi_rmnet_work_exit);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _RMNET_QMI_I_H
|
||||
@ -9,6 +10,7 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/pm_wakeup.h>
|
||||
|
||||
#define MAX_MQ_NUM 16
|
||||
#define MAX_CLIENT_NUM 2
|
||||
@ -97,6 +99,8 @@ struct qmi_info {
|
||||
bool ps_enabled;
|
||||
bool dl_msg_active;
|
||||
bool ps_ignore_grant;
|
||||
bool wakelock_active;
|
||||
struct wakeup_source *ws;
|
||||
};
|
||||
|
||||
enum data_ep_type_enum_v01 {
|
||||
|
Loading…
Reference in New Issue
Block a user