Add sysfs interface to read System Manager syslog and system info
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/firmware/imx/sm-misc.c | 97 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/drivers/firmware/imx/sm-misc.c b/drivers/firmware/imx/sm-misc.c
index fc3ee12c2be878e0285183e3381c9514a63d5142..55485a3c4a5c615102a377f41025a6911d746770 100644
--- a/drivers/firmware/imx/sm-misc.c
+++ b/drivers/firmware/imx/sm-misc.c
@@ -44,6 +44,100 @@ static int scmi_imx_misc_ctrl_notifier(struct notifier_block *nb,
return 0;
}
+static ssize_t syslog_show(struct device *device, struct device_attribute *attr,
+ char *buf)
+{
+ struct scmi_imx_misc_sys_sleep_rec *rec;
+ struct scmi_imx_misc_syslog *syslog;
+ int ret;
+ size_t len = 0;
+
+ if (!ph)
+ return 0;
+
+ syslog = kmalloc(sizeof(*syslog), GFP_KERNEL);
+ if (!syslog)
+ return -ENOMEM;
+
+ ret = imx_misc_ctrl_ops->misc_syslog(ph, sizeof(*syslog), syslog);
+ if (ret) {
+ kfree(syslog);
+ return ret;
+ }
+
+ rec = &syslog->syssleeprecord;
+
+ len += sysfs_emit_at(buf, len, "Wake Vector = %u\n", rec->wakesource);
+ len += sysfs_emit_at(buf, len, "Sys sleep mode = %u\n", rec->syssleepmode);
+ len += sysfs_emit_at(buf, len, "Sys sleep flags = 0x%08x\n", rec->syssleepflags);
+ len += sysfs_emit_at(buf, len, "MIX power status = 0x%08x\n", rec->mixpwrstat);
+ len += sysfs_emit_at(buf, len, "MEM power status = 0x%08x\n", rec->mempwrstat);
+ len += sysfs_emit_at(buf, len, "PLL power status = 0x%08x\n", rec->pllpwrstat);
+ len += sysfs_emit_at(buf, len, "Sleep latency = %u\n", rec->sleepentryusec);
+ len += sysfs_emit_at(buf, len, "Wake latency = %u\n", rec->sleepexitusec);
+ len += sysfs_emit_at(buf, len, "Sleep count = %u\n", rec->sleepcnt);
+
+ kfree(syslog);
+
+ return len;
+}
+
+static DEVICE_ATTR_RO(syslog);
+
+static ssize_t system_info_show(struct device *device, struct device_attribute *attr,
+ char *buf)
+{
+ struct scmi_imx_misc_system_info *info;
+ int len = 0;
+ int ret;
+
+ if (!ph)
+ return 0;
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ ret = imx_misc_ctrl_ops->misc_discover_build_info(ph, info);
+ if (ret)
+ goto err;
+
+ ret = imx_misc_ctrl_ops->misc_cfg_info(ph, info);
+ if (ret)
+ goto err;
+
+ ret = imx_misc_ctrl_ops->misc_silicon_info(ph, info);
+ if (ret)
+ goto err;
+
+ ret = imx_misc_ctrl_ops->misc_board_info(ph, info);
+ if (ret)
+ goto err;
+
+ len += sysfs_emit_at(buf, len, "SM Version = Build %u, Commit 08%x\n",
+ info->buildnum, info->buildcommit);
+ len += sysfs_emit_at(buf, len, "SM Config = %s, mSel=%u\n",
+ info->cfgname, info->msel);
+ len += sysfs_emit_at(buf, len, "Silicon = %s\n", info->siname);
+ len += sysfs_emit_at(buf, len, "Board = %s, attr=0x%08x\n",
+ info->brdname, info->brd_attributes);
+
+ ret = len;
+err:
+ kfree(info);
+ return ret;
+}
+
+static DEVICE_ATTR_RO(system_info);
+
+static struct attribute *sm_misc_attrs[] = {
+ &dev_attr_syslog.attr,
+ &dev_attr_system_info.attr,
+ NULL,
+};
+
+ATTRIBUTE_GROUPS(sm_misc);
+
static int scmi_imx_misc_ctrl_probe(struct scmi_device *sdev)
{
const struct scmi_handle *handle = sdev->handle;
@@ -108,6 +202,9 @@ static const struct scmi_device_id scmi_id_table[] = {
MODULE_DEVICE_TABLE(scmi, scmi_id_table);
static struct scmi_driver scmi_imx_misc_ctrl_driver = {
+ .driver = {
+ .dev_groups = sm_misc_groups,
+ },
.name = "scmi-imx-misc-ctrl",
.probe = scmi_imx_misc_ctrl_probe,
.id_table = scmi_id_table,
--
2.37.1
On Fri, Jun 27, 2025 at 02:03:50PM +0800, Peng Fan wrote:
> Add sysfs interface to read System Manager syslog and system info
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
> drivers/firmware/imx/sm-misc.c | 97 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 97 insertions(+)
>
> diff --git a/drivers/firmware/imx/sm-misc.c b/drivers/firmware/imx/sm-misc.c
> index fc3ee12c2be878e0285183e3381c9514a63d5142..55485a3c4a5c615102a377f41025a6911d746770 100644
> --- a/drivers/firmware/imx/sm-misc.c
> +++ b/drivers/firmware/imx/sm-misc.c
> @@ -44,6 +44,100 @@ static int scmi_imx_misc_ctrl_notifier(struct notifier_block *nb,
> return 0;
> }
>
> +static ssize_t syslog_show(struct device *device, struct device_attribute *attr,
> + char *buf)
> +{
> + struct scmi_imx_misc_sys_sleep_rec *rec;
> + struct scmi_imx_misc_syslog *syslog;
> + int ret;
> + size_t len = 0;
> +
> + if (!ph)
> + return 0;
> +
> + syslog = kmalloc(sizeof(*syslog), GFP_KERNEL);
> + if (!syslog)
> + return -ENOMEM;
> +
> + ret = imx_misc_ctrl_ops->misc_syslog(ph, sizeof(*syslog), syslog);
> + if (ret) {
> + kfree(syslog);
> + return ret;
> + }
> +
> + rec = &syslog->syssleeprecord;
> +
> + len += sysfs_emit_at(buf, len, "Wake Vector = %u\n", rec->wakesource);
> + len += sysfs_emit_at(buf, len, "Sys sleep mode = %u\n", rec->syssleepmode);
> + len += sysfs_emit_at(buf, len, "Sys sleep flags = 0x%08x\n", rec->syssleepflags);
> + len += sysfs_emit_at(buf, len, "MIX power status = 0x%08x\n", rec->mixpwrstat);
> + len += sysfs_emit_at(buf, len, "MEM power status = 0x%08x\n", rec->mempwrstat);
> + len += sysfs_emit_at(buf, len, "PLL power status = 0x%08x\n", rec->pllpwrstat);
> + len += sysfs_emit_at(buf, len, "Sleep latency = %u\n", rec->sleepentryusec);
> + len += sysfs_emit_at(buf, len, "Wake latency = %u\n", rec->sleepexitusec);
> + len += sysfs_emit_at(buf, len, "Sleep count = %u\n", rec->sleepcnt);
> +
Why can't this be individual files and values ?
--
Regards,
Sudeep
On Wed, Jul 02, 2025 at 04:22:47PM +0100, Sudeep Holla wrote:
>On Fri, Jun 27, 2025 at 02:03:50PM +0800, Peng Fan wrote:
>> Add sysfs interface to read System Manager syslog and system info
>>
>> Signed-off-by: Peng Fan <peng.fan@nxp.com>
>> ---
>> drivers/firmware/imx/sm-misc.c | 97 ++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 97 insertions(+)
>>
>> diff --git a/drivers/firmware/imx/sm-misc.c b/drivers/firmware/imx/sm-misc.c
>> index fc3ee12c2be878e0285183e3381c9514a63d5142..55485a3c4a5c615102a377f41025a6911d746770 100644
>> --- a/drivers/firmware/imx/sm-misc.c
>> +++ b/drivers/firmware/imx/sm-misc.c
>> @@ -44,6 +44,100 @@ static int scmi_imx_misc_ctrl_notifier(struct notifier_block *nb,
>> return 0;
>> }
>>
>> +static ssize_t syslog_show(struct device *device, struct device_attribute *attr,
>> + char *buf)
>> +{
>> + struct scmi_imx_misc_sys_sleep_rec *rec;
>> + struct scmi_imx_misc_syslog *syslog;
>> + int ret;
>> + size_t len = 0;
>> +
>> + if (!ph)
>> + return 0;
>> +
>> + syslog = kmalloc(sizeof(*syslog), GFP_KERNEL);
>> + if (!syslog)
>> + return -ENOMEM;
>> +
>> + ret = imx_misc_ctrl_ops->misc_syslog(ph, sizeof(*syslog), syslog);
>> + if (ret) {
>> + kfree(syslog);
>> + return ret;
>> + }
>> +
>> + rec = &syslog->syssleeprecord;
>> +
>> + len += sysfs_emit_at(buf, len, "Wake Vector = %u\n", rec->wakesource);
>> + len += sysfs_emit_at(buf, len, "Sys sleep mode = %u\n", rec->syssleepmode);
>> + len += sysfs_emit_at(buf, len, "Sys sleep flags = 0x%08x\n", rec->syssleepflags);
>> + len += sysfs_emit_at(buf, len, "MIX power status = 0x%08x\n", rec->mixpwrstat);
>> + len += sysfs_emit_at(buf, len, "MEM power status = 0x%08x\n", rec->mempwrstat);
>> + len += sysfs_emit_at(buf, len, "PLL power status = 0x%08x\n", rec->pllpwrstat);
>> + len += sysfs_emit_at(buf, len, "Sleep latency = %u\n", rec->sleepentryusec);
>> + len += sysfs_emit_at(buf, len, "Wake latency = %u\n", rec->sleepexitusec);
>> + len += sysfs_emit_at(buf, len, "Sleep count = %u\n", rec->sleepcnt);
>> +
>
>Why can't this be individual files and values ?
The System manager firmware provides a command "syslog" to dump
all the information, I just follow same.
With individual files, some values may not be consistent, because
system behaviour may change during reading two files.
Regards,
Peng
>
>--
>Regards,
>Sudeep
On Fri, Jul 04, 2025 at 06:28:02PM +0800, Peng Fan wrote:
> On Wed, Jul 02, 2025 at 04:22:47PM +0100, Sudeep Holla wrote:
> >On Fri, Jun 27, 2025 at 02:03:50PM +0800, Peng Fan wrote:
> >> Add sysfs interface to read System Manager syslog and system info
> >>
> >> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> >> ---
> >> drivers/firmware/imx/sm-misc.c | 97 ++++++++++++++++++++++++++++++++++++++++++
> >> 1 file changed, 97 insertions(+)
> >>
> >> diff --git a/drivers/firmware/imx/sm-misc.c b/drivers/firmware/imx/sm-misc.c
> >> index fc3ee12c2be878e0285183e3381c9514a63d5142..55485a3c4a5c615102a377f41025a6911d746770 100644
> >> --- a/drivers/firmware/imx/sm-misc.c
> >> +++ b/drivers/firmware/imx/sm-misc.c
> >> @@ -44,6 +44,100 @@ static int scmi_imx_misc_ctrl_notifier(struct notifier_block *nb,
> >> return 0;
> >> }
> >>
> >> +static ssize_t syslog_show(struct device *device, struct device_attribute *attr,
> >> + char *buf)
> >> +{
> >> + struct scmi_imx_misc_sys_sleep_rec *rec;
> >> + struct scmi_imx_misc_syslog *syslog;
> >> + int ret;
> >> + size_t len = 0;
> >> +
> >> + if (!ph)
> >> + return 0;
> >> +
> >> + syslog = kmalloc(sizeof(*syslog), GFP_KERNEL);
> >> + if (!syslog)
> >> + return -ENOMEM;
> >> +
> >> + ret = imx_misc_ctrl_ops->misc_syslog(ph, sizeof(*syslog), syslog);
> >> + if (ret) {
> >> + kfree(syslog);
> >> + return ret;
> >> + }
> >> +
> >> + rec = &syslog->syssleeprecord;
> >> +
> >> + len += sysfs_emit_at(buf, len, "Wake Vector = %u\n", rec->wakesource);
> >> + len += sysfs_emit_at(buf, len, "Sys sleep mode = %u\n", rec->syssleepmode);
> >> + len += sysfs_emit_at(buf, len, "Sys sleep flags = 0x%08x\n", rec->syssleepflags);
> >> + len += sysfs_emit_at(buf, len, "MIX power status = 0x%08x\n", rec->mixpwrstat);
> >> + len += sysfs_emit_at(buf, len, "MEM power status = 0x%08x\n", rec->mempwrstat);
> >> + len += sysfs_emit_at(buf, len, "PLL power status = 0x%08x\n", rec->pllpwrstat);
> >> + len += sysfs_emit_at(buf, len, "Sleep latency = %u\n", rec->sleepentryusec);
> >> + len += sysfs_emit_at(buf, len, "Wake latency = %u\n", rec->sleepexitusec);
> >> + len += sysfs_emit_at(buf, len, "Sleep count = %u\n", rec->sleepcnt);
> >> +
> >
> >Why can't this be individual files and values ?
>
> The System manager firmware provides a command "syslog" to dump
> all the information, I just follow same.
>
> With individual files, some values may not be consistent, because
> system behaviour may change during reading two files.
>
You definitely need to convince Greg if you take this approach. I am sure
he prefers single value sysfs files.
--
Regards,
Sudeep
Hi Peng,
kernel test robot noticed the following build warnings:
[auto build test WARNING on ecb259c4f70dd5c83907809f45bf4dc6869961d7]
url: https://github.com/intel-lab-lkp/linux/commits/Peng-Fan/firmware-arm_scmi-imx-Add-documentation-for-MISC_BOARD_INFO/20250627-140736
base: ecb259c4f70dd5c83907809f45bf4dc6869961d7
patch link: https://lore.kernel.org/r/20250627-sm-misc-api-v1-v1-7-2b99481fe825%40nxp.com
patch subject: [PATCH 7/7] firmware: imx: sm-misc: Dump syslog and system info
config: x86_64-buildonly-randconfig-005-20250627 (https://download.01.org/0day-ci/archive/20250628/202506282233.n54Z23oc-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250628/202506282233.n54Z23oc-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/202506282233.n54Z23oc-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/firmware/imx/sm-misc.c: In function 'syslog_show':
drivers/firmware/imx/sm-misc.c:58:18: error: implicit declaration of function 'kmalloc'; did you mean 'mm_alloc'? [-Werror=implicit-function-declaration]
58 | syslog = kmalloc(sizeof(*syslog), GFP_KERNEL);
| ^~~~~~~
| mm_alloc
>> drivers/firmware/imx/sm-misc.c:58:16: warning: assignment to 'struct scmi_imx_misc_syslog *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
58 | syslog = kmalloc(sizeof(*syslog), GFP_KERNEL);
| ^
drivers/firmware/imx/sm-misc.c:64:17: error: implicit declaration of function 'kfree' [-Werror=implicit-function-declaration]
64 | kfree(syslog);
| ^~~~~
drivers/firmware/imx/sm-misc.c: In function 'system_info_show':
>> drivers/firmware/imx/sm-misc.c:97:14: warning: assignment to 'struct scmi_imx_misc_system_info *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
97 | info = kmalloc(sizeof(*info), GFP_KERNEL);
| ^
cc1: some warnings being treated as errors
vim +58 drivers/firmware/imx/sm-misc.c
46
47 static ssize_t syslog_show(struct device *device, struct device_attribute *attr,
48 char *buf)
49 {
50 struct scmi_imx_misc_sys_sleep_rec *rec;
51 struct scmi_imx_misc_syslog *syslog;
52 int ret;
53 size_t len = 0;
54
55 if (!ph)
56 return 0;
57
> 58 syslog = kmalloc(sizeof(*syslog), GFP_KERNEL);
59 if (!syslog)
60 return -ENOMEM;
61
62 ret = imx_misc_ctrl_ops->misc_syslog(ph, sizeof(*syslog), syslog);
63 if (ret) {
64 kfree(syslog);
65 return ret;
66 }
67
68 rec = &syslog->syssleeprecord;
69
70 len += sysfs_emit_at(buf, len, "Wake Vector = %u\n", rec->wakesource);
71 len += sysfs_emit_at(buf, len, "Sys sleep mode = %u\n", rec->syssleepmode);
72 len += sysfs_emit_at(buf, len, "Sys sleep flags = 0x%08x\n", rec->syssleepflags);
73 len += sysfs_emit_at(buf, len, "MIX power status = 0x%08x\n", rec->mixpwrstat);
74 len += sysfs_emit_at(buf, len, "MEM power status = 0x%08x\n", rec->mempwrstat);
75 len += sysfs_emit_at(buf, len, "PLL power status = 0x%08x\n", rec->pllpwrstat);
76 len += sysfs_emit_at(buf, len, "Sleep latency = %u\n", rec->sleepentryusec);
77 len += sysfs_emit_at(buf, len, "Wake latency = %u\n", rec->sleepexitusec);
78 len += sysfs_emit_at(buf, len, "Sleep count = %u\n", rec->sleepcnt);
79
80 kfree(syslog);
81
82 return len;
83 }
84
85 static DEVICE_ATTR_RO(syslog);
86
87 static ssize_t system_info_show(struct device *device, struct device_attribute *attr,
88 char *buf)
89 {
90 struct scmi_imx_misc_system_info *info;
91 int len = 0;
92 int ret;
93
94 if (!ph)
95 return 0;
96
> 97 info = kmalloc(sizeof(*info), GFP_KERNEL);
98 if (!info)
99 return -ENOMEM;
100
101 ret = imx_misc_ctrl_ops->misc_discover_build_info(ph, info);
102 if (ret)
103 goto err;
104
105 ret = imx_misc_ctrl_ops->misc_cfg_info(ph, info);
106 if (ret)
107 goto err;
108
109 ret = imx_misc_ctrl_ops->misc_silicon_info(ph, info);
110 if (ret)
111 goto err;
112
113 ret = imx_misc_ctrl_ops->misc_board_info(ph, info);
114 if (ret)
115 goto err;
116
117 len += sysfs_emit_at(buf, len, "SM Version = Build %u, Commit 08%x\n",
118 info->buildnum, info->buildcommit);
119 len += sysfs_emit_at(buf, len, "SM Config = %s, mSel=%u\n",
120 info->cfgname, info->msel);
121 len += sysfs_emit_at(buf, len, "Silicon = %s\n", info->siname);
122 len += sysfs_emit_at(buf, len, "Board = %s, attr=0x%08x\n",
123 info->brdname, info->brd_attributes);
124
125 ret = len;
126 err:
127 kfree(info);
128 return ret;
129 }
130
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Hi Peng,
kernel test robot noticed the following build errors:
[auto build test ERROR on ecb259c4f70dd5c83907809f45bf4dc6869961d7]
url: https://github.com/intel-lab-lkp/linux/commits/Peng-Fan/firmware-arm_scmi-imx-Add-documentation-for-MISC_BOARD_INFO/20250627-140736
base: ecb259c4f70dd5c83907809f45bf4dc6869961d7
patch link: https://lore.kernel.org/r/20250627-sm-misc-api-v1-v1-7-2b99481fe825%40nxp.com
patch subject: [PATCH 7/7] firmware: imx: sm-misc: Dump syslog and system info
config: i386-buildonly-randconfig-001-20250628 (https://download.01.org/0day-ci/archive/20250628/202506280217.aZih1pGT-lkp@intel.com/config)
compiler: clang version 20.1.7 (https://github.com/llvm/llvm-project 6146a88f60492b520a36f8f8f3231e15f3cc6082)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250628/202506280217.aZih1pGT-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/202506280217.aZih1pGT-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/firmware/imx/sm-misc.c:58:11: error: call to undeclared function 'kmalloc'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
58 | syslog = kmalloc(sizeof(*syslog), GFP_KERNEL);
| ^
drivers/firmware/imx/sm-misc.c:58:11: note: did you mean 'mm_alloc'?
include/linux/sched/mm.h:16:26: note: 'mm_alloc' declared here
16 | extern struct mm_struct *mm_alloc(void);
| ^
>> drivers/firmware/imx/sm-misc.c:58:9: error: incompatible integer to pointer conversion assigning to 'struct scmi_imx_misc_syslog *' from 'int' [-Wint-conversion]
58 | syslog = kmalloc(sizeof(*syslog), GFP_KERNEL);
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/firmware/imx/sm-misc.c:64:3: error: call to undeclared function 'kfree'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
64 | kfree(syslog);
| ^
drivers/firmware/imx/sm-misc.c:80:2: error: call to undeclared function 'kfree'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
80 | kfree(syslog);
| ^
drivers/firmware/imx/sm-misc.c:97:9: error: call to undeclared function 'kmalloc'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
97 | info = kmalloc(sizeof(*info), GFP_KERNEL);
| ^
>> drivers/firmware/imx/sm-misc.c:97:7: error: incompatible integer to pointer conversion assigning to 'struct scmi_imx_misc_system_info *' from 'int' [-Wint-conversion]
97 | info = kmalloc(sizeof(*info), GFP_KERNEL);
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/firmware/imx/sm-misc.c:127:2: error: call to undeclared function 'kfree'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
127 | kfree(info);
| ^
7 errors generated.
vim +/kmalloc +58 drivers/firmware/imx/sm-misc.c
46
47 static ssize_t syslog_show(struct device *device, struct device_attribute *attr,
48 char *buf)
49 {
50 struct scmi_imx_misc_sys_sleep_rec *rec;
51 struct scmi_imx_misc_syslog *syslog;
52 int ret;
53 size_t len = 0;
54
55 if (!ph)
56 return 0;
57
> 58 syslog = kmalloc(sizeof(*syslog), GFP_KERNEL);
59 if (!syslog)
60 return -ENOMEM;
61
62 ret = imx_misc_ctrl_ops->misc_syslog(ph, sizeof(*syslog), syslog);
63 if (ret) {
> 64 kfree(syslog);
65 return ret;
66 }
67
68 rec = &syslog->syssleeprecord;
69
70 len += sysfs_emit_at(buf, len, "Wake Vector = %u\n", rec->wakesource);
71 len += sysfs_emit_at(buf, len, "Sys sleep mode = %u\n", rec->syssleepmode);
72 len += sysfs_emit_at(buf, len, "Sys sleep flags = 0x%08x\n", rec->syssleepflags);
73 len += sysfs_emit_at(buf, len, "MIX power status = 0x%08x\n", rec->mixpwrstat);
74 len += sysfs_emit_at(buf, len, "MEM power status = 0x%08x\n", rec->mempwrstat);
75 len += sysfs_emit_at(buf, len, "PLL power status = 0x%08x\n", rec->pllpwrstat);
76 len += sysfs_emit_at(buf, len, "Sleep latency = %u\n", rec->sleepentryusec);
77 len += sysfs_emit_at(buf, len, "Wake latency = %u\n", rec->sleepexitusec);
78 len += sysfs_emit_at(buf, len, "Sleep count = %u\n", rec->sleepcnt);
79
80 kfree(syslog);
81
82 return len;
83 }
84
85 static DEVICE_ATTR_RO(syslog);
86
87 static ssize_t system_info_show(struct device *device, struct device_attribute *attr,
88 char *buf)
89 {
90 struct scmi_imx_misc_system_info *info;
91 int len = 0;
92 int ret;
93
94 if (!ph)
95 return 0;
96
> 97 info = kmalloc(sizeof(*info), GFP_KERNEL);
98 if (!info)
99 return -ENOMEM;
100
101 ret = imx_misc_ctrl_ops->misc_discover_build_info(ph, info);
102 if (ret)
103 goto err;
104
105 ret = imx_misc_ctrl_ops->misc_cfg_info(ph, info);
106 if (ret)
107 goto err;
108
109 ret = imx_misc_ctrl_ops->misc_silicon_info(ph, info);
110 if (ret)
111 goto err;
112
113 ret = imx_misc_ctrl_ops->misc_board_info(ph, info);
114 if (ret)
115 goto err;
116
117 len += sysfs_emit_at(buf, len, "SM Version = Build %u, Commit 08%x\n",
118 info->buildnum, info->buildcommit);
119 len += sysfs_emit_at(buf, len, "SM Config = %s, mSel=%u\n",
120 info->cfgname, info->msel);
121 len += sysfs_emit_at(buf, len, "Silicon = %s\n", info->siname);
122 len += sysfs_emit_at(buf, len, "Board = %s, attr=0x%08x\n",
123 info->brdname, info->brd_attributes);
124
125 ret = len;
126 err:
127 kfree(info);
128 return ret;
129 }
130
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
On Fri, Jun 27, 2025 at 02:03:50PM +0800, Peng Fan wrote:
> Add sysfs interface to read System Manager syslog and system info
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
> drivers/firmware/imx/sm-misc.c | 97 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 97 insertions(+)
>
> diff --git a/drivers/firmware/imx/sm-misc.c b/drivers/firmware/imx/sm-misc.c
> index fc3ee12c2be878e0285183e3381c9514a63d5142..55485a3c4a5c615102a377f41025a6911d746770 100644
> --- a/drivers/firmware/imx/sm-misc.c
> +++ b/drivers/firmware/imx/sm-misc.c
> @@ -44,6 +44,100 @@ static int scmi_imx_misc_ctrl_notifier(struct notifier_block *nb,
> return 0;
> }
>
> +static ssize_t syslog_show(struct device *device, struct device_attribute *attr,
> + char *buf)
> +{
> + struct scmi_imx_misc_sys_sleep_rec *rec;
> + struct scmi_imx_misc_syslog *syslog;
> + int ret;
> + size_t len = 0;
> +
> + if (!ph)
> + return 0;
> +
> + syslog = kmalloc(sizeof(*syslog), GFP_KERNEL);
> + if (!syslog)
> + return -ENOMEM;
> +
> + ret = imx_misc_ctrl_ops->misc_syslog(ph, sizeof(*syslog), syslog);
...ah...so you basically cast to void a structure of u32 words and then
expect that the firmware perfectly aligned with how the struct is
defined here....size checks assures no out-of-bounds BUT the meaning of
he blob itself is entirely up to FW and kernel being aligned, since no
type checking is done of any kind and fields are NOT reference by
name...so may I ask why ? ..also because the scmi_imx_misc_syslog seems
pretty tiny to need iterators to parse back the reply...do you have so
tiny transpotr message size ?
..anyway I would suggest at least to add some sort of version-field to
the struct so that at least you can detect if the FW spits out something
that is not what your driver expect or is ready to handle...especially
if you plan to extend or modify the layout of the structs in the future.
> + if (ret) {
> + kfree(syslog);
> + return ret;
> + }
> +
> + rec = &syslog->syssleeprecord;
> +
> + len += sysfs_emit_at(buf, len, "Wake Vector = %u\n", rec->wakesource);
> + len += sysfs_emit_at(buf, len, "Sys sleep mode = %u\n", rec->syssleepmode);
> + len += sysfs_emit_at(buf, len, "Sys sleep flags = 0x%08x\n", rec->syssleepflags);
> + len += sysfs_emit_at(buf, len, "MIX power status = 0x%08x\n", rec->mixpwrstat);
> + len += sysfs_emit_at(buf, len, "MEM power status = 0x%08x\n", rec->mempwrstat);
> + len += sysfs_emit_at(buf, len, "PLL power status = 0x%08x\n", rec->pllpwrstat);
> + len += sysfs_emit_at(buf, len, "Sleep latency = %u\n", rec->sleepentryusec);
> + len += sysfs_emit_at(buf, len, "Wake latency = %u\n", rec->sleepexitusec);
> + len += sysfs_emit_at(buf, len, "Sleep count = %u\n", rec->sleepcnt);
> +
... how wonder how much is still frowned upon to serve such big multiline
structured information payloads from sysfs ... (asking for a friend :P)
> + kfree(syslog);
> +
> + return len;
> +}
> +
> +static DEVICE_ATTR_RO(syslog);
> +
> +static ssize_t system_info_show(struct device *device, struct device_attribute *attr,
> + char *buf)
> +{
> + struct scmi_imx_misc_system_info *info;
> + int len = 0;
> + int ret;
> +
> + if (!ph)
> + return 0;
> +
> + info = kmalloc(sizeof(*info), GFP_KERNEL);
> + if (!info)
> + return -ENOMEM;
> +
> + ret = imx_misc_ctrl_ops->misc_discover_build_info(ph, info);
> + if (ret)
> + goto err;
> +
> + ret = imx_misc_ctrl_ops->misc_cfg_info(ph, info);
> + if (ret)
> + goto err;
> +
> + ret = imx_misc_ctrl_ops->misc_silicon_info(ph, info);
> + if (ret)
> + goto err;
> +
> + ret = imx_misc_ctrl_ops->misc_board_info(ph, info);
> + if (ret)
> + goto err;
> +
> + len += sysfs_emit_at(buf, len, "SM Version = Build %u, Commit 08%x\n",
> + info->buildnum, info->buildcommit);
> + len += sysfs_emit_at(buf, len, "SM Config = %s, mSel=%u\n",
> + info->cfgname, info->msel);
> + len += sysfs_emit_at(buf, len, "Silicon = %s\n", info->siname);
> + len += sysfs_emit_at(buf, len, "Board = %s, attr=0x%08x\n",
> + info->brdname, info->brd_attributes);
...so some of this stuff Build/Silicon/BoaRD info has pretty much
'forever' lifetime...are you sure you want to query them out of the FW
each time you issue a sysfs show ?
Cannot you simply dump this stuff once for all at probve time and
instead query misc_cfg_info() upon each show to refresh only the data
that will change ?
(this also corroborates my idea that you should somehow partition this
data into distinct structs by their lifetime...
Thanks,
Cristian
On Fri, Jun 27, 2025 at 03:11:03PM +0100, Cristian Marussi wrote:
>On Fri, Jun 27, 2025 at 02:03:50PM +0800, Peng Fan wrote:
>> Add sysfs interface to read System Manager syslog and system info
>>
>> Signed-off-by: Peng Fan <peng.fan@nxp.com>
>> ---
>> drivers/firmware/imx/sm-misc.c | 97 ++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 97 insertions(+)
>>
>> diff --git a/drivers/firmware/imx/sm-misc.c b/drivers/firmware/imx/sm-misc.c
>> index fc3ee12c2be878e0285183e3381c9514a63d5142..55485a3c4a5c615102a377f41025a6911d746770 100644
>> --- a/drivers/firmware/imx/sm-misc.c
>> +++ b/drivers/firmware/imx/sm-misc.c
>> @@ -44,6 +44,100 @@ static int scmi_imx_misc_ctrl_notifier(struct notifier_block *nb,
>> return 0;
>> }
>>
>> +static ssize_t syslog_show(struct device *device, struct device_attribute *attr,
>> + char *buf)
>> +{
>> + struct scmi_imx_misc_sys_sleep_rec *rec;
>> + struct scmi_imx_misc_syslog *syslog;
>> + int ret;
>> + size_t len = 0;
>> +
>> + if (!ph)
>> + return 0;
>> +
>> + syslog = kmalloc(sizeof(*syslog), GFP_KERNEL);
>> + if (!syslog)
>> + return -ENOMEM;
>> +
>> + ret = imx_misc_ctrl_ops->misc_syslog(ph, sizeof(*syslog), syslog);
>
>...ah...so you basically cast to void a structure of u32 words and then
>expect that the firmware perfectly aligned with how the struct is
>defined here....size checks assures no out-of-bounds BUT the meaning of
>he blob itself is entirely up to FW and kernel being aligned, since no
>type checking is done of any kind and fields are NOT reference by
>name...so may I ask why ?
I thought to use "u32 *syslog", but this needs a cast in
misc_syslog(x,y,(u32 *)syslog), or I could directly change
the misc_syslog function prototype to use 'struct scmi_imx_misc_syslog *'.
No specific reason, just think 'void *' could avoid a cast.
..also because the scmi_imx_misc_syslog seems
>pretty tiny to need iterators to parse back the reply...do you have so
>tiny transpotr message size ?
The transport memory size is 0x80 bytes, it could cover the current
syslog, but I am not sure whether in future, the firmware could
extend to add more information.
In our firmware there is one more field that I not include in this patchset,
because it is default not built in in firmware:
typedef struct
{
/*! System sleep record */
dev_sm_sys_sleep_rec_t sysSleepRecord;
/*! Device error log */
uint32_t devErrLog;
#ifdef DEV_SM_MSG_PROF_CNT
/*! Message profiling record */
dev_sm_sys_msg_rec_t sysMsgRecord;
#endif
} dev_sm_syslog_t;
typedef struct
{
uint32_t scmiChannel; /*!< Caller SCMI channel */
uint32_t chanType; /*!< SCMI channel type */
uint32_t protocolId; /*!< SCMI protocol ID */
uint32_t msgId; /*!< SCMI message ID */
uint32_t msgLatUsec; /*!< Message latency */
} dev_sm_sys_msg_prof_t;
/*!
* Message profile record
*/
typedef struct
{
/*! MSG profile log */
dev_sm_sys_msg_prof_t msgProf[DEV_SM_MSG_PROF_CNT];
} dev_sm_sys_msg_rec_t;
With profiling, we need iterator to get all the information.
In our default FW build, DEV_SM_MSG_PROF_CNT is not defined, but
I could keep iterator in case DEV_SM_MSG_PROF_CNT enabled in future.
>
>..anyway I would suggest at least to add some sort of version-field to
>the struct so that at least you can detect if the FW spits out something
>that is not what your driver expect or is ready to handle...especially
>if you plan to extend or modify the layout of the structs in the future.
Would you please share more insights on what version is needed here?
You mean add a field for syslog protocol as below?
struct scmi_imx_misc_syslog {
uint32_t version; //Set as protocol version and display it in sysfs show ops?
struct scmi_imx_misc_sys_sleep_rec syssleeprecord;
uint32_t deverrlog;
};
>
>
>> + if (ret) {
>> + kfree(syslog);
>> + return ret;
>> + }
>> +
>> + rec = &syslog->syssleeprecord;
>> +
>> + len += sysfs_emit_at(buf, len, "Wake Vector = %u\n", rec->wakesource);
>> + len += sysfs_emit_at(buf, len, "Sys sleep mode = %u\n", rec->syssleepmode);
>> + len += sysfs_emit_at(buf, len, "Sys sleep flags = 0x%08x\n", rec->syssleepflags);
>> + len += sysfs_emit_at(buf, len, "MIX power status = 0x%08x\n", rec->mixpwrstat);
>> + len += sysfs_emit_at(buf, len, "MEM power status = 0x%08x\n", rec->mempwrstat);
>> + len += sysfs_emit_at(buf, len, "PLL power status = 0x%08x\n", rec->pllpwrstat);
>> + len += sysfs_emit_at(buf, len, "Sleep latency = %u\n", rec->sleepentryusec);
>> + len += sysfs_emit_at(buf, len, "Wake latency = %u\n", rec->sleepexitusec);
>> + len += sysfs_emit_at(buf, len, "Sleep count = %u\n", rec->sleepcnt);
>> +
>
>... how wonder how much is still frowned upon to serve such big multiline
>structured information payloads from sysfs ... (asking for a friend :P)
Just take what our firmware console displays.
And in case the firmware does not have a dedicated uart on some
boards, using syslog to show similar info would be prefered,
so ...
>
>
>> + kfree(syslog);
>> +
>> + return len;
>> +}
>> +
>> +static DEVICE_ATTR_RO(syslog);
>> +
>> +static ssize_t system_info_show(struct device *device, struct device_attribute *attr,
>> + char *buf)
>> +{
>> + struct scmi_imx_misc_system_info *info;
>> + int len = 0;
>> + int ret;
>> +
>> + if (!ph)
>> + return 0;
>> +
>> + info = kmalloc(sizeof(*info), GFP_KERNEL);
>> + if (!info)
>> + return -ENOMEM;
>> +
>> + ret = imx_misc_ctrl_ops->misc_discover_build_info(ph, info);
>> + if (ret)
>> + goto err;
>> +
>> + ret = imx_misc_ctrl_ops->misc_cfg_info(ph, info);
>> + if (ret)
>> + goto err;
>> +
>> + ret = imx_misc_ctrl_ops->misc_silicon_info(ph, info);
>> + if (ret)
>> + goto err;
>> +
>> + ret = imx_misc_ctrl_ops->misc_board_info(ph, info);
>> + if (ret)
>> + goto err;
>> +
>> + len += sysfs_emit_at(buf, len, "SM Version = Build %u, Commit 08%x\n",
>> + info->buildnum, info->buildcommit);
>> + len += sysfs_emit_at(buf, len, "SM Config = %s, mSel=%u\n",
>> + info->cfgname, info->msel);
>> + len += sysfs_emit_at(buf, len, "Silicon = %s\n", info->siname);
>> + len += sysfs_emit_at(buf, len, "Board = %s, attr=0x%08x\n",
>> + info->brdname, info->brd_attributes);
>
>...so some of this stuff Build/Silicon/BoaRD info has pretty much
>'forever' lifetime...are you sure you want to query them out of the FW
>each time you issue a sysfs show ?
>
>Cannot you simply dump this stuff once for all at probve time and
>instead query misc_cfg_info() upon each show to refresh only the data
>that will change ?
>
>(this also corroborates my idea that you should somehow partition this
>data into distinct structs by their lifetime...
In next version, I will change to use probe to query the information and
use sysfs to give userspace an interface to get the queried information.
Thanks,
Peng
>
>Thanks,
>Cristian
© 2016 - 2026 Red Hat, Inc.