diff options
author | Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> | 2020-02-14 17:50:47 -0800 |
---|---|---|
committer | Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> | 2020-02-18 13:01:22 -0800 |
commit | b092b50c5452330f9d0b0fef22ecce617093df93 (patch) | |
tree | 8598e84349ede7e95369e9daa1f72c0942f53f86 | |
parent | c93506932fc4870b824f8412a34775d37900b04c (diff) | |
download | data-kernel-b092b50c5452330f9d0b0fef22ecce617093df93.tar.gz |
drivers: rmnet_shs: Fix invalid mask on vnd creation
For a time after a vnd is created, the shs internal map_mask is updated
to an invalid state. If this happens during data transfer it could cause
invalid cpu states.
This fix will cause the map_mask to only take into acount already initialized
vnd rps values.
Fixes the following-
Unable to handle kernel write to read-only memory at virtual address ffffff99a0b5484c
pc : rmnet_shs_flush_lock_table+0x264/0x688 [rmnet_shs]
lr : rmnet_shs_flush_lock_table+0x238/0x688 [rmnet_shs]
Call trace:
rmnet_shs_flush_lock_table+0x264/0x688 [rmnet_shs]
rmnet_shs_chain_to_skb_list+0x320/0x340 [rmnet_shs]
rmnet_shs_assign+0x980/0x1290 [rmnet_shs]
rmnet_deliver_skb+0x240/0x410
rmnet_frag_deliver+0x618/0x778
rmnet_perf_core_flush_curr_pkt+0x12c/0x148 [rmnet_perf]
rmnet_perf_tcp_opt_ingress+0x88/0x268 [rmnet_perf]
rmnet_perf_opt_ingress+0x348/0x398 [rmnet_perf]
rmnet_perf_core_desc_entry+0x128/0x180 [rmnet_perf]
rmnet_frag_ingress_handler+0x3a8/0x578
rmnet_rx_handler+0x230/0x400
__netif_receive_skb_core+0x518/0xd60
process_backlog+0x1d4/0x438
net_rx_action+0x124/0x5b8
__do_softirq+0x2f8/0x5d8
irq_exit+0xec/0x110
handle_IPI+0x1b8/0x2f8
gic_handle_irq+0x10c/0x1d0
el0_irq_naked+0x50/0x5c
Change-Id: I4c10ebb83140eb14ee3b643d057e3de29dfa851b
Acked-by: Raul Martinez <mraul@qti.qualcomm.com>
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
-rw-r--r-- | drivers/rmnet/shs/rmnet_shs_wq.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/drivers/rmnet/shs/rmnet_shs_wq.c b/drivers/rmnet/shs/rmnet_shs_wq.c index 4c69b57..620a41f 100644 --- a/drivers/rmnet/shs/rmnet_shs_wq.c +++ b/drivers/rmnet/shs/rmnet_shs_wq.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +/* Copyright (c) 2018-2020 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 @@ -1875,19 +1875,30 @@ void rmnet_shs_update_cfg_mask(void) { /* Start with most avaible mask all eps could share*/ u8 mask = UPDATE_MASK; + u8 rps_enabled = 0; struct rmnet_shs_wq_ep_s *ep; list_for_each_entry(ep, &rmnet_shs_wq_ep_tbl, ep_list_id) { if (!ep->is_ep_active) continue; - /* Bitwise and to get common mask VNDs with different mask - * will have UNDEFINED behavior + /* Bitwise and to get common mask from non-null masks. + * VNDs with different mask will have UNDEFINED behavior */ - mask &= ep->rps_config_msk; + if (ep->rps_config_msk) { + mask &= ep->rps_config_msk; + rps_enabled = 1; + } + } + + if (!rps_enabled) { + rmnet_shs_cfg.map_mask = 0; + rmnet_shs_cfg.map_len = 0; + return; + } else if (rmnet_shs_cfg.map_mask != mask) { + rmnet_shs_cfg.map_mask = mask; + rmnet_shs_cfg.map_len = rmnet_shs_get_mask_len(mask); } - rmnet_shs_cfg.map_mask = mask; - rmnet_shs_cfg.map_len = rmnet_shs_get_mask_len(mask); } void rmnet_shs_wq_update_stats(void) |