diff mbox series

PM / devfreq: Show trans_stat info via debugfs

Message ID 20230914102317.29302-1-jiazi.li@transsion.com (mailing list archive)
State Accepted
Delegated to: Chanwoo Choi
Headers show
Series PM / devfreq: Show trans_stat info via debugfs | expand

Commit Message

Jiazi Li Sept. 14, 2023, 10:23 a.m. UTC
For device with over PAGE_SIZE bytes trans_stat info, trans_stat
in sysfs just show a prompt information.
Create a trans_stat node in debugfs, show detailed information.

Signed-off-by: Jiazi Li <jiazi.li@transsion.com>
---
 drivers/devfreq/devfreq.c | 79 ++++++++++++++++++++++++++++++++++++++-
 include/linux/devfreq.h   |  2 +
 2 files changed, 80 insertions(+), 1 deletion(-)

Comments

kernel test robot Sept. 14, 2023, 1:24 p.m. UTC | #1
Hi Jiazi,

kernel test robot noticed the following build warnings:

[auto build test WARNING on chanwoo/devfreq-testing]
[also build test WARNING on linus/master v6.6-rc1 next-20230914]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Jiazi-Li/PM-devfreq-Show-trans_stat-info-via-debugfs/20230914-182515
base:   https://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git devfreq-testing
patch link:    https://lore.kernel.org/r/20230914102317.29302-1-jiazi.li%40transsion.com
patch subject: [PATCH] PM / devfreq: Show trans_stat info via debugfs
config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20230914/202309142101.hL5Buk6G-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230914/202309142101.hL5Buk6G-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202309142101.hL5Buk6G-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/devfreq/devfreq.c:1699: warning: Function parameter or member 'unused' not described in 'devfreq_trans_stat_show'
>> drivers/devfreq/devfreq.c:1699: warning: Excess function parameter 'data' description in 'devfreq_trans_stat_show'


vim +1699 drivers/devfreq/devfreq.c

  1689	
  1690	/**
  1691	 * devfreq_trans_stat_show() - show trans stat info through debugfs
  1692	 * @s:		seq_file instance to show trans_stat info of devfreq devices
  1693	 * @data:	not used
  1694	 *
  1695	 * Show detailed information for some device which has more than PAGE_SIZE
  1696	 * bytes of trans stat info.
  1697	 */
  1698	static int devfreq_trans_stat_show(struct seq_file *s, void *unused)
> 1699	{
  1700		struct devfreq *df = s->private;
  1701		unsigned int max_state;
  1702		int i, j;
  1703	
  1704		if (!df->profile)
  1705			return -EINVAL;
  1706		max_state = df->max_state;
  1707	
  1708		if (max_state == 0) {
  1709			seq_puts(s, "Not Supported.\n");
  1710			return 0;
  1711		}
  1712	
  1713		mutex_lock(&df->lock);
  1714		if (!df->stop_polling &&
  1715				devfreq_update_status(df, df->previous_freq)) {
  1716			mutex_unlock(&df->lock);
  1717			return 0;
  1718		}
  1719		mutex_unlock(&df->lock);
  1720	
  1721		seq_puts(s, "     From  :   To\n");
  1722		seq_puts(s, "           :");
  1723		for (i = 0; i < max_state; i++)
  1724			seq_printf(s, "%10lu", df->freq_table[i]);
  1725	
  1726		seq_puts(s, "   time(ms)\n");
  1727	
  1728		for (i = 0; i < max_state; i++) {
  1729			if (df->freq_table[i] == df->previous_freq)
  1730				seq_puts(s, "*");
  1731			else
  1732				seq_puts(s, " ");
  1733	
  1734			seq_printf(s, "%10lu:", df->freq_table[i]);
  1735	
  1736			for (j = 0; j < max_state; j++)
  1737				seq_printf(s, "%10u",
  1738					df->stats.trans_table[(i * max_state) + j]);
  1739	
  1740			seq_printf(s, "%10llu\n", (u64)
  1741				jiffies64_to_msecs(df->stats.time_in_state[i]));
  1742		}
  1743	
  1744		seq_printf(s, "Total transition : %u\n", df->stats.total_trans);
  1745	
  1746		return 0;
  1747	}
  1748	DEFINE_SHOW_ATTRIBUTE(devfreq_trans_stat);
  1749
diff mbox series

Patch

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index e36cbb920ec8..08847734ecee 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -940,6 +940,8 @@  struct devfreq *devfreq_add_device(struct device *dev,
 		goto err_init;
 	}
 	create_sysfs_files(devfreq, devfreq->governor);
+	devfreq->debugfs_dir =
+		debugfs_create_dir(dev_name(&(devfreq->dev)), devfreq_debugfs);
 
 	list_add(&devfreq->node, &devfreq_list);
 
@@ -978,6 +980,7 @@  int devfreq_remove_device(struct devfreq *devfreq)
 
 	devfreq_cooling_unregister(devfreq->cdev);
 
+	debugfs_remove_recursive(devfreq->debugfs_dir);
 	if (devfreq->governor) {
 		devfreq->governor->event_handler(devfreq,
 						 DEVFREQ_GOV_STOP, NULL);
@@ -1682,6 +1685,66 @@  static ssize_t available_frequencies_show(struct device *d,
 }
 static DEVICE_ATTR_RO(available_frequencies);
 
+/**
+ * devfreq_trans_stat_show() - show trans stat info through debugfs
+ * @s:		seq_file instance to show trans_stat info of devfreq devices
+ * @data:	not used
+ *
+ * Show detailed information for some device which has more than PAGE_SIZE
+ * bytes of trans stat info.
+ */
+static int devfreq_trans_stat_show(struct seq_file *s, void *unused)
+{
+	struct devfreq *df = s->private;
+	unsigned int max_state;
+	int i, j;
+
+	if (!df->profile)
+		return -EINVAL;
+	max_state = df->max_state;
+
+	if (max_state == 0) {
+		seq_puts(s, "Not Supported.\n");
+		return 0;
+	}
+
+	mutex_lock(&df->lock);
+	if (!df->stop_polling &&
+			devfreq_update_status(df, df->previous_freq)) {
+		mutex_unlock(&df->lock);
+		return 0;
+	}
+	mutex_unlock(&df->lock);
+
+	seq_puts(s, "     From  :   To\n");
+	seq_puts(s, "           :");
+	for (i = 0; i < max_state; i++)
+		seq_printf(s, "%10lu", df->freq_table[i]);
+
+	seq_puts(s, "   time(ms)\n");
+
+	for (i = 0; i < max_state; i++) {
+		if (df->freq_table[i] == df->previous_freq)
+			seq_puts(s, "*");
+		else
+			seq_puts(s, " ");
+
+		seq_printf(s, "%10lu:", df->freq_table[i]);
+
+		for (j = 0; j < max_state; j++)
+			seq_printf(s, "%10u",
+				df->stats.trans_table[(i * max_state) + j]);
+
+		seq_printf(s, "%10llu\n", (u64)
+			jiffies64_to_msecs(df->stats.time_in_state[i]));
+	}
+
+	seq_printf(s, "Total transition : %u\n", df->stats.total_trans);
+
+	return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(devfreq_trans_stat);
+
 static ssize_t trans_stat_show(struct device *dev,
 			       struct device_attribute *attr, char *buf)
 {
@@ -1694,8 +1757,22 @@  static ssize_t trans_stat_show(struct device *dev,
 		return -EINVAL;
 	max_state = df->max_state;
 
-	if (max_state == 0)
+	if (max_state == 0) {
 		return sprintf(buf, "Not Supported.\n");
+	} else if (max_state > 12) {
+		/*
+		 * In theory, 13 states will use more than PAGE_SIZE
+		 * bytes, show detail info through debugfs
+		 */
+		if (!df->trans_stat)
+			df->trans_stat = debugfs_create_file("trans_stat", 0444,
+					df->debugfs_dir, df,
+					&devfreq_trans_stat_fops);
+		return sprintf(buf,
+				"This device's data size exceeds the limit of sysfs.\n"
+				"Please use debugfs for detailed information:\n"
+				"/sys/kernel/debug/devfreq/.../trans_stat\n");
+	}
 
 	mutex_lock(&df->lock);
 	if (!df->stop_polling &&
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index d312ffbac4dd..7df3f9e51d28 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -209,6 +209,8 @@  struct devfreq {
 
 	/* information for device frequency transitions */
 	struct devfreq_stats stats;
+	struct dentry *debugfs_dir;
+	struct dentry *trans_stat;
 
 	struct srcu_notifier_head transition_notifier_list;