ソースを参照

qcacmn: Add umac implementation of get_wake_lock stats

Add changes to support get wake lock stats from within cp_stats component.

Change-Id: I93855e4a1635afa97b4d5235ddb9cd92654f943d
CRs-Fixed: 2210309
Naveen Rawat 7 年 前
コミット
d24bebbf24

+ 4 - 0
qdf/inc/qdf_types.h

@@ -862,6 +862,10 @@ QDF_STATUS qdf_ipv6_parse(const char *ipv6_str, struct qdf_ipv6_addr *out_addr);
 
 #define QDF_MAX_NUM_CHAN   (128)
 
+#define QDF_BCAST_MAC_ADDR (0xFF)
+#define QDF_MCAST_IPV4_MAC_ADDR (0x01)
+#define QDF_MCAST_IPV6_MAC_ADDR (0x33)
+
 /**
  * struct qdf_tso_frag_t - fragments of a single TCP segment
  * @paddr_low_32: Lower 32 bits of the buffer pointer

+ 1 - 0
umac/cp_stats/core/src/wlan_cp_stats_comp_handler.c

@@ -25,6 +25,7 @@
 #include "wlan_cp_stats_comp_handler.h"
 #include "wlan_cp_stats_defs.h"
 #include <wlan_cp_stats_ucfg_api.h>
+#include <wlan_cp_stats_utils_api.h>
 
 static QDF_STATUS
 wlan_cp_stats_psoc_comp_obj_config

+ 14 - 6
umac/cp_stats/core/src/wlan_cp_stats_defs.h

@@ -41,11 +41,15 @@
  * @psoc_obj: pointer to psoc
  * @psoc_comp_priv_obj[]: component's private object pointers
  * @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
  */
 struct psoc_cp_stats {
 	struct wlan_objmgr_psoc *psoc_obj;
 	void *psoc_comp_priv_obj[WLAN_CP_STATS_MAX_COMPONENTS];
 	qdf_spinlock_t psoc_cp_stats_lock;
+	struct psoc_cmn_cp_stats *cmn_stats;
+	void *obj_stats;
 };
 
 /**
@@ -242,14 +246,18 @@ static inline
 struct psoc_cp_stats *wlan_cp_stats_get_psoc_stats_obj(struct wlan_objmgr_psoc
 							*psoc)
 {
-	struct psoc_cp_stats *psoc_cs = NULL;
+	struct cp_stats_context *csc;
 
-	if (psoc) {
-		psoc_cs = wlan_objmgr_psoc_get_comp_private_obj
-				(psoc, WLAN_UMAC_COMP_CP_STATS);
-	}
+	if (!psoc)
+		return NULL;
+
+	csc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
+						    WLAN_UMAC_COMP_CP_STATS);
+
+	if (!csc)
+		return NULL;
 
-	return psoc_cs;
+	return csc->psoc_cs;
 }
 
 /**

+ 8 - 0
umac/cp_stats/core/src/wlan_cp_stats_obj_mgr_handler.c

@@ -28,7 +28,12 @@
 #include "wlan_cp_stats_defs.h"
 #include "wlan_cp_stats_da_api.h"
 #include "wlan_cp_stats_ol_api.h"
+
+#include "wlan_cp_stats_defs.h"
+#include "wlan_cp_stats_ic_ucfg_handler.h"
+
 #include <wlan_cp_stats_ucfg_api.h>
+#include "wlan_cp_stats_utils_api.h"
 
 QDF_STATUS
 wlan_cp_stats_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, void *arg)
@@ -108,6 +113,7 @@ wlan_cp_stats_psoc_obj_create_handler_return:
 			qdf_mem_free(csc);
 			csc = NULL;
 		}
+		return status;
 	}
 
 	cp_stats_debug("cp stats context attach at psoc");
@@ -132,6 +138,8 @@ wlan_cp_stats_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc, void *arg)
 
 	wlan_objmgr_psoc_component_obj_detach(psoc,
 			WLAN_UMAC_COMP_CP_STATS, csc);
+	if (csc->cp_stats_psoc_obj_deinit)
+		csc->cp_stats_psoc_obj_deinit(csc->psoc_cs);
 	qdf_mem_free(csc->psoc_cs);
 	if (csc->cp_stats_ctx_deinit)
 		csc->cp_stats_ctx_deinit(csc);

+ 3 - 0
umac/cp_stats/core/src/wlan_cp_stats_ol_api.c

@@ -30,6 +30,9 @@
 #include "wlan_cp_stats_cmn_api_i.h"
 #include <wlan_cp_stats_ucfg_api.h>
 
+#include "wlan_cp_stats_ic_ucfg_handler.h"
+#include <wlan_cp_stats_utils_api.h>
+
 QDF_STATUS wlan_cp_stats_psoc_obj_init_ol(struct psoc_cp_stats *psoc_cs)
 {
 	qdf_spinlock_create(&psoc_cs->psoc_cp_stats_lock);

+ 57 - 0
umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h

@@ -34,4 +34,61 @@
 
 #ifndef __WLAN_CP_STATS_MC_DEFS_H__
 #define __WLAN_CP_STATS_MC_DEFS_H__
+
+/**
+ * struct wake_lock_stats - wake lock stats structure
+ * @ucast_wake_up_count:        Unicast wakeup count
+ * @bcast_wake_up_count:        Broadcast wakeup count
+ * @ipv4_mcast_wake_up_count:   ipv4 multicast wakeup count
+ * @ipv6_mcast_wake_up_count:   ipv6 multicast wakeup count
+ * @ipv6_mcast_ra_stats:        ipv6 multicast ra stats
+ * @ipv6_mcast_ns_stats:        ipv6 multicast ns stats
+ * @ipv6_mcast_na_stats:        ipv6 multicast na stats
+ * @icmpv4_count:               ipv4 icmp packet count
+ * @icmpv6_count:               ipv6 icmp packet count
+ * @rssi_breach_wake_up_count:  rssi breach wakeup count
+ * @low_rssi_wake_up_count:     low rssi wakeup count
+ * @gscan_wake_up_count:        gscan wakeup count
+ * @pno_complete_wake_up_count: pno complete wakeup count
+ * @pno_match_wake_up_count:    pno match wakeup count
+ * @oem_response_wake_up_count: oem response wakeup count
+ * @pwr_save_fail_detected:     pwr save fail detected wakeup count
+ * @scan_11d                    11d scan wakeup count
+ */
+struct wake_lock_stats {
+	uint32_t ucast_wake_up_count;
+	uint32_t bcast_wake_up_count;
+	uint32_t ipv4_mcast_wake_up_count;
+	uint32_t ipv6_mcast_wake_up_count;
+	uint32_t ipv6_mcast_ra_stats;
+	uint32_t ipv6_mcast_ns_stats;
+	uint32_t ipv6_mcast_na_stats;
+	uint32_t icmpv4_count;
+	uint32_t icmpv6_count;
+	uint32_t rssi_breach_wake_up_count;
+	uint32_t low_rssi_wake_up_count;
+	uint32_t gscan_wake_up_count;
+	uint32_t pno_complete_wake_up_count;
+	uint32_t pno_match_wake_up_count;
+	uint32_t oem_response_wake_up_count;
+	uint32_t pwr_save_fail_detected;
+	uint32_t scan_11d;
+};
+
+/**
+ * struct psoc_mc_cp_stats -       psoc specific stats
+ * @wow_unspecified_wake_up_count: number of non-wow related wake ups
+ */
+struct psoc_mc_cp_stats {
+	uint32_t wow_unspecified_wake_up_count;
+};
+
+/**
+ * struct vdev_mc_cp_stats -    vdev specific stats
+ * @wow_stats:                  wake_lock stats for vdev
+ */
+struct vdev_mc_cp_stats {
+	struct wake_lock_stats wow_stats;
+};
+
 #endif /* __WLAN_CP_STATS_MC_DEFS_H__ */

+ 14 - 0
umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_tgt_api.h

@@ -26,6 +26,20 @@
 
 #ifdef QCA_SUPPORT_CP_STATS
 
+/**
+ * tgt_mc_cp_stats_inc_wake_lock_stats() : API to increment wake lock stats
+ * given the wake reason code
+ * @psoc: pointer to psoc object
+ * @reason: wake reason
+ * @stats: vdev wow stats to update
+ * @unspecified_wake_count: unspecified wake count to update
+ *
+ * Return : status of operation
+ */
+QDF_STATUS tgt_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc *psoc,
+				uint32_t reason, struct wake_lock_stats *stats,
+				uint32_t *unspecified_wake_count);
+
 #endif /* QCA_SUPPORT_CP_STATS */
 #endif /* __WLAN_CP_STATS_MC_TGT_API_H__ */
 

+ 83 - 1
umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h

@@ -27,6 +27,88 @@
 
 #ifdef QCA_SUPPORT_CP_STATS
 
+#include <wlan_objmgr_psoc_obj.h>
+#include <wlan_objmgr_vdev_obj.h>
+#include <wlan_cp_stats_mc_defs.h>
+
+struct psoc_cp_stats;
+struct vdev_cp_stats;
+
+/**
+ * ucfg_mc_cp_stats_get_psoc_wake_lock_stats() : API to get wake lock stats from
+ * psoc
+ * @psoc: pointer to psoc object
+ * @stats: stats object to populate
+ *
+ * Return : status of operation
+ */
+QDF_STATUS ucfg_mc_cp_stats_get_psoc_wake_lock_stats(
+						struct wlan_objmgr_psoc *psoc,
+						struct wake_lock_stats *stats);
+
+/**
+ * ucfg_mc_cp_stats_get_vdev_wake_lock_stats() : API to get wake lock stats from
+ * vdev
+ * @vdev: pointer to vdev object
+ * @stats: stats object to populate
+ *
+ * Return : status of operation
+ */
+QDF_STATUS ucfg_mc_cp_stats_get_vdev_wake_lock_stats(
+						struct wlan_objmgr_vdev *vdev,
+						struct wake_lock_stats *stats);
+
+/**
+ * ucfg_mc_cp_stats_inc_wake_lock_stats_by_protocol() : API to increment wake
+ * lock stats given the protocol of the packet that was received.
+ * @psoc: pointer to psoc object
+ * @vdev_id: vdev_id for which the packet was received
+ * @protocol: protocol of the packet that was received
+ *
+ * Return : status of operation
+ */
+QDF_STATUS ucfg_mc_cp_stats_inc_wake_lock_stats_by_protocol(
+					struct wlan_objmgr_psoc *psoc,
+					uint8_t vdev_id,
+					enum qdf_proto_subtype protocol);
+
+/**
+ * ucfg_mc_cp_stats_inc_wake_lock_stats_by_protocol() : API to increment wake
+ * lock stats given destnation of packet that was received.
+ * @psoc: pointer to psoc object
+ * @dest_mac: destinamtion mac address of packet that was received
+ *
+ * Return : status of operation
+ */
+QDF_STATUS ucfg_mc_cp_stats_inc_wake_lock_stats_by_dst_addr(
+					struct wlan_objmgr_psoc *psoc,
+					uint8_t vdev_id, uint8_t *dest_mac);
+
+/**
+ * ucfg_mc_cp_stats_inc_wake_lock_stats() : API to increment wake lock stats
+ * given wake reason.
+ * @psoc: pointer to psoc object
+ * @vdev_id: vdev_id on with WOW was received
+ * @reason: reason of WOW
+ *
+ * Return : status of operation
+ */
+QDF_STATUS ucfg_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc *psoc,
+						uint8_t vdev_id,
+						uint32_t reason);
+
+/**
+ * ucfg_mc_cp_stats_write_wow_stats() - Writes WOW stats to buffer
+ * @psoc: pointer to psoc object
+ * @buffer: The char buffer to write to
+ * @max_len: The maximum number of chars to write
+ * @ret: number of bytes written
+ *
+ * Return - status of operation
+ */
+QDF_STATUS ucfg_mc_cp_stats_write_wow_stats(
+				struct wlan_objmgr_psoc *psoc,
+				char *buffer, uint16_t max_len, int *ret);
+
 #endif /* QCA_SUPPORT_CP_STATS */
 #endif /* __WLAN_CP_STATS_UCFG_API_H__ */
-

+ 23 - 0
umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c

@@ -23,3 +23,26 @@
  * from southbound interface
  */
 
+#include "target_if_cp_stats.h"
+#include "wlan_cp_stats_mc_defs.h"
+#include "wlan_cp_stats_tgt_api.h"
+#include "wlan_cp_stats_mc_tgt_api.h"
+#include "../../core/src/wlan_cp_stats_defs.h"
+#include <wlan_cp_stats_utils_api.h>
+
+
+QDF_STATUS tgt_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc *psoc,
+					       uint32_t reason,
+					       struct wake_lock_stats *stats,
+					       uint32_t *unspecified_wake_count)
+{
+	struct wlan_lmac_if_cp_stats_tx_ops *tx_ops;
+
+	tx_ops = target_if_cp_stats_get_tx_ops(psoc);
+	if (!tx_ops)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	tx_ops->inc_wake_lock_stats(reason, stats, unspecified_wake_count);
+
+	return QDF_STATUS_SUCCESS;
+}

+ 376 - 1
umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c

@@ -17,8 +17,383 @@
  */
 
 /**
- * DOC: wlan_cp_stats_mc_ucfg_api.h
+ * DOC: wlan_cp_stats_mc_ucfg_api.c
  *
  * This file provide API definitions required for northbound interaction
  */
 
+#include <wlan_objmgr_psoc_obj.h>
+#include <wlan_cp_stats_utils_api.h>
+#include <wlan_cp_stats_mc_ucfg_api.h>
+#include <wlan_cp_stats_mc_tgt_api.h>
+#include "../../core/src/wlan_cp_stats_defs.h"
+#include "../../core/src/wlan_cp_stats_cmn_api_i.h"
+
+QDF_STATUS wlan_cp_stats_psoc_cs_init(struct psoc_cp_stats *psoc_cs)
+{
+	psoc_cs->obj_stats = qdf_mem_malloc(sizeof(struct psoc_mc_cp_stats));
+	if (!psoc_cs->obj_stats) {
+		cp_stats_err("malloc failed");
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_cp_stats_psoc_cs_deinit(struct psoc_cp_stats *psoc_cs)
+{
+	qdf_mem_free(psoc_cs->obj_stats);
+	psoc_cs->obj_stats = NULL;
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_cp_stats_vdev_cs_init(struct vdev_cp_stats *vdev_cs)
+{
+	vdev_cs->vdev_stats = qdf_mem_malloc(sizeof(struct vdev_mc_cp_stats));
+	if (!vdev_cs->vdev_stats) {
+		cp_stats_err("malloc failed");
+		return QDF_STATUS_E_NOMEM;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_cp_stats_vdev_cs_deinit(struct vdev_cp_stats *vdev_cs)
+{
+	qdf_mem_free(vdev_cs->vdev_stats);
+	vdev_cs->vdev_stats = NULL;
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_cp_stats_pdev_cs_init(struct pdev_cp_stats *pdev_cs)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_cp_stats_pdev_cs_deinit(struct pdev_cp_stats *pdev_cs)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_cp_stats_peer_cs_init(struct peer_cp_stats *peer_cs)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_cp_stats_peer_cs_deinit(struct peer_cp_stats *peer_cs)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS ucfg_mc_cp_stats_inc_wake_lock_stats_by_protocol(
+					struct wlan_objmgr_psoc *psoc,
+					uint8_t vdev_id,
+					enum qdf_proto_subtype protocol)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct wake_lock_stats *stats;
+	struct vdev_mc_cp_stats *vdev_mc_stats;
+	struct vdev_cp_stats *vdev_cp_stats_priv;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_CP_STATS_ID);
+	if (!vdev) {
+		cp_stats_err("vdev numm for vdev_id: %d", vdev_id);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev);
+	if (!vdev_cp_stats_priv) {
+		cp_stats_err("vdev cp stats object is null");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
+	vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
+	stats = &vdev_mc_stats->wow_stats;
+	switch (protocol) {
+	case QDF_PROTO_ICMP_RES:
+		stats->icmpv4_count++;
+		break;
+	case QDF_PROTO_ICMPV6_REQ:
+	case QDF_PROTO_ICMPV6_RES:
+	case QDF_PROTO_ICMPV6_RS:
+		stats->icmpv6_count++;
+		break;
+	case QDF_PROTO_ICMPV6_RA:
+		stats->icmpv6_count++;
+		stats->ipv6_mcast_ra_stats++;
+		break;
+	case QDF_PROTO_ICMPV6_NS:
+		stats->icmpv6_count++;
+		stats->ipv6_mcast_ns_stats++;
+		break;
+	case QDF_PROTO_ICMPV6_NA:
+		stats->icmpv6_count++;
+		stats->ipv6_mcast_na_stats++;
+		break;
+	default:
+		break;
+	}
+
+	wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS ucfg_mc_cp_stats_inc_wake_lock_stats_by_dst_addr(
+					struct wlan_objmgr_psoc *psoc,
+					uint8_t vdev_id, uint8_t *dest_mac)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct wake_lock_stats *stats;
+	struct vdev_mc_cp_stats *vdev_mc_stats;
+	struct vdev_cp_stats *vdev_cp_stats_priv;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_CP_STATS_ID);
+	if (!vdev) {
+		cp_stats_err("vdev numm for vdev_id: %d", vdev_id);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev);
+	if (!vdev_cp_stats_priv) {
+		cp_stats_err("vdev cp stats object is null");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
+	vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
+	stats = &vdev_mc_stats->wow_stats;
+	switch (*dest_mac) {
+	case QDF_BCAST_MAC_ADDR:
+		stats->bcast_wake_up_count++;
+		break;
+	case QDF_MCAST_IPV4_MAC_ADDR:
+		stats->ipv4_mcast_wake_up_count++;
+		break;
+	case QDF_MCAST_IPV6_MAC_ADDR:
+		stats->ipv6_mcast_wake_up_count++;
+		break;
+	default:
+		stats->ucast_wake_up_count++;
+		break;
+	}
+
+	wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS ucfg_mc_cp_stats_inc_wake_lock_stats(struct wlan_objmgr_psoc *psoc,
+						uint8_t vdev_id,
+						uint32_t reason)
+{
+	struct wake_lock_stats *stats;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct wlan_objmgr_vdev *vdev = NULL;
+	struct psoc_mc_cp_stats *psoc_mc_stats;
+	struct psoc_cp_stats *psoc_cp_stats_priv;
+	struct vdev_mc_cp_stats *vdev_mc_stats;
+	struct vdev_cp_stats *vdev_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 QDF_STATUS_E_NULL_VALUE;
+	}
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_CP_STATS_ID);
+	if (!vdev) {
+		cp_stats_err("vdev numm for vdev_id: %d", vdev_id);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev);
+	if (!vdev_cp_stats_priv) {
+		cp_stats_err("vdev cp stats object is null");
+		status = QDF_STATUS_E_NULL_VALUE;
+		goto release_vdev_ref;
+	}
+
+	wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv);
+	wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
+
+	psoc_mc_stats = psoc_cp_stats_priv->obj_stats;
+	vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
+	stats = &vdev_mc_stats->wow_stats;
+	status = tgt_mc_cp_stats_inc_wake_lock_stats(psoc, reason, stats,
+				&psoc_mc_stats->wow_unspecified_wake_up_count);
+	wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
+	wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv);
+
+release_vdev_ref:
+	if (vdev)
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
+
+	return status;
+}
+
+/**
+ * vdev_iterator() - iterator function to collect wake_lock_stats from all vdev
+ * @psoc: pointer to psoc object
+ * @vdev: pointer to vdev object
+ * @arg: stats object pointer passed as arg
+ *
+ * Return - none
+ */
+static void vdev_iterator(struct wlan_objmgr_psoc *psoc, void *vdev, void *arg)
+{
+	struct wake_lock_stats *vdev_stats;
+	struct wake_lock_stats *stats = arg;
+	struct vdev_mc_cp_stats *vdev_mc_stats;
+	struct vdev_cp_stats *vdev_cp_stats_priv;
+
+	vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev);
+	if (NULL == vdev_cp_stats_priv) {
+		cp_stats_err("vdev cp stats object is null");
+		return;
+	}
+
+	wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
+	vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
+	vdev_stats = &vdev_mc_stats->wow_stats;
+	stats->ucast_wake_up_count += vdev_stats->ucast_wake_up_count;
+	stats->bcast_wake_up_count += vdev_stats->bcast_wake_up_count;
+	stats->ipv4_mcast_wake_up_count += vdev_stats->ipv4_mcast_wake_up_count;
+	stats->ipv6_mcast_wake_up_count += vdev_stats->ipv6_mcast_wake_up_count;
+	stats->ipv6_mcast_ra_stats += vdev_stats->ipv6_mcast_ra_stats;
+	stats->ipv6_mcast_ns_stats += vdev_stats->ipv6_mcast_ns_stats;
+	stats->ipv6_mcast_na_stats += vdev_stats->ipv6_mcast_na_stats;
+	stats->icmpv4_count += vdev_stats->icmpv4_count;
+	stats->icmpv6_count += vdev_stats->icmpv6_count;
+	stats->rssi_breach_wake_up_count +=
+			vdev_stats->rssi_breach_wake_up_count;
+	stats->low_rssi_wake_up_count += vdev_stats->low_rssi_wake_up_count;
+	stats->gscan_wake_up_count += vdev_stats->gscan_wake_up_count;
+	stats->pno_complete_wake_up_count +=
+			vdev_stats->pno_complete_wake_up_count;
+	stats->pno_match_wake_up_count += vdev_stats->pno_match_wake_up_count;
+	stats->oem_response_wake_up_count +=
+			vdev_stats->oem_response_wake_up_count;
+	stats->pwr_save_fail_detected += vdev_stats->pwr_save_fail_detected;
+	stats->scan_11d += vdev_stats->scan_11d;
+	wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
+}
+
+QDF_STATUS ucfg_mc_cp_stats_get_psoc_wake_lock_stats(
+						struct wlan_objmgr_psoc *psoc,
+						struct wake_lock_stats *stats)
+{
+	struct psoc_cp_stats *psoc_cp_stats_priv;
+	struct psoc_mc_cp_stats *psoc_mc_stats;
+
+	psoc_cp_stats_priv = wlan_cp_stats_get_psoc_stats_obj(psoc);
+	if (NULL == psoc_cp_stats_priv) {
+		cp_stats_err("psoc cp stats object is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv);
+	psoc_mc_stats = psoc_cp_stats_priv->obj_stats;
+	/* iterate through all vdevs, and get wow stats from vdev_cs object */
+	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, vdev_iterator,
+				     stats, true, WLAN_CP_STATS_ID);
+	wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS ucfg_mc_cp_stats_get_vdev_wake_lock_stats(
+						struct wlan_objmgr_vdev *vdev,
+						struct wake_lock_stats *stats)
+{
+	struct vdev_cp_stats *vdev_cp_stats_priv;
+	struct vdev_mc_cp_stats *vdev_mc_stats;
+
+	vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev);
+	if (NULL == vdev_cp_stats_priv) {
+		cp_stats_err("vdev cp stats object is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
+	vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
+	qdf_mem_copy(stats, &vdev_mc_stats->wow_stats, sizeof(*stats));
+	wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS ucfg_mc_cp_stats_write_wow_stats(
+				struct wlan_objmgr_psoc *psoc,
+				char *buffer, uint16_t max_len, int *ret)
+{
+	QDF_STATUS status;
+	uint32_t unspecified_wake_count;
+	struct wake_lock_stats wow_stats = {0};
+	struct psoc_mc_cp_stats *psoc_mc_stats;
+	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 QDF_STATUS_E_NULL_VALUE;
+	}
+
+	/* get stats from psoc */
+	status = ucfg_mc_cp_stats_get_psoc_wake_lock_stats(psoc, &wow_stats);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		cp_stats_err("Failed to get WoW stats");
+		return status;
+	}
+
+	wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv);
+	psoc_mc_stats = psoc_cp_stats_priv->obj_stats;
+	unspecified_wake_count = psoc_mc_stats->wow_unspecified_wake_up_count;
+	wlan_cp_stats_psoc_obj_unlock(psoc_cp_stats_priv);
+
+	*ret = qdf_scnprintf(buffer, max_len,
+			     "WoW Wake Reasons\n"
+			     "\tunspecified wake count: %u\n"
+			     "\tunicast: %u\n"
+			     "\tbroadcast: %u\n"
+			     "\tIPv4 multicast: %u\n"
+			     "\tIPv6 multicast: %u\n"
+			     "\tIPv6 multicast RA: %u\n"
+			     "\tIPv6 multicast NS: %u\n"
+			     "\tIPv6 multicast NA: %u\n"
+			     "\tICMPv4: %u\n"
+			     "\tICMPv6: %u\n"
+			     "\tRSSI Breach: %u\n"
+			     "\tLow RSSI: %u\n"
+			     "\tG-Scan: %u\n"
+			     "\tPNO Complete: %u\n"
+			     "\tPNO Match: %u\n"
+			     "\tOEM rsp wake_count: %u\n"
+			     "\twake count due to pwr_save_fail_detected: %u\n"
+			     "\twake count due to 11d scan: %u\n",
+			     unspecified_wake_count,
+			     wow_stats.ucast_wake_up_count,
+			     wow_stats.bcast_wake_up_count,
+			     wow_stats.ipv4_mcast_wake_up_count,
+			     wow_stats.ipv6_mcast_wake_up_count,
+			     wow_stats.ipv6_mcast_ra_stats,
+			     wow_stats.ipv6_mcast_ns_stats,
+			     wow_stats.ipv6_mcast_na_stats,
+			     wow_stats.icmpv4_count,
+			     wow_stats.icmpv6_count,
+			     wow_stats.rssi_breach_wake_up_count,
+			     wow_stats.low_rssi_wake_up_count,
+			     wow_stats.gscan_wake_up_count,
+			     wow_stats.pno_complete_wake_up_count,
+			     wow_stats.pno_match_wake_up_count,
+			     wow_stats.oem_response_wake_up_count,
+			     wow_stats.pwr_save_fail_detected,
+			     wow_stats.scan_11d);
+
+	return QDF_STATUS_SUCCESS;
+}

+ 7 - 1
umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h

@@ -73,7 +73,8 @@ struct scheduler_msg;
 
 #ifdef QCA_SUPPORT_CP_STATS
 #include <wlan_cp_stats_tgt_api.h>
-#endif
+#include <wlan_cp_stats_mc_defs.h>
+#endif /* QCA_SUPPORT_CP_STATS */
 
 #ifdef QCA_SUPPORT_CP_STATS
 /**
@@ -85,6 +86,11 @@ struct scheduler_msg;
 struct wlan_lmac_if_cp_stats_tx_ops {
 	QDF_STATUS (*cp_stats_attach)(struct wlan_objmgr_psoc *psoc);
 	QDF_STATUS (*cp_stats_detach)(struct wlan_objmgr_psoc *posc);
+#ifdef CONFIG_MCL
+	void (*inc_wake_lock_stats)(uint32_t reason,
+				    struct wake_lock_stats *stats,
+				    uint32_t *unspecified_wake_count);
+#endif
 };
 
 /**