qcacmn: Register API to flush frags in dp peer ops

Register dp_peer_flush_frags API in dp peer ops
for flushing fragments for a particular peer.

Bug: 175626671
Test: Regression test
Change-Id: Ia179d3160bdc306ec965c465134042c66a0c40a6
CRs-Fixed: 2874366
Signed-off-by: Hsiu-Chang Chen <hsiuchangchen@google.com>
diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h
index 495fb64..f484908 100644
--- a/dp/wifi3.0/dp_internal.h
+++ b/dp/wifi3.0/dp_internal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, 2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -1395,4 +1395,15 @@
 
 }
 
+/**
+ * dp_peer_flush_frags() - Flush all fragments for a particular
+ *  peer
+ * @pdev - dp pdev handle
+ * @vdev_id - vdev id
+ * @peer_addr - peer mac address
+ *
+ * Return: None
+ */
+void dp_peer_flush_frags(struct cdp_pdev *pdev, uint8_t vdev_id,
+			 uint8_t *peer_mac);
 #endif /* #ifndef _DP_INTERNAL_H_ */
diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c
index 1204101..17d4f44 100644
--- a/dp/wifi3.0/dp_main.c
+++ b/dp/wifi3.0/dp_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -9975,6 +9975,7 @@
 	.peer_get_peer_mac_addr = dp_peer_get_peer_mac_addr,
 	.get_vdev_for_peer = dp_get_vdev_for_peer,
 	.get_peer_state = dp_get_peer_state,
+	.peer_flush_frags = dp_peer_flush_frags,
 };
 #endif
 
diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c
index b332621..e59200f 100644
--- a/dp/wifi3.0/dp_peer.c
+++ b/dp/wifi3.0/dp_peer.c
@@ -3586,3 +3586,33 @@
 
 	return false;
 }
+
+void dp_peer_flush_frags(struct cdp_pdev *pdev, uint8_t vdev_id,
+			 uint8_t *peer_mac)
+{
+	struct dp_pdev *dp_pdev = (struct dp_pdev *)pdev;
+	struct dp_peer *peer;
+	struct dp_rx_tid *rx_tid;
+	uint8_t tid;
+
+	if (!dp_pdev || !dp_pdev->soc)
+		return;
+
+	peer = dp_peer_find_hash_find(dp_pdev->soc, peer_mac, 0, vdev_id);
+	if (!peer)
+		return;
+
+	dp_info("Flushing fragments for peer " QDF_MAC_ADDR_STR,
+		QDF_MAC_ADDR_ARRAY(peer->mac_addr.raw));
+
+	for (tid = 0; tid < DP_MAX_TIDS; tid++) {
+		rx_tid = &peer->rx_tid[tid];
+
+		qdf_spin_lock_bh(&rx_tid->tid_lock);
+		dp_rx_defrag_waitlist_remove(peer, tid);
+		dp_rx_reorder_flush_frag(peer, tid);
+		qdf_spin_unlock_bh(&rx_tid->tid_lock);
+	}
+
+	dp_peer_unref_delete(peer);
+}