RDMA/nes: Forward packets for a new connection with stale APBVT entry

Under heavy traffic, there is a small windows when an APBVT entry is
not yet removed and a new connection is established.  Packets for the
new connection are dropped until APBVT entry is removed.  This patch
will forward the packets instead of dropping them.

Signed-off-by: Faisal Latif <faisal.latif@intel.com>
Signed-off-by: Chien Tung <chien.tin.tung@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index c259ddc..f34fa6f 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -86,7 +86,7 @@
 	struct nes_cm_node *);
 static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *,
 	struct nes_cm_node *);
-static void mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
+static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
 	struct sk_buff *);
 static int mini_cm_dealloc_core(struct nes_cm_core *);
 static int mini_cm_get(struct nes_cm_core *);
@@ -2076,7 +2076,7 @@
  * recv_pkt - recv an ETHERNET packet, and process it through CM
  * node state machine
  */
-static void mini_cm_recv_pkt(struct nes_cm_core *cm_core,
+static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
 	struct nes_vnic *nesvnic, struct sk_buff *skb)
 {
 	struct nes_cm_node *cm_node = NULL;
@@ -2084,23 +2084,16 @@
 	struct iphdr *iph;
 	struct tcphdr *tcph;
 	struct nes_cm_info nfo;
+	int skb_handled = 1;
 
 	if (!skb)
-		return;
+		return 0;
 	if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) {
-		dev_kfree_skb_any(skb);
-		return;
+		return 0;
 	}
 
 	iph = (struct iphdr *)skb->data;
 	tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr));
-	skb_reset_network_header(skb);
-	skb_set_transport_header(skb, sizeof(*tcph));
-	if (!tcph) {
-		dev_kfree_skb_any(skb);
-		return;
-	}
-	skb->len = ntohs(iph->tot_len);
 
 	nfo.loc_addr = ntohl(iph->daddr);
 	nfo.loc_port = ntohs(tcph->dest);
@@ -2121,23 +2114,21 @@
 			/* Only type of packet accepted are for */
 			/* the PASSIVE open (syn only) */
 			if ((!tcph->syn) || (tcph->ack)) {
-				cm_packets_dropped++;
+				skb_handled = 0;
 				break;
 			}
 			listener = find_listener(cm_core, nfo.loc_addr,
 				nfo.loc_port,
 				NES_CM_LISTENER_ACTIVE_STATE);
-			if (listener) {
-				nfo.cm_id = listener->cm_id;
-				nfo.conn_type = listener->conn_type;
-			} else {
-				nes_debug(NES_DBG_CM, "Unable to find listener "
-					"for the pkt\n");
-				cm_packets_dropped++;
-				dev_kfree_skb_any(skb);
+			if (!listener) {
+				nfo.cm_id = NULL;
+				nfo.conn_type = 0;
+				nes_debug(NES_DBG_CM, "Unable to find listener for the pkt\n");
+				skb_handled = 0;
 				break;
 			}
-
+			nfo.cm_id = listener->cm_id;
+			nfo.conn_type = listener->conn_type;
 			cm_node = make_cm_node(cm_core, nesvnic, &nfo,
 				listener);
 			if (!cm_node) {
@@ -2163,9 +2154,13 @@
 			dev_kfree_skb_any(skb);
 			break;
 		}
+		skb_reset_network_header(skb);
+		skb_set_transport_header(skb, sizeof(*tcph));
+		skb->len = ntohs(iph->tot_len);
 		process_packet(cm_node, skb, cm_core);
 		rem_ref_cm_node(cm_core, cm_node);
 	} while (0);
+	return skb_handled;
 }
 
 
@@ -2985,15 +2980,16 @@
  */
 int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice)
 {
+	int rc = 0;
 	cm_packets_received++;
 	if ((g_cm_core) && (g_cm_core->api)) {
-		g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb);
+		rc = g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb);
 	} else {
 		nes_debug(NES_DBG_CM, "Unable to process packet for CM,"
 				" cm is not setup properly.\n");
 	}
 
-	return 0;
+	return rc;
 }