summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarout Hedeshian <harouth@codeaurora.org>2014-12-09 09:06:09 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:05:26 -0700
commit6734942a8de3c58c3f77b259247a30aecbdcd106 (patch)
tree495630f829a49b791da6df8f47ea6fc01e152767
parent6ec986478d6bb9a960a119ea106cdaf04cebfb80 (diff)
net: rmnet_data: Handle VND level MAP flow control with flow ID 0xFFFFFFFF
Flow control the entire RmNet Data virtual network device whenever we receive a MAP flow control command with flow ID 0xFFFFFFFF. Since it is guaranteed that we will never mix 0xFFFFFFFF with other flow IDs (e.g.. disable 0xFFFFFFFF enable 0x00000001), TC based flow control is not required. Instead netif stop/wake queue APIs are used in immediate context. CRs-Fixed: 767337 Change-Id: I8eff0988fa38726284789b70e045cc4b1dbb5d4e Signed-off-by: Harout Hedeshian <harouth@codeaurora.org>
-rw-r--r--net/rmnet_data/rmnet_data_vnd.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/net/rmnet_data/rmnet_data_vnd.c b/net/rmnet_data/rmnet_data_vnd.c
index 8013165bc57d..193ef8160962 100644
--- a/net/rmnet_data/rmnet_data_vnd.c
+++ b/net/rmnet_data/rmnet_data_vnd.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -61,6 +61,7 @@ struct rmnet_vnd_private_s {
rwlock_t flow_map_lock;
struct list_head flow_head;
+ struct rmnet_map_flow_mapping_s root_flow;
};
#define RMNET_VND_FC_QUEUED 0
@@ -1024,6 +1025,11 @@ int rmnet_vnd_do_flow_control(struct net_device *dev,
BUG();
read_lock(&dev_conf->flow_map_lock);
+ if (map_flow_id == 0xFFFFFFFF) {
+ itm = &(dev_conf->root_flow);
+ goto nolookup;
+ }
+
itm = _rmnet_vnd_get_flow_map(dev_conf, map_flow_id);
if (!itm) {
@@ -1031,8 +1037,23 @@ int rmnet_vnd_do_flow_control(struct net_device *dev,
map_flow_id);
goto fcdone;
}
+
+nolookup:
if (v4_seq == 0 || v4_seq >= atomic_read(&(itm->v4_seq))) {
atomic_set(&(itm->v4_seq), v4_seq);
+ if (map_flow_id == 0xFFFFFFFF) {
+ LOGD("Setting VND TX queue state to %d", enable);
+ /* Although we expect similar number of enable/disable
+ * commands, optimize for the disable. That is more
+ * latency sensitive than enable
+ */
+ if (unlikely(enable))
+ netif_wake_queue(dev);
+ else
+ netif_stop_queue(dev);
+ trace_rmnet_fc_map(0xFFFFFFFF, 0, enable);
+ goto fcdone;
+ }
for (i = 0; i < RMNET_MAP_FLOW_NUM_TC_HANDLE; i++) {
if (itm->tc_flow_valid[i] == 1) {
LOGD("Found [%s][0x%08X][%d:0x%08X]",