qcacmn: Process FW stats event on VDEV_DOWN

FW sends vdev stats on vdev down, current host
implementation does not process this event as host is
only processing the stats events for which stats are
requested.
On vdev down FW sends the last available vdev stats and
based on that host updates it's RSSI on disconnect.
With CP stats infrastructure host is not processing
this event and is not updating rssi on disconnect.

To address above issue add a logic to process all the
vdev stats event received by host.

Change-Id: I9a5c32d061562cd3e3741cd9fe4a69f3278e7a98
CRs-Fixed: 2497104
diff --git a/umac/cp_stats/core/src/wlan_cp_stats_defs.h b/umac/cp_stats/core/src/wlan_cp_stats_defs.h
index a71c392..762cdfe 100644
--- a/umac/cp_stats/core/src/wlan_cp_stats_defs.h
+++ b/umac/cp_stats/core/src/wlan_cp_stats_defs.h
@@ -47,6 +47,8 @@
  * @psoc_cp_stats_lock: lock to protect object
  * @cmn_stats: stats common for AP and STA devices
  * @obj_stats: stats specific to AP or STA devices
+ * @legacy_stats_cb: callback to update the stats received from FW through
+ * asynchronous events.
  */
 struct psoc_cp_stats {
 	struct wlan_objmgr_psoc *psoc_obj;
@@ -54,6 +56,7 @@
 	qdf_spinlock_t psoc_cp_stats_lock;
 	struct psoc_cmn_cp_stats *cmn_stats;
 	psoc_ext_cp_stats_t *obj_stats;
+	void (*legacy_stats_cb)(void *stats);
 };
 
 /**
diff --git a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h
index 5b14851..200eef9 100644
--- a/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h
+++ b/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h
@@ -205,6 +205,17 @@
 QDF_STATUS ucfg_mc_cp_stats_set_rate_flags(struct wlan_objmgr_vdev *vdev,
 					   enum tx_rate_info flags);
 
+/**
+ * ucfg_mc_cp_stats_register_lost_link_info_cb() - API to register lost link
+ * info callback
+ * @psoc: pointer to psoc object
+ * @lost_link_cp_stats_info_cb: Lost link info callback to be registered
+ *
+ */
+void ucfg_mc_cp_stats_register_lost_link_info_cb(
+		struct wlan_objmgr_psoc *psoc,
+		void (*lost_link_cp_stats_info_cb)(void *stats_ev));
+
 #ifdef WLAN_POWER_MANAGEMENT_OFFLOAD
 /**
  * ucfg_mc_cp_stats_register_pmo_handler() - API to register pmo handler
diff --git a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c
index a77494c..e517fb8 100644
--- a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c
+++ b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c
@@ -848,6 +848,16 @@
 	}
 }
 
+static void tgt_mc_cp_send_lost_link_stats(struct wlan_objmgr_psoc *psoc,
+					   struct stats_event *ev)
+{
+	struct psoc_cp_stats *psoc_cp_stats_priv;
+
+	psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc);
+	if (psoc_cp_stats_priv && psoc_cp_stats_priv->legacy_stats_cb)
+		psoc_cp_stats_priv->legacy_stats_cb(ev);
+}
+
 QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc,
 					       struct stats_event *ev)
 {
@@ -862,6 +872,7 @@
 
 	tgt_mc_cp_stats_extract_cca_stats(psoc, ev);
 
+	tgt_mc_cp_send_lost_link_stats(psoc, ev);
 	return QDF_STATUS_SUCCESS;
 }
 
diff --git a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c
index 97779ef..ca85ca1 100644
--- a/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c
+++ b/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c
@@ -640,6 +640,21 @@
 	return QDF_STATUS_SUCCESS;
 }
 
+void ucfg_mc_cp_stats_register_lost_link_info_cb(
+			struct wlan_objmgr_psoc *psoc,
+			void (*lost_link_cp_stats_info_cb)(void *stats_ev))
+{
+	struct psoc_cp_stats *psoc_cp_stats_priv;
+
+	psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc);
+	if (!psoc_cp_stats_priv) {
+		cp_stats_err("psoc cp stats object is null");
+		return;
+	}
+
+	psoc_cp_stats_priv->legacy_stats_cb = lost_link_cp_stats_info_cb;
+}
+
 #ifdef WLAN_POWER_MANAGEMENT_OFFLOAD
 static QDF_STATUS
 ucfg_mc_cp_stats_suspend_req_handler(struct wlan_objmgr_psoc *psoc)