summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>2020-01-10 18:20:45 -0800
committerSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>2020-01-10 18:20:45 -0800
commitbdc07671ca3f0f6e5d37f667ce028fe128636679 (patch)
tree7979f5bad7674fea0925861255eaa894d579455b
parentc7a5aef3cb6d95bd0b307dce66df341be8a91a3d (diff)
downloaddata-kernel-bdc07671ca3f0f6e5d37f667ce028fe128636679.tar.gz
drivers: shs: Clear out pending core switch timers on cleanup
In case there is a burst of data beyond a threshold, the core switch timer will try to schedule a worker once the timer expires. While the pending work is cleaned up on timer expiry, the pending timers itself are not cleared up. As part of this change, the core switch module parameter is reset on start of cleanup to ensure no more timers are configured during the cleanup. Fixes the following- 399.705316: <6> Modules linked in: rmnet_perf(O) [last unloaded: rmnet_shs] 399.734305: <2> pstate: 20400085 (nzCv daIf +PAN -UAO) 399.739251: <2> pc : rb_insert_color+0x10/0x168 399.743555: <2> lr : timerqueue_add+0x88/0xc0 400.413555: <2> Call trace: 400.416084: <2> rb_insert_color+0x10/0x168 400.420042: <2> enqueue_hrtimer+0x198/0x1c0 400.424081: <2> __hrtimer_run_queues+0x4e8/0x5b0 400.428568: <2> hrtimer_interrupt+0x108/0x350 400.432793: <2> arch_timer_handler_virt+0x40/0x50 400.437373: <2> handle_percpu_devid_irq+0x1dc/0x428 400.442122: <2> __handle_domain_irq+0xa0/0xf8 400.446345: <2> gic_handle_irq+0x154/0x1d4 400.450298: <2> el1_irq+0xb4/0x130 CRs-fixed: 2594249 Change-Id: I6e4a1982ce4665340cb1a75d0ec17d1db3f286fc Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
-rw-r--r--drivers/rmnet/shs/rmnet_shs.h4
-rw-r--r--drivers/rmnet/shs/rmnet_shs_config.c6
-rwxr-xr-xdrivers/rmnet/shs/rmnet_shs_main.c19
3 files changed, 21 insertions, 8 deletions
diff --git a/drivers/rmnet/shs/rmnet_shs.h b/drivers/rmnet/shs/rmnet_shs.h
index f6ce09e..b7bf773 100644
--- a/drivers/rmnet/shs/rmnet_shs.h
+++ b/drivers/rmnet/shs/rmnet_shs.h
@@ -299,7 +299,7 @@ extern int (*rmnet_shs_skb_entry)(struct sk_buff *skb,
int rmnet_shs_is_lpwr_cpu(u16 cpu);
void rmnet_shs_cancel_table(void);
void rmnet_shs_rx_wq_init(void);
-void rmnet_shs_rx_wq_exit(void);
+unsigned int rmnet_shs_rx_wq_exit(void);
int rmnet_shs_get_mask_len(u8 mask);
int rmnet_shs_chk_and_flush_node(struct rmnet_shs_skbn_s *node,
@@ -314,7 +314,7 @@ void rmnet_shs_assign(struct sk_buff *skb, struct rmnet_port *port);
void rmnet_shs_flush_table(u8 is_force_flush, u8 ctxt);
void rmnet_shs_cpu_node_remove(struct rmnet_shs_skbn_s *node);
void rmnet_shs_init(struct net_device *dev, struct net_device *vnd);
-void rmnet_shs_exit(void);
+void rmnet_shs_exit(unsigned int cpu_switch);
void rmnet_shs_ps_on_hdlr(void *port);
void rmnet_shs_ps_off_hdlr(void *port);
void rmnet_shs_update_cpu_proc_q_all_cpus(void);
diff --git a/drivers/rmnet/shs/rmnet_shs_config.c b/drivers/rmnet/shs/rmnet_shs_config.c
index e6b4002..6a628dc 100644
--- a/drivers/rmnet/shs/rmnet_shs_config.c
+++ b/drivers/rmnet/shs/rmnet_shs_config.c
@@ -99,14 +99,16 @@ static int rmnet_shs_dev_notify_cb(struct notifier_block *nb,
* phy_dev is going down.
*/
if (!rmnet_vnd_total && rmnet_shs_cfg.rmnet_shs_init_complete) {
+ unsigned int cpu_switch;
+
pr_info("rmnet_shs deinit %s going down ", dev->name);
RCU_INIT_POINTER(rmnet_shs_skb_entry, NULL);
qmi_rmnet_ps_ind_deregister(rmnet_shs_cfg.port,
&rmnet_shs_cfg.rmnet_idl_ind_cb);
rmnet_shs_cancel_table();
- rmnet_shs_rx_wq_exit();
+ cpu_switch = rmnet_shs_rx_wq_exit();
rmnet_shs_wq_exit();
- rmnet_shs_exit();
+ rmnet_shs_exit(cpu_switch);
trace_rmnet_shs_high(RMNET_SHS_MODULE,
RMNET_SHS_MODULE_INIT_WQ,
0xDEF, 0xDEF, 0xDEF,
diff --git a/drivers/rmnet/shs/rmnet_shs_main.c b/drivers/rmnet/shs/rmnet_shs_main.c
index ae66460..2accd29 100755
--- a/drivers/rmnet/shs/rmnet_shs_main.c
+++ b/drivers/rmnet/shs/rmnet_shs_main.c
@@ -1359,14 +1359,25 @@ void rmnet_shs_rx_wq_init(void)
INIT_WORK(&shs_rx_work.work, rmnet_flush_buffered);
}
-void rmnet_shs_rx_wq_exit(void)
+unsigned int rmnet_shs_rx_wq_exit(void)
{
+ unsigned int cpu_switch = rmnet_shs_inst_rate_switch;
int i;
- for (i = 0; i < MAX_CPUS; i++)
+ /* Disable any further core_flush timer starts untill cleanup
+ * is complete.
+ */
+ rmnet_shs_inst_rate_switch = 0;
+
+ for (i = 0; i < MAX_CPUS; i++) {
+ hrtimer_cancel(&GET_CTIMER(i));
+
cancel_work_sync(&rmnet_shs_cfg.core_flush[i].work);
+ }
cancel_work_sync(&shs_rx_work.work);
+
+ return cpu_switch;
}
void rmnet_shs_ps_on_hdlr(void *port)
@@ -1724,7 +1735,7 @@ void rmnet_shs_assign(struct sk_buff *skb, struct rmnet_port *port)
/* Cancels the flushing timer if it has been armed
* Deregisters DL marker indications
*/
-void rmnet_shs_exit(void)
+void rmnet_shs_exit(unsigned int cpu_switch)
{
rmnet_shs_freq_exit();
rmnet_shs_cfg.dl_mrk_ind_cb.dl_hdr_handler = NULL;
@@ -1738,5 +1749,5 @@ void rmnet_shs_exit(void)
memset(&rmnet_shs_cfg, 0, sizeof(rmnet_shs_cfg));
rmnet_shs_cfg.port = NULL;
rmnet_shs_cfg.rmnet_shs_init_complete = 0;
-
+ rmnet_shs_inst_rate_switch = cpu_switch;
}