Thread (5 messages) 5 messages, 2 authors, 2021-03-18

Re: [Linux-stm32] [PATCH v9 22/33] counter: Internalize sysfs interface code

From: William Breathitt Gray <hidden>
Date: 2021-03-18 14:23:35
Also in: linux-iio, lkml

On Thu, Mar 18, 2021 at 11:10:29AM +0100, Fabrice Gasnier wrote:
On 3/18/21 10:21 AM, Fabrice Gasnier wrote:
quoted
On 3/14/21 10:08 AM, William Breathitt Gray wrote:
quoted
On Sun, Mar 14, 2021 at 04:56:44PM +0900, William Breathitt Gray wrote:
quoted
On Fri, Mar 12, 2021 at 04:02:42PM +0100, Fabrice Gasnier wrote:
quoted
On 3/9/21 2:19 PM, William Breathitt Gray wrote:
quoted
+static ssize_t enums_available_show(const u32 *const enums,
+				    const size_t num_enums,
+				    const char *const strs[], char *buf)
+{
+	size_t len = 0;
+	size_t index;
+
+	for (index = 0; index < num_enums; index++)
+		len += sysfs_emit(buf + len, "%s\n", strs[enums[index]]);
+
+	return len;
+}
+
+static ssize_t strs_available_show(const struct counter_available *const avail,
+				   char *buf)
+{
+	size_t len = 0;
+	size_t index;
+
+	for (index = 0; index < avail->num_items; index++)
+		len += sysfs_emit(buf + len, "%s\n", avail->strs[index]);
+
+	return len;
+}
Hi William,

I was willing to do some testing on this series, on the stm32 counter
drivers, since we released few fixes around them.

I tried to apply this series against current testing branch, with few
patches applied (so it applies cleanly):
- dt-bindings: counter: add interrupt-counter binding
- counter: add IRQ or GPIO based counter
- counter: stm32-timer-cnt: fix ceiling miss-alignment with reload register
- counter: stm32-timer-cnt: fix ceiling write max value
 counter: stm32-timer-cnt: Report count function when SLAVE_MODE_DISABLED


For both the "stm32-lptimer-cnt" and "stm32-timer-cnt" drivers, I get a
warning message and stack dump in "sysfs_emit" when reading the
available functions from sysfs.
I started to do some testing on v8 of this series last week. I didn't
noticed that.

For both the "stm32-lptimer-cnt", there are 2 functions currently I get
1 stack dump. Only the "increase" function is printed correctly.

For the "stm32-timer-cnt", there are 4 functions currently, I get 3
stack dumps. Only the "increase" function is printed correctly

Sample log for "stm32-timer-cnt:

root@stm32mp1:/sys/devices/platform/soc/44000000.timer/44000000.timer:counter/counter0#
cat count0/function_available
[ 4689.195506] ------------[ cut here ]------------
[ 4689.198747] WARNING: CPU: 1 PID: 5841 at fs/sysfs/file.c:737
sysfs_emit+0x88/0x94
[ 4689.206233] invalid sysfs_emit: buf:f4a66208
[ 4689.210553] Modules linked in: sha256_generic libsha256 sha256_arm
cfg80211 panel_orisetech_otm8009a snd_soc_hdmi_codec
snd_soc_stm32_sai_sub stm32_lptimers
[ 4689.261444] CPU: 1 PID: 5841 Comm: cat Tainted: G        W
5.12.0-rc1 #534
[ 4689.268999] Hardware name: STM32 (Device Tree Support)
[ 4689.274166] [<c0310b38>] (unwind_backtrace) from [<c030b4ec>]
(show_stack+0x10/0x14)
[ 4689.281942] [<c030b4ec>] (show_stack) from [<c0fede70>]
(dump_stack+0xc0/0xd4)
[ 4689.289199] [<c0fede70>] (dump_stack) from [<c0345624>]
(__warn+0xec/0x148)
[ 4689.296194] [<c0345624>] (__warn) from [<c0fe9e90>]
(warn_slowpath_fmt+0x98/0xbc)
[ 4689.303714] [<c0fe9e90>] (warn_slowpath_fmt) from [<c0548ee0>]
(sysfs_emit+0x88/0x94)
[ 4689.311586] [<c0548ee0>] (sysfs_emit) from [<bf115de8>]
(counter_comp_available_show+0x11c/0x1a4 [counter])
[ 4689.321382] [<bf115de8>] (counter_comp_available_show [counter]) from
[<c0a21b70>] (dev_attr_show+0x18/0x48)
[ 4689.331263] [<c0a21b70>] (dev_attr_show) from [<c0549014>]
(sysfs_kf_seq_show+0x88/0xf0)
[ 4689.339394] [<c0549014>] (sysfs_kf_seq_show) from [<c04da6e8>]
(seq_read_iter+0x1a4/0x554)
[ 4689.347703] [<c04da6e8>] (seq_read_iter) from [<c04af6f0>]
(vfs_read+0x1ac/0x2c4)
[ 4689.355224] [<c04af6f0>] (vfs_read) from [<c04afc20>]
(ksys_read+0x64/0xdc)
[ 4689.362219] [<c04afc20>] (ksys_read) from [<c03000c0>]
(ret_fast_syscall+0x0/0x58)
[ 4689.369827] Exception stack(0xc7261fa8 to 0xc7261ff0)
[ 4689.374906] 1fa0:                   00000000 00020000 00000003
b6f35000 00020000 00000000
[ 4689.383126] 1fc0: 00000000 00020000 b6f56ce0 00000003 00000003
00000000 00020000 00000000
[ 4689.391344] 1fe0: 00000003 be8239a8 410bff27 4104c066
...
2 more stack dumps follow
...
[ 4689.810479] ---[ end trace 59ed79949efe984c ]---
increase

I get similar backtrace with other _available attributes:
$ cat signal0_action_available
$ cat signal1_action_available

Do you think I'm doing something wrong ?

I tested then "quadrature x4" on the timer driver... It seems all fine.

Best regards
Fabrice
quoted
+
+static ssize_t counter_comp_available_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	const struct counter_attribute *const a = to_counter_attribute(attr);
+	const struct counter_count *const count = a->parent;
+	const struct counter_synapse *const synapse = a->comp.priv;
+	const struct counter_available *const avail = a->comp.priv;
+
+	switch (a->comp.type) {
+	case COUNTER_COMP_FUNCTION:
+		return enums_available_show(count->functions_list,
+					    count->num_functions,
+					    counter_function_str, buf);
+	case COUNTER_COMP_SYNAPSE_ACTION:
+		return enums_available_show(synapse->actions_list,
+					    synapse->num_actions,
+					    counter_synapse_action_str, buf);
+	case COUNTER_COMP_ENUM:
+		return strs_available_show(avail, buf);
+	case COUNTER_COMP_COUNT_MODE:
+		return enums_available_show(avail->enums, avail->num_items,
+					    counter_count_mode_str, buf);
+	default:
+		return -EINVAL;
+	}
+}
Hi Fabrice,

I can confirm that I'm hitting this regression as well with the
104-quad-8 driver. The warning seems to be caused by the
offset_in_page(buf) check in sysfs_emit(). It looks like the first loop
in enums_available_show() calls sysfs_emit() correctly, but subsequent
loops have an invalid buf offset.

The enums_available_show() callback is rather simple: call sysfs_emit()
for each enum string and increment buf by the length written each time.
I haven't modified this function since v8, so I am somewhat confused
about why the buf offset would be invalid here now. I wonder if there
has been a change somewhere else in the kernel that is causing
sysfs_emit() to now return an incorrect length.

William Breathitt Gray
Fabrice,

Would you be able to check the values of buf and len before they enter
sysfs_emit()? I think redefining the enums_available_show() function
like this should suffice:

static ssize_t enums_available_show(const u32 *const enums,
                                    const size_t num_enums,
                                    const char *const strs[], char *buf)
{
        size_t len = 0;
        size_t index;

        for (index = 0; index < num_enums; index++){
                pr_info("buf: %p\tbuf+len: %p\tlen: %zu\n", buf, buf + len, len);
                len += sysfs_emit(buf + len, "%s\n", strs[enums[index]]);
        }

        return len;
}

I want to see whether the issue is due to the sysfs_emit() return value
or the value of buf.
Hi William,

Sorry for the delay,

I'm getting strange results on buf+len. Here's the result I'm getting
with same test as above:

[  170.190995] buf: 5daf3333    buf+len: 5daf3333       len: 0
[  170.194383] buf: 5daf3333    buf+len: 22c37039       len: 9
[  170.199268] ------------[ cut here ]------------
...
[  170.404810] buf: 5daf3333    buf+len: 22c37039       len: 9
[  170.409663] ------------[ cut here ]------------
...
[  170.615265] buf: 5daf3333    buf+len: 22c37039       len: 9
[  170.620117] ------------[ cut here ]------------
...
increase
William,

I did the same, with %px instead of %p, and i'm getting:

[  124.001041] buf: c60fb000    buf+len: c60fb000       len: 0
[  124.009442] buf: c60fb000    buf+len: c60fb009       len: 9
[  124.019118] ------------[ cut here ]------------
...
So, I believe this is caused by the offset_in_page(buf) check, in
sysfs_emit().

I also double checked it on the v8 patchset, and I already had the same
behavior. So I likely didn't checked the available attrs earlier. Sorry
for this confusion.

Best Regards,
Fabrice
Ah, I forgot %p doesn't show the true address. Okay so it looks like we
can't use sysfs_emit() with an offset. I'll change these sysfs_emit()
lines to use scnprintf() instead and that should prevent the warnings
from triggering.

Thanks,

William Breathitt Gray
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help