Parcourir la source

qcacld-3.0: Move power stats from debugfs to sysfs

Move power stats from the debugs to sysfs. Also previously
power stats was maintained per vdev but the data received
from the firmware is per pdev. Hence move the power stats
implementation from vdev to pdev.

Change-Id: I10df003fe8f79d35d0758b56d971f4973d27750b
CRs-Fixed: 2345097
Arunk Khandavalli il y a 6 ans
Parent
commit
890f6d9c7e

+ 46 - 0
core/hdd/inc/wlan_hdd_sysfs.h

@@ -20,6 +20,20 @@
 #define _WLAN_HDD_SYSFS_H_
 
 #ifdef WLAN_SYSFS
+/**
+ * hdd_sysfs_create_driver_root_obj() - create driver root kobject
+ *
+ * Return: none
+ */
+void hdd_sysfs_create_driver_root_obj(void);
+
+/**
+ * hdd_sysfs_destroy_driver_root_obj() - destroy driver root kobject
+ *
+ * Return: none
+ */
+void hdd_sysfs_destroy_driver_root_obj(void);
+
 /**
  * hdd_sysfs_create_version_interface() - create version interface
  * @psoc: PSOC ptr
@@ -34,7 +48,29 @@ void hdd_sysfs_create_version_interface(struct wlan_objmgr_psoc *psoc);
  * Return: none
  */
 void hdd_sysfs_destroy_version_interface(void);
+/**
+ * hdd_sysfs_create_powerstats_interface() - create power_stats interface
+ *
+ * Return: none
+ */
+void hdd_sysfs_create_powerstats_interface(void);
+/**
+ * hdd_sysfs_destroy_powerstats_interface() - destroy power_stats interface
+ *
+ * Return: none
+ */
+void hdd_sysfs_destroy_powerstats_interface(void);
 #else
+static inline
+void hdd_sysfs_create_driver_root_obj(void)
+{
+}
+
+static inline
+void hdd_sysfs_destroy_driver_root_obj(void)
+{
+}
+
 static inline
 void hdd_sysfs_create_version_interface(struct wlan_objmgr_psoc *psoc)
 {
@@ -44,5 +80,15 @@ static inline
 void hdd_sysfs_destroy_version_interface(void)
 {
 }
+
+static inline
+void hdd_sysfs_create_powerstats_interface(void)
+{
+}
+
+static inline
+void hdd_sysfs_destroy_powerstats_interface(void)
+{
+}
 #endif
 #endif

+ 0 - 259
core/hdd/src/wlan_hdd_debugfs.c

@@ -37,10 +37,6 @@
 #define MAX_USER_COMMAND_SIZE_WOWL_PATTERN 512
 #define MAX_USER_COMMAND_SIZE_FRAME 4096
 
-#ifdef WLAN_POWER_DEBUGFS
-#define POWER_DEBUGFS_BUFFER_MAX_LEN 4096
-#endif
-
 #define MAX_DEBUGFS_WAIT_ITERATIONS 20
 #define DEBUGFS_WAIT_SLEEP_TIME 100
 
@@ -424,227 +420,6 @@ static ssize_t wcnss_patterngen_write(struct file *file,
 	return ret;
 }
 
-#ifdef WLAN_POWER_DEBUGFS
-struct power_stats_priv {
-	struct power_stats_response power_stats;
-};
-
-static void hdd_power_debugstats_dealloc(void *priv)
-{
-	struct power_stats_priv *stats = priv;
-
-	qdf_mem_free(stats->power_stats.debug_registers);
-}
-
-static void hdd_power_debugstats_cb(struct power_stats_response *response,
-				    void *context)
-{
-	struct osif_request *request;
-	struct power_stats_priv *priv;
-	uint32_t *debug_registers;
-	uint32_t debug_registers_len;
-
-	hdd_enter();
-
-	request = osif_request_get(context);
-	if (!request) {
-		hdd_err("Obsolete request");
-		return;
-	}
-
-	priv = osif_request_priv(request);
-
-	/* copy fixed-sized data */
-	priv->power_stats = *response;
-
-	/* copy variable-size data */
-	if (response->num_debug_register) {
-		debug_registers_len = (sizeof(response->debug_registers[0]) *
-				       response->num_debug_register);
-		debug_registers = qdf_mem_malloc(debug_registers_len);
-		priv->power_stats.debug_registers = debug_registers;
-		if (debug_registers) {
-			qdf_mem_copy(debug_registers,
-				     response->debug_registers,
-				     debug_registers_len);
-		} else {
-			hdd_err("Power stats memory alloc fails!");
-			priv->power_stats.num_debug_register = 0;
-		}
-	}
-	osif_request_complete(request);
-	osif_request_put(request);
-	hdd_exit();
-}
-
-/**
- * __wlan_hdd_read_power_debugfs() - API to collect Chip power stats from FW
- * @file: file pointer
- * @buf: buffer
- * @count: count
- * @pos: position pointer
- *
- * Return: Number of bytes read on success, error number otherwise
- */
-static ssize_t __wlan_hdd_read_power_debugfs(struct file *file,
-		char __user *buf,
-		size_t count, loff_t *pos)
-{
-	struct hdd_adapter *adapter;
-	struct hdd_context *hdd_ctx;
-	QDF_STATUS status;
-	struct power_stats_response *chip_power_stats;
-	ssize_t ret_cnt = 0;
-	int j;
-	unsigned int len = 0;
-	char *power_debugfs_buf = NULL;
-	void *cookie;
-	struct osif_request *request;
-	struct power_stats_priv	*priv;
-	static const struct osif_request_params params = {
-		.priv_size = sizeof(*priv),
-		.timeout_ms = WLAN_WAIT_TIME_STATS,
-		.dealloc = hdd_power_debugstats_dealloc,
-	};
-
-	hdd_enter();
-	adapter = (struct hdd_adapter *)file->private_data;
-	if ((!adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic)) {
-		hdd_err("Invalid adapter or adapter has invalid magic");
-		return -EINVAL;
-	}
-
-	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
-	ret_cnt = wlan_hdd_validate_context(hdd_ctx);
-	if (0 != ret_cnt)
-		return ret_cnt;
-
-	if (!wlan_hdd_validate_modules_state(hdd_ctx))
-		return -EINVAL;
-
-	request = osif_request_alloc(&params);
-	if (!request) {
-		hdd_err("Request allocation failure");
-		return -ENOMEM;
-	}
-	cookie = osif_request_cookie(request);
-
-	status = sme_power_debug_stats_req(hdd_ctx->mac_handle,
-					   hdd_power_debugstats_cb,
-					   cookie);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		hdd_err("chip power stats request failed");
-		ret_cnt = -EINVAL;
-		goto cleanup;
-	}
-
-	ret_cnt = osif_request_wait_for_response(request);
-	if (ret_cnt) {
-		hdd_err("Target response timed out Power stats");
-		ret_cnt = -ETIMEDOUT;
-		goto cleanup;
-	}
-
-	priv = osif_request_priv(request);
-	chip_power_stats = &priv->power_stats;
-
-	power_debugfs_buf = qdf_mem_malloc(POWER_DEBUGFS_BUFFER_MAX_LEN);
-	if (!power_debugfs_buf) {
-		hdd_err("Power stats buffer alloc fails!");
-		ret_cnt = -EINVAL;
-		goto cleanup;
-	}
-
-	len += scnprintf(power_debugfs_buf, POWER_DEBUGFS_BUFFER_MAX_LEN,
-			"POWER DEBUG STATS\n=================\n"
-			"cumulative_sleep_time_ms: %d\n"
-			"cumulative_total_on_time_ms: %d\n"
-			"deep_sleep_enter_counter: %d\n"
-			"last_deep_sleep_enter_tstamp_ms: %d\n"
-			"debug_register_fmt: %d\n"
-			"num_debug_register: %d\n",
-			chip_power_stats->cumulative_sleep_time_ms,
-			chip_power_stats->cumulative_total_on_time_ms,
-			chip_power_stats->deep_sleep_enter_counter,
-			chip_power_stats->last_deep_sleep_enter_tstamp_ms,
-			chip_power_stats->debug_register_fmt,
-			chip_power_stats->num_debug_register);
-
-	for (j = 0; j < chip_power_stats->num_debug_register; j++) {
-		if ((POWER_DEBUGFS_BUFFER_MAX_LEN - len) > 0)
-			len += scnprintf(power_debugfs_buf + len,
-					POWER_DEBUGFS_BUFFER_MAX_LEN - len,
-					"debug_registers[%d]: 0x%x\n", j,
-					chip_power_stats->debug_registers[j]);
-		else
-			j = chip_power_stats->num_debug_register;
-	}
-
-	ret_cnt = simple_read_from_buffer(buf, count, pos,
-					  power_debugfs_buf, len);
-
- cleanup:
-	qdf_mem_free(power_debugfs_buf);
-	osif_request_put(request);
-
-	return ret_cnt;
-}
-
-/**
- * wlan_hdd_read_power_debugfs() - SSR wrapper function to read power debugfs
- * @file: file pointer
- * @buf: buffer
- * @count: count
- * @pos: position pointer
- *
- * Return: Number of bytes read on success, error number otherwise
- */
-static ssize_t wlan_hdd_read_power_debugfs(struct file *file,
-		char __user *buf,
-		size_t count, loff_t *pos)
-{
-	int ret;
-
-	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_read_power_debugfs(file, buf, count, pos);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-
-/**
- * __wlan_hdd_open_power_debugfs() - Function to save private on open
- * @inode: Pointer to inode structure
- * @file: file pointer
- *
- * Return: zero
- */
-static int __wlan_hdd_open_power_debugfs(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-
-/**
- * wlan_hdd_open_power_debugfs() - SSR wrapper function to save private on open
- * @inode: Pointer to inode structure
- * @file: file pointer
- *
- * Return: zero
- */
-static int wlan_hdd_open_power_debugfs(struct inode *inode, struct file *file)
-{
-	int ret;
-
-	cds_ssr_protect(__func__);
-	ret = __wlan_hdd_open_power_debugfs(inode, file);
-	cds_ssr_unprotect(__func__);
-
-	return ret;
-}
-#endif
-
 /**
  * __wcnss_debugfs_open() - Generic debugfs open() handler
  * @inode: inode of the debugfs file
@@ -709,37 +484,6 @@ static const struct file_operations fops_patterngen = {
 	.llseek = default_llseek,
 };
 
-#ifdef WLAN_POWER_DEBUGFS
-static const struct file_operations fops_powerdebugs = {
-	.read = wlan_hdd_read_power_debugfs,
-	.open = wlan_hdd_open_power_debugfs,
-	.owner = THIS_MODULE,
-	.llseek = default_llseek,
-};
-
-/**
- * wlan_hdd_create_power_stats_file() - API to create power stats file
- * @adapter: interface adapter pointer
- *
- * Return: QDF_STATUS
- */
-static QDF_STATUS wlan_hdd_create_power_stats_file(struct hdd_adapter *adapter)
-{
-	if (!debugfs_create_file("power_stats", 00400 | 00040 | 00004,
-				adapter->debugfs_phy, adapter,
-				&fops_powerdebugs))
-		return QDF_STATUS_E_FAILURE;
-
-	return QDF_STATUS_SUCCESS;
-}
-
-#else
-static QDF_STATUS wlan_hdd_create_power_stats_file(struct hdd_adapter *adapter)
-{
-	return QDF_STATUS_SUCCESS;
-}
-#endif
-
 /**
  * hdd_debugfs_init() - Initialize debugfs interface
  * @adapter: interface adapter pointer
@@ -771,9 +515,6 @@ QDF_STATUS hdd_debugfs_init(struct hdd_adapter *adapter)
 					&fops_patterngen))
 		return QDF_STATUS_E_FAILURE;
 
-	if (QDF_STATUS_SUCCESS != wlan_hdd_create_power_stats_file(adapter))
-		return QDF_STATUS_E_FAILURE;
-
 	if (0 != wlan_hdd_create_ll_stats_file(adapter))
 		return QDF_STATUS_E_FAILURE;
 

+ 9 - 2
core/hdd/src/wlan_hdd_main.c

@@ -2781,7 +2781,9 @@ int hdd_wlan_start_modules(struct hdd_context *hdd_ctx, bool reinit)
 		hdd_register_policy_manager_callback(
 			hdd_ctx->psoc);
 
+		hdd_sysfs_create_driver_root_obj();
 		hdd_sysfs_create_version_interface(hdd_ctx->psoc);
+		hdd_sysfs_create_powerstats_interface();
 		hdd_update_hw_sw_info(hdd_ctx);
 
 		if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
@@ -2793,7 +2795,7 @@ int hdd_wlan_start_modules(struct hdd_context *hdd_ctx, bool reinit)
 		ret = hdd_configure_cds(hdd_ctx);
 		if (ret) {
 			hdd_err("Failed to Enable cds modules; errno: %d", ret);
-			goto post_disable;
+			goto destroy_driver_sysfs;
 		}
 
 		hdd_enable_power_management();
@@ -2818,7 +2820,10 @@ int hdd_wlan_start_modules(struct hdd_context *hdd_ctx, bool reinit)
 
 	return 0;
 
-post_disable:
+destroy_driver_sysfs:
+	hdd_sysfs_destroy_powerstats_interface();
+	hdd_sysfs_destroy_version_interface();
+	hdd_sysfs_destroy_driver_root_obj();
 	cds_post_disable();
 
 cds_txrx_free:
@@ -11004,7 +11009,9 @@ int hdd_wlan_stop_modules(struct hdd_context *hdd_ctx, bool ftm_mode)
 		goto done;
 	}
 
+	hdd_sysfs_destroy_powerstats_interface();
 	hdd_sysfs_destroy_version_interface();
+	hdd_sysfs_destroy_driver_root_obj();
 	hdd_debug("Closing CDS modules!");
 
 	qdf_status = cds_post_disable();

+ 202 - 18
core/hdd/src/wlan_hdd_sysfs.c

@@ -31,6 +31,9 @@
 #include "wlan_hdd_sysfs.h"
 #include "qwlan_version.h"
 #include "cds_api.h"
+#include <wlan_osif_request_manager.h>
+#include <qdf_mem.h>
+#include <sir_api.h>
 
 #define MAX_PSOC_ID_SIZE 10
 
@@ -106,6 +109,152 @@ static ssize_t show_fw_version(struct kobject *kobj,
 	ret_val = __show_fw_version(kobj, attr, buf);
 	cds_ssr_unprotect(__func__);
 
+	return ret_val;
+};
+
+struct power_stats_priv {
+	struct power_stats_response power_stats;
+};
+
+static void hdd_power_debugstats_dealloc(void *priv)
+{
+	struct power_stats_priv *stats = priv;
+
+	qdf_mem_free(stats->power_stats.debug_registers);
+	stats->power_stats.debug_registers = NULL;
+}
+
+static void hdd_power_debugstats_cb(struct power_stats_response *response,
+				    void *context)
+{
+	struct osif_request *request;
+	struct power_stats_priv *priv;
+	uint32_t *debug_registers;
+	uint32_t debug_registers_len;
+
+	hdd_enter();
+
+	request = osif_request_get(context);
+	if (!request) {
+		hdd_err("Obsolete request");
+		return;
+	}
+
+	priv = osif_request_priv(request);
+
+	/* copy fixed-sized data */
+	priv->power_stats = *response;
+
+	/* copy variable-size data */
+	if (response->num_debug_register) {
+		debug_registers_len = (sizeof(response->debug_registers[0]) *
+				       response->num_debug_register);
+		debug_registers = qdf_mem_malloc(debug_registers_len);
+		priv->power_stats.debug_registers = debug_registers;
+		if (debug_registers) {
+			qdf_mem_copy(debug_registers,
+				     response->debug_registers,
+				     debug_registers_len);
+		} else {
+			hdd_err("Power stats memory alloc fails!");
+			priv->power_stats.num_debug_register = 0;
+		}
+	}
+	osif_request_complete(request);
+	osif_request_put(request);
+	hdd_exit();
+}
+
+static ssize_t __show_device_power_stats(struct kobject *kobj,
+					 struct kobj_attribute *attr,
+					 char *buf)
+{
+	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	QDF_STATUS status;
+	struct power_stats_response *chip_power_stats;
+	ssize_t ret_cnt = 0;
+	int j;
+	void *cookie;
+	struct osif_request *request;
+	struct power_stats_priv *priv;
+	static const struct osif_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_STATS,
+		.dealloc = hdd_power_debugstats_dealloc,
+	};
+
+	hdd_enter();
+
+	ret_cnt = wlan_hdd_validate_context(hdd_ctx);
+	if (ret_cnt)
+		return ret_cnt;
+
+	request = osif_request_alloc(&params);
+	if (!request) {
+		hdd_err("Request allocation failure");
+		return -ENOMEM;
+	}
+	cookie = osif_request_cookie(request);
+
+	status = sme_power_debug_stats_req(hdd_ctx->mac_handle,
+					   hdd_power_debugstats_cb,
+					   cookie);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("chip power stats request failed");
+		ret_cnt = -EINVAL;
+		goto cleanup;
+	}
+
+	ret_cnt = osif_request_wait_for_response(request);
+	if (ret_cnt) {
+		hdd_err("Target response timed out Power stats");
+		ret_cnt = -ETIMEDOUT;
+		goto cleanup;
+	}
+	priv = osif_request_priv(request);
+	chip_power_stats = &priv->power_stats;
+
+	ret_cnt += scnprintf(buf, PAGE_SIZE,
+			"POWER DEBUG STATS\n=================\n"
+			"cumulative_sleep_time_ms: %d\n"
+			"cumulative_total_on_time_ms: %d\n"
+			"deep_sleep_enter_counter: %d\n"
+			"last_deep_sleep_enter_tstamp_ms: %d\n"
+			"debug_register_fmt: %d\n"
+			"num_debug_register: %d\n",
+			chip_power_stats->cumulative_sleep_time_ms,
+			chip_power_stats->cumulative_total_on_time_ms,
+			chip_power_stats->deep_sleep_enter_counter,
+			chip_power_stats->last_deep_sleep_enter_tstamp_ms,
+			chip_power_stats->debug_register_fmt,
+			chip_power_stats->num_debug_register);
+
+	for (j = 0; j < chip_power_stats->num_debug_register; j++) {
+		if ((PAGE_SIZE - ret_cnt) > 0)
+			ret_cnt += scnprintf(buf + ret_cnt,
+					PAGE_SIZE - ret_cnt,
+					"debug_registers[%d]: 0x%x\n", j,
+					chip_power_stats->debug_registers[j]);
+		else
+			j = chip_power_stats->num_debug_register;
+	}
+
+cleanup:
+	osif_request_put(request);
+	hdd_exit();
+	return ret_cnt;
+}
+
+static ssize_t show_device_power_stats(struct kobject *kobj,
+				       struct kobj_attribute *attr,
+				       char *buf)
+{
+	ssize_t ret_val;
+
+	cds_ssr_protect(__func__);
+	ret_val = __show_device_power_stats(kobj, attr, buf);
+	cds_ssr_unprotect(__func__);
+
 	return ret_val;
 }
 
@@ -113,6 +262,8 @@ static struct kobj_attribute dr_ver_attribute =
 	__ATTR(driver_version, 0440, show_driver_version, NULL);
 static struct kobj_attribute fw_ver_attribute =
 	__ATTR(version, 0440, show_fw_version, NULL);
+static struct kobj_attribute power_stats_attribute =
+	__ATTR(power_stats, 0440, show_device_power_stats, NULL);
 
 void hdd_sysfs_create_version_interface(struct wlan_objmgr_psoc *psoc)
 {
@@ -120,22 +271,15 @@ void hdd_sysfs_create_version_interface(struct wlan_objmgr_psoc *psoc)
 	uint32_t psoc_id;
 	char buf[MAX_PSOC_ID_SIZE];
 
-	driver_kobject = kobject_create_and_add(DRIVER_NAME, kernel_kobj);
-	if (!driver_kobject) {
-		hdd_err("could not allocate driver kobject");
+	if (!driver_kobject || !wlan_kobject) {
+		hdd_err("could not get driver kobject!");
 		return;
 	}
 
-	wlan_kobject = kobject_create_and_add("wlan", driver_kobject);
-	if (!wlan_kobject) {
-		hdd_err("could not allocate wlan kobject");
-		goto free_drv_kobj;
-	}
-
 	error = sysfs_create_file(wlan_kobject, &dr_ver_attribute.attr);
 	if (error) {
 		hdd_err("could not create wlan sysfs file");
-		goto free_wlan_kobj;
+		return;
 	}
 
 	fw_kobject = kobject_create_and_add("fw", wlan_kobject);
@@ -168,14 +312,6 @@ free_psoc_kobj:
 free_fw_kobj:
 	kobject_put(fw_kobject);
 	fw_kobject = NULL;
-
-free_wlan_kobj:
-	kobject_put(wlan_kobject);
-	wlan_kobject = NULL;
-
-free_drv_kobj:
-	kobject_put(driver_kobject);
-	driver_kobject = NULL;
 }
 
 void hdd_sysfs_destroy_version_interface(void)
@@ -185,8 +321,56 @@ void hdd_sysfs_destroy_version_interface(void)
 		psoc_kobject = NULL;
 		kobject_put(fw_kobject);
 		fw_kobject = NULL;
+	}
+}
+
+void hdd_sysfs_create_powerstats_interface(void)
+{
+	int error;
+
+	if (!driver_kobject) {
+		hdd_err("could not get driver kobject!");
+		return;
+	}
+
+	error = sysfs_create_file(driver_kobject, &power_stats_attribute.attr);
+	if (error)
+		hdd_err("could not create power_stats sysfs file");
+}
+
+void hdd_sysfs_destroy_powerstats_interface(void)
+{
+	if (!driver_kobject) {
+		hdd_err("could not get driver kobject!");
+		return;
+	}
+	sysfs_remove_file(driver_kobject, &power_stats_attribute.attr);
+}
+
+void hdd_sysfs_create_driver_root_obj(void)
+{
+	driver_kobject = kobject_create_and_add(DRIVER_NAME, kernel_kobj);
+	if (!driver_kobject) {
+		hdd_err("could not allocate driver kobject");
+		return;
+	}
+
+	wlan_kobject = kobject_create_and_add("wlan", driver_kobject);
+	if (!wlan_kobject) {
+		hdd_err("could not allocate wlan kobject");
+		kobject_put(driver_kobject);
+		driver_kobject = NULL;
+	}
+}
+
+void hdd_sysfs_destroy_driver_root_obj(void)
+{
+	if (wlan_kobject) {
 		kobject_put(wlan_kobject);
 		wlan_kobject = NULL;
+	}
+
+	if (driver_kobject) {
 		kobject_put(driver_kobject);
 		driver_kobject = NULL;
 	}