[qca-nss-sfe] Remove active list for the ipv4

to maintain the active list needs use lock, use new packets
number to mark active connection.

Change-Id: Id676f6b47c72ea898f45f014848f5d24d6cb98e0
Signed-off-by: Ken Zhu <quic_guigenz@quicinc.com>
diff --git a/sfe_ipv4.c b/sfe_ipv4.c
index 70b1e53..de2e383 100644
--- a/sfe_ipv4.c
+++ b/sfe_ipv4.c
@@ -381,23 +381,6 @@
 
 	hlist_del_init_rcu(&cm->hnode);
 
-	/*
-	 * If the connection match entry is in the active list remove it.
-	 */
-	if (cm->active) {
-		if (likely(cm->active_prev)) {
-			cm->active_prev->active_next = cm->active_next;
-		} else {
-			si->active_head = cm->active_next;
-		}
-
-		if (likely(cm->active_next)) {
-			cm->active_next->active_prev = cm->active_prev;
-		} else {
-			si->active_tail = cm->active_prev;
-		}
-	}
-
 }
 
 /*
@@ -575,6 +558,13 @@
 		si->all_connections_tail = c->all_connections_prev;
 	}
 
+	/*
+	 * If I am the next sync connection, move the sync to my next or head.
+	 */
+	if (unlikely(si->wc_next == c)) {
+		si->wc_next = c->all_connections_next;
+	}
+
 	c->removed = true;
 	si->num_connections--;
 	return true;
@@ -959,25 +949,6 @@
 	atomic_inc(&cm->rx_packet_count);
 	atomic_add(len, &cm->rx_byte_count);
 
-	/*
-	 * If we're not already on the active list then insert ourselves at the tail
-	 * of the current list.
-	 */
-	if (unlikely(!cm->active)) {
-		spin_lock_bh(&si->lock);
-		if (unlikely(!cm->active)) {
-			cm->active = true;
-			cm->active_prev = si->active_tail;
-			if (likely(si->active_tail)) {
-				si->active_tail->active_next = cm;
-			} else {
-				si->active_head = cm;
-			}
-			si->active_tail = cm;
-		}
-		spin_unlock_bh(&si->lock);
-	}
-
 	xmit_dev = cm->xmit_dev;
 	skb->dev = xmit_dev;
 
@@ -1564,26 +1535,6 @@
 	atomic_inc(&cm->rx_packet_count);
 	atomic_add(len, &cm->rx_byte_count);
 
-	/*
-	 * If we're not already on the active list then insert ourselves at the tail
-	 * of the current list.
-	 */
-	if (unlikely(!cm->active)) {
-		spin_lock_bh(&si->lock);
-		if (unlikely(!cm->active)) {
-
-			cm->active = true;
-			cm->active_prev = si->active_tail;
-			if (likely(si->active_tail)) {
-				si->active_tail->active_next = cm;
-			} else {
-				si->active_head = cm;
-			}
-			si->active_tail = cm;
-		}
-		spin_unlock_bh(&si->lock);
-	}
-
 	xmit_dev = cm->xmit_dev;
 	skb->dev = xmit_dev;
 
@@ -2172,9 +2123,6 @@
 	}
 
 #endif
-	original_cm->active_next = NULL;
-	original_cm->active_prev = NULL;
-	original_cm->active = false;
 
 	/*
 	 * For PPP links we don't write an L2 header.  For everything else we do.
@@ -2239,9 +2187,6 @@
 	}
 
 #endif
-	reply_cm->active_next = NULL;
-	reply_cm->active_prev = NULL;
-	reply_cm->active = false;
 
 	/*
 	 * For PPP links we don't write an L2 header.  For everything else we do.
@@ -2473,6 +2418,7 @@
 	u64 now_jiffies;
 	int quota;
 	sfe_sync_rule_callback_t sync_rule_callback;
+	struct sfe_ipv4_connection *c;
 
 	now_jiffies = get_jiffies_64();
 
@@ -2486,75 +2432,65 @@
 	spin_lock_bh(&si->lock);
 
 	/*
+	 * If we have reached the end of the connection list, walk from
+	 * the connection head.
+	 */
+	c = si->wc_next;
+	if (unlikely(!c)) {
+		c = si->all_connections_head;
+	}
+
+	/*
 	 * Get an estimate of the number of connections to parse in this sync.
 	 */
 	quota = (si->num_connections + 63) / 64;
 
 	/*
-	 * Walk the "active" list and sync the connection state.
+	 * Walk the "all connection" list and sync the connection state.
 	 */
-	while (quota--) {
+	while (likely(c && quota)) {
 		struct sfe_ipv4_connection_match *cm;
 		struct sfe_ipv4_connection_match *counter_cm;
-		struct sfe_ipv4_connection *c;
 		struct sfe_connection_sync sis;
 
-		cm = si->active_head;
-		if (!cm) {
-			break;
-		}
+		cm = c->original_match;
+		counter_cm = c->reply_match;
 
 		/*
-		 * There's a possibility that our counter match is in the active list too.
-		 * If it is then remove it.
+		 * Didn't receive packets in the original direction or reply
+		 * direction, move to the next connection.
 		 */
-		counter_cm = cm->counter_match;
-		if (counter_cm->active) {
-			counter_cm->active = false;
-
-			/*
-			 * We must have a connection preceding this counter match
-			 * because that's the one that got us to this point, so we don't have
-			 * to worry about removing the head of the list.
-			 */
-			counter_cm->active_prev->active_next = counter_cm->active_next;
-
-			if (likely(counter_cm->active_next)) {
-				counter_cm->active_next->active_prev = counter_cm->active_prev;
-			} else {
-				si->active_tail = counter_cm->active_prev;
-			}
-
-			counter_cm->active_next = NULL;
-			counter_cm->active_prev = NULL;
+		if ((!atomic_read(&cm->rx_packet_count)) && !(atomic_read(&counter_cm->rx_packet_count))) {
+			c = c->all_connections_next;
+			continue;
 		}
 
-		/*
-		 * Now remove the head of the active scan list.
-		 */
-		cm->active = false;
-		si->active_head = cm->active_next;
-		if (likely(cm->active_next)) {
-			cm->active_next->active_prev = NULL;
-		} else {
-			si->active_tail = NULL;
-		}
-		cm->active_next = NULL;
+		quota--;
 
-		/*
-		 * Sync the connection state.
-		 */
-		c = cm->connection;
 		sfe_ipv4_gen_sync_sfe_ipv4_connection(si, c, &sis, SFE_SYNC_REASON_STATS, now_jiffies);
 
+		si->wc_next = c->all_connections_next;
+
 		/*
 		 * We don't want to be holding the lock when we sync!
 		 */
 		spin_unlock_bh(&si->lock);
 		sync_rule_callback(&sis);
 		spin_lock_bh(&si->lock);
+
+		/*
+		 * c must be set and used in the same lock/unlock window;
+		 * because c could be removed when we don't hold the lock,
+		 * so delay grabbing until after the callback and relock.
+		 */
+		c = si->wc_next;
 	}
 
+	/*
+	 * At the end of the sync, put the wc_next to the connection we left.
+	 */
+	si->wc_next = c;
+
 	spin_unlock_bh(&si->lock);
 	rcu_read_unlock();
 
diff --git a/sfe_ipv4.h b/sfe_ipv4.h
index 25411aa..da2f748 100644
--- a/sfe_ipv4.h
+++ b/sfe_ipv4.h
@@ -66,10 +66,6 @@
 	struct sfe_ipv4_connection *connection;
 	struct sfe_ipv4_connection_match *counter_match;
 					/* Matches the flow in the opposite direction as the one in *connection */
-	struct sfe_ipv4_connection_match *active_next;
-	struct sfe_ipv4_connection_match *active_prev;
-	bool active;			/* Flag to indicate if we're on the active list */
-
 	/*
 	 * Characteristics that identify flows that match this rule.
 	 */
@@ -260,10 +256,6 @@
  */
 struct sfe_ipv4 {
 	spinlock_t lock;		/* Lock for SMP correctness */
-	struct sfe_ipv4_connection_match *active_head;
-					/* Head of the list of recently active connections */
-	struct sfe_ipv4_connection_match *active_tail;
-					/* Tail of the list of recently active connections */
 	struct sfe_ipv4_connection *all_connections_head;
 					/* Head of the list of all connections */
 	struct sfe_ipv4_connection *all_connections_tail;
@@ -290,6 +282,8 @@
 	struct sfe_ipv4_stats __percpu *stats_pcpu;
 					/* Per CPU statistics. */
 
+	struct sfe_ipv4_connection *wc_next; /* Connection list walk pointer for stats sync */
+
 	/*
 	 * Control state.
 	 */