summaryrefslogtreecommitdiff
path: root/drivers/rmnet/shs/rmnet_shs_wq.c
diff options
context:
space:
mode:
authorarnav_s <arnav_s@codeaurora.org>2019-03-23 11:41:36 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2019-03-26 11:52:26 -0700
commitf5c70f1c6affa97a0a78194d6172a834db5db3b3 (patch)
tree50889095ac5a90f3f8caa9a5da008b6f41158ac0 /drivers/rmnet/shs/rmnet_shs_wq.c
parent1ec54bfcd4402ffde4c144a9409cc056070df9d0 (diff)
downloaddata-kernel-f5c70f1c6affa97a0a78194d6172a834db5db3b3.tar.gz
Fast-Forward driver/rmnet folder from 4.0 to 5.0
CRs-Fixed: 2423695 Change-Id: I3524afc3252d918b336a6026727ce7f8026dc7b0
Diffstat (limited to 'drivers/rmnet/shs/rmnet_shs_wq.c')
-rw-r--r--drivers/rmnet/shs/rmnet_shs_wq.c77
1 files changed, 63 insertions, 14 deletions
diff --git a/drivers/rmnet/shs/rmnet_shs_wq.c b/drivers/rmnet/shs/rmnet_shs_wq.c
index 42f316c..6f22589 100644
--- a/drivers/rmnet/shs/rmnet_shs_wq.c
+++ b/drivers/rmnet/shs/rmnet_shs_wq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019 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
@@ -101,6 +101,14 @@ unsigned long long rmnet_shs_cpu_rx_pps[MAX_CPUS];
module_param_array(rmnet_shs_cpu_rx_pps, ullong, 0, 0444);
MODULE_PARM_DESC(rmnet_shs_cpu_rx_pps, "SHS stamp pkt enq rate per CPU");
+unsigned long long rmnet_shs_cpu_qhead_diff[MAX_CPUS];
+module_param_array(rmnet_shs_cpu_qhead_diff, ullong, 0, 0444);
+MODULE_PARM_DESC(rmnet_shs_cpu_qhead_diff, "SHS nw stack queue processed diff");
+
+unsigned long long rmnet_shs_cpu_qhead_total[MAX_CPUS];
+module_param_array(rmnet_shs_cpu_qhead_total, ullong, 0, 0444);
+MODULE_PARM_DESC(rmnet_shs_cpu_qhead_total, "SHS nw stack queue processed total");
+
unsigned long rmnet_shs_flow_hash[MAX_SUPPORTED_FLOWS_DEBUG];
module_param_array(rmnet_shs_flow_hash, ulong, 0, 0444);
MODULE_PARM_DESC(rmnet_shs_flow_hash, "SHS stamp hash flow");
@@ -297,7 +305,7 @@ void rmnet_shs_wq_hstat_alloc_nodes(u8 num_nodes_to_allocate, u8 is_store_perm)
struct rmnet_shs_wq_hstat_s *hnode = NULL;
while (num_nodes_to_allocate > 0) {
- hnode = kzalloc(sizeof(*hnode), 0);
+ hnode = kzalloc(sizeof(*hnode), GFP_ATOMIC);
if (hnode) {
hnode->is_perm = is_store_perm;
rmnet_shs_wq_hstat_reset_node(hnode);
@@ -349,7 +357,8 @@ struct rmnet_shs_wq_hstat_s *rmnet_shs_wq_get_new_hstat_node(void)
* However, this newly allocated memory will be released as soon as we
* realize that this flow is inactive
*/
- ret_node = kzalloc(sizeof(*hnode), 0);
+ ret_node = kzalloc(sizeof(*hnode), GFP_ATOMIC);
+
if (!ret_node) {
rmnet_shs_crit_err[RMNET_SHS_WQ_ALLOC_HSTAT_ERR]++;
return NULL;
@@ -534,7 +543,8 @@ static void rmnet_shs_wq_refresh_cpu_rates_debug(u16 cpu,
rmnet_shs_cpu_rx_flows[cpu] = cpu_p->flows;
rmnet_shs_cpu_rx_bytes[cpu] = cpu_p->rx_bytes;
rmnet_shs_cpu_rx_pkts[cpu] = cpu_p->rx_skbs;
-
+ rmnet_shs_cpu_qhead_diff[cpu] = cpu_p->qhead_diff;
+ rmnet_shs_cpu_qhead_total[cpu] = cpu_p->qhead_total;
}
static void rmnet_shs_wq_refresh_dl_mrkr_stats(void)
@@ -596,10 +606,21 @@ static void rmnet_shs_wq_refresh_cpu_stats(u16 cpu)
struct rmnet_shs_wq_cpu_rx_pkt_q_s *cpu_p;
time_t tdiff;
u64 new_skbs, new_bytes;
+ u32 new_qhead;
cpu_p = &rmnet_shs_rx_flow_tbl.cpu_list[cpu];
new_skbs = cpu_p->rx_skbs - cpu_p->last_rx_skbs;
+ new_qhead = rmnet_shs_get_cpu_qhead(cpu);
+ if (cpu_p->qhead_start == 0) {
+ cpu_p->qhead_start = new_qhead;
+ }
+
+ cpu_p->last_qhead = cpu_p->qhead;
+ cpu_p->qhead = new_qhead;
+ cpu_p->qhead_diff = cpu_p->qhead - cpu_p->last_qhead;
+ cpu_p->qhead_total = cpu_p->qhead - cpu_p->qhead_start;
+
if (rmnet_shs_cpu_node_tbl[cpu].wqprio)
rmnet_shs_cpu_node_tbl[cpu].wqprio = (rmnet_shs_cpu_node_tbl[cpu].wqprio + 1)
% (PRIO_BACKOFF);
@@ -661,16 +682,20 @@ void rmnet_shs_wq_update_cpu_rx_tbl(struct rmnet_shs_wq_hstat_s *hstat_p)
if (hstat_p->inactive_duration > 0)
return;
+ rcu_read_lock();
map = rcu_dereference(node_p->dev->_rx->rps_map);
- if (!map)
+ if (!map || node_p->map_index > map->len || !map->len) {
+ rcu_read_unlock();
return;
+ }
map_idx = node_p->map_index;
cpu_num = map->cpus[map_idx];
skb_diff = hstat_p->rx_skb - hstat_p->last_rx_skb;
byte_diff = hstat_p->rx_bytes - hstat_p->last_rx_bytes;
+ rcu_read_unlock();
if (hstat_p->is_new_flow) {
rmnet_shs_wq_cpu_list_add(hstat_p,
@@ -825,6 +850,7 @@ u16 rmnet_shs_wq_find_cpu_to_move_flows(u16 current_cpu,
u16 cpu_to_move = current_cpu;
u16 cpu_num;
u8 is_core_in_msk;
+ u32 cpu_to_move_util = 0;
if (!ep) {
rmnet_shs_crit_err[RMNET_SHS_WQ_EP_ACCESS_ERR]++;
@@ -834,13 +860,15 @@ u16 rmnet_shs_wq_find_cpu_to_move_flows(u16 current_cpu,
cur_cpu_list_p = &rx_flow_tbl_p->cpu_list[current_cpu];
cur_cpu_rx_pps = cur_cpu_list_p->rx_pps;
pps_uthresh = rmnet_shs_cpu_rx_max_pps_thresh[current_cpu];
+ pps_lthresh = rmnet_shs_cpu_rx_min_pps_thresh[current_cpu];
+
/* If we are already on a perf core and required pps is beyond
* beyond the capacity that even perf cores aren't sufficient
* there is nothing much we can do. So we will continue to let flows
* process packets on same perf core
*/
if (!rmnet_shs_is_lpwr_cpu(current_cpu) &&
- (cur_cpu_rx_pps > pps_uthresh)) {
+ (cur_cpu_rx_pps > pps_lthresh)) {
return cpu_to_move;
}
/* If a core (should only be lpwr was marked prio we don't touch it
@@ -874,10 +902,11 @@ u16 rmnet_shs_wq_find_cpu_to_move_flows(u16 current_cpu,
current_cpu, cpu_num, reqd_pps,
cpu_rx_pps, NULL, NULL);
- /* Return the first available CPU */
- if ((reqd_pps > pps_lthresh) && (reqd_pps < pps_uthresh)) {
+ /* Return the most available valid CPU */
+ if ((reqd_pps > pps_lthresh) && (reqd_pps < pps_uthresh) &&
+ cpu_rx_pps <= cpu_to_move_util) {
cpu_to_move = cpu_num;
- break;
+ cpu_to_move_util = cpu_rx_pps;
}
}
@@ -886,7 +915,6 @@ u16 rmnet_shs_wq_find_cpu_to_move_flows(u16 current_cpu,
current_cpu, cpu_to_move, cur_cpu_rx_pps,
rx_flow_tbl_p->cpu_list[cpu_to_move].rx_pps,
NULL, NULL);
-
return cpu_to_move;
}
@@ -1206,14 +1234,14 @@ void rmnet_shs_wq_update_ep_rps_msk(struct rmnet_shs_wq_ep_s *ep)
rmnet_shs_crit_err[RMNET_SHS_WQ_EP_ACCESS_ERR]++;
return;
}
-
+ rcu_read_lock();
map = rcu_dereference(ep->ep->egress_dev->_rx->rps_map);
ep->rps_config_msk = 0;
if (map != NULL) {
for (len = 0; len < map->len; len++)
ep->rps_config_msk |= (1 << map->cpus[len]);
}
-
+ rcu_read_unlock();
ep->default_core_msk = ep->rps_config_msk & 0x0F;
ep->pri_core_msk = ep->rps_config_msk & 0xF0;
}
@@ -1260,6 +1288,26 @@ void rmnet_shs_wq_refresh_ep_masks(void)
rmnet_shs_wq_update_ep_rps_msk(ep);
}
}
+
+void rmnet_shs_update_cfg_mask(void)
+{
+ /* Start with most avaible mask all eps could share*/
+ u8 mask = UPDATE_MASK;
+ 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
+ */
+ mask &= ep->rps_config_msk;
+ }
+ rmnet_shs_cfg.map_mask = mask;
+ rmnet_shs_cfg.map_len = rmnet_shs_get_mask_len(mask);
+}
+
static void rmnet_shs_wq_update_stats(void)
{
struct timespec time;
@@ -1268,6 +1316,7 @@ static void rmnet_shs_wq_update_stats(void)
(void) getnstimeofday(&time);
rmnet_shs_wq_tnsec = RMNET_SHS_SEC_TO_NSEC(time.tv_sec) + time.tv_nsec;
rmnet_shs_wq_refresh_ep_masks();
+ rmnet_shs_update_cfg_mask();
list_for_each_entry(hnode, &rmnet_shs_wq_hstat_tbl, hstat_node_id) {
if (!hnode)
@@ -1363,7 +1412,7 @@ void rmnet_shs_wq_gather_rmnet_ep(struct net_device *dev)
trace_rmnet_shs_wq_high(RMNET_SHS_WQ_EP_TBL,
RMNET_SHS_WQ_EP_TBL_INIT,
0xDEF, 0xDEF, 0xDEF, 0xDEF, ep, NULL);
- ep_wq = kzalloc(sizeof(*ep_wq), 0);
+ ep_wq = kzalloc(sizeof(*ep_wq), GFP_ATOMIC);
if (!ep_wq) {
rmnet_shs_crit_err[RMNET_SHS_WQ_ALLOC_EP_TBL_ERR]++;
return;
@@ -1423,7 +1472,7 @@ void rmnet_shs_wq_init(struct net_device *dev)
}
rmnet_shs_delayed_wq = kmalloc(sizeof(struct rmnet_shs_delay_wq_s),
- GFP_ATOMIC);
+ GFP_ATOMIC);
if (!rmnet_shs_delayed_wq) {
rmnet_shs_crit_err[RMNET_SHS_WQ_ALLOC_DEL_WQ_ERR]++;